From cec3e3f88978097c32027f6df8a9f8c6a5453499 Mon Sep 17 00:00:00 2001 From: Andrei Kurilov <18027129+akurilov@users.noreply.github.com> Date: Sun, 24 Mar 2024 00:28:58 +0200 Subject: [PATCH] save [skip ci] --- web/api/events.js | 81 ++++++++++++++++++++++++++ web/api/evts.js | 44 -------------- web/api/sources.js | 45 +++++++++++++++ web/api/subscriptions.js | 94 +++++++++++++++++++++++++++++- web/index.html | 3 +- web/intcomm.js | 64 +++++--------------- web/pub-msg-new.html | 1 + web/pub-msg-new.js | 54 ++++------------- web/pub-src-details.html | 2 + web/pub-src-details.js | 50 +++------------- web/pub-src-new.html | 1 + web/pub-src-new.js | 23 ++------ web/pub.html | 2 + web/pub.js | 27 ++------- web/query.js | 122 ++++++++++++--------------------------- web/sub-details.html | 1 + web/sub-details.js | 103 ++++++--------------------------- web/sub-new.html | 1 + web/sub-new.js | 63 +++++--------------- web/sub.html | 1 + web/sub.js | 2 +- 21 files changed, 341 insertions(+), 443 deletions(-) create mode 100644 web/api/events.js delete mode 100644 web/api/evts.js diff --git a/web/api/events.js b/web/api/events.js new file mode 100644 index 0000000..93a981b --- /dev/null +++ b/web/api/events.js @@ -0,0 +1,81 @@ +const Events = { + abortController: new AbortController(), +} + +Events.longPoll = function (subId, deadline) { + const headers = getAuthHeaders(); + let optsReq = { + method: "GET", + headers: headers, + }; + const timeout = deadline - Date.now(); + return fetch(`/v1/events/${subId}`, optsReq) + .then(resp => { + clearTimeout(setTimeout(() => { + Events.abortController.abort(); + }, timeout)); + if (!resp.ok) { + throw new Error(`Request failed with status: ${resp.status}`); + } + return resp.json(); + }) + .catch(e => { + console.log(e); + return null; + }) + .then(data => { + if (data != null && data.hasOwnProperty("msgs") && data.msgs.length > 0) { + console.log(`Read subscription ${subId}: got ${data.msgs.length} new events`); + return data.msgs; + } else { + console.log(`Read subscription ${subId}: no new events`); + return null; + } + }); +}; + +// uuidv4 +Events.newId = function () { + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { + var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); + return v.toString(16); + }); +} + +Events.publishInternal = function (payload, headers) { + return fetch("/v1/pub/internal", { + method: "POST", + headers: headers, + body: JSON.stringify(payload), + }) + .then(resp => { + if (!resp.ok) { + resp.text().then(errMsg => console.error(errMsg)); + throw new Error(`Request failed ${resp.status}`); + } + return resp.json(); + }) + .then(_ => { + return true; + }) + .catch(err => { + alert(err); + return false; + }); +} + +Events.publish = function (payload, headers) { + return fetch("/v1/pub", { + method: "POST", + headers: headers, + body: JSON.stringify(payload), + }) + .then(resp => { + if (!resp.ok) { + resp.text().then(errMsg => console.error(errMsg)); + throw new Error(`Request failed ${resp.status}`); + } + return resp.json(); + }) + +} \ No newline at end of file diff --git a/web/api/evts.js b/web/api/evts.js deleted file mode 100644 index 6a13d0c..0000000 --- a/web/api/evts.js +++ /dev/null @@ -1,44 +0,0 @@ -const Events = { - abortController: new AbortController(), -} - -Events.longPoll = function (subId, deadline) { - Events.audioCtx = new (window.AudioContext || window.webkitAudioContext)(); - Events.audioSnd = new Audio("inbox-notification.wav"); - Events.audioSrc = Events.audioCtx.createMediaElementSource(Events.audioSnd); - Events.audioSrc.connect(Events.audioCtx.destination); - const headers = getAuthHeaders(); - let optsReq = { - method: "GET", - headers: headers, - }; - const timeout = deadline - Date.now(); - return fetch(`/v1/events/${subId}`, optsReq) - .then(resp => { - clearTimeout(setTimeout(() => { - Events.abortController.abort(); - }, timeout)); - if (!resp.ok) { - throw new Error(`Request failed with status: ${resp.status}`); - } - return resp.json(); - }) - .catch(e => { - console.log(e); - return null; - }) - .then(data => { - if (data != null && data.hasOwnProperty("msgs") && data.msgs.length > 0) { - try { - Events.audioSnd.play(); - } catch (e) { - console.log(e); - } - console.log(`Read subscription ${subId}: got ${data.msgs.length} new events`); - return data.msgs; - } else { - console.log(`Read subscription ${subId}: no new events`); - return null; - } - }); -}; diff --git a/web/api/sources.js b/web/api/sources.js index f18f61a..9b0b905 100644 --- a/web/api/sources.js +++ b/web/api/sources.js @@ -7,3 +7,48 @@ Sources.fetchListPage = function (type, own, order, limit, filter, headers) { cache: "force-cache", }); } + +Sources.fetch = function (typ, addrEnc, headers) { + headers["X-Awakari-Src-Addr"] = addrEnc; + return fetch(`/v1/src/${typ}`, { + method: "GET", + headers: headers, + cache: "default", + }) + .then(resp => { + if (!resp.ok) { + throw new Error(`Request failed with status: ${resp.status}`); + } + return resp.json(); + }); +} + +Sources.delete = function (typ, addrEnc, headers) { + headers["X-Awakari-Src-Addr"] = addrEnc; + return fetch(`/v1/src/${typ}`, { + method: "DELETE", + headers: headers, + }) + .then(resp => { + if (!resp.ok) { + throw new Error(`Request failed with status: ${resp.status}`); + } + return resp; + }) +} + +Sources.add = function (srcType, srcAddr, updFreq, headers) { + const payload = { + "limit": { + "freq": updFreq, + }, + "src": { + "addr": srcAddr, + } + } + return fetch(`/v1/src/${srcType}`, { + method: "POST", + headers: headers, + body: JSON.stringify(payload), + }); +} \ No newline at end of file diff --git a/web/api/subscriptions.js b/web/api/subscriptions.js index 24d8a51..d24fefd 100644 --- a/web/api/subscriptions.js +++ b/web/api/subscriptions.js @@ -1,7 +1,7 @@ const Subscriptions = {}; -Subscriptions.fetchListPage = function (cursor, order, filter, headers) { - return fetch(`/v1/sub?limit=${pageLimit}&cursor=${cursor}&order=${order}&filter=${encodeURIComponent(filter)}`, { +Subscriptions.fetchListPage = function (cursor, order, limit, filter, headers) { + return fetch(`/v1/sub?limit=${limit}&cursor=${cursor}&order=${order}&filter=${encodeURIComponent(filter)}`, { method: "GET", headers: headers, cache: "no-cache", @@ -13,3 +13,93 @@ Subscriptions.fetchListPage = function (cursor, order, filter, headers) { return resp.json(); }) } + +Subscriptions.delete = function (id, headers) { + let optsReq = { + method: "DELETE", + headers: headers, + }; + return fetch(`/v1/sub/${id}`, optsReq) + .then(resp => { + if (!resp.ok) { + resp.text().then(errMsg => console.error(errMsg)); + throw new Error(`Failed to delete the subscription ${id}: ${resp.status}`); + } + }); +} + +Subscriptions.create = function (descr, enabled, expires, cond, headers) { + const payload = { + description: descr, + enabled: enabled, + cond: cond, + } + if (expires) { + payload.expires = expires.toISOString(); + } + const optsReq = { + method: "POST", + headers: headers, + body: JSON.stringify(payload) + }; + return fetch(`/v1/sub`, optsReq) + .then(resp => { + if (!resp.ok) { + resp.text().then(errMsg => console.error(errMsg)); + if (resp.status === 429) { + throw new Error("Subscription count limit reached. Please contact awakari@awakari.com and request to increase the limit."); + } else { + throw new Error(`Failed to create a new subscription: ${resp.status}`); + } + } + return resp.json(); + }) + .then(data => { + if (data) { + return data.id; + } else { + throw new Error(`Empty create subscription response`); + } + }) + +} + +Subscriptions.fetch = function (id, headers) { + const optsReq = { + method: "GET", + headers: headers, + cache: "default", + } + return fetch(`/v1/sub/${id}`, optsReq) + .then(resp => { + if (!resp.ok) { + throw new Error(`Failed to fetch the subscription ${id}, status: ${resp.status}`); + } + return resp.json(); + }) +} + +Subscriptions.update = function (id, descr, enabled, expires, cond, headers) { + const payload = { + id: id, + description: descr, + enabled: enabled, + cond: cond, + } + if (expires) { + payload.expires = expires.toISOString(); + } + const optsReq = { + method: "PUT", + headers: headers, + body: JSON.stringify(payload) + } + return fetch(`/v1/sub/${id}`, optsReq) + .then(resp => { + if (!resp.ok) { + resp.text().then(errMsg => console.error(errMsg)) + throw new Error(`Failed to update the subscription ${id}, status: ${resp.status}`); + } + return resp.json(); + }); +} \ No newline at end of file diff --git a/web/index.html b/web/index.html index 9d6e941..8ceb689 100644 --- a/web/index.html +++ b/web/index.html @@ -143,9 +143,10 @@ - + + diff --git a/web/intcomm.js b/web/intcomm.js index 16d4a3b..7598d8d 100644 --- a/web/intcomm.js +++ b/web/intcomm.js @@ -17,7 +17,7 @@ async function requestIncreasePublishingDailyLimit(objId) { } if (inc > 0) { const payload = { - id: uuidv4(), + id: Events.newId(), specVersion: "1.0", source: "awakari.com", type: "com.awakari.webapp", @@ -40,7 +40,8 @@ async function requestIncreasePublishingDailyLimit(objId) { }, text_data: `User ${userIdCurrent} requests to increase the publishing daily limit for ${objId} by ${inc}`, } - if (await submitMessageInternal(payload, userIdCurrent)) { + const headers = getAuthHeaders(); + if (await Events.publishInternal(payload, headers)) { document.getElementById("request-increase-success-dialog").style.display = "block"; document.getElementById("request-id").innerText = payload.id; } @@ -56,7 +57,7 @@ async function requestPublishingSourceDedicated(addr){ const reason = prompt(msg); if (reason) { const payload = { - id: uuidv4(), + id: Events.newId(), specVersion: "1.0", source: "awakari.com", type: "com.awakari.webapp", @@ -79,7 +80,8 @@ async function requestPublishingSourceDedicated(addr){ }, text_data: `User ${userIdCurrent} requests to make the source ${addr} dedicated`, } - if (await submitMessageInternal(payload, userIdCurrent)) { + const headers = getAuthHeaders(); + if (await Events.publishInternal(payload, headers)) { document.getElementById("request-increase-success-dialog").style.display = "block"; document.getElementById("request-id").innerText = payload.id; document.getElementById("pub-src-nominate").disabled = true; @@ -99,7 +101,7 @@ async function requestIncreaseSubscriptionsLimit(userId) { } if (inc > 0) { const payload = { - id: uuidv4(), + id: Events.newId(), specVersion: "1.0", source: "awakari.com", type: "com.awakari.webapp", @@ -122,7 +124,8 @@ async function requestIncreaseSubscriptionsLimit(userId) { }, text_data: `User ${userId} requests to increase the subscriptions limit by ${inc}`, } - if (await submitMessageInternal(payload, userId)) { + const headers = getAuthHeaders(); + if (await Events.publishInternal(payload, headers)) { document.getElementById("request-increase-success-dialog").style.display = "block"; document.getElementById("request-id").innerText = payload.id; } @@ -137,7 +140,7 @@ async function reportPublishingSourceInappropriate(srcAddr) { const reason = prompt(`Please specify the reason why do you think the source is inappropriate.\nSource: ${srcAddr}`) if (reason) { const payload = { - id: uuidv4(), + id: Events.newId(), specVersion: "1.0", source: "awakari.com", type: "com.awakari.webapp", @@ -157,7 +160,8 @@ async function reportPublishingSourceInappropriate(srcAddr) { }, text_data: `User ${userIdCurrent} reports the inappropriate publishing source ${srcAddr}, reason: ${reason}`, } - if (await submitMessageInternal(payload, userIdCurrent)) { + const headers = getAuthHeaders(); + if (await Events.publishInternal(payload, headers)) { document.getElementById("report-success-dialog").style.display = "block"; document.getElementById("report-id").innerText = payload.id; } @@ -169,7 +173,7 @@ async function reportPublicationInappropriate(srcAddr, evtLink, evtId) { const reason = prompt(`Please specify the reason why do you think the message is inappropriate.\nMessage link: ${evtLink}`) if (reason) { const payload = { - id: uuidv4(), + id: Events.newId(), specVersion: "1.0", source: "awakari.com", type: "com.awakari.webapp", @@ -192,48 +196,10 @@ async function reportPublicationInappropriate(srcAddr, evtLink, evtId) { }, text_data: `User ${userIdCurrent} reports the inappropriate message from ${srcAddr}, reason: ${reason}`, } - if (await submitMessageInternal(payload, userIdCurrent)) { + const headers = getAuthHeaders(); + if (await Events.publishInternal(payload, headers)) { document.getElementById("report-success-dialog").style.display = "block"; document.getElementById("report-id").innerText = payload.id; } } } - -function submitMessageInternal(payload, userId) { - let headers = { - "X-Awakari-Group-Id": defaultGroupId, - } - const authToken = localStorage.getItem(keyAuthToken); - if (authToken) { - headers["Authorization"] = `Bearer ${authToken}`; - } - if (userId) { - headers["X-Awakari-User-Id"] = userId; - } - return fetch("/v1/pub/internal", { - method: "POST", - headers: headers, - body: JSON.stringify(payload), - }) - .then(resp => { - if (!resp.ok) { - resp.text().then(errMsg => console.error(errMsg)); - throw new Error(`Request failed ${resp.status}`); - } - return resp.json(); - }) - .then(_ => { - return true; - }) - .catch(err => { - alert(err); - return false; - }) -} - -function uuidv4() { - return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { - var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); - return v.toString(16); - }); -} diff --git a/web/pub-msg-new.html b/web/pub-msg-new.html index 249d557..784da1b 100644 --- a/web/pub-msg-new.html +++ b/web/pub-msg-new.html @@ -14,6 +14,7 @@ + diff --git a/web/pub-msg-new.js b/web/pub-msg-new.js index 8fa2824..9827fac 100644 --- a/web/pub-msg-new.js +++ b/web/pub-msg-new.js @@ -13,7 +13,7 @@ async function loadForm() { document.getElementById("msg_attrs").value = "{}"; document.getElementById("msg_attrs_form").innerHTML = ""; - document.getElementById("msg_id").value = uuidv4(); + document.getElementById("msg_id").value = Events.newId(); putMessageAttribute("time", "timestamp", new Date().toISOString(), true); const authProvider = localStorage.getItem(keyAuthProvider); @@ -71,36 +71,21 @@ async function msgAttrNameChanged(evt) { } // const attrVal = document.getElementById("msg_attr_value"); - return fetch(`/v1/status/attr/values/${k}`, { - method: "GET", - cache: "force-cache", - }) - .then(resp => { + return Status + .fetchAttributeValues(k) + .then(vals => { const valsHtml = document.getElementById("msg_attr_val_opts"); valsHtml.innerHTML = ""; attrVal.placeholder = ""; - if (resp.ok) { - resp.json().then(vals => { - if (vals && vals.length > 0) { - attrVal.placeholder = vals[0]; - for (const v of vals) { - valsHtml.innerHTML += ``; - } - } - }) - } else { - console.log(`Failed to load sample values for key ${k}, response status: ${resp.status}`); + if (vals && vals.length > 0) { + attrVal.placeholder = vals[0]; + for (const v of vals) { + valsHtml.innerHTML += ``; + } } }) } -function uuidv4() { - return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { - var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); - return v.toString(16); - }); -} - function isBase64Encoded(str) { const base64Regex = /^[A-Za-z0-9+/=]*$/; return base64Regex.test(str) && str.length % 4 === 0; @@ -222,8 +207,6 @@ function deleteMessageAttribute(name) { } function submitMsg() { - const authToken = localStorage.getItem(keyAuthToken); - const userId = localStorage.getItem(keyUserId); const payload = { id: document.getElementById("msg_id").value, specVersion: "1.0", @@ -233,22 +216,9 @@ function submitMsg() { text_data: document.getElementById("msg_txt_data").value, } document.getElementById("wait").style.display = "block"; - fetch("/v1/pub", { - method: "POST", - headers: { - "Authorization": `Bearer ${authToken}`, - "X-Awakari-Group-Id": defaultGroupId, - "X-Awakari-User-Id": userId, - }, - body: JSON.stringify(payload), - }) - .then(resp => { - if (!resp.ok) { - resp.text().then(errMsg => console.error(errMsg)); - throw new Error(`Request failed ${resp.status}`); - } - return resp.json(); - }) + const headers = getAuthHeaders(); + Events + .publish(payload, headers) .then(_ => { alert("Message has been sent"); loadForm(); // reset diff --git a/web/pub-src-details.html b/web/pub-src-details.html index e723ea6..77b76a0 100644 --- a/web/pub-src-details.html +++ b/web/pub-src-details.html @@ -12,7 +12,9 @@ + + diff --git a/web/pub-src-details.js b/web/pub-src-details.js index 1f42db1..6dcbc91 100644 --- a/web/pub-src-details.js +++ b/web/pub-src-details.js @@ -15,29 +15,9 @@ async function loadSource() { document.body.classList.add('waiting-cursor'); document.getElementById("wait").style.display = "block"; // - let headers = { - "X-Awakari-Group-Id": defaultGroupId, - "X-Awakari-Src-Addr": addrEnc, - } - const authToken = localStorage.getItem(keyAuthToken); - if (authToken) { - headers["Authorization"] = `Bearer ${authToken}`; - } - const userId = localStorage.getItem(keyUserId); - if (userId) { - headers["X-Awakari-User-Id"] = userId; - } - const counts = await fetch(`/v1/src/${typ}`, { - method: "GET", - headers: headers, - cache: "default", - }) - .then(resp => { - if (!resp.ok) { - throw new Error(`Request failed with status: ${resp.status}`); - } - return resp.json(); - }) + let headers = getAuthHeaders(); + const counts = await Sources + .fetch(typ, addrEnc, headers) .then(data => { if (data != null) { switch (typ) { @@ -98,7 +78,7 @@ async function loadSource() { document.getElementById("last_upd").innerText = data.lastUpdate; } const btnDel = document.getElementById("button_src_del"); - if (data.groupId === defaultGroupId && data.userId === userId) { + if (data.groupId === defaultGroupId && data.userId === headers["X-Awakari-User-Id"]) { btnDel.removeAttribute("disabled"); btnDel.onclick = () => deleteSource(typ, addrEnc); } else { @@ -194,26 +174,10 @@ async function drawFreqChart(addr, counts) { } function deleteSource(typ, addrEnc) { - - let authToken = localStorage.getItem(keyAuthToken); - let userId = localStorage.getItem(keyUserId); - if (confirm(`Confirm delete source ${decodeURIComponent(addrEnc)}?`)) { - fetch(`/v1/src/${typ}`, { - method: "DELETE", - headers: { - "Authorization": `Bearer ${authToken}`, - "X-Awakari-Group-Id": defaultGroupId, - "X-Awakari-User-Id": userId, - "X-Awakari-Src-Addr": addrEnc, - }, - }) - .then(resp => { - if (!resp.ok) { - throw new Error(`Request failed with status: ${resp.status}`); - } - return resp; - }) + let headers = getAuthHeaders(); + Sources + .delete(typ, addrEnc, headers) .then(_ => { alert(`Source ${decodeURIComponent(addrEnc)} deleted successfully`); window.location.assign("pub.html"); diff --git a/web/pub-src-new.html b/web/pub-src-new.html index 9957490..3c87330 100644 --- a/web/pub-src-new.html +++ b/web/pub-src-new.html @@ -12,6 +12,7 @@ + diff --git a/web/pub-src-new.js b/web/pub-src-new.js index f2a092e..1bcee84 100644 --- a/web/pub-src-new.js +++ b/web/pub-src-new.js @@ -52,8 +52,6 @@ function showSrcDetails() { } function addSource() { - const authToken = localStorage.getItem(keyAuthToken); - const userId = localStorage.getItem(keyUserId); const srcType = document.getElementById("src_type").value; let srcAddr; switch (srcType) { @@ -94,24 +92,11 @@ function addSource() { } break } - const payload = { - "limit": { - "freq": parseInt(document.getElementById("feed_upd_freq").value), - }, - "src": { - "addr": srcAddr, - } - } + const headers = getAuthHeaders(); + const feedUpdFreq = parseInt(document.getElementById("feed_upd_freq").value); document.getElementById("wait").style.display = "block"; - fetch(`/v1/src/${srcType}`, { - method: "POST", - headers: { - "Authorization": `Bearer ${authToken}`, - "X-Awakari-Group-Id": defaultGroupId, - "X-Awakari-User-Id": userId, - }, - body: JSON.stringify(payload), - }) + Sources + .add(srcType, srcAddr, feedUpdFreq, headers) .then(resp => resp.text().then(msg => { if (resp.ok) { if (msg.length === 0) { diff --git a/web/pub.html b/web/pub.html index 608d329..0198f2c 100644 --- a/web/pub.html +++ b/web/pub.html @@ -29,7 +29,9 @@ + + + diff --git a/web/sub-details.js b/web/sub-details.js index 2db11a4..95cda3c 100644 --- a/web/sub-details.js +++ b/web/sub-details.js @@ -55,31 +55,9 @@ function loadSubscription() { // const data = {"description":"Exoplanets","enabled":true,"cond":{"gc":{"logic":"Or","group":[{"tc":{"id":"txt_651f009c25fef58d2c176c06","term":"exoplanet экзопланета экзопланет экзопланеты экзопланету"}},{"gc":{"group":[{"tc":{"id":"txt_651f009c25fef58d2c176c13","term":"planet"}},{"tc":{"id":"txt_651f009c25fef58d2c176c27","term":"extrasolar"}}]}}]}},"expires":"0001-01-01T00:00:00Z"}; // editor.setValue(data.cond); // - let headers = { - "X-Awakari-Group-Id": defaultGroupId, - } - const authToken = localStorage.getItem(keyAuthToken); - if (authToken) { - headers["Authorization"] = `Bearer ${authToken}`; - } - const userId = localStorage.getItem(keyUserId); - if (userId) { - headers["X-Awakari-User-Id"] = userId; - } - let optsReq = { - method: "GET", - headers: headers, - cache: "default", - } - - document.getElementById("wait").style.display = "block"; - fetch(`/v1/sub/${id}`, optsReq) - .then(resp => { - if (!resp.ok) { - throw new Error(`Request failed with status: ${resp.status}`); - } - return resp.json(); - }) + const headers = getAuthHeaders(); + Subscriptions + .fetch(id, headers) .then(data => { if (data != null) { document.getElementById("description").value = data.description; @@ -101,48 +79,21 @@ function loadSubscription() { function updateSubscription() { const id = document.getElementById("id").value; - if (confirm(`Confirm update subscription ${id}?`)) { - let payload = { - id: id, - description: document.getElementById("description").value, - enabled: document.getElementById("enabled").checked, - cond: editor.getValue(0), - } - const expires = document.getElementById("expires").value; + if (confirm(`Update subscription ${id}?`)) { + const descr = document.getElementById("description").value; + const enabled = document.getElementById("enabled").checked; + const cond = editor.getValue(0); + let expires = document.getElementById("expires").value; if (expires && expires !== "") { const d = new Date(expires); - payload.expires = new Date(d.getTime() - d.getTimezoneOffset() * 60_000).toISOString(); + expires = new Date(d.getTime() - d.getTimezoneOffset() * 60_000); } else { - payload.expires = null; - } - - let headers = { - "X-Awakari-Group-Id": defaultGroupId, - } - const authToken = localStorage.getItem(keyAuthToken); - if (authToken) { - headers["Authorization"] = `Bearer ${authToken}`; - } - const userId = localStorage.getItem(keyUserId); - if (userId) { - headers["X-Awakari-User-Id"] = userId; + expires = null; } - - let optsReq = { - method: "PUT", - headers: headers, - body: JSON.stringify(payload) - } - + const headers = getAuthHeaders(); document.getElementById("wait").style.display = "block"; - fetch(`/v1/sub/${id}`, optsReq) - .then(resp => { - if (!resp.ok) { - resp.text().then(errMsg => console.error(errMsg)) - throw new Error(`Request failed ${resp.status}`); - } - return resp.json(); - }) + Subscriptions + .update(id, descr, enabled, expires, cond, headers) .then(_ => { alert(`Updated subscription: ${id}`); window.location.assign("sub.html"); @@ -158,31 +109,11 @@ function updateSubscription() { function deleteSubscription() { const id = document.getElementById("id").value; - if (confirm(`Confirm delete subscription ${id}?`)) { - let headers = { - "X-Awakari-Group-Id": defaultGroupId, - } - const authToken = localStorage.getItem(keyAuthToken); - if (authToken) { - headers["Authorization"] = `Bearer ${authToken}`; - } - const userId = localStorage.getItem(keyUserId); - if (userId) { - headers["X-Awakari-User-Id"] = userId; - } - let optsReq = { - method: "DELETE", - headers: headers, - cache: "default", - } + if (confirm(`Delete subscription ${id}?`)) { + const headers = getAuthHeaders(); document.getElementById("wait").style.display = "block"; - fetch(`/v1/sub/${id}`, optsReq) - .then(resp => { - if (!resp.ok) { - throw new Error(`Request failed with status: ${resp.status}`); - } - return resp.json(); - }) + Subscriptions + .delete(id, headers) .then(_ => { alert(`Deleted subscription ${id}`); window.location.assign("sub.html"); diff --git a/web/sub-new.html b/web/sub-new.html index 7169a90..c05c76b 100644 --- a/web/sub-new.html +++ b/web/sub-new.html @@ -19,6 +19,7 @@ + diff --git a/web/sub-new.js b/web/sub-new.js index 94d4cf7..c2b8bac 100644 --- a/web/sub-new.js +++ b/web/sub-new.js @@ -48,60 +48,29 @@ window.JSONEditor.defaults.callbacks = { function createSubscription() { let validationErr = ""; - let payload = { - description: document.getElementById("description").value, - enabled: true, - cond: { - not: false, - gc: { - logic: 0, - group: [] - } - }, - } - const expires = document.getElementById("expires").value; + let expires = document.getElementById("expires").value; if (expires && expires !== "") { const d = new Date(expires); - payload.expires = new Date(d.getTime() - d.getTimezoneOffset() * 60_000).toISOString(); + expires = new Date(d.getTime() - d.getTimezoneOffset() * 60_000); + } else { + expires = null; } - if (payload.description === "") { + const cond = editor.getValue(0); + const descr = document.getElementById("description").value; + if (descr === "") { validationErr = "empty description"; - } else { - payload.cond = editor.getValue(0); } if (validationErr === "") { - let headers = { - "X-Awakari-Group-Id": defaultGroupId, - } - const authToken = localStorage.getItem(keyAuthToken); - if (authToken) { - headers["Authorization"] = `Bearer ${authToken}`; - } - const userId = localStorage.getItem(keyUserId); - if (userId) { - headers["X-Awakari-User-Id"] = userId; - } - let optsReq = { - method: "POST", - headers: headers, - body: JSON.stringify(payload) - }; + const headers = getAuthHeaders(); + const userId = headers["X-Awakari-User-Id"]; document.getElementById("wait").style.display = "block"; - fetch(`/v1/sub`, optsReq) - .then(resp => { - if (!resp.ok) { - resp.text().then(errMsg => console.error(errMsg)); - throw new Error(`Request failed ${resp.status}`); - } - return resp.json(); - }) - .then(data => { - if (data) { - document.getElementById("sub-new-success-dialog").style.display = "block"; - document.getElementById("new-sub-id").innerText = data.id; - if (userId && userId.startsWith("tg://user?id=")) { - document.getElementById("sub-new-success-btn-tg").style.display = "block"; - } + Subscriptions + .create(descr, true, expires, cond, headers) + .then(id => { + document.getElementById("sub-new-success-dialog").style.display = "block"; + document.getElementById("new-sub-id").innerText = id; + if (userId && userId.startsWith("tg://user?id=")) { + document.getElementById("sub-new-success-btn-tg").style.display = "block"; } }) .catch(err => { diff --git a/web/sub.html b/web/sub.html index b6e9847..e99cc1c 100644 --- a/web/sub.html +++ b/web/sub.html @@ -28,6 +28,7 @@ + diff --git a/web/sub.js b/web/sub.js index 54ceb91..6e36eaa 100644 --- a/web/sub.js +++ b/web/sub.js @@ -77,7 +77,7 @@ function loadSubscriptions(filter) { const headers = getAuthHeaders(); Subscriptions - .fetchListPage(cursor, order, filter, headers) + .fetchListPage(cursor, order, pageLimit, filter, headers) .then(data => { if (data != null) {