import { Alert, Button, createStyles, Group, Stack, Tabs, Text, ThemeIcon } from '@mantine/core'; import { useForm } from '@mantine/form'; import { ContextModalProps } from '@mantine/modals'; import { hideNotification, showNotification } from '@mantine/notifications'; import { IconAccessPoint, IconAdjustments, IconAlertTriangle, IconBrush, IconClick, IconPlug, } from '@tabler/icons'; import { useTranslation } from 'next-i18next'; import Image from 'next/image'; import { useState } from 'react'; import { useConfigContext } from '../../../../config/provider'; import { useConfigStore } from '../../../../config/store'; import { ServiceType } from '../../../../types/service'; 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 { DebouncedServiceIcon } from './Tabs/Shared/DebouncedServiceIcon'; import { EditServiceModalTab } from './Tabs/type'; const serviceUrlRegex = '(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 EditServiceModal = ({ context, id, innerProps, }: ContextModalProps<{ service: ServiceType }>) => { const { t } = useTranslation(); const { classes } = useStyles(); const { name: configName, config } = useConfigContext(); const updateConfig = useConfigStore((store) => store.updateConfig); const form = useForm({ initialValues: innerProps.service, validate: { name: (name) => (!name ? 'Name is required' : null), url: (url) => { if (!url) { return 'Url is required'; } if (!url.match(serviceUrlRegex)) { 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: { onClickUrl: (url: string) => { if (url === undefined || url.length < 1) { return null; } if (!url.match(serviceUrlRegex)) { return 'Uri override is not a valid uri'; } return null; }, }, }, validateInputOnChange: true, }); const onSubmit = (values: ServiceType) => { if (!configName) { return; } updateConfig(configName, (previousConfig) => ({ ...previousConfig, services: [...previousConfig.services.filter((x) => x.id !== form.values.id), form.values], })); // also close the parent modal context.closeAll(); }; const [activeTab, setActiveTab] = useState('general'); const tryCloseModal = () => { if (form.isDirty()) { showNotification({ id: 'unsaved-edit-service-modal-changes', title: 'You have unsaved changes', message: ( If you close, your changes will be discarded and not saved. ), }); return; } 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 Service'}
setActiveTab(tab as EditServiceModalTab)} defaultValue="general" > } icon={} value="general" > General } icon={} value="behaviour" > Behaviour } icon={} value="network" > Network } icon={} value="appearance" > Appearance } icon={} value="integration" > Integration setActiveTab(targetTab)} />
); }; const useStyles = createStyles(() => ({ serviceImage: { objectFit: 'contain', }, }));