import { Alert, Button, Card, Flex, Group, MultiSelect, NumberInput, Select, Slider, Stack, Switch, Text, TextInput, Title, } from '@mantine/core'; import { ContextModalProps } from '@mantine/modals'; import { IconAlertTriangle, IconPlaylistX, IconPlus } from '@tabler/icons-react'; import { Trans, useTranslation } from 'next-i18next'; import { FC, useState } from 'react'; import { useConfigContext } from '~/config/provider'; import { useConfigStore } from '~/config/store'; import { mapObject } from '~/tools/client/objects'; import type { IDraggableListInputValue, IWidgetOptionValue } from '~/widgets/widgets'; import { IWidget } from '~/widgets/widgets'; import Widgets from '../../../../widgets'; import { InfoCard } from '../../../InfoCard/InfoCard'; import { DraggableList } from './Inputs/DraggableList'; import { LocationSelection } from './Inputs/LocationSelection'; import { StaticDraggableList } from './Inputs/StaticDraggableList'; export type WidgetEditModalInnerProps = { widgetId: string; widgetType: string; options: IWidget['properties']; widgetOptions: IWidget['properties']; }; export type IntegrationOptionsValueType = IWidget['properties'][string]; export const WidgetsEditModal = ({ context, id, innerProps, }: ContextModalProps) => { const { t } = useTranslation([`modules/${innerProps.widgetType}`, 'common']); const [moduleProperties, setModuleProperties] = useState(innerProps.options); const items = Object.entries(innerProps.widgetOptions ?? {}) as [ string, IntegrationOptionsValueType, ][]; // Find the Key in the "Widgets" Object that matches the widgetId const currentWidgetDefinition = Widgets[innerProps.widgetType as keyof typeof Widgets]; const { name: configName } = useConfigContext(); const updateConfig = useConfigStore((x) => x.updateConfig); if (!configName || !innerProps.options) return null; const handleChange = (key: string, value: IntegrationOptionsValueType) => { setModuleProperties((prev) => { const copyOfPrev: any = { ...prev }; copyOfPrev[key] = value; return copyOfPrev; }); }; const handleSave = () => { updateConfig( configName, (prev) => { const currentWidget = prev.widgets.find((x) => x.id === innerProps.widgetId); currentWidget!.properties = moduleProperties; return { ...prev, widgets: [...prev.widgets.filter((x) => x.id !== innerProps.widgetId), currentWidget!], }; }, true ); context.closeModal(id); }; return ( {items.map(([key, _], index) => { const option = (currentWidgetDefinition as any).options[key] as IWidgetOptionValue; const value = moduleProperties[key] ?? option.defaultValue; if (!option) { return ( } color="red"> , code: }} /> ); } return ( ); })} ); }; // Widget switch // Widget options are computed based on their type. // here you can define new types for options (along with editing the widgets.d.ts file) const WidgetOptionTypeSwitch: FC<{ option: IWidgetOptionValue; widgetId: string; propName: string; value: any; handleChange: (key: string, value: IntegrationOptionsValueType) => void; }> = ({ option, widgetId, propName: key, value, handleChange }) => { const { t } = useTranslation([`modules/${widgetId}`, 'common']); const info = option.info ?? false; const link = option.infoLink ?? undefined; if (option.hide) return null; switch (option.type) { case 'switch': return ( handleChange(key, ev.currentTarget.checked)} {...option.inputProps} /> {info && } ); case 'text': return ( {t(`descriptor.settings.${key}.label`)} {info && } handleChange(key, ev.currentTarget.value)} {...option.inputProps} /> ); case 'multi-select': return ( {t(`descriptor.settings.${key}.label`)} {info && } handleChange(key, v)} withinPortal {...option.inputProps} /> ); case 'select': const items = typeof option.data === 'function' ? option.data() : option.data; const data = items.map((dataType) => { return !dataType.label ? { value: dataType.value, label: t(`descriptor.settings.${key}.data.${dataType.value}`), } : dataType; }); return ( {t(`descriptor.settings.${key}.label`)} {info && }