From e95bb2e117bcc1b313b886d52c721af027e7661d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Jaenisch?= Date: Wed, 14 Aug 2024 17:13:07 +0200 Subject: [PATCH] feat: add notifications to settings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is currently a mock as we have no notification mechanism in place. Also, I need to figure out how to talk to Vervis' API first. That being said, this step allows for translations at least. Signed-off-by: André Jaenisch --- package-lock.json | 4 +- package.json | 2 +- src/lib/components/molecules/Settings.svelte | 3 + .../molecules/SettingsNotifications.svelte | 98 ++++ src/lib/i18n/locales/bg.json | 18 +- src/lib/i18n/locales/de.json | 548 +++++++++--------- src/lib/i18n/locales/en.json | 18 +- src/lib/i18n/locales/pl.json | 18 +- .../SettingsNotifications.stories.ts | 26 + .../molecules/SettingsNotifications.test.ts | 86 +++ 10 files changed, 549 insertions(+), 272 deletions(-) create mode 100644 src/lib/components/molecules/SettingsNotifications.svelte create mode 100644 stories/molecules/SettingsNotifications.stories.ts create mode 100644 tests/components/molecules/SettingsNotifications.test.ts diff --git a/package-lock.json b/package-lock.json index 1e2227e..427c50c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "anvil", - "version": "0.0.13", + "version": "0.0.14", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "anvil", - "version": "0.0.13", + "version": "0.0.14", "dependencies": { "@floating-ui/dom": "1.6.8", "@fontsource/spline-sans-mono": "5.0.20", diff --git a/package.json b/package.json index aa5f996..f7d0254 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "anvil", - "version": "0.0.13", + "version": "0.0.14", "private": true, "scripts": { "dev": "vite dev", diff --git a/src/lib/components/molecules/Settings.svelte b/src/lib/components/molecules/Settings.svelte index 9d3a627..877d149 100644 --- a/src/lib/components/molecules/Settings.svelte +++ b/src/lib/components/molecules/Settings.svelte @@ -15,6 +15,7 @@ You should have received a copy of the GNU Affero General Public License along w import SettingsAccount from './SettingsAccount.svelte'; import SettingsAppearance from './SettingsAppearance.svelte'; import SettingsKeys from './SettingsKeys.svelte'; + import SettingsNotifications from './SettingsNotifications.svelte'; import SettingsSidebar from '../atoms/SettingsSidebar.svelte'; import SettingsProfile from './SettingsProfile.svelte'; @@ -36,5 +37,7 @@ You should have received a copy of the GNU Affero General Public License along w {:else if activeSetting === 'appearance'} + {:else if activeSetting === 'notifications'} + {/if} diff --git a/src/lib/components/molecules/SettingsNotifications.svelte b/src/lib/components/molecules/SettingsNotifications.svelte new file mode 100644 index 0000000..abcc627 --- /dev/null +++ b/src/lib/components/molecules/SettingsNotifications.svelte @@ -0,0 +1,98 @@ + + + + +
+
+ {$_('settings.notifications.headline')} +
+
+
+ {$_('settings.notifications.mentions.headline')} +
+

+ {@html $_('settings.notifications.mentions.intro', { + values: { blockElementOpen: '', blockElementClose: '', instance, username } + })} +

+ + {#if isNotifiedOnMention} + {$_('settings.notifications.mentions.labelYes')} + {:else} + {$_('settings.notifications.mentions.labelNo')} + {/if} + +
+ +
+
+ {$_('settings.notifications.default.headline')} +
+

+ {$_('settings.notifications.default.intro')} +

+
+ + + +
+
+
diff --git a/src/lib/i18n/locales/bg.json b/src/lib/i18n/locales/bg.json index 0d14bac..a86f8b8 100644 --- a/src/lib/i18n/locales/bg.json +++ b/src/lib/i18n/locales/bg.json @@ -206,7 +206,23 @@ } }, "notifications": { - "label": "" + "default": { + "headline": "", + "intro": "", + "notification": { + "all": "", + "off": "", + "mentioned": "" + } + }, + "headline": "", + "label": "", + "mentions": { + "headline": "", + "intro": "", + "labelNo": "", + "labelYes": "" + } }, "profile": { "avatar": { diff --git a/src/lib/i18n/locales/de.json b/src/lib/i18n/locales/de.json index 540ab3f..03e7e92 100644 --- a/src/lib/i18n/locales/de.json +++ b/src/lib/i18n/locales/de.json @@ -1,268 +1,284 @@ { - "overlay": { - "avatar": { - "about_anvil": "Über Anvil", - "dark_mode": "Nachtmodus", - "profile": "Profil", - "settings": "Einstellungen", - "sign_out": "Ausloggen" - } - }, - "page": { - "import_project": { - "form": { - "avatar": "Avatar", - "components": "Komponenten", - "fields": { - "avatar": { - "label": "Bild hochladen" - }, - "description": { - "label": "Beschreibung", - "placeholder": "Beschreibe das Projekt in unter 100 Zeichen..." - }, - "issues": { - "label": "Issues" - }, - "name": { - "error": "Dieses Feld ist erforderlich", - "label": "Name", - "placeholder": "Name des Projekts..." - }, - "pr": { - "label": "Pullrequest" - }, - "repository": { - "hint": "optional: von Git-Repository importieren", - "label": "Repository", - "placeholder": "URL des Git-Repositorys" - } - }, - "submit": "Projekt erstellen" - }, - "heading": "Projekt erstellen", - "intro": "Neues F2-Projekt zu Anvil hinzufügen." - }, - "login": { - "form": { - "fields": { - "account": { - "label": "Accountname" - }, - "passphrase": { - "label": "Passwort", - "placeholder": "Passwort" - }, - "server": { - "label": "F2-Server" - } - }, - "reset": "Passwort zurücksetzen", - "submit": "Einloggen", - "validation": { - "incorrect": "Accountname oder Kennwort sind falsch.", - "missing": "Das Account-Feld ist verbindlich." - } - }, - "heading": "Einloggen", - "intro": "Die Einwahldaten ausfüllen um Anvil mit deinem F2-Account zu benutzen." - }, - "profile": { - "activities": { - "block_or_report": "{blockElementOpen}blockieren{blockElementClose} oder {reportElementOpen}melden{reportElementClose}", - "like": "Gefällt mir" - }, - "heading": "Profil für", - "history": { - "activities": { - "commits": { - "actions": { - "browse": "", - "copy": "Kopieren" - }, - "number": "", - "relative_time": "" - }, - "setup": { - "description": "Das F2-Konto @{username}@{instance} wurde erfolgreich innerhalb von {created_with} erstellt", - "summary": "Kontoeinstellungen" - } - }, - "heading": "Aktivitäten" - }, - "menu": { - "actions": { - "fork": "", - "star": "", - "watch": "" - }, - "buttons": { - "avatar": "", - "issues": "", - "notifications": "Benachrichtigungen", - "prs": "" - }, - "details": { - "branches": "", - "commits": "Commits", - "files": "Dateien", - "issues": "", - "merge_requests": "", - "moderation": "Moderation", - "overview": "Übersicht", - "people": "", - "repository": "", - "roles": "Rollen", - "tags": "Schlagworte" - } - }, - "projects": { - "actions": { - "fork": "Fork", - "star": "Favorisieren", - "watch": "Beobachten" - }, - "add_or_import": "{addElementOpen}Ein Projekt hinzufügen{addElementClose} oder {importElementOpen}Ein Projekt importieren{importElementClose}.", - "empty": "Bisher keine Projekte hinzugefügt.", - "heading": "Projekte" - }, - "repositories": { - "heading": "" - } - }, - "projects": { - "file_table": { - "updated": "Aktualisiert: {relativeTime}" - }, - "form": { - "fields": { - "more_filters": { - "submit": "Weitere Filter" - }, - "projects": { - "submit": "Meine Projekte" - }, - "search": { - "placeholder": "Suchen oder filtern", - "submit": "Absenden" - }, - "starred": { - "submit": "Favorisiert" - } - } - }, - "nav": { - "next": "Weiter", - "previous": "Zurück" - }, - "table": { - "heading": { - "last_updated": "Letzte Aktualisierung", - "name": "Name" - } - } - }, - "welcome": { - "create": "", - "intro": "", - "headline": "Willkommen bei Anvil", - "login": "", - "logo": { - "alt": "" - }, - "reset": "" - } - }, - "settings": { - "headline": "", - "account": { - "delete": "", - "f2": { - "label": "", - "placeholder": "" - }, - "headline": "", - "label": "", - "password": { - "label": "", - "reset": "" - }, - "verification": { - "label": "" - } - }, - "appearance": { - "headline": "", - "label": "", - "tab_indent": { - "headline": "", - "intro": "" - }, - "theme": { - "auto": "", - "dark": "", - "headline": "", - "light": "" - } - }, - "notifications": { - "label": "" - }, - "profile": { - "avatar": { - "headline": "", - "remove": "", - "upload": "" - }, - "bio": { - "label": "", - "placeholder": "" - }, - "extra": { - "content": { - "placeholder": "" - }, - "headline": "", - "hint": "", - "label": { - "placeholder": "" - } - }, - "headline": "", - "label": "", - "name": { - "label": "", - "placeholder": "" - }, - "pronouns": { - "label": "" - } - }, - "ssh_gpg_keys": { - "gpg": { - "add": "", - "headline": "", - "key": { - "placeholder": "" - }, - "remove": "", - "title": { - "placeholder": "" - } - }, - "headline": "", - "label": "", - "ssh": { - "add": "", - "headline": "", - "key": { - "placeholder": "" - }, - "remove": "", - "title": { - "placeholder": "" - } - } - } - } + "overlay": { + "avatar": { + "about_anvil": "Über Anvil", + "dark_mode": "Nachtmodus", + "profile": "Profil", + "settings": "Einstellungen", + "sign_out": "Ausloggen" + } + }, + "page": { + "import_project": { + "form": { + "avatar": "Avatar", + "components": "Komponenten", + "fields": { + "avatar": { + "label": "Bild hochladen" + }, + "description": { + "label": "Beschreibung", + "placeholder": "Beschreibe das Projekt in unter 100 Zeichen..." + }, + "issues": { + "label": "Issues" + }, + "name": { + "error": "Dieses Feld ist erforderlich", + "label": "Name", + "placeholder": "Name des Projekts..." + }, + "pr": { + "label": "Pullrequest" + }, + "repository": { + "hint": "optional: von Git-Repository importieren", + "label": "Repository", + "placeholder": "URL des Git-Repositorys" + } + }, + "submit": "Projekt erstellen" + }, + "heading": "Projekt erstellen", + "intro": "Neues F2-Projekt zu Anvil hinzufügen." + }, + "login": { + "form": { + "fields": { + "account": { + "label": "Accountname" + }, + "passphrase": { + "label": "Passwort", + "placeholder": "Passwort" + }, + "server": { + "label": "F2-Server" + } + }, + "reset": "Passwort zurücksetzen", + "submit": "Einloggen", + "validation": { + "incorrect": "Accountname oder Kennwort sind falsch.", + "missing": "Das Account-Feld ist verbindlich." + } + }, + "heading": "Einloggen", + "intro": "Die Einwahldaten ausfüllen um Anvil mit deinem F2-Account zu benutzen." + }, + "profile": { + "activities": { + "block_or_report": "{blockElementOpen}blockieren{blockElementClose} oder {reportElementOpen}melden{reportElementClose}", + "like": "Gefällt mir" + }, + "heading": "Profil für", + "history": { + "activities": { + "commits": { + "actions": { + "browse": "", + "copy": "Kopieren" + }, + "number": "", + "relative_time": "" + }, + "setup": { + "description": "Das F2-Konto @{username}@{instance} wurde erfolgreich innerhalb von {created_with} erstellt", + "summary": "Kontoeinstellungen" + } + }, + "heading": "Aktivitäten" + }, + "menu": { + "actions": { + "fork": "", + "star": "", + "watch": "" + }, + "buttons": { + "avatar": "", + "issues": "", + "notifications": "Benachrichtigungen", + "prs": "" + }, + "details": { + "branches": "", + "commits": "Commits", + "files": "Dateien", + "issues": "", + "merge_requests": "", + "moderation": "Moderation", + "overview": "Übersicht", + "people": "", + "repository": "", + "roles": "Rollen", + "tags": "Schlagworte" + } + }, + "projects": { + "actions": { + "fork": "Fork", + "star": "Favorisieren", + "watch": "Beobachten" + }, + "add_or_import": "{addElementOpen}Ein Projekt hinzufügen{addElementClose} oder {importElementOpen}Ein Projekt importieren{importElementClose}.", + "empty": "Bisher keine Projekte hinzugefügt.", + "heading": "Projekte" + }, + "repositories": { + "heading": "" + } + }, + "projects": { + "file_table": { + "updated": "Aktualisiert: {relativeTime}" + }, + "form": { + "fields": { + "more_filters": { + "submit": "Weitere Filter" + }, + "projects": { + "submit": "Meine Projekte" + }, + "search": { + "placeholder": "Suchen oder filtern", + "submit": "Absenden" + }, + "starred": { + "submit": "Favorisiert" + } + } + }, + "nav": { + "next": "Weiter", + "previous": "Zurück" + }, + "table": { + "heading": { + "last_updated": "Letzte Aktualisierung", + "name": "Name" + } + } + }, + "welcome": { + "create": "", + "intro": "", + "headline": "Willkommen bei Anvil", + "login": "", + "logo": { + "alt": "" + }, + "reset": "" + } + }, + "settings": { + "headline": "", + "account": { + "delete": "", + "f2": { + "label": "", + "placeholder": "" + }, + "headline": "", + "label": "", + "password": { + "label": "", + "reset": "" + }, + "verification": { + "label": "" + } + }, + "appearance": { + "headline": "", + "label": "", + "tab_indent": { + "headline": "", + "intro": "" + }, + "theme": { + "auto": "", + "dark": "", + "headline": "", + "light": "" + } + }, + "notifications": { + "default": { + "headline": "", + "intro": "", + "notification": { + "all": "", + "off": "", + "mentioned": "" + } + }, + "headline": "", + "label": "", + "mentions": { + "headline": "", + "intro": "", + "labelNo": "", + "labelYes": "" + } + }, + "profile": { + "avatar": { + "headline": "", + "remove": "", + "upload": "" + }, + "bio": { + "label": "", + "placeholder": "" + }, + "extra": { + "content": { + "placeholder": "" + }, + "headline": "", + "hint": "", + "label": { + "placeholder": "" + } + }, + "headline": "", + "label": "", + "name": { + "label": "", + "placeholder": "" + }, + "pronouns": { + "label": "" + } + }, + "ssh_gpg_keys": { + "gpg": { + "add": "", + "headline": "", + "key": { + "placeholder": "" + }, + "remove": "", + "title": { + "placeholder": "" + } + }, + "headline": "", + "label": "", + "ssh": { + "add": "", + "headline": "", + "key": { + "placeholder": "" + }, + "remove": "", + "title": { + "placeholder": "" + } + } + } + } } diff --git a/src/lib/i18n/locales/en.json b/src/lib/i18n/locales/en.json index dc048e9..addd58e 100644 --- a/src/lib/i18n/locales/en.json +++ b/src/lib/i18n/locales/en.json @@ -206,7 +206,23 @@ } }, "notifications": { - "label": "Notifications" + "default": { + "headline": "Default notification", + "intro": "The default notification setting for starred projects", + "notification": { + "all": "All activity", + "off": "Turn off", + "mentioned": "Mentions only" + } + }, + "headline": "Notifications", + "label": "Notifications", + "mentions": { + "headline": "Mentions", + "intro": "Receive notifications when {blockElementOpen}@{username}@{instance}{blockElementClose} is mentioned.", + "labelNo": "Off", + "labelYes": "On" + } }, "profile": { "avatar": { diff --git a/src/lib/i18n/locales/pl.json b/src/lib/i18n/locales/pl.json index b6b8bca..5d69954 100644 --- a/src/lib/i18n/locales/pl.json +++ b/src/lib/i18n/locales/pl.json @@ -206,7 +206,23 @@ } }, "notifications": { - "label": "" + "default": { + "headline": "", + "intro": "", + "notification": { + "all": "", + "off": "", + "mentioned": "" + } + }, + "headline": "", + "label": "", + "mentions": { + "headline": "", + "intro": "", + "labelNo": "", + "labelYes": "" + } }, "profile": { "avatar": { diff --git a/stories/molecules/SettingsNotifications.stories.ts b/stories/molecules/SettingsNotifications.stories.ts new file mode 100644 index 0000000..908cddb --- /dev/null +++ b/stories/molecules/SettingsNotifications.stories.ts @@ -0,0 +1,26 @@ +/* Stories for SettingsNotifications molecule. + * Copyright (C) 2024 André Jaenisch + * SPDX-FileCopyrightText: 2024 André Jaenisch + * SPDX-License-Identifier: AGPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License along with this program. If not, see . + */ + +import type { Meta, StoryObj } from '@storybook/svelte'; + +import SettingsNotifications from '$lib/components/molecules/SettingsNotifications.svelte'; + +const meta = { + title: 'Molecules/SettingsNotifications', + component: SettingsNotifications, + tags: ['autodocs'] +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Plain: Story = {}; diff --git a/tests/components/molecules/SettingsNotifications.test.ts b/tests/components/molecules/SettingsNotifications.test.ts new file mode 100644 index 0000000..5c38a2b --- /dev/null +++ b/tests/components/molecules/SettingsNotifications.test.ts @@ -0,0 +1,86 @@ +/* Component test for SettingsNotifications molecule. + * Copyright (C) 2024 André Jaenisch + * SPDX-FileCopyrightText: 2024 André Jaenisch + * SPDX-License-Identifier: AGPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License along with this program. If not, see . + */ + +import '@testing-library/jest-dom'; +import { render, screen } from '@testing-library/svelte'; +import { init, locale, register } from 'svelte-i18n'; + +import SettingsNotifications from '../../../src/lib/components/molecules/SettingsNotifications.svelte'; +import enMessages from '../../../src/lib/i18n/locales/en.json'; + +describe('SettingsNotifications.svelte', () => { + beforeEach(() => { + register('en', () => import('../../../src/lib/i18n/locales/en.json')); + init({ fallbackLocale: 'en', initialLocale: 'en' }); + locale.set('en'); + }); + + it('should mount', () => { + // Arrange + // Nothing to prepare + + // Act + const { container } = render(SettingsNotifications); + + // Assert + expect(container).toBeTruthy(); + }); + + it('should have a slide toggle', () => { + // Arrange + // Nothing to prepare + + // Act + render(SettingsNotifications); + + // Assert + expect( + screen.getByLabelText(enMessages.settings.notifications.mentions.labelNo) + ).toBeInTheDocument(); + }); + + describe('when slide is toggled', () => { + it('should update the label', async () => { + // Arrange + // Nothing to prepare + + // Act + render(SettingsNotifications); + const slideToggle = screen.getByLabelText(enMessages.settings.notifications.mentions.labelNo); + await slideToggle.click(); + + // Assert + expect( + screen.getByLabelText(enMessages.settings.notifications.mentions.labelYes) + ).toBeInTheDocument(); + }); + }); + + it('should have a default notification radio group', () => { + // Arrange + // Nothing to prepare + + // Act + render(SettingsNotifications); + + // Assert + expect( + screen.getByLabelText(enMessages.settings.notifications.default.notification.all) + ).toBeInTheDocument(); + expect( + screen.getByLabelText(enMessages.settings.notifications.default.notification.off) + ).toBeInTheDocument(); + expect( + screen.getByLabelText(enMessages.settings.notifications.default.notification.mentioned) + ).toBeInTheDocument(); + }); +});