import { Selector } from "@/components"; import { useModals, withModal } from "@/modules/modals"; import { BuildKey, useSelectorOptions } from "@/utilities"; import { ASSERT } from "@/utilities/console"; import { Button, Divider, Group, Text as MantineText, SimpleGrid, Stack, } from "@mantine/core"; import { useForm } from "@mantine/form"; import { capitalize } from "lodash"; import { FunctionComponent, forwardRef, useCallback, useMemo, useRef, useState, } from "react"; import { Card, Check, Chips, Selector as GlobalSelector, Message, Password, Text, } from "../components"; import { FormContext, FormValues, runHooks, useFormActions, useStagedValues, } from "../utilities/FormValues"; import { SettingsProvider, useSettings } from "../utilities/SettingsProvider"; import { useSettingValue } from "../utilities/hooks"; import { ProviderInfo, ProviderList } from "./list"; const ProviderKey = "settings-general-enabled_providers"; export const ProviderView: FunctionComponent = () => { const settings = useSettings(); const staged = useStagedValues(); const providers = useSettingValue(ProviderKey); const { update } = useFormActions(); const modals = useModals(); const select = useCallback( (v?: ProviderInfo) => { if (settings) { modals.openContextModal(ProviderModal, { payload: v ?? null, enabledProviders: providers ?? [], staged, settings, onChange: update, }); } }, [modals, providers, settings, staged, update] ); const cards = useMemo(() => { if (providers) { return providers .flatMap((v) => { const item = ProviderList.find((inn) => inn.key === v); if (item) { return item; } else { return []; } }) .map((v, idx) => ( select(v)} > )); } else { return []; } }, [providers, select]); return ( {cards} select()}> ); }; interface ProviderToolProps { payload: ProviderInfo | null; // TODO: Find a better solution to pass this info to modal enabledProviders: readonly string[]; staged: LooseObject; settings: Settings; onChange: (v: LooseObject) => void; } const SelectItem = forwardRef< HTMLDivElement, { payload: ProviderInfo; label: string } >(({ payload: { description }, label, ...other }, ref) => { return ( {label} {description} ); }); const ProviderTool: FunctionComponent = ({ payload, enabledProviders, staged, settings, onChange, }) => { const modals = useModals(); const onChangeRef = useRef(onChange); onChangeRef.current = onChange; const [info, setInfo] = useState>(payload); const form = useForm({ initialValues: { settings: staged, hooks: {}, }, }); const deletePayload = useCallback(() => { if (payload && enabledProviders) { const idx = enabledProviders.findIndex((v) => v === payload.key); if (idx !== -1) { const newProviders = [...enabledProviders]; newProviders.splice(idx, 1); onChangeRef.current({ [ProviderKey]: newProviders }); modals.closeAll(); } } }, [payload, enabledProviders, modals]); const submit = useCallback( (values: FormValues) => { if (info && enabledProviders) { const changes = { ...values.settings }; const hooks = values.hooks; // Add this provider if not exist if (enabledProviders.find((v) => v === info.key) === undefined) { const newProviders = [...enabledProviders, info.key]; changes[ProviderKey] = newProviders; } // Apply submit hooks runHooks(hooks, changes); onChangeRef.current(changes); modals.closeAll(); } }, [info, enabledProviders, modals] ); const canSave = info !== null; const onSelect = useCallback((item: Nullable) => { if (item) { setInfo(item); } else { setInfo({ key: "", description: "Unknown Provider", }); } }, []); const availableOptions = useMemo( () => ProviderList.filter( (v) => enabledProviders?.find((p) => p === v.key && p !== info?.key) === undefined ), [info?.key, enabledProviders] ); const options = useSelectorOptions( availableOptions, (v) => v.name ?? capitalize(v.key) ); const inputs = useMemo(() => { if (info === null || info.inputs === undefined) { return null; } const itemKey = info.key; const elements: JSX.Element[] = []; info.inputs?.forEach((value) => { const key = value.key; const label = value.name ?? capitalize(value.key); const options = value.options ?? []; switch (value.type) { case "text": elements.push( ); return; case "password": elements.push( ); return; case "switch": elements.push( ); return; case "select": elements.push( ); return; case "chips": elements.push( ); return; default: ASSERT(false, "Implement your new input here"); } }); return {elements}; }, [info]); return ( {info?.description} {inputs} ); }; const ProviderModal = withModal(ProviderTool, "provider-tool", { title: "Provider", });