✨ Add preferences to preferences page
This commit is contained in:
@@ -66,6 +66,7 @@
|
|||||||
"dayjs": "^1.11.7",
|
"dayjs": "^1.11.7",
|
||||||
"dockerode": "^3.3.2",
|
"dockerode": "^3.3.2",
|
||||||
"fily-publish-gridstack": "^0.0.13",
|
"fily-publish-gridstack": "^0.0.13",
|
||||||
|
"flag-icons": "^6.9.2",
|
||||||
"framer-motion": "^10.0.0",
|
"framer-motion": "^10.0.0",
|
||||||
"html-entities": "^2.3.3",
|
"html-entities": "^2.3.3",
|
||||||
"i18next": "^22.5.1",
|
"i18next": "^22.5.1",
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import {
|
|||||||
getServiceSidePackageAttributes,
|
getServiceSidePackageAttributes,
|
||||||
} from '../tools/server/getPackageVersion';
|
} from '../tools/server/getPackageVersion';
|
||||||
import { theme } from '../tools/server/theme/theme';
|
import { theme } from '../tools/server/theme/theme';
|
||||||
|
import "/node_modules/flag-icons/css/flag-icons.min.css";
|
||||||
|
|
||||||
function App(
|
function App(
|
||||||
this: any,
|
this: any,
|
||||||
|
|||||||
@@ -1,16 +1,84 @@
|
|||||||
import { Title } from '@mantine/core';
|
import { Group, Select, Stack, Text, Title } from '@mantine/core';
|
||||||
import Head from 'next/head';
|
import Head from 'next/head';
|
||||||
|
import { forwardRef } from 'react';
|
||||||
|
import { AccessibilitySettings } from '~/components/Settings/Customization/Accessibility/AccessibilitySettings';
|
||||||
import { MainLayout } from '~/components/layout/admin/main-admin.layout';
|
import { MainLayout } from '~/components/layout/admin/main-admin.layout';
|
||||||
|
import { languages } from '~/tools/language';
|
||||||
|
|
||||||
const PreferencesPage = () => {
|
const PreferencesPage = () => {
|
||||||
|
const data = languages.map((language) => ({
|
||||||
|
image: 'https://img.icons8.com/clouds/256/000000/futurama-bender.png',
|
||||||
|
label: language.originalName,
|
||||||
|
description: language.translatedName,
|
||||||
|
value: language.shortName,
|
||||||
|
country: language.country,
|
||||||
|
}));
|
||||||
return (
|
return (
|
||||||
<MainLayout>
|
<MainLayout>
|
||||||
<Head>
|
<Head>
|
||||||
<title>Preferences • Homarr</title>
|
<title>Preferences • Homarr</title>
|
||||||
</Head>
|
</Head>
|
||||||
<Title>Preferences</Title>
|
<Title mb="xl">Preferences</Title>
|
||||||
|
|
||||||
|
<Stack spacing={5}>
|
||||||
|
<Title order={2} size="lg">
|
||||||
|
Localization
|
||||||
|
</Title>
|
||||||
|
|
||||||
|
<Select
|
||||||
|
label="Language"
|
||||||
|
itemComponent={SelectItem}
|
||||||
|
data={data}
|
||||||
|
searchable
|
||||||
|
maxDropdownHeight={400}
|
||||||
|
filter={(value, item) =>
|
||||||
|
item.label.toLowerCase().includes(value.toLowerCase().trim()) ||
|
||||||
|
item.description.toLowerCase().includes(value.toLowerCase().trim())
|
||||||
|
}
|
||||||
|
withAsterisk
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Select
|
||||||
|
label="First day of the week"
|
||||||
|
data={[
|
||||||
|
{ value: 'monday', label: 'Monday' },
|
||||||
|
{ value: 'sunday', label: 'Sunday' },
|
||||||
|
{ value: 'saturday', label: 'Saturday' },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Title order={2} size="lg" mt="lg" mb="md">
|
||||||
|
Accessibility
|
||||||
|
</Title>
|
||||||
|
|
||||||
|
<AccessibilitySettings />
|
||||||
|
</Stack>
|
||||||
</MainLayout>
|
</MainLayout>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
interface ItemProps extends React.ComponentPropsWithoutRef<'div'> {
|
||||||
|
image: string;
|
||||||
|
label: string;
|
||||||
|
description: string;
|
||||||
|
country: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SelectItem = forwardRef<HTMLDivElement, ItemProps>(
|
||||||
|
({ image, label, description, country, ...others }: ItemProps, ref) => (
|
||||||
|
<div ref={ref} {...others}>
|
||||||
|
<Group noWrap>
|
||||||
|
<span className={`fi fi-${country?.toLowerCase()}`}></span>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<Text size="sm">{label}</Text>
|
||||||
|
<Text size="xs" opacity={0.65}>
|
||||||
|
{description}
|
||||||
|
</Text>
|
||||||
|
</div>
|
||||||
|
</Group>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
export default PreferencesPage;
|
export default PreferencesPage;
|
||||||
|
|||||||
@@ -4,11 +4,18 @@ export class Language {
|
|||||||
translatedName: string;
|
translatedName: string;
|
||||||
emoji: string;
|
emoji: string;
|
||||||
|
|
||||||
constructor(shortName: string, originalName: string, translatedName: string, emoji: string) {
|
/**
|
||||||
|
* The country identified b<y the ISO-3166 alpha 2 code:
|
||||||
|
* https://www.iso.org/obp/ui/#search
|
||||||
|
*/
|
||||||
|
country?: string;
|
||||||
|
|
||||||
|
constructor(shortName: string, originalName: string, translatedName: string, emoji: string, country: string) {
|
||||||
this.shortName = shortName;
|
this.shortName = shortName;
|
||||||
this.originalName = originalName;
|
this.originalName = originalName;
|
||||||
this.translatedName = translatedName;
|
this.translatedName = translatedName;
|
||||||
this.emoji = emoji;
|
this.emoji = emoji;
|
||||||
|
this.country = country;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -18,12 +25,14 @@ export const languages: Language[] = [
|
|||||||
originalName: 'Deutsch',
|
originalName: 'Deutsch',
|
||||||
translatedName: 'German',
|
translatedName: 'German',
|
||||||
emoji: '🇩🇪',
|
emoji: '🇩🇪',
|
||||||
|
country: 'DE'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
shortName: 'en',
|
shortName: 'en',
|
||||||
originalName: 'English',
|
originalName: 'English',
|
||||||
translatedName: 'English',
|
translatedName: 'English',
|
||||||
emoji: '🇬🇧',
|
emoji: '🇬🇧',
|
||||||
|
country: 'GB'
|
||||||
},
|
},
|
||||||
// Danish
|
// Danish
|
||||||
{
|
{
|
||||||
@@ -31,6 +40,7 @@ export const languages: Language[] = [
|
|||||||
originalName: 'Dansk',
|
originalName: 'Dansk',
|
||||||
translatedName: 'Danish',
|
translatedName: 'Danish',
|
||||||
emoji: '🇩🇰',
|
emoji: '🇩🇰',
|
||||||
|
country: 'DK'
|
||||||
},
|
},
|
||||||
// Hebrew
|
// Hebrew
|
||||||
{
|
{
|
||||||
@@ -38,36 +48,42 @@ export const languages: Language[] = [
|
|||||||
originalName: 'עברית',
|
originalName: 'עברית',
|
||||||
translatedName: 'Hebrew',
|
translatedName: 'Hebrew',
|
||||||
emoji: '🇮🇱',
|
emoji: '🇮🇱',
|
||||||
|
country: 'IL'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
shortName: 'es',
|
shortName: 'es',
|
||||||
originalName: 'Español',
|
originalName: 'Español',
|
||||||
translatedName: 'Spanish',
|
translatedName: 'Spanish',
|
||||||
emoji: '🇪🇸',
|
emoji: '🇪🇸',
|
||||||
|
country: 'ES'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
shortName: 'fr',
|
shortName: 'fr',
|
||||||
originalName: 'Français',
|
originalName: 'Français',
|
||||||
translatedName: 'French',
|
translatedName: 'French',
|
||||||
emoji: '🇫🇷',
|
emoji: '🇫🇷',
|
||||||
|
country: 'FR'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
shortName: 'it',
|
shortName: 'it',
|
||||||
originalName: 'Italiano',
|
originalName: 'Italiano',
|
||||||
translatedName: 'Italian',
|
translatedName: 'Italian',
|
||||||
emoji: '🇮🇹',
|
emoji: '🇮🇹',
|
||||||
|
country: 'IT'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
shortName: 'ja',
|
shortName: 'ja',
|
||||||
originalName: '日本語',
|
originalName: '日本語',
|
||||||
translatedName: 'Japanese',
|
translatedName: 'Japanese',
|
||||||
emoji: '🇯🇵',
|
emoji: '🇯🇵',
|
||||||
|
country: 'JP'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
shortName: 'ko',
|
shortName: 'ko',
|
||||||
originalName: '한국어',
|
originalName: '한국어',
|
||||||
translatedName: 'Korean',
|
translatedName: 'Korean',
|
||||||
emoji: '🇰🇷',
|
emoji: '🇰🇷',
|
||||||
|
country: 'KR'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
shortName: 'lol',
|
shortName: 'lol',
|
||||||
@@ -81,6 +97,7 @@ export const languages: Language[] = [
|
|||||||
originalName: 'Norsk',
|
originalName: 'Norsk',
|
||||||
translatedName: 'Norwegian',
|
translatedName: 'Norwegian',
|
||||||
emoji: '🇳🇴',
|
emoji: '🇳🇴',
|
||||||
|
country: 'NO'
|
||||||
},
|
},
|
||||||
// Slovak
|
// Slovak
|
||||||
{
|
{
|
||||||
@@ -88,36 +105,42 @@ export const languages: Language[] = [
|
|||||||
originalName: 'Slovenčina',
|
originalName: 'Slovenčina',
|
||||||
translatedName: 'Slovak',
|
translatedName: 'Slovak',
|
||||||
emoji: '🇸🇰',
|
emoji: '🇸🇰',
|
||||||
|
country: 'SK'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
shortName: 'nl',
|
shortName: 'nl',
|
||||||
originalName: 'Nederlands',
|
originalName: 'Nederlands',
|
||||||
translatedName: 'Dutch',
|
translatedName: 'Dutch',
|
||||||
emoji: '🇳🇱',
|
emoji: '🇳🇱',
|
||||||
|
country: 'NL'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
shortName: 'pl',
|
shortName: 'pl',
|
||||||
originalName: 'Polski',
|
originalName: 'Polski',
|
||||||
translatedName: 'Polish',
|
translatedName: 'Polish',
|
||||||
emoji: '🇵🇱',
|
emoji: '🇵🇱',
|
||||||
|
country: 'PL'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
shortName: 'pt',
|
shortName: 'pt',
|
||||||
originalName: 'Português',
|
originalName: 'Português',
|
||||||
translatedName: 'Portuguese',
|
translatedName: 'Portuguese',
|
||||||
emoji: '🇵🇹',
|
emoji: '🇵🇹',
|
||||||
|
country: 'PT'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
shortName: 'ru',
|
shortName: 'ru',
|
||||||
originalName: 'Русский',
|
originalName: 'Русский',
|
||||||
translatedName: 'Russian',
|
translatedName: 'Russian',
|
||||||
emoji: '🇷🇺',
|
emoji: '🇷🇺',
|
||||||
|
country: 'RU'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
shortName: 'sl',
|
shortName: 'sl',
|
||||||
originalName: 'Slovenščina',
|
originalName: 'Slovenščina',
|
||||||
translatedName: 'Slovenian',
|
translatedName: 'Slovenian',
|
||||||
emoji: '🇸🇮',
|
emoji: '🇸🇮',
|
||||||
|
country: 'SI'
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -125,12 +148,14 @@ export const languages: Language[] = [
|
|||||||
originalName: 'Svenska',
|
originalName: 'Svenska',
|
||||||
translatedName: 'Swedish',
|
translatedName: 'Swedish',
|
||||||
emoji: '🇸🇪',
|
emoji: '🇸🇪',
|
||||||
|
country: 'SE'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
shortName: 'uk',
|
shortName: 'uk',
|
||||||
originalName: 'Українська',
|
originalName: 'Українська',
|
||||||
translatedName: 'Ukrainian',
|
translatedName: 'Ukrainian',
|
||||||
emoji: '🇺🇦',
|
emoji: '🇺🇦',
|
||||||
|
country: 'UA'
|
||||||
},
|
},
|
||||||
// Vietnamese
|
// Vietnamese
|
||||||
{
|
{
|
||||||
@@ -138,30 +163,35 @@ export const languages: Language[] = [
|
|||||||
originalName: 'Tiếng Việt',
|
originalName: 'Tiếng Việt',
|
||||||
translatedName: 'Vietnamese',
|
translatedName: 'Vietnamese',
|
||||||
emoji: '🇻🇳',
|
emoji: '🇻🇳',
|
||||||
|
country: 'VN'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
shortName: 'zh',
|
shortName: 'zh',
|
||||||
originalName: '中文',
|
originalName: '中文',
|
||||||
translatedName: 'Chinese',
|
translatedName: 'Chinese',
|
||||||
emoji: '🇨🇳',
|
emoji: '🇨🇳',
|
||||||
|
country: 'CN'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
shortName: 'el',
|
shortName: 'el',
|
||||||
originalName: 'Ελληνικά',
|
originalName: 'Ελληνικά',
|
||||||
translatedName: 'Greek',
|
translatedName: 'Greek',
|
||||||
emoji: '🇬🇷',
|
emoji: '🇬🇷',
|
||||||
|
country: 'GR'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
shortName: 'tr',
|
shortName: 'tr',
|
||||||
originalName: 'Türkçe',
|
originalName: 'Türkçe',
|
||||||
translatedName: 'Turkish',
|
translatedName: 'Turkish',
|
||||||
emoji: '🇹🇷',
|
emoji: '🇹🇷',
|
||||||
|
country: 'TR'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
shortName: 'lv',
|
shortName: 'lv',
|
||||||
originalName: 'Latvian',
|
originalName: 'Latvian',
|
||||||
translatedName: 'Latvian',
|
translatedName: 'Latvian',
|
||||||
emoji: '🇱🇻',
|
emoji: '🇱🇻',
|
||||||
|
country: 'LV'
|
||||||
},
|
},
|
||||||
// Croatian
|
// Croatian
|
||||||
{
|
{
|
||||||
@@ -169,6 +199,7 @@ export const languages: Language[] = [
|
|||||||
originalName: 'Hrvatski',
|
originalName: 'Hrvatski',
|
||||||
translatedName: 'Croatian',
|
translatedName: 'Croatian',
|
||||||
emoji: '🇭🇷',
|
emoji: '🇭🇷',
|
||||||
|
country: 'HR'
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -5217,6 +5217,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"flag-icons@npm:^6.9.2":
|
||||||
|
version: 6.9.2
|
||||||
|
resolution: "flag-icons@npm:6.9.2"
|
||||||
|
checksum: ba2754c65ae4a943ac7042be9ec039243bd5fc2d6cec59228c46549ccadf20f272b22a1d1e8940a830b86b0d2fda1e53f8dd3866937a40c7d90b8fae789b122d
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"flat-cache@npm:^3.0.4":
|
"flat-cache@npm:^3.0.4":
|
||||||
version: 3.0.4
|
version: 3.0.4
|
||||||
resolution: "flat-cache@npm:3.0.4"
|
resolution: "flat-cache@npm:3.0.4"
|
||||||
@@ -5882,6 +5889,7 @@ __metadata:
|
|||||||
eslint-plugin-unused-imports: ^3.0.0
|
eslint-plugin-unused-imports: ^3.0.0
|
||||||
eslint-plugin-vitest: ^0.2.0
|
eslint-plugin-vitest: ^0.2.0
|
||||||
fily-publish-gridstack: ^0.0.13
|
fily-publish-gridstack: ^0.0.13
|
||||||
|
flag-icons: ^6.9.2
|
||||||
framer-motion: ^10.0.0
|
framer-motion: ^10.0.0
|
||||||
happy-dom: ^10.0.0
|
happy-dom: ^10.0.0
|
||||||
html-entities: ^2.3.3
|
html-entities: ^2.3.3
|
||||||
|
|||||||
Reference in New Issue
Block a user