feat: extract SettingsSidebar into component
This is in need of at least one refactoring. Skeleton is redesigning the AppRail we are using here. The layout is hard to style. This implementation interacts with a drawer, but it will likely be dropped in the final version. Signed-off-by: André Jaenisch <andre.jaenisch@posteo.de>
This commit is contained in:
parent
5d1bada084
commit
ead9d281d0
9 changed files with 343 additions and 3 deletions
4
package-lock.json
generated
4
package-lock.json
generated
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "anvil",
|
"name": "anvil",
|
||||||
"version": "0.0.8",
|
"version": "0.0.10",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "anvil",
|
"name": "anvil",
|
||||||
"version": "0.0.8",
|
"version": "0.0.10",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@floating-ui/dom": "1.6.7",
|
"@floating-ui/dom": "1.6.7",
|
||||||
"axios": "1.7.2",
|
"axios": "1.7.2",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "anvil",
|
"name": "anvil",
|
||||||
"version": "0.0.8",
|
"version": "0.0.10",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite dev",
|
"dev": "vite dev",
|
||||||
|
|
125
src/lib/components/atoms/SettingsSidebar.svelte
Normal file
125
src/lib/components/atoms/SettingsSidebar.svelte
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
<!--
|
||||||
|
SettingsSidebar atom.
|
||||||
|
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 <http://www.gnu.org/licenses/>.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { AppRail, AppRailAnchor, AppRailTile, getDrawerStore } from '@skeletonlabs/skeleton';
|
||||||
|
import { _, locale, locales } from 'svelte-i18n';
|
||||||
|
import { Bell24, Gear24, Key24, Paintbrush24, Person24 } from 'svelte-octicons';
|
||||||
|
|
||||||
|
let currentTile = 0;
|
||||||
|
const drawerStore = getDrawerStore();
|
||||||
|
|
||||||
|
function onTileChanged(ev) {
|
||||||
|
const settings = { id: ev.target.value };
|
||||||
|
drawerStore.open(settings);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<AppRail aspectRatio="auto" gap="gap-8" height="h-auto" width="w-[230px]" spacing="my-2">
|
||||||
|
<svelte:fragment slot="lead">
|
||||||
|
<AppRailTile
|
||||||
|
regionLabel="!text-3xl text-surface-500 bg-surface-100 float-start w-full text-start ps-8 pt-8 -my-2"
|
||||||
|
>{$_('settings.headline')}</AppRailTile
|
||||||
|
>
|
||||||
|
</svelte:fragment>
|
||||||
|
<AppRailTile
|
||||||
|
bind:group={currentTile}
|
||||||
|
name="profile"
|
||||||
|
value="profile"
|
||||||
|
on:change={onTileChanged}
|
||||||
|
regionLabel="float-start ps-2 py-1 text-surface-500"
|
||||||
|
regionLead="float-start ps-8 text-surface-500"
|
||||||
|
title={$_('settings.profile.label')}
|
||||||
|
>
|
||||||
|
<svelte:fragment slot="lead">
|
||||||
|
<Person24 fill="currentColor" class="inline" />
|
||||||
|
</svelte:fragment>
|
||||||
|
<span>{$_('settings.profile.label')}</span>
|
||||||
|
</AppRailTile>
|
||||||
|
<AppRailTile
|
||||||
|
bind:group={currentTile}
|
||||||
|
name="account"
|
||||||
|
value="account"
|
||||||
|
on:change={onTileChanged}
|
||||||
|
regionLabel="float-start ps-2 py-1 text-surface-500"
|
||||||
|
regionLead="float-start ps-8 text-surface-500"
|
||||||
|
title={$_('settings.account.label')}
|
||||||
|
>
|
||||||
|
<svelte:fragment slot="lead">
|
||||||
|
<Gear24 fill="currentColor" class="inline" />
|
||||||
|
</svelte:fragment>
|
||||||
|
<span>{$_('settings.account.label')}</span>
|
||||||
|
</AppRailTile>
|
||||||
|
<AppRailTile
|
||||||
|
bind:group={currentTile}
|
||||||
|
name="ssh_gpg_keys"
|
||||||
|
value="ssh_gpg_keys"
|
||||||
|
on:change={onTileChanged}
|
||||||
|
regionLabel="float-start ps-2 py-1 text-surface-500"
|
||||||
|
regionLead="float-start ps-8 text-surface-500"
|
||||||
|
title={$_('settings.ssh_gpg_keys.label')}
|
||||||
|
>
|
||||||
|
<svelte:fragment slot="lead">
|
||||||
|
<Key24 fill="currentColor" class="inline" />
|
||||||
|
</svelte:fragment>
|
||||||
|
<span>{$_('settings.ssh_gpg_keys.label')}</span>
|
||||||
|
</AppRailTile>
|
||||||
|
<AppRailTile
|
||||||
|
bind:group={currentTile}
|
||||||
|
name="appearance"
|
||||||
|
value="appearance"
|
||||||
|
on:change={onTileChanged}
|
||||||
|
regionLabel="float-start ps-2 py-1 text-surface-500"
|
||||||
|
regionLead="float-start ps-8 text-surface-500"
|
||||||
|
title={$_('settings.appearance.label')}
|
||||||
|
>
|
||||||
|
<svelte:fragment slot="lead">
|
||||||
|
<Paintbrush24 fill="currentColor" class="inline" />
|
||||||
|
</svelte:fragment>
|
||||||
|
<span>{$_('settings.appearance.label')}</span>
|
||||||
|
</AppRailTile>
|
||||||
|
<AppRailTile
|
||||||
|
bind:group={currentTile}
|
||||||
|
name="notifications"
|
||||||
|
value="notifications"
|
||||||
|
on:change={onTileChanged}
|
||||||
|
regionLabel="float-start ps-2 py-1 text-surface-500"
|
||||||
|
regionLead="float-start ps-8 text-surface-500"
|
||||||
|
title={$_('settings.notifications.label')}
|
||||||
|
>
|
||||||
|
<svelte:fragment slot="lead">
|
||||||
|
<Bell24 fill="currentColor" class="inline" />
|
||||||
|
</svelte:fragment>
|
||||||
|
<span>{$_('settings.notifications.label')}</span>
|
||||||
|
</AppRailTile>
|
||||||
|
<svelte:fragment slot="trail">
|
||||||
|
<select bind:value={$locale} class="select">
|
||||||
|
{#each $locales as locale}
|
||||||
|
<option value={locale}>{locale}</option>
|
||||||
|
{/each}
|
||||||
|
</select>
|
||||||
|
<AppRailAnchor
|
||||||
|
href="https://matrix.to/#/#general-forgefed:matrix.batsense.net"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
>
|
||||||
|
Matrix
|
||||||
|
</AppRailAnchor>
|
||||||
|
<AppRailAnchor href="https://forgefed.org" target="_blank" rel="noreferrer">
|
||||||
|
ForgeFed
|
||||||
|
</AppRailAnchor>
|
||||||
|
<AppRailAnchor href="https://codeberg.org/anvil/anvil" target="_blank" rel="noreferrer">
|
||||||
|
Code
|
||||||
|
</AppRailAnchor>
|
||||||
|
</svelte:fragment>
|
||||||
|
</AppRail>
|
|
@ -172,5 +172,23 @@
|
||||||
},
|
},
|
||||||
"reset": ""
|
"reset": ""
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"headline": "",
|
||||||
|
"account": {
|
||||||
|
"label": ""
|
||||||
|
},
|
||||||
|
"appearance": {
|
||||||
|
"label": ""
|
||||||
|
},
|
||||||
|
"notifications": {
|
||||||
|
"label": ""
|
||||||
|
},
|
||||||
|
"profile": {
|
||||||
|
"label": ""
|
||||||
|
},
|
||||||
|
"ssh_gpg_keys": {
|
||||||
|
"label": ""
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -172,5 +172,23 @@
|
||||||
},
|
},
|
||||||
"reset": ""
|
"reset": ""
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"headline": "",
|
||||||
|
"account": {
|
||||||
|
"label": ""
|
||||||
|
},
|
||||||
|
"appearance": {
|
||||||
|
"label": ""
|
||||||
|
},
|
||||||
|
"notifications": {
|
||||||
|
"label": ""
|
||||||
|
},
|
||||||
|
"profile": {
|
||||||
|
"label": ""
|
||||||
|
},
|
||||||
|
"ssh_gpg_keys": {
|
||||||
|
"label": ""
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -172,5 +172,23 @@
|
||||||
},
|
},
|
||||||
"reset": "Reset passphrase"
|
"reset": "Reset passphrase"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"headline": "Settings",
|
||||||
|
"account": {
|
||||||
|
"label": "Account"
|
||||||
|
},
|
||||||
|
"appearance": {
|
||||||
|
"label": "Appearance"
|
||||||
|
},
|
||||||
|
"notifications": {
|
||||||
|
"label": "Notifications"
|
||||||
|
},
|
||||||
|
"profile": {
|
||||||
|
"label": "Profile"
|
||||||
|
},
|
||||||
|
"ssh_gpg_keys": {
|
||||||
|
"label": "SSH/GPG Keys"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -172,5 +172,23 @@
|
||||||
},
|
},
|
||||||
"reset": ""
|
"reset": ""
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"headline": "",
|
||||||
|
"account": {
|
||||||
|
"label": ""
|
||||||
|
},
|
||||||
|
"appearance": {
|
||||||
|
"label": ""
|
||||||
|
},
|
||||||
|
"notifications": {
|
||||||
|
"label": ""
|
||||||
|
},
|
||||||
|
"profile": {
|
||||||
|
"label": ""
|
||||||
|
},
|
||||||
|
"ssh_gpg_keys": {
|
||||||
|
"label": ""
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -172,5 +172,23 @@
|
||||||
},
|
},
|
||||||
"reset": ""
|
"reset": ""
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"headline": "",
|
||||||
|
"account": {
|
||||||
|
"label": ""
|
||||||
|
},
|
||||||
|
"appearance": {
|
||||||
|
"label": ""
|
||||||
|
},
|
||||||
|
"notifications": {
|
||||||
|
"label": ""
|
||||||
|
},
|
||||||
|
"profile": {
|
||||||
|
"label": ""
|
||||||
|
},
|
||||||
|
"ssh_gpg_keys": {
|
||||||
|
"label": ""
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
125
tests/components/atoms/SettingsSidebar.test.ts
Normal file
125
tests/components/atoms/SettingsSidebar.test.ts
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
/* Component test for SettingsSidebar atom.
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import '@testing-library/jest-dom';
|
||||||
|
import { render, screen } from '@testing-library/svelte';
|
||||||
|
import { get, readable } from 'svelte/store';
|
||||||
|
import { init, locale, register } from 'svelte-i18n';
|
||||||
|
|
||||||
|
import SettingsSidebar from '../../../src/lib/components/atoms/SettingsSidebar.svelte';
|
||||||
|
import enMessages from '../../../src/lib/i18n/locales/en.json';
|
||||||
|
|
||||||
|
describe('SettingsSidebar.svelte', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
register('en', () => import('../../../src/lib/i18n/locales/en.json'));
|
||||||
|
init({ fallbackLocale: 'en', initialLocale: 'en' });
|
||||||
|
locale.set('en');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should mount', () => {
|
||||||
|
// Arrange
|
||||||
|
// See https://testing-library.com/docs/svelte-testing-library/example#contexts
|
||||||
|
const drawerStore = readable([]);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const { container } = render(SettingsSidebar, {
|
||||||
|
context: new Map([['drawerStore', drawerStore]])
|
||||||
|
});
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(container).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have a headline', () => {
|
||||||
|
// Arrange
|
||||||
|
// See https://testing-library.com/docs/svelte-testing-library/example#contexts
|
||||||
|
const drawerStore = readable([]);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
render(SettingsSidebar, {
|
||||||
|
context: new Map([['drawerStore', drawerStore]])
|
||||||
|
});
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(screen.getByText(enMessages.settings.headline)).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have a profile tile', () => {
|
||||||
|
// Arrange
|
||||||
|
// See https://testing-library.com/docs/svelte-testing-library/example#contexts
|
||||||
|
const drawerStore = readable([]);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
render(SettingsSidebar, {
|
||||||
|
context: new Map([['drawerStore', drawerStore]])
|
||||||
|
});
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(screen.getByText(enMessages.settings.profile.label)).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have an account tile', () => {
|
||||||
|
// Arrange
|
||||||
|
// See https://testing-library.com/docs/svelte-testing-library/example#contexts
|
||||||
|
const drawerStore = readable([]);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
render(SettingsSidebar, {
|
||||||
|
context: new Map([['drawerStore', drawerStore]])
|
||||||
|
});
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(screen.getByText(enMessages.settings.account.label)).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have a SSH/GPG keys tile', () => {
|
||||||
|
// Arrange
|
||||||
|
// See https://testing-library.com/docs/svelte-testing-library/example#contexts
|
||||||
|
const drawerStore = readable([]);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
render(SettingsSidebar, {
|
||||||
|
context: new Map([['drawerStore', drawerStore]])
|
||||||
|
});
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(screen.getByText(enMessages.settings.ssh_gpg_keys.label)).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have an appearance tile', () => {
|
||||||
|
// Arrange
|
||||||
|
// See https://testing-library.com/docs/svelte-testing-library/example#contexts
|
||||||
|
const drawerStore = readable([]);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
render(SettingsSidebar, {
|
||||||
|
context: new Map([['drawerStore', drawerStore]])
|
||||||
|
});
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(screen.getByText(enMessages.settings.appearance.label)).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have a notifications tile', () => {
|
||||||
|
// Arrange
|
||||||
|
// See https://testing-library.com/docs/svelte-testing-library/example#contexts
|
||||||
|
const drawerStore = readable([]);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
render(SettingsSidebar, {
|
||||||
|
context: new Map([['drawerStore', drawerStore]])
|
||||||
|
});
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(screen.getByText(enMessages.settings.notifications.label)).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in a new issue