From 0fe5d9d628354bc02f2f78dedbebe91c4ff6d470 Mon Sep 17 00:00:00 2001 From: Johannes Zellner Date: Tue, 18 Mar 2025 16:53:15 +0100 Subject: [PATCH] Add notification panel --- dashboard/package-lock.json | 28 ++--- dashboard/package.json | 4 +- dashboard/src/components/Headerbar.vue | 125 +++++++++++++++++---- dashboard/src/models/NotificationsModel.js | 36 ++++++ 4 files changed, 156 insertions(+), 37 deletions(-) create mode 100644 dashboard/src/models/NotificationsModel.js diff --git a/dashboard/package-lock.json b/dashboard/package-lock.json index 6a14b55e2..6025433a1 100644 --- a/dashboard/package-lock.json +++ b/dashboard/package-lock.json @@ -25,9 +25,9 @@ "jquery": "^3.7.1", "marked": "^15.0.7", "moment-timezone": "^0.5.47", - "pankow": "^2.10.2", + "pankow": "^2.10.3", "pankow-viewers": "^1.0.11", - "sass": "^1.85.1", + "sass": "^1.86.0", "vite": "^6.2.2", "vue": "^3.5.13", "vue-i18n": "^11.1.2", @@ -2351,9 +2351,9 @@ } }, "node_modules/pankow": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/pankow/-/pankow-2.10.2.tgz", - "integrity": "sha512-J0BkBajRhDjElVCQ+1AYxX9n07+ofwmmlPcCmkRkqd0N5xUmNFUnD74WM/6qXN625XU9rORCbCeuPX/IsB2uCA==", + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/pankow/-/pankow-2.10.3.tgz", + "integrity": "sha512-z7ptMlRGACpL3T6bNml5HlI+qgrLeb7+ImKfTE+UDqu/IBiyOrU9eabzhFlg0GUBbISZd0DPHhInWUdIywDLPQ==", "license": "ISC", "dependencies": { "@fontsource/inter": "^5.2.5", @@ -2528,9 +2528,9 @@ } }, "node_modules/sass": { - "version": "1.85.1", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.85.1.tgz", - "integrity": "sha512-Uk8WpxM5v+0cMR0XjX9KfRIacmSG86RH4DCCZjLU2rFh5tyutt9siAXJ7G+YfxQ99Q6wrRMbMlVl6KqUms71ag==", + "version": "1.86.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.86.0.tgz", + "integrity": "sha512-zV8vGUld/+mP4KbMLJMX7TyGCuUp7hnkOScgCMsWuHtns8CWBoz+vmEhoGMXsaJrbUP8gj+F1dLvVe79sK8UdA==", "license": "MIT", "dependencies": { "chokidar": "^4.0.0", @@ -4155,9 +4155,9 @@ } }, "pankow": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/pankow/-/pankow-2.10.2.tgz", - "integrity": "sha512-J0BkBajRhDjElVCQ+1AYxX9n07+ofwmmlPcCmkRkqd0N5xUmNFUnD74WM/6qXN625XU9rORCbCeuPX/IsB2uCA==", + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/pankow/-/pankow-2.10.3.tgz", + "integrity": "sha512-z7ptMlRGACpL3T6bNml5HlI+qgrLeb7+ImKfTE+UDqu/IBiyOrU9eabzhFlg0GUBbISZd0DPHhInWUdIywDLPQ==", "requires": { "@fontsource/inter": "^5.2.5", "@fortawesome/fontawesome-free": "^6.7.2", @@ -4266,9 +4266,9 @@ } }, "sass": { - "version": "1.85.1", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.85.1.tgz", - "integrity": "sha512-Uk8WpxM5v+0cMR0XjX9KfRIacmSG86RH4DCCZjLU2rFh5tyutt9siAXJ7G+YfxQ99Q6wrRMbMlVl6KqUms71ag==", + "version": "1.86.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.86.0.tgz", + "integrity": "sha512-zV8vGUld/+mP4KbMLJMX7TyGCuUp7hnkOScgCMsWuHtns8CWBoz+vmEhoGMXsaJrbUP8gj+F1dLvVe79sK8UdA==", "requires": { "@parcel/watcher": "^2.4.1", "chokidar": "^4.0.0", diff --git a/dashboard/package.json b/dashboard/package.json index f8254517b..052ad7f9d 100644 --- a/dashboard/package.json +++ b/dashboard/package.json @@ -26,9 +26,9 @@ "jquery": "^3.7.1", "marked": "^15.0.7", "moment-timezone": "^0.5.47", - "pankow": "^2.10.2", + "pankow": "^2.10.3", "pankow-viewers": "^1.0.11", - "sass": "^1.85.1", + "sass": "^1.86.0", "vite": "^6.2.2", "vue": "^3.5.13", "vue-i18n": "^11.1.2", diff --git a/dashboard/src/components/Headerbar.vue b/dashboard/src/components/Headerbar.vue index 22bb42e9e..92fe2b58b 100644 --- a/dashboard/src/components/Headerbar.vue +++ b/dashboard/src/components/Headerbar.vue @@ -1,11 +1,85 @@ @@ -41,16 +107,6 @@ const props = defineProps(['profile', 'subscription']); .headerbar a { display: flex; align-items: center; - padding: 6px 15px; - border-radius: var(--pankow-border-radius); - color: var(--pankow-text-color); -} - -.headerbar a:focus, -.headerbar a:active, -.headerbar a:hover { - text-decoration: none; - background-color: var(--pankow-color-background-hover); } .headerbar-avatar { @@ -60,4 +116,31 @@ const props = defineProps(['profile', 'subscription']); border-radius: var(--pankow-border-radius); } +.notification-item { + margin-bottom: 10px; + padding-bottom: 10px; + cursor: pointer; + border-bottom: 1px solid var(--pankow-input-border-color); + position: relative; +} + +.notification-item-title { + display: flex; + justify-content: space-between; + align-items: center; +} + +.notification-item:hover .notification-item-title { + font-weight: bold; +} + +.notification-read-button { + visibility: hidden; + margin-right: 10px; +} + +.notification-item:hover .notification-read-button { + visibility: visible; +} + diff --git a/dashboard/src/models/NotificationsModel.js b/dashboard/src/models/NotificationsModel.js new file mode 100644 index 000000000..d68e09032 --- /dev/null +++ b/dashboard/src/models/NotificationsModel.js @@ -0,0 +1,36 @@ + +import { fetcher } from 'pankow'; +import { API_ORIGIN } from '../constants.js'; + +function create() { + const accessToken = localStorage.token; + + return { + async list(acknowledged = false) { + let result; + try { + result = await fetcher.get(`${API_ORIGIN}/api/v1/notifications`, { acknowledged, access_token: accessToken }); + } catch (e) { + return [e]; + } + + if (result.status !== 200) return [result]; + return [null, result.body.notifications]; + }, + async update(id, acknowledged) { + let result; + try { + result = await fetcher.post(`${API_ORIGIN}/api/v1/notifications/${id}`, { acknowledged }, { access_token: accessToken }); + } catch (e) { + return [e]; + } + + if (result.status !== 204) return [result]; + return [null]; + }, + }; +} + +export default { + create, +};