From 1c53ad7b22b5ef107b1206a2c2202531a5f5506e Mon Sep 17 00:00:00 2001 From: cxumol Date: Fri, 17 Nov 2023 18:21:22 +0000 Subject: [PATCH 1/9] Update db.js and App.svelte --- src/lib/db.js | 1 + src/routes/App.svelte | 10 ++-------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/lib/db.js b/src/lib/db.js index 577e4fe..61fe47b 100644 --- a/src/lib/db.js +++ b/src/lib/db.js @@ -33,6 +33,7 @@ class DB { const defaultData = getDefaultData(); const response = await fetch(`https://${this.cf_workers}/get/${this.username}`, { headers: myheaders }); if (!response.ok) { + console.debug(myheaders); // use default data return getDefaultData(); } diff --git a/src/routes/App.svelte b/src/routes/App.svelte index e2d20b5..a7ed5f0 100644 --- a/src/routes/App.svelte +++ b/src/routes/App.svelte @@ -9,7 +9,6 @@ let needToken; const isInstanceDemo = true; - console.log("now data is", data); // import utils import {DB} from '$lib/db.js'; @@ -131,15 +130,10 @@ return result; }; - - - - - - window.onhashchange = function () { + window.onhashchange = async function () { username = window.location.hash.split('#')[1]; db = new DB(cf_workers, username); - data = db.getData(username); + data = await db.getData(username); updatePageReadMe(); }; function tryUploadData(){ From 718a55aa3c86087f08062b88f1c5d1cd43bf2aae Mon Sep 17 00:00:00 2001 From: cxumol Date: Fri, 17 Nov 2023 18:24:19 +0000 Subject: [PATCH 2/9] fix: upgrade async data loading of window.onhashchange --- src/lib/db.js | 1 - src/routes/App.svelte | 4 ---- 2 files changed, 5 deletions(-) diff --git a/src/lib/db.js b/src/lib/db.js index 61fe47b..577e4fe 100644 --- a/src/lib/db.js +++ b/src/lib/db.js @@ -33,7 +33,6 @@ class DB { const defaultData = getDefaultData(); const response = await fetch(`https://${this.cf_workers}/get/${this.username}`, { headers: myheaders }); if (!response.ok) { - console.debug(myheaders); // use default data return getDefaultData(); } diff --git a/src/routes/App.svelte b/src/routes/App.svelte index a7ed5f0..67ccf2c 100644 --- a/src/routes/App.svelte +++ b/src/routes/App.svelte @@ -115,9 +115,6 @@ alert('Nothing changed. No need to save.'); return false; } - // else{ - // console.log{currentDataStr == jsonedData, currentDataStr , jsonedData} - // } return true; } @@ -178,7 +175,6 @@ function checkToken() { data = data; if (['\\', '"'].some((el) => data.token.includes(el))) alert('disallowed characters'); - // console.log(data.token) } // color-code auto correction, from "Light Blue" to "light-blue" From c5fc624c2343c7170f8a1dc45f79e62d5ecfc501 Mon Sep 17 00:00:00 2001 From: cxumol Date: Fri, 17 Nov 2023 18:31:21 +0000 Subject: [PATCH 3/9] fix: migrate window.needToken to DB. needToken --- src/lib/db.js | 1 - src/routes/App.svelte | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/lib/db.js b/src/lib/db.js index 577e4fe..c15972f 100644 --- a/src/lib/db.js +++ b/src/lib/db.js @@ -48,7 +48,6 @@ class DB { } async uploadData(myDataStr) { - const response = await fetch(`https://${this.cf_workers}/set/${this.username}`, { headers: myheaders, method: 'POST', diff --git a/src/routes/App.svelte b/src/routes/App.svelte index 67ccf2c..4b4d591 100644 --- a/src/routes/App.svelte +++ b/src/routes/App.svelte @@ -6,7 +6,7 @@ let uploadingIconConfig = { color: 'green', icon: 'backup' }; const dataSizeLimit = Number(12345); const cf_workers = 'urlinkcat.t6.workers.dev'; - let needToken; + // let needToken; const isInstanceDemo = true; @@ -329,7 +329,7 @@ - {#if needToken} + {#if db.needToken}
This page requires admin token to save data. Token: Date: Fri, 17 Nov 2023 18:36:07 +0000 Subject: [PATCH 4/9] format: apply format tool --- src/lib/db.js | 131 ++++++++++++++++++++------------------- src/routes/+page.js | 2 +- src/routes/+page.svelte | 2 +- src/routes/App.svelte | 25 +++----- static/data_default.json | 84 ++++++++++++------------- 5 files changed, 120 insertions(+), 124 deletions(-) diff --git a/src/lib/db.js b/src/lib/db.js index c15972f..91e926b 100644 --- a/src/lib/db.js +++ b/src/lib/db.js @@ -1,65 +1,66 @@ -const myheaders = { - Origin: window.location.origin, - 'Content-Type': 'text/plain' -}; - -async function getDefaultData(){ - const response = await fetch(`/data_default.json`); - if (!response.ok){ - throw new Error(response); - }else{ - return await response.json(); - } -} - -function dataKeysUpdate(template, toAlign){ - for (const k of Object.keys(template)) { - if (!toAlign.hasOwnProperty(k)) { - console.log(`data field updated implicitly, updated key:${k}`); - toAlign[k] = template[k]; - } - } - return toAlign; -} - -class DB { - constructor(cf_workers, username){ - this.cf_workers = cf_workers; - this.username = username; - this.needToken = null; - } - - async getData() { - const defaultData = getDefaultData(); - const response = await fetch(`https://${this.cf_workers}/get/${this.username}`, { headers: myheaders }); - if (!response.ok) { - // use default data - return getDefaultData(); - } - if (response.headers.get('x-need-token')) { - this.needToken = true; - console.log('A token is required to edit this page'); - } else { - this.needToken = false; - } - const result = await response.json(); - const cloudData = dataKeysUpdate(defaultData, result); - return cloudData; - } - - async uploadData(myDataStr) { - const response = await fetch(`https://${this.cf_workers}/set/${this.username}`, { - headers: myheaders, - method: 'POST', - body: myDataStr - }) - if (!response.ok) { - response.text().then((msg) => alert(`unsuccessful data uploading \nReason: ${msg}`)); - return {uploadingState: 'bad'} - } - return {uploadingState: 'ok'}; - } -} - - -export {DB}; \ No newline at end of file +const myheaders = { + Origin: window.location.origin, + 'Content-Type': 'text/plain' +}; + +async function getDefaultData() { + const response = await fetch(`/data_default.json`); + if (!response.ok) { + throw new Error(response); + } else { + return await response.json(); + } +} + +function dataKeysUpdate(template, toAlign) { + for (const k of Object.keys(template)) { + if (!toAlign.hasOwnProperty(k)) { + console.log(`data field updated implicitly, updated key:${k}`); + toAlign[k] = template[k]; + } + } + return toAlign; +} + +class DB { + constructor(cf_workers, username) { + this.cf_workers = cf_workers; + this.username = username; + this.needToken = null; + } + + async getData() { + const defaultData = getDefaultData(); + const response = await fetch(`https://${this.cf_workers}/get/${this.username}`, { + headers: myheaders + }); + if (!response.ok) { + // use default data + return getDefaultData(); + } + if (response.headers.get('x-need-token')) { + this.needToken = true; + console.log('A token is required to edit this page'); + } else { + this.needToken = false; + } + const result = await response.json(); + const cloudData = dataKeysUpdate(defaultData, result); + return cloudData; + } + + async uploadData(myDataStr) { + const response = await fetch(`https://${this.cf_workers}/set/${this.username}`, { + headers: myheaders, + method: 'POST', + body: myDataStr + }); + if (!response.ok) { + response.text().then((msg) => alert(`unsuccessful data uploading \nReason: ${msg}`)); + return { uploadingState: 'bad' }; + } + return { uploadingState: 'ok' }; + } +} + +export { DB }; diff --git a/src/routes/+page.js b/src/routes/+page.js index 1321b91..0b8cda5 100644 --- a/src/routes/+page.js +++ b/src/routes/+page.js @@ -4,4 +4,4 @@ export async function load({ fetch }) { const res = await fetch(`/data_default.json`); const data = await res.json(); return data; -} \ No newline at end of file +} diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 22f663e..9ebf700 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -8,4 +8,4 @@ - + diff --git a/src/routes/App.svelte b/src/routes/App.svelte index 4b4d591..b38f28d 100644 --- a/src/routes/App.svelte +++ b/src/routes/App.svelte @@ -9,19 +9,16 @@ // let needToken; const isInstanceDemo = true; - // import utils - import {DB} from '$lib/db.js'; + import { DB } from '$lib/db.js'; // import markdown import * as markdown from '@logue/markdown-wasm'; import { onMount } from 'svelte'; onMount(async () => { - // await initData(); await markdown.ready(); await initData(); - }); // init username @@ -33,14 +30,14 @@ let db = new DB(cf_workers, username); // Init data - async function initData(){ + async function initData() { data = await db.getData(username); //.then((result) => data = result); data.token = ''; // fron-end-only key data = data; - dataSnapshot = JSON.stringify(data); + dataSnapshot = JSON.stringify(data); updatePageReadMe(); } - + const updatePageReadMe = async () => { data = data; pageReadme = markdown.parse(data.readme.content, { @@ -133,23 +130,21 @@ data = await db.getData(username); updatePageReadMe(); }; - function tryUploadData(){ + function tryUploadData() { const currentDataStr = JSON.stringify(data); if (!data_validate(currentDataStr, dataSizeLimit)) { const uploadingState = 'bad'; changeIcon(uploadingState); return false; } - db.uploadData(currentDataStr).then(({uploadingState})=>{ - changeIcon(uploadingState) - if (uploadingState=='ok'){ - dataSnapshot = JSON.stringify(data); + db.uploadData(currentDataStr).then(({ uploadingState }) => { + changeIcon(uploadingState); + if (uploadingState == 'ok') { + dataSnapshot = JSON.stringify(data); } - }) + }); } - - function chooseIcon(uploadingState) { switch (uploadingState) { case 'ok': diff --git a/static/data_default.json b/static/data_default.json index a7a52cd..be9d6cf 100644 --- a/static/data_default.json +++ b/static/data_default.json @@ -1,42 +1,42 @@ -{ - "title":{ - "color":"indigo", - "name":"URL Link Catalog" - }, - "readme":{ - "content":"## README - This is a default page\nURLinkCat (URL Link Catalog) is a **free, open-source, fully customizable, multi-user, cloud-synced** bookmark web app. \n\n I am a default README.md for any URLinkCat pages, so feel free to modify my content. For detailed instructions on how to create your own bookmark collection page, please visit https://github.com/cxumol/URLinkCat. \n\nIf you find it interesting as a developer, please consider giving this project a star on GitHub." - }, - "categories":[ - { - "name":"How to Use", - "color":"brown", - "sites":[ - { - "name":"User Guide", - "icon":"info", - "url":"https://github.com/cxumol/URLinkCat/blob/master/README.md" - }, - { - "icon":"theater_comedy", - "url":"https://urlinkcat.pages.dev/#demo", - "name":"Examples" - }, - { - "name":"Icons Available to Use", - "icon":"search", - "url":"https://fonts.google.com/icons?selected=Material+Icons&icon.query=" - }, - { - "icon":"palette", - "url":"https://github.com/alexanderGugel/papier/blob/master/src/config.styl", - "name":"Colors Available to Use" - }, - { - "icon":"cloud_sync", - "url":"javascript:alert('click bottom-right cloud button to save your changes at this #pageid')", - "name":"Don't Forget to Save to Cloud" - } - ] - } - ] -} \ No newline at end of file +{ + "title": { + "color": "indigo", + "name": "URL Link Catalog" + }, + "readme": { + "content": "## README - This is a default page\nURLinkCat (URL Link Catalog) is a **free, open-source, fully customizable, multi-user, cloud-synced** bookmark web app. \n\n I am a default README.md for any URLinkCat pages, so feel free to modify my content. For detailed instructions on how to create your own bookmark collection page, please visit https://github.com/cxumol/URLinkCat. \n\nIf you find it interesting as a developer, please consider giving this project a star on GitHub." + }, + "categories": [ + { + "name": "How to Use", + "color": "brown", + "sites": [ + { + "name": "User Guide", + "icon": "info", + "url": "https://github.com/cxumol/URLinkCat/blob/master/README.md" + }, + { + "icon": "theater_comedy", + "url": "https://urlinkcat.pages.dev/#demo", + "name": "Examples" + }, + { + "name": "Icons Available to Use", + "icon": "search", + "url": "https://fonts.google.com/icons?selected=Material+Icons&icon.query=" + }, + { + "icon": "palette", + "url": "https://github.com/alexanderGugel/papier/blob/master/src/config.styl", + "name": "Colors Available to Use" + }, + { + "icon": "cloud_sync", + "url": "javascript:alert('click bottom-right cloud button to save your changes at this #pageid')", + "name": "Don't Forget to Save to Cloud" + } + ] + } + ] +} From bf1756ff2f9f34c0ca84ca99c965d5f30fc49d52 Mon Sep 17 00:00:00 2001 From: cxumol Date: Fri, 17 Nov 2023 18:39:28 +0000 Subject: [PATCH 5/9] refactor: remove uploadingState from window --- src/routes/App.svelte | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/routes/App.svelte b/src/routes/App.svelte index b38f28d..616d803 100644 --- a/src/routes/App.svelte +++ b/src/routes/App.svelte @@ -2,11 +2,9 @@ export let data; let dataSnapshot; let pageReadme; - let uploadingState; // TODO let uploadingIconConfig = { color: 'green', icon: 'backup' }; const dataSizeLimit = Number(12345); const cf_workers = 'urlinkcat.t6.workers.dev'; - // let needToken; const isInstanceDemo = true; // import utils @@ -161,8 +159,8 @@ function changeIcon(uploadingState) { uploadingIconConfig = chooseIcon(uploadingState); setTimeout(() => { - uploadingState = ''; - changeIcon(''); + const uploadingState = ''; + changeIcon(uploadingState); }, 5000); } From 9a45365958db4191981602f0af5eb4dfb406b30b Mon Sep 17 00:00:00 2001 From: cxumol Date: Fri, 17 Nov 2023 19:11:04 +0000 Subject: [PATCH 6/9] refactor: re-order funcs and decouple utils --- src/lib/utils.js | 8 +++++++ src/routes/App.svelte | 49 +++++++++++++++++++++---------------------- 2 files changed, 32 insertions(+), 25 deletions(-) create mode 100644 src/lib/utils.js diff --git a/src/lib/utils.js b/src/lib/utils.js new file mode 100644 index 0000000..a912b98 --- /dev/null +++ b/src/lib/utils.js @@ -0,0 +1,8 @@ +function newRandomID() { + let result = Math.random().toString(36).slice(-8); + while (result.length < 8) { + result = Math.random().toString(36).slice(-8); + } + return result; + }; +export { newRandomID }; \ No newline at end of file diff --git a/src/routes/App.svelte b/src/routes/App.svelte index 616d803..bf42908 100644 --- a/src/routes/App.svelte +++ b/src/routes/App.svelte @@ -9,15 +9,10 @@ // import utils import { DB } from '$lib/db.js'; + import { newRandomID } from '$lib/utils.js'; - // import markdown + // import external dependency import * as markdown from '@logue/markdown-wasm'; - import { onMount } from 'svelte'; - onMount(async () => { - // await initData(); - await markdown.ready(); - await initData(); - }); // init username let username = window.location.hash.split('#')[1]; @@ -31,21 +26,31 @@ async function initData() { data = await db.getData(username); //.then((result) => data = result); data.token = ''; // fron-end-only key - data = data; + data = data; // TODO: refactor in Svelte 5 dataSnapshot = JSON.stringify(data); updatePageReadMe(); } - const updatePageReadMe = async () => { + async function updatePageReadMe() { data = data; pageReadme = markdown.parse(data.readme.content, { parseFlags: markdown.ParseFlags.DEFAULT | markdown.ParseFlags.NO_HTML // NO_HTML for safety reason (xss) }); }; + // async init + import { onMount } from 'svelte'; + onMount(async () => { + // await initData(); + await markdown.ready(); + await initData(); + }); + + // init components import Lock from './Lock.svelte'; let unlocked = false; + // page data updators function delItem(sites, site_i) { sites[site_i].undo = true; data = data; @@ -96,7 +101,14 @@ data = data; } - // data processing + // page data handlers + + window.onhashchange = async function () { + username = window.location.hash.split('#')[1]; + db = new DB(cf_workers, username); + data = await db.getData(username); + updatePageReadMe(); + }; function data_validate(currentDataStr, dataSizeLimit) { if (currentDataStr.length > dataSizeLimit) { @@ -114,20 +126,6 @@ return true; } - const newRandomID = function () { - let result = Math.random().toString(36).slice(-8); - while (result.length < 8) { - result = Math.random().toString(36).slice(-8); - } - return result; - }; - - window.onhashchange = async function () { - username = window.location.hash.split('#')[1]; - db = new DB(cf_workers, username); - data = await db.getData(username); - updatePageReadMe(); - }; function tryUploadData() { const currentDataStr = JSON.stringify(data); if (!data_validate(currentDataStr, dataSizeLimit)) { @@ -143,6 +141,7 @@ }); } + // Icon as upload indicator function chooseIcon(uploadingState) { switch (uploadingState) { case 'ok': @@ -159,7 +158,7 @@ function changeIcon(uploadingState) { uploadingIconConfig = chooseIcon(uploadingState); setTimeout(() => { - const uploadingState = ''; + uploadingState = ''; //closure changeIcon(uploadingState); }, 5000); } From c7cee75855873c110917fff872d64644846e1a85 Mon Sep 17 00:00:00 2001 From: cxumol Date: Fri, 17 Nov 2023 19:19:23 +0000 Subject: [PATCH 7/9] wording: minor --- src/routes/App.svelte | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/routes/App.svelte b/src/routes/App.svelte index bf42908..f3f1d9b 100644 --- a/src/routes/App.svelte +++ b/src/routes/App.svelte @@ -102,7 +102,6 @@ } // page data handlers - window.onhashchange = async function () { username = window.location.hash.split('#')[1]; db = new DB(cf_workers, username); @@ -323,7 +322,7 @@ {#if db.needToken}
- This page requires admin token to save data. Token: Date: Fri, 17 Nov 2023 19:21:02 +0000 Subject: [PATCH 8/9] wording: minor --- src/routes/+page.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 9ebf700..3d2fc40 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -5,7 +5,7 @@ URLinkCat - + From a13bc726d641007584211f5fe8396d03d40538a1 Mon Sep 17 00:00:00 2001 From: cxumol Date: Fri, 17 Nov 2023 19:24:07 +0000 Subject: [PATCH 9/9] format: apply code styler --- src/lib/utils.js | 16 ++++++++-------- src/routes/+page.svelte | 5 ++++- src/routes/App.svelte | 12 ++++++------ 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/src/lib/utils.js b/src/lib/utils.js index a912b98..a824a67 100644 --- a/src/lib/utils.js +++ b/src/lib/utils.js @@ -1,8 +1,8 @@ -function newRandomID() { - let result = Math.random().toString(36).slice(-8); - while (result.length < 8) { - result = Math.random().toString(36).slice(-8); - } - return result; - }; -export { newRandomID }; \ No newline at end of file +function newRandomID() { + let result = Math.random().toString(36).slice(-8); + while (result.length < 8) { + result = Math.random().toString(36).slice(-8); + } + return result; +} +export { newRandomID }; diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 3d2fc40..21be755 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -5,7 +5,10 @@ URLinkCat - + diff --git a/src/routes/App.svelte b/src/routes/App.svelte index f3f1d9b..38aa255 100644 --- a/src/routes/App.svelte +++ b/src/routes/App.svelte @@ -36,7 +36,7 @@ pageReadme = markdown.parse(data.readme.content, { parseFlags: markdown.ParseFlags.DEFAULT | markdown.ParseFlags.NO_HTML // NO_HTML for safety reason (xss) }); - }; + } // async init import { onMount } from 'svelte'; @@ -103,11 +103,11 @@ // page data handlers window.onhashchange = async function () { - username = window.location.hash.split('#')[1]; - db = new DB(cf_workers, username); - data = await db.getData(username); - updatePageReadMe(); - }; + username = window.location.hash.split('#')[1]; + db = new DB(cf_workers, username); + data = await db.getData(username); + updatePageReadMe(); + }; function data_validate(currentDataStr, dataSizeLimit) { if (currentDataStr.length > dataSizeLimit) {