From: Nick Downing Date: Tue, 25 Jan 2022 00:47:10 +0000 (+1100) Subject: Implement draft updating thread in /my_account/sign_up/index.html.jst (avoids possibi... X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?p=ndcode_site.git;a=commitdiff_plain;h=4f94bcd56fb593600c3ac7d4e041cb9e848e9290 Implement draft updating thread in /my_account/sign_up/index.html.jst (avoids possibility of concurrent draft updates), use oninput rather than onchange event --- diff --git a/_lib/navbar.jst b/_lib/navbar.jst index 7ec7234..c3e7c18 100644 --- a/_lib/navbar.jst +++ b/_lib/navbar.jst @@ -310,7 +310,7 @@ return async (env, head, body, scripts) => { }, // scripts async _out => { - script(src="/js/api_call.js") {} + script(src="/js/utils.js") {} script { // this function can be overridden in a further script diff --git a/contact/index.html.jst b/contact/index.html.jst index a6b78a8..fd46d2f 100644 --- a/contact/index.html.jst +++ b/contact/index.html.jst @@ -142,7 +142,7 @@ return async env => { }, // scripts async _out => { - //script(src="/js/api_call.js") {} + //script(src="/js/utils.js") {} script { let draft_timeout_running = false diff --git a/js/api_call.js.min b/js/api_call.js.min deleted file mode 100644 index bde4a54..0000000 --- a/js/api_call.js.min +++ /dev/null @@ -1,26 +0,0 @@ -Problem = class { - constructor(title, detail, status) { - this.title = title - this.detail = detail - this.status = status - } - - static from(error) { - return ( - error instanceof Problem ? - error : - new Problem('Bad request', (error.stack || error.message), 400) - ) - } -} - -api_call = async (endpoint, ...args) => { - let response = await fetch( - endpoint, - {method: 'POST', body: JSON.stringify(args)} - ) - let result = await response.json() - if (!response.ok) - throw new Problem(result.title, result.detail, result.status) - return result -} diff --git a/js/utils.js.min b/js/utils.js.min new file mode 100644 index 0000000..b7dd5d2 --- /dev/null +++ b/js/utils.js.min @@ -0,0 +1,93 @@ +Mutex = class { + constructor() { + this.done = null + } + + async acquire() { + while (this.done !== null) + await this.done.promise + let done = {} + done.promise = new Promise( + (resolve, reject) => {done.resolve = resolve} + ) + this.done = done + } + + release() { + let done = this.done + assert(done !== null) + this.done = null + done.resolve() + } +} + +BinarySemaphore = class { + constructor(value) { + if (value) + this.done = null + else { + let done = {} + done.promise = new Promise( + (resolve, reject) => {done.resolve = resolve} + ) + this.done = done + } + } + + async acquire() { + while (this.done !== null) + await this.done.promise + let done = {} + done.promise = new Promise( + (resolve, reject) => {done.resolve = resolve} + ) + this.done = done + } + + try_acquire() { + if (this.done !== null) + return false + let done = {} + done.promise = new Promise( + (resolve, reject) => {done.resolve = resolve} + ) + this.done = done + return true + } + + release() { + let done = this.done + if (done === null) + return false + this.done = null + done.resolve() + return true + } +} + +Problem = class { + constructor(title, detail, status) { + this.title = title + this.detail = detail + this.status = status + } + + static from(error) { + return ( + error instanceof Problem ? + error : + new Problem('Bad request', (error.stack || error.message), 400) + ) + } +} + +api_call = async (endpoint, ...args) => { + let response = await fetch( + endpoint, + {method: 'POST', body: JSON.stringify(args)} + ) + let result = await response.json() + if (!response.ok) + throw new Problem(result.title, result.detail, result.status) + return result +} diff --git a/my_account/index.html.jst b/my_account/index.html.jst index 765aaa6..724ed5c 100644 --- a/my_account/index.html.jst +++ b/my_account/index.html.jst @@ -207,7 +207,7 @@ return async env => { } if (signed_in_as !== undefined) { - //script(src="/js/api_call.js") {} + //script(src="/js/utils.js") {} script { let step_1_dirty = ${JSON.stringify(draft_details !== null)} diff --git a/my_account/password_reset/index.html.jst b/my_account/password_reset/index.html.jst index b788899..f0ee4cf 100644 --- a/my_account/password_reset/index.html.jst +++ b/my_account/password_reset/index.html.jst @@ -96,7 +96,7 @@ return async env => { }, // scripts async _out => { - //script(src="/js/api_call.js") {} + //script(src="/js/utils.js") {} script { let step_1 = async () => { diff --git a/my_account/send_verification_email/index.html.jst b/my_account/send_verification_email/index.html.jst index 03ffbd6..c9fe99b 100644 --- a/my_account/send_verification_email/index.html.jst +++ b/my_account/send_verification_email/index.html.jst @@ -88,7 +88,7 @@ return async env => { }, // scripts async _out => { - //script(src="/js/api_call.js") {} + //script(src="/js/utils.js") {} script { let step_1 = async () => { diff --git a/my_account/sign_up/index.html.jst b/my_account/sign_up/index.html.jst index 339458e..060cee5 100644 --- a/my_account/sign_up/index.html.jst +++ b/my_account/sign_up/index.html.jst @@ -154,29 +154,28 @@ return async env => { }, // scripts async _out => { - //script(src="/js/api_call.js") {} + //script(src="/js/utils.js") {} script { - let draft_timeout_running = false - let draft_timeout_handler = async () => { - draft_timeout_running = false - await api_call( - '/api/account/sign_up/set_draft.json', - { - email: document.getElementById('email').value.slice(0, 256).toLowerCase(), - given_names: document.getElementById('given-names').value.slice(0, 256), - family_name: document.getElementById('family-name').value.slice(0, 256), - contact_me: document.getElementById('contact-me').checked ? true : false + let input_semaphore = new BinarySemaphore(false) + ;( + async () => { + while (true) { + await input_semaphore.acquire() + await new Promise(resolve => setTimeout(resolve, 3000)) + input_semaphore.try_acquire() + await api_call( + '/api/account/sign_up/set_draft.json', + { + email: document.getElementById('email').value.slice(0, 256).toLowerCase(), + given_names: document.getElementById('given-names').value.slice(0, 256), + family_name: document.getElementById('family-name').value.slice(0, 256), + contact_me: document.getElementById('contact-me').checked ? true : false + } + ) } - ) - //console.log('draft', await api_call('/api/account/sign_up/get_draft.json')) - } - let draft_change_handler = () => { - if (!draft_timeout_running) { - draft_timeout_running = true - setTimeout(draft_timeout_handler, 5000) } - } + )() // ignore returned promise (start thread) let details let card_1 = async () => { @@ -271,25 +270,29 @@ return async env => { 'DOMContentLoaded', () => { document.getElementById('given-names').addEventListener( - 'change', - draft_change_handler + 'input', + () => {input_semaphore.release()} ) document.getElementById('family-name').addEventListener( - 'change', - draft_change_handler + 'input', + () => {input_semaphore.release()} ) document.getElementById('email').addEventListener( - 'change', - draft_change_handler - ) - document.getElementById('password').addEventListener( - 'change', - draft_change_handler + 'input', + () => {input_semaphore.release()} ) + //document.getElementById('password').addEventListener( + // 'input', + // () => {input_semaphore.release()} + //) document.getElementById('contact-me').addEventListener( - 'change', - draft_change_handler + 'input', + () => {input_semaphore.release()} ) + //document.getElementById('verification-code').addEventListener( + // 'input', + // () => {input_semaphore.release()} + //) let image_seq = 1 document.getElementById('card-1-new-code').addEventListener( diff --git a/my_account/verify_email/index.html.jst b/my_account/verify_email/index.html.jst index 417dc33..e9b335a 100644 --- a/my_account/verify_email/index.html.jst +++ b/my_account/verify_email/index.html.jst @@ -102,7 +102,7 @@ return async env => { }, // scripts async _out => { - //script(src="/js/api_call.js") {} + //script(src="/js/utils.js") {} script { let step_1 = async () => { diff --git a/my_account/verify_password/index.html.jst b/my_account/verify_password/index.html.jst index 52944be..a7c9925 100644 --- a/my_account/verify_password/index.html.jst +++ b/my_account/verify_password/index.html.jst @@ -102,7 +102,7 @@ return async env => { }, // scripts async _out => { - //script(src="/js/api_call.js") {} + //script(src="/js/utils.js") {} script { let step_1 = async () => {