import { useCallback } from 'react' import { Field, Form, Formik } from 'formik' import { inferQueryOutput, inferMutationInput, trpc } from '~/utils/trpc' import IVInputField from '~/components/IVInputField' import IVTextInput from '~/components/IVTextInput' import IVTextArea from '~/components/IVTextArea' import { slugToName } from '~/utils/text' import IVButton from '~/components/IVButton' import IconInfo from '~/icons/compiled/Info' import IVCheckbox from '~/components/IVCheckbox' import { useDialogState } from '~/components/IVDialog' import ArchiveDialog from '~/components/ActionSettings/ArchiveDialog' import IVAlert from '~/components/IVAlert' import { useIsFeatureEnabled } from '~/utils/useIsFeatureEnabled' function OverrideMetaTextField({ id, label, helpText, errorMessage, metaValue, actionValue, defaultValue = '', placeholder, disabled, onChange, multiline = false, }: { id: string label: string errorMessage?: React.ReactNode helpText?: string metaValue: string | null | undefined actionValue: string | null | undefined defaultValue?: string placeholder?: string disabled?: boolean onChange: (value: string | null) => void multiline?: boolean }) { const isOverriding = metaValue != null const InputComponent = multiline ? IVTextArea : IVTextInput return ( <> ) => { if (disabled) return onChange(e.target.value) }} readOnly={!!actionValue && !isOverriding} disabled={disabled || (!!actionValue && !isOverriding)} placeholder={placeholder} /> {!disabled && actionValue != null && ( { onChange(isOverriding ? null : actionValue ?? defaultValue) }} /> )} ) } function OverrideMetaToggleField({ id, label, helpText, metaValue, actionValue, defaultValue, disabled, onChange, }: { id: string label: string helpText?: string metaValue: boolean | null | undefined actionValue: boolean | null | undefined defaultValue: false disabled?: boolean onChange: (value: boolean | null) => void }) { const isOverriding = metaValue != null return (
{ if (disabled) return onChange(e.target.checked) }} disabled={disabled || !isOverriding} /> {!disabled && actionValue != null && ( { onChange(isOverriding ? null : actionValue ?? defaultValue) }} /> )}
) } function OverrideNotice({ label, buttonLabel, onClick }) { return (

{label}

) } export default function ActionGeneralSettings({ action, onSuccess, onError, refetch, }: { action: inferQueryOutput<'action.one'> onSuccess: () => void onError: () => void refetch: () => void }) { const archiveDialog = useDialogState() const updateMeta = trpc.useMutation('action.general.update') const generalConfigEnabled = useIsFeatureEnabled( 'ACTION_METADATA_GENERAL_CONFIG' ) const validateName = useCallback( (name: string | undefined | null) => { name = name?.trim() if (action.name && !name) return if (!name) { return 'Please enter a name.' } }, [action] ) const isArchived = action.metadata?.archivedAt return (
{isArchived && (

This action has been archived.{` `} {' '} to restore it to your Actions list.

)} {!generalConfigEnabled && (

Actions are configured in code. See{' '} defining actions documentation {' '} for more information.

)} ['data']> initialTouched={{ name: true, }} initialValues={{ name: action.metadata?.name ?? (action.name ? undefined : slugToName(action.slug)), backgroundable: action.metadata?.backgroundable, description: action.metadata?.description, }} validateOnBlur={false} validateOnChange={false} validate={({ name }) => { const nameValidation = validateName(name) if (nameValidation) { return { name: nameValidation, } } }} onSubmit={async data => { if (updateMeta.isLoading || !generalConfigEnabled) return if ( action.schedules.length && (data.backgroundable === false || (!action.backgroundable && !data.backgroundable)) ) { if ( !window.confirm( "Turning off 'Allow running in background' will remove this action's schedule. Are you sure you want to turn off this setting?" ) ) { return } } updateMeta.mutate( { actionId: action.id, data }, { onSuccess, onError } ) }} > {({ errors, touched, isValid, values, setFieldValue }) => (
{ setFieldValue('name', val) }} /> { setFieldValue('description', val) }} multiline />
{ setFieldValue('backgroundable', val) }} />
{generalConfigEnabled ? ( ) : ( /* Just to make the flex still work */
)} {!isArchived && (
)}
{updateMeta.isError && (
Sorry, there was a problem updating the action.
)} )}
) }