diff --git a/package-lock.json b/package-lock.json
index 372400f..1e49ca4 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,14 +1,15 @@
{
"name": "anvil",
- "version": "0.0.11",
+ "version": "0.0.12",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "anvil",
- "version": "0.0.11",
+ "version": "0.0.12",
"dependencies": {
"@floating-ui/dom": "1.6.8",
+ "@fontsource/spline-sans-mono": "5.0.20",
"axios": "1.7.2",
"cheerio": "1.0.0-rc.12"
},
@@ -2202,6 +2203,11 @@
"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.5.tgz",
"integrity": "sha512-sTcG+QZ6fdEUObICavU+aB3Mp8HY4n14wYHdxK4fXjPmv3PXZZeY5RaguJmGyeH/CJQhX3fqKUtS4qc1LoHwhQ=="
},
+ "node_modules/@fontsource/spline-sans-mono": {
+ "version": "5.0.20",
+ "resolved": "https://registry.npmjs.org/@fontsource/spline-sans-mono/-/spline-sans-mono-5.0.20.tgz",
+ "integrity": "sha512-4u23nOkNK1B6rkmNfiodQaMu9CKtKzrK/lTEAhBuQT08cTm6544uTQSoH8ssylDbdyYZZAWyVA2Mua/TdIuoxQ=="
+ },
"node_modules/@formatjs/ecma402-abstract": {
"version": "1.18.2",
"resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.18.2.tgz",
diff --git a/package.json b/package.json
index 3f3c8e7..79ba940 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "anvil",
- "version": "0.0.11",
+ "version": "0.0.12",
"private": true,
"scripts": {
"dev": "vite dev",
@@ -75,6 +75,7 @@
"type": "module",
"dependencies": {
"@floating-ui/dom": "1.6.8",
+ "@fontsource/spline-sans-mono": "5.0.20",
"axios": "1.7.2",
"cheerio": "1.0.0-rc.12"
}
diff --git a/src/lib/components/molecules/Settings.svelte b/src/lib/components/molecules/Settings.svelte
index c915308..173b039 100644
--- a/src/lib/components/molecules/Settings.svelte
+++ b/src/lib/components/molecules/Settings.svelte
@@ -13,6 +13,7 @@ You should have received a copy of the GNU Affero General Public License along w
+
+
+
+ {$_('settings.ssh_gpg_keys.headline')}
+
+
+
+
+ {$_('settings.ssh_gpg_keys.ssh.headline')}
+
+
+
+ {#each ssh_keys as key}
+
+
+ {key.title}
+ {key.fingerprint}
+
+
+ {/each}
+
+
+
+
+
+
+
+
+ {$_('settings.ssh_gpg_keys.gpg.headline')}
+
+
+
+ {#each gpg_keys as key}
+
+
+ {key.title}
+ {key.fingerprint}
+
+
+ {/each}
+
+
+
+
+
+
+
diff --git a/src/lib/i18n/locales/bg.json b/src/lib/i18n/locales/bg.json
index 9776dec..e403b4f 100644
--- a/src/lib/i18n/locales/bg.json
+++ b/src/lib/i18n/locales/bg.json
@@ -228,7 +228,30 @@
}
},
"ssh_gpg_keys": {
- "label": ""
+ "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/de.json b/src/lib/i18n/locales/de.json
index e2aa512..e16ce33 100644
--- a/src/lib/i18n/locales/de.json
+++ b/src/lib/i18n/locales/de.json
@@ -228,7 +228,30 @@
}
},
"ssh_gpg_keys": {
- "label": ""
+ "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 87086ae..d61f59e 100644
--- a/src/lib/i18n/locales/en.json
+++ b/src/lib/i18n/locales/en.json
@@ -228,7 +228,30 @@
}
},
"ssh_gpg_keys": {
- "label": "SSH/GPG Keys"
+ "gpg": {
+ "add": "Add GPG key",
+ "headline": "GPG",
+ "key": {
+ "placeholder": "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+ },
+ "remove": "Remove",
+ "title": {
+ "placeholder": "Title"
+ }
+ },
+ "headline": "SSH/GPG Keys",
+ "label": "SSH/GPG Keys",
+ "ssh": {
+ "add": "Add SSH key",
+ "headline": "SSH",
+ "key": {
+ "placeholder": "Begins with 'ssh-rsa', 'ecdsa-sha2-nistp256', 'ecdsa-sha2-nistp384', 'ecdsa-sha2-nistp521', 'ssh-ed25519', 'sk-ecdsa-sha2-nistp256@openssh.com', or 'sk-ssh-ed25519@openssh.com'"
+ },
+ "remove": "Remove",
+ "title": {
+ "placeholder": "Title"
+ }
+ }
}
}
}
diff --git a/src/lib/i18n/locales/he.json b/src/lib/i18n/locales/he.json
index 7a796e8..6724254 100644
--- a/src/lib/i18n/locales/he.json
+++ b/src/lib/i18n/locales/he.json
@@ -228,7 +228,30 @@
}
},
"ssh_gpg_keys": {
- "label": ""
+ "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/pl.json b/src/lib/i18n/locales/pl.json
index b1082b1..5a093ed 100644
--- a/src/lib/i18n/locales/pl.json
+++ b/src/lib/i18n/locales/pl.json
@@ -228,7 +228,30 @@
}
},
"ssh_gpg_keys": {
- "label": ""
+ "gpg": {
+ "add": "",
+ "headline": "",
+ "key": {
+ "placeholder": ""
+ },
+ "remove": "",
+ "title": {
+ "placeholder": ""
+ }
+ },
+ "headline": "",
+ "label": "",
+ "ssh": {
+ "add": "",
+ "headline": "",
+ "key": {
+ "placeholder": ""
+ },
+ "remove": "",
+ "title": {
+ "placeholder": ""
+ }
+ }
}
}
}
diff --git a/stories/icons/Key24.stories.ts b/stories/icons/Key24.stories.ts
new file mode 100644
index 0000000..4f210eb
--- /dev/null
+++ b/stories/icons/Key24.stories.ts
@@ -0,0 +1,36 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2020-present Eric Liu
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ */
+
+/*
+ * SPDX-FileCopyrightText: 2020 - 2024 Eric Liu
+ * SPDX-License-Identifier: MIT
+ */
+
+import type { Meta, StoryObj } from '@storybook/svelte';
+import { Key24 } from 'svelte-octicons';
+
+const meta = {
+ title: 'Icons/Key24',
+ component: Key24,
+ tags: ['autodocs'],
+ argTypes: {
+ fill: {
+ control: 'color'
+ }
+ }
+} satisfies Meta;
+
+export default meta;
+type Story = StoryObj;
+
+export const Plain: Story = {};
diff --git a/stories/molecules/SetttingsKeys.stories.ts b/stories/molecules/SetttingsKeys.stories.ts
new file mode 100644
index 0000000..98f63ff
--- /dev/null
+++ b/stories/molecules/SetttingsKeys.stories.ts
@@ -0,0 +1,26 @@
+/* Stories for SettingsKeys 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 SettingsKeys from '$lib/components/molecules/SettingsKeys.svelte';
+
+const meta = {
+ title: 'Molecules/SettingsKeys',
+ component: SettingsKeys,
+ tags: ['autodocs']
+} satisfies Meta;
+
+export default meta;
+type Story = StoryObj;
+
+export const Plain: Story = {};
diff --git a/tailwind.config.js b/tailwind.config.js
index 49bb458..a54981f 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -24,7 +24,20 @@ export default {
join(require.resolve('@skeletonlabs/skeleton'), '../**/*.{html,js,svelte,ts}')
],
theme: {
- extend: {}
+ extend: {},
+ fontFamily: {
+ mono: [
+ 'ui-monospace',
+ 'Spline Sans Mono',
+ 'SFMono-Regular',
+ 'Menlo',
+ 'Monaco',
+ 'Consolas',
+ 'Liberation Mono',
+ 'Courier New',
+ 'monospace'
+ ]
+ }
},
plugins: [require('@tailwindcss/typography'), forms, skeleton]
};
diff --git a/tests/components/molecules/SettingsKeys.test.ts b/tests/components/molecules/SettingsKeys.test.ts
new file mode 100644
index 0000000..df80210
--- /dev/null
+++ b/tests/components/molecules/SettingsKeys.test.ts
@@ -0,0 +1,95 @@
+/* Component test for SettingsKeys 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 SettingsKeys from '../../../src/lib/components/molecules/SettingsKeys.svelte';
+import enMessages from '../../../src/lib/i18n/locales/en.json';
+
+describe('SettingsKeys.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(SettingsKeys);
+
+ // Assert
+ expect(container).toBeTruthy();
+ });
+
+ describe('SSH', () => {
+ it('should have a way to remove a SSH key', () => {
+ // Arrange
+ // Currently those keys are hardcoded
+ const numberOfKeys = 2 /* SSH */ + 1; /* GPG */
+
+ // Act
+ render(SettingsKeys);
+
+ // Assert
+ expect(
+ screen.getAllByRole('button', { name: enMessages.settings.ssh_gpg_keys.ssh.remove })
+ ).toHaveLength(numberOfKeys);
+ });
+
+ it('should have a way to add a SSH key', () => {
+ // Arrange
+ // Nothing to prepare
+
+ // Act
+ render(SettingsKeys);
+
+ // Assert
+ expect(
+ screen.getByRole('button', { name: enMessages.settings.ssh_gpg_keys.ssh.add })
+ ).toBeInTheDocument();
+ });
+ });
+
+ describe('GPG', () => {
+ it('should have a way to remove a GPG key', () => {
+ // Arrange
+ // Currently those keys are hardcoded
+ const numberOfKeys = 2 /* SSH */ + 1; /* GPG */
+
+ // Act
+ render(SettingsKeys);
+
+ // Assert
+ expect(
+ screen.getAllByRole('button', { name: enMessages.settings.ssh_gpg_keys.gpg.remove })
+ ).toHaveLength(numberOfKeys);
+ });
+
+ it('should have a way to add a GPG key', () => {
+ // Arrange
+ // Nothing to prepare
+
+ // Act
+ render(SettingsKeys);
+
+ // Assert
+ expect(
+ screen.getByRole('button', { name: enMessages.settings.ssh_gpg_keys.gpg.add })
+ ).toBeInTheDocument();
+ });
+ });
+});