diff --git a/package-lock.json b/package-lock.json index 1e49ca4..1e2227e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "anvil", - "version": "0.0.12", + "version": "0.0.13", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "anvil", - "version": "0.0.12", + "version": "0.0.13", "dependencies": { "@floating-ui/dom": "1.6.8", "@fontsource/spline-sans-mono": "5.0.20", diff --git a/package.json b/package.json index 79ba940..aa5f996 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "anvil", - "version": "0.0.12", + "version": "0.0.13", "private": true, "scripts": { "dev": "vite dev", diff --git a/src/lib/components/molecules/Settings.svelte b/src/lib/components/molecules/Settings.svelte index 173b039..7f1a104 100644 --- a/src/lib/components/molecules/Settings.svelte +++ b/src/lib/components/molecules/Settings.svelte @@ -13,15 +13,34 @@ You should have received a copy of the GNU Affero General Public License along w
@@ -33,5 +52,7 @@ You should have received a copy of the GNU Affero General Public License along w {:else if activeSetting === 'ssh_gpg_keys'} + {:else if activeSetting === 'appearance'} + {/if}
diff --git a/src/lib/components/molecules/SettingsAppearance.svelte b/src/lib/components/molecules/SettingsAppearance.svelte new file mode 100644 index 0000000..ffa45bf --- /dev/null +++ b/src/lib/components/molecules/SettingsAppearance.svelte @@ -0,0 +1,68 @@ + + + + +
+
+ {$_('settings.appearance.headline')} +
+
+
+ {$_('settings.appearance.theme.headline')} +
+
+ + + +
+
+ +
+
+ {$_('settings.appearance.tab_indent.headline')} +
+

{$_('settings.appearance.tab_indent.intro')}

+ +
+
diff --git a/src/lib/i18n/locales/bg.json b/src/lib/i18n/locales/bg.json index e403b4f..0d14bac 100644 --- a/src/lib/i18n/locales/bg.json +++ b/src/lib/i18n/locales/bg.json @@ -192,7 +192,18 @@ } }, "appearance": { - "label": "" + "headline": "", + "label": "", + "tab_indent": { + "headline": "", + "intro": "" + }, + "theme": { + "auto": "", + "dark": "", + "headline": "", + "light": "" + } }, "notifications": { "label": "" diff --git a/src/lib/i18n/locales/de.json b/src/lib/i18n/locales/de.json index 13f00ec..6f3ec0d 100644 --- a/src/lib/i18n/locales/de.json +++ b/src/lib/i18n/locales/de.json @@ -1,257 +1,268 @@ { - "overlay": { - "avatar": { - "about_anvil": "Über Anvil", - "dark_mode": "", - "profile": "", - "settings": "", - "sign_out": "" - } - }, - "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": "" - }, - "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": "", - "prs": "" - }, - "details": { - "branches": "", - "commits": "", - "files": "", - "issues": "", - "merge_requests": "", - "moderation": "", - "overview": "", - "people": "", - "repository": "", - "roles": "", - "tags": "" - } - }, - "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": { - "label": "" - }, - "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": "", + "profile": "", + "settings": "", + "sign_out": "" + } + }, + "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": "" + }, + "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": "", + "prs": "" + }, + "details": { + "branches": "", + "commits": "", + "files": "", + "issues": "", + "merge_requests": "", + "moderation": "", + "overview": "", + "people": "", + "repository": "", + "roles": "", + "tags": "" + } + }, + "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": "" + } + } + } + } } diff --git a/src/lib/i18n/locales/en.json b/src/lib/i18n/locales/en.json index d61f59e..dc048e9 100644 --- a/src/lib/i18n/locales/en.json +++ b/src/lib/i18n/locales/en.json @@ -192,7 +192,18 @@ } }, "appearance": { - "label": "Appearance" + "headline": "Appearance", + "label": "Appearance", + "tab_indent": { + "headline": "Tab indenting", + "intro": "Number of spaces per tab in code view." + }, + "theme": { + "auto": "Auto", + "dark": "Dark", + "headline": "Theme", + "light": "Light" + } }, "notifications": { "label": "Notifications" diff --git a/src/lib/i18n/locales/he.json b/src/lib/i18n/locales/he.json index 6724254..c8889c6 100644 --- a/src/lib/i18n/locales/he.json +++ b/src/lib/i18n/locales/he.json @@ -192,7 +192,18 @@ } }, "appearance": { - "label": "" + "headline": "", + "label": "", + "tab_indent": { + "headline": "", + "intro": "" + }, + "theme": { + "auto": "", + "dark": "", + "headline": "", + "light": "" + } }, "notifications": { "label": "" diff --git a/src/lib/i18n/locales/pl.json b/src/lib/i18n/locales/pl.json index 5a093ed..b6b8bca 100644 --- a/src/lib/i18n/locales/pl.json +++ b/src/lib/i18n/locales/pl.json @@ -192,7 +192,18 @@ } }, "appearance": { - "label": "" + "headline": "", + "label": "", + "tab_indent": { + "headline": "", + "intro": "" + }, + "theme": { + "auto": "", + "dark": "", + "headline": "", + "light": "" + } }, "notifications": { "label": "" diff --git a/stories/molecules/SettingsAppearance.stories.ts b/stories/molecules/SettingsAppearance.stories.ts new file mode 100644 index 0000000..7f54190 --- /dev/null +++ b/stories/molecules/SettingsAppearance.stories.ts @@ -0,0 +1,26 @@ +/* Stories for SettingsAppearance 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 SettingsAppearance from '$lib/components/molecules/SettingsAppearance.svelte'; + +const meta = { + title: 'Molecules/SettingsAppearance', + component: SettingsAppearance, + tags: ['autodocs'] +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Plain: Story = {}; diff --git a/tests/components/molecules/SettingsAppearance.test.ts b/tests/components/molecules/SettingsAppearance.test.ts new file mode 100644 index 0000000..195b333 --- /dev/null +++ b/tests/components/molecules/SettingsAppearance.test.ts @@ -0,0 +1,82 @@ +/* Component test for SettingsAppearance 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 SettingsAppearance from '../../../src/lib/components/molecules/SettingsAppearance.svelte'; +import enMessages from '../../../src/lib/i18n/locales/en.json'; + +describe('SettingsAppearance.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(SettingsAppearance); + + // Assert + expect(container).toBeTruthy(); + }); + + it('should have a radio group for themes', () => { + // Arrange + // Nothing to prepare + + // Act + render(SettingsAppearance); + + // Assert + expect(screen.getByLabelText(enMessages.settings.appearance.theme.light)).toBeInTheDocument(); + expect(screen.getByLabelText(enMessages.settings.appearance.theme.dark)).toBeInTheDocument(); + expect(screen.getByLabelText(enMessages.settings.appearance.theme.auto)).toBeInTheDocument(); + }); + + describe('when clicking a theme', () => { + it('should dispatch a switch-theme event', () => { + // Arrange + const listener = vi.fn(); + + // Act + const { component } = render(SettingsAppearance); + component.$on('switch-theme', listener); + const darkTheme = screen.getByLabelText(enMessages.settings.appearance.theme.dark); + darkTheme.click(); + const ev = new CustomEvent({ detail: 'dark' }); + + // Assert + expect(listener).toHaveBeenCalledOnce(); + expect(listener).toHaveBeenCalledWith(ev); + }); + }); + + // TODO: Mark up proper label and input + it.skip('should have a tab indent input', () => { + // Arrange + // Nothing to prepare + + // Act + render(SettingsAppearance); + + // Assert + expect( + screen.getByPlaceholderText(enMessages.settings.appearance.tab_indent.label) + ).toBeInTheDocument(); + }); +});