From b10c416f9e72da39fb5f7398c7c67faaab008a5e Mon Sep 17 00:00:00 2001 From: zeripath Date: Fri, 24 Apr 2020 04:57:38 +0100 Subject: Use AJAX for notifications table (#10961) * Use AJAX for notifications table Signed-off-by: Andrew Thornton * move to separate js Signed-off-by: Andrew Thornton * placate golangci-lint Signed-off-by: Andrew Thornton * Add autoupdating notification count Signed-off-by: Andrew Thornton * Fix wipeall Signed-off-by: Andrew Thornton * placate tests Signed-off-by: Andrew Thornton * Try hidden Signed-off-by: Andrew Thornton * Try hide and hidden Signed-off-by: Andrew Thornton * More auto-update improvements Only run checker on pages that have a count Change starting checker to 10s with a back-off to 60s if there is no change Signed-off-by: Andrew Thornton * string comparison! Signed-off-by: Andrew Thornton * as per @silverwind Signed-off-by: Andrew Thornton * add configurability as per @6543 Signed-off-by: Andrew Thornton * Add documentation as per @6543 Signed-off-by: Andrew Thornton * Use CSRF header not query Signed-off-by: Andrew Thornton * Further JS improvements Fix @etzelia update notification table request Fix @silverwind comments Co-Authored-By: silverwind Signed-off-by: Andrew Thornton * Simplify the notification count fns Signed-off-by: Andrew Thornton Co-authored-by: silverwind --- web_src/js/features/notification.js | 110 ++++++++++++++++++++++++++++++++++++ web_src/js/index.js | 8 +++ 2 files changed, 118 insertions(+) create mode 100644 web_src/js/features/notification.js (limited to 'web_src/js') diff --git a/web_src/js/features/notification.js b/web_src/js/features/notification.js new file mode 100644 index 0000000000..3f2af4de91 --- /dev/null +++ b/web_src/js/features/notification.js @@ -0,0 +1,110 @@ +const {AppSubUrl, csrf, NotificationSettings} = window.config; + +export function initNotificationsTable() { + $('#notification_table .button').on('click', async function () { + const data = await updateNotification( + $(this).data('url'), + $(this).data('status'), + $(this).data('page'), + $(this).data('q'), + $(this).data('notification-id'), + ); + + $('#notification_div').replaceWith(data); + initNotificationsTable(); + await updateNotificationCount(); + + return false; + }); +} + +export function initNotificationCount() { + if (NotificationSettings.MinTimeout <= 0) { + return; + } + + const notificationCount = $('.notification_count'); + + if (notificationCount.length > 0) { + const fn = (timeout, lastCount) => { + setTimeout(async () => { + await updateNotificationCountWithCallback(fn, timeout, lastCount); + }, timeout); + }; + + fn(NotificationSettings.MinTimeout, notificationCount.text()); + } +} + +async function updateNotificationCountWithCallback(callback, timeout, lastCount) { + const currentCount = $('.notification_count').text(); + if (lastCount !== currentCount) { + callback(NotificationSettings.MinTimeout, currentCount); + return; + } + + const newCount = await updateNotificationCount(); + let needsUpdate = false; + + if (lastCount !== newCount) { + needsUpdate = true; + timeout = NotificationSettings.MinTimeout; + } else if (timeout < NotificationSettings.MaxTimeout) { + timeout += NotificationSettings.TimeoutStep; + } + + callback(timeout, newCount); + + const notificationDiv = $('#notification_div'); + if (notificationDiv.length > 0 && needsUpdate) { + const data = await $.ajax({ + type: 'GET', + url: `${AppSubUrl}/notifications?${notificationDiv.data('params')}`, + data: { + 'div-only': true, + } + }); + notificationDiv.replaceWith(data); + initNotificationsTable(); + } +} + +async function updateNotificationCount() { + const data = await $.ajax({ + type: 'GET', + url: `${AppSubUrl}/api/v1/notifications/new`, + headers: { + 'X-Csrf-Token': csrf, + }, + }); + + const notificationCount = $('.notification_count'); + if (data.new === 0) { + notificationCount.addClass('hidden'); + } else { + notificationCount.removeClass('hidden'); + } + + notificationCount.text(`${data.new}`); + + return `${data.new}`; +} + +async function updateNotification(url, status, page, q, notificationID) { + if (status !== 'pinned') { + $(`#notification_${notificationID}`).remove(); + } + + return $.ajax({ + type: 'POST', + url, + data: { + _csrf: csrf, + notification_id: notificationID, + status, + page, + q, + noredirect: true, + }, + }); +} diff --git a/web_src/js/index.js b/web_src/js/index.js index ed747765a0..9e699c1a2e 100644 --- a/web_src/js/index.js +++ b/web_src/js/index.js @@ -18,6 +18,7 @@ import initDateTimePicker from './features/datetimepicker.js'; import createDropzone from './features/dropzone.js'; import highlight from './features/highlight.js'; import ActivityTopAuthors from './components/ActivityTopAuthors.vue'; +import {initNotificationsTable, initNotificationCount} from './features/notification.js'; const {AppSubUrl, StaticUrlPrefix, csrf} = window.config; @@ -2431,6 +2432,11 @@ $(document).ready(async () => { window.location = $(this).data('href'); }); + // make table element clickable like a link + $('td[data-href]').click(function () { + window.location = $(this).data('href'); + }); + // Dropzone const $dropzone = $('#dropzone'); if ($dropzone.length > 0) { @@ -2606,6 +2612,8 @@ $(document).ready(async () => { initRepoStatusChecker(); initTemplateSearch(); initContextPopups(); + initNotificationsTable(); + initNotificationCount(); // Repo clone url. if ($('#repo-clone-url').length > 0) { -- cgit v1.2.3