import { Alert, Button, Group, Popover, Stack, Tabs, Text, ThemeIcon } from '@mantine/core'; import { useForm } from '@mantine/form'; import { useDisclosure } from '@mantine/hooks'; import { ContextModalProps } from '@mantine/modals'; import { IconAccessPoint, IconAdjustments, IconAlertTriangle, IconBrush, IconClick, IconPlug, } from '@tabler/icons-react'; import { useTranslation } from 'next-i18next'; import { useState } from 'react'; import { useConfigContext } from '../../../../config/provider'; import { useConfigStore } from '../../../../config/store'; import { AppType } from '../../../../types/app'; import { DebouncedImage } from '../../../IconSelector/DebouncedImage'; import { useEditModeStore } from '../../Views/useEditModeStore'; import { AppearanceTab } from './Tabs/AppereanceTab/AppereanceTab'; import { BehaviourTab } from './Tabs/BehaviourTab/BehaviourTab'; import { GeneralTab } from './Tabs/GeneralTab/GeneralTab'; import { IntegrationTab } from './Tabs/IntegrationTab/IntegrationTab'; import { NetworkTab } from './Tabs/NetworkTab/NetworkTab'; import { EditAppModalTab } from './Tabs/type'; const appUrlRegex = '(https?://(?:www.|(?!www))\\[?[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\\]?.[^\\s]{2,}|www.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9].[^\\s]{2,}|https?://(?:www.|(?!www))\\[?[a-zA-Z0-9]+\\]?.[^\\s]{2,}|www.[a-zA-Z0-9]+.[^\\s]{2,})'; export const EditAppModal = ({ context, id, innerProps, }: ContextModalProps<{ app: AppType; allowAppNamePropagation: boolean }>) => { const { t } = useTranslation(['layout/modals/add-app', 'common']); const { name: configName, config } = useConfigContext(); const updateConfig = useConfigStore((store) => store.updateConfig); const { enabled: isEditMode } = useEditModeStore(); const [allowAppNamePropagation, setAllowAppNamePropagation] = useState( innerProps.allowAppNamePropagation ); const form = useForm({ initialValues: innerProps.app, validate: { name: (name) => (!name ? 'Name is required' : null), url: (url) => { if (!url) { return 'Url is required'; } if (!url.match(appUrlRegex)) { return 'Value is not a valid url'; } return null; }, appearance: { iconUrl: (url: string) => { if (url.length < 1) { return 'This field is required'; } return null; }, }, behaviour: { externalUrl: (url: string) => { if (url === undefined || url.length < 1) { return null; } if (!url.match(appUrlRegex)) { return 'Uri override is not a valid uri'; } return null; }, }, }, validateInputOnChange: true, }); const onSubmit = (values: AppType) => { if (!configName) { return; } updateConfig( configName, (previousConfig) => ({ ...previousConfig, apps: [ ...previousConfig.apps.filter((x) => x.id !== values.id), { ...values, }, ], }), true, !isEditMode ); // also close the parent modal context.closeAll(); }; const [activeTab, setActiveTab] = useState('general'); const closeModal = () => { context.closeModal(id); }; const validationErrors = Object.keys(form.errors); const ValidationErrorIndicator = ({ keys }: { keys: string[] }) => { const relevantErrors = validationErrors.filter((x) => keys.includes(x)); return ( ); }; return ( <> {configName === undefined || (config === undefined && ( There was an unexpected problem loading the configuration. Functionality might be restricted. Please report this incident. ))} {form.values.name ?? 'New App'}
setActiveTab(tab as EditAppModalTab)} defaultValue="general" radius="md" > } icon={} value="general" > {t('tabs.general')} } icon={} value="behaviour" > {t('tabs.behaviour')} } icon={} value="network" > {t('tabs.network')} } icon={} value="appearance" > {t('tabs.appearance')} } icon={} value="integration" > {t('tabs.integration')} setActiveTab(targetTab)} /> setAllowAppNamePropagation(false)} allowAppNamePropagation={allowAppNamePropagation} />
); }; const SaveButton = ({ formIsValid }: { formIsValid: boolean }) => { const [opened, { close, open }] = useDisclosure(false); const { t } = useTranslation(['layout/modals/add-app', 'common']); return (
{t('validation.popover')}
); };