From 2c461a6695d16d2549e5a69b4198f88246733dd8 Mon Sep 17 00:00:00 2001 From: Aj - Thomas Date: Tue, 10 May 2022 20:33:11 +0200 Subject: [PATCH 01/12] Add a module enabler Add module enabler in settings. This loops over all the exported Modules in the components/modules folder and renders them. (Interpreted language magic/ metaclasses) --- components/Settings/ModuleEnabler.tsx | 43 +++++++++++++++++++++++++++ components/Settings/SettingsMenu.tsx | 2 ++ components/modules/calendar/index.ts | 1 + components/modules/date/index.ts | 1 + components/modules/index.ts | 2 ++ components/modules/moduleWrapper.tsx | 7 +++++ tools/types.ts | 1 + 7 files changed, 57 insertions(+) create mode 100644 components/Settings/ModuleEnabler.tsx create mode 100644 components/modules/calendar/index.ts create mode 100644 components/modules/date/index.ts create mode 100644 components/modules/index.ts diff --git a/components/Settings/ModuleEnabler.tsx b/components/Settings/ModuleEnabler.tsx new file mode 100644 index 000000000..fd08b5c80 --- /dev/null +++ b/components/Settings/ModuleEnabler.tsx @@ -0,0 +1,43 @@ +import { Group, Switch } from '@mantine/core'; +import * as Modules from '../modules'; +import { useConfig } from '../../tools/state'; + +export default function ModuleEnabler(props: any) { + const { config, setConfig } = useConfig(); + // Loop over each module with their title + const modules = Object.keys(Modules); + // Match the enabled modules with the modules array + let enabledModules = config.settings.enabledModules ?? []; + enabledModules = modules.filter((module) => enabledModules.includes(module)); + return ( + + {modules.map((module: string) => ( + { + if (e.currentTarget.checked) { + setConfig({ + ...config, + settings: { + ...config.settings, + enabledModules: [...enabledModules, module], + }, + }); + } else { + setConfig({ + ...config, + settings: { + ...config.settings, + enabledModules: enabledModules.filter((m) => m !== module), + }, + }); + } + }} + /> + ))} + + ); +} diff --git a/components/Settings/SettingsMenu.tsx b/components/Settings/SettingsMenu.tsx index 70b7c48cd..41ef8c9ef 100644 --- a/components/Settings/SettingsMenu.tsx +++ b/components/Settings/SettingsMenu.tsx @@ -14,6 +14,7 @@ import { Settings as SettingsIcon } from 'tabler-icons-react'; import { useConfig } from '../../tools/state'; import { ColorSchemeSwitch } from '../ColorSchemeToggle/ColorSchemeSwitch'; import SaveConfigComponent from '../Config/SaveConfig'; +import ModuleEnabler from './ModuleEnabler'; function SettingsMenu(props: any) { const { config, setConfig } = useConfig(); @@ -63,6 +64,7 @@ function SettingsMenu(props: any) { label="Enable search bar" /> + module.replace('Module', '')); + const isShown = enabledModulesTitles.includes(module.title); const theme = useMantineTheme(); return ( From d58465142c07ecc603f20103dd4b575869293db2 Mon Sep 17 00:00:00 2001 From: Aj - Thomas Date: Wed, 11 May 2022 08:55:38 +0200 Subject: [PATCH 08/12] Add regex matching for add shelf item Resolves not fetching when the users didn't put a / at the end of the service url --- components/AppShelf/AddAppShelfItem.tsx | 54 ++++++++++++++----------- 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/components/AppShelf/AddAppShelfItem.tsx b/components/AppShelf/AddAppShelfItem.tsx index d8e619a9d..e78eccb92 100644 --- a/components/AppShelf/AddAppShelfItem.tsx +++ b/components/AppShelf/AddAppShelfItem.tsx @@ -10,9 +10,9 @@ import { AspectRatio, Text, Card, + LoadingOverlay, } from '@mantine/core'; -import { useForm } from '@mantine/hooks'; -import { UseForm } from '@mantine/hooks/lib/use-form/use-form'; +import { useForm } from '@mantine/form'; import { motion } from 'framer-motion'; import { useState } from 'react'; import { Apps } from 'tabler-icons-react'; @@ -72,16 +72,7 @@ export default function AddItemShelfItem(props: any) { ); } -function MatchIcon( - name: string, - form: UseForm<{ - type: any; - name: any; - icon: any; - url: any; - apiKey: any; - }> -) { +function MatchIcon(name: string, form: any) { // TODO: In order to avoid all the requests, we could fetch // https://data.jsdelivr.com/v1/package/gh/IceWhaleTech/AppIcon@main // and then iterate over the files -> files -> name and then remove the extension (.png) @@ -102,6 +93,8 @@ function MatchIcon( export function AddAppShelfItemForm(props: { setOpened: (b: boolean) => void } & any) { const { setOpened } = props; const { addService, config, setConfig } = useConfig(); + const [isLoading, setLoading] = useState(false); + const form = useForm({ initialValues: { type: props.type ?? 'Other', @@ -110,6 +103,23 @@ export function AddAppShelfItemForm(props: { setOpened: (b: boolean) => void } & url: props.url ?? '', apiKey: props.apiKey ?? (undefined as unknown as string), }, + validate: { + apiKey: (value: string) => null, + // Validate icon with a regex + icon: (value: string) => { + if (!value.match(/^https?:\/\/.+\.(png|jpg|jpeg|gif)$/)) { + return 'Please enter a valid icon URL'; + } + return null; + }, + // Validate url with a regex http/https + url: (value: string) => { + if (!value.match(/^https?:\/\/.+\/$/)) { + return 'Please enter a valid URL (that ends with a /)'; + } + return null; + }, + }, }); return ( @@ -152,44 +162,40 @@ export function AddAppShelfItemForm(props: { setOpened: (b: boolean) => void } & form.setFieldValue('icon', match); } }} - error={form.errors.name && 'Invalid name'} + error={form.errors.name && 'Invalid icon url'} /> { - form.setFieldValue('icon', event.currentTarget.value); - }} - error={form.errors.icon && 'Icon url is invalid'} + {...form.getInputProps('icon')} /> form.setFieldValue('url', event.currentTarget.value)} - error={form.errors.url && 'Service url is invalid'} + {...form.getInputProps('url')} />