From 4197de2b2e95a933da7d34eeb4897519e72af1e3 Mon Sep 17 00:00:00 2001 From: Elio Struyf Date: Fri, 28 Jun 2024 17:42:19 +0200 Subject: [PATCH] #824 - Added support in single image field --- package.json | 22 ++-- package.nls.json | 1 + src/models/PanelSettings.ts | 2 +- .../components/Fields/FieldCustomAction.tsx | 103 ++++++++++++------ .../components/Fields/FieldTitle.tsx | 12 +- .../components/Fields/PreviewImageField.tsx | 14 ++- .../components/Fields/TagPicker.tsx | 6 +- .../components/Fields/TextField.tsx | 8 +- .../components/Fields/WrapperField.tsx | 5 +- 9 files changed, 113 insertions(+), 60 deletions(-) diff --git a/package.json b/package.json index fcd7a316..fe21bdd6 100644 --- a/package.json +++ b/package.json @@ -1550,8 +1550,12 @@ } } }, - "action": { - "$ref": "#customscript" + "actions": { + "type": "array", + "description": "%setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.actions.description%", + "items": { + "$ref": "#customscript" + } } }, "additionalProperties": false, @@ -2659,23 +2663,23 @@ "group": "navigation@0", "when": "view == frontMatter.explorer" }, - { - "command": "frontMatter.collapseSections", - "group": "navigation@1", - "when": "view == frontMatter.explorer" - }, { "command": "frontMatter.mode.switch", - "group": "navigation@2", + "group": "navigation@1", "when": "view == frontMatter.explorer && frontMatter:has:modes == true" }, { "command": "frontMatter.project.switch", - "group": "navigation@3", + "group": "navigation@2", "when": "view == frontMatter.explorer && frontMatter:project:switch:enabled" }, { "command": "frontMatter.settings.refresh", + "group": "navigation@3", + "when": "view == frontMatter.explorer" + }, + { + "command": "frontMatter.collapseSections", "group": "navigation@4", "when": "view == frontMatter.explorer" }, diff --git a/package.nls.json b/package.nls.json index f3a9a0ce..d7f7f44b 100644 --- a/package.nls.json +++ b/package.nls.json @@ -231,6 +231,7 @@ "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.when.properties.operator.description": "The operator to use", "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.when.properties.value.description": "The value to compare", "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.when.properties.caseSensitive.description": "Specify if the comparison is case sensitive. Default: true", + "setting.frontMatter.taxonomy.contentTypes.items.properties.fields.items.properties.actions.description": "Specify the field custom actions", "setting.frontMatter.taxonomy.contentTypes.items.properties.pageBundle.description": "Specify if you want to create a folder when creating new content.", "setting.frontMatter.taxonomy.contentTypes.items.properties.previewPath.description": "Defines a custom preview path for the content type.", "setting.frontMatter.taxonomy.contentTypes.items.properties.trailingSlash.description": "Specify if you want to add a trailing slash to the preview URL.", diff --git a/src/models/PanelSettings.ts b/src/models/PanelSettings.ts index b13b517e..12fe7bdf 100644 --- a/src/models/PanelSettings.ts +++ b/src/models/PanelSettings.ts @@ -143,7 +143,7 @@ export interface Field { when?: WhenClause; // Custom action - action?: CustomScript; + actions?: CustomScript[]; } export interface NumberOptions { diff --git a/src/panelWebView/components/Fields/FieldCustomAction.tsx b/src/panelWebView/components/Fields/FieldCustomAction.tsx index 11967380..4c641d33 100644 --- a/src/panelWebView/components/Fields/FieldCustomAction.tsx +++ b/src/panelWebView/components/Fields/FieldCustomAction.tsx @@ -1,48 +1,85 @@ import * as React from 'react'; import { CustomScript } from '../../../models'; import { messageHandler } from '@estruyf/vscode/dist/client'; -import { CodeBracketIcon } from '@heroicons/react/24/outline'; +import { CodeBracketIcon, CommandLineIcon } from '@heroicons/react/24/solid'; import { CommandToCode } from '../../CommandToCode'; import { LocalizationKey, localize } from '../../../localization'; +import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '../../../components/shadcn/Dropdown'; export interface IFieldCustomActionProps { - action: CustomScript; + actions: CustomScript[]; disabled?: boolean; triggerLoading?: (message?: string) => void; onChange: (value: any) => void; } -export const FieldCustomAction: React.FunctionComponent = ({ action, disabled, triggerLoading, onChange }: React.PropsWithChildren) => { +export const FieldCustomAction: React.FunctionComponent = ({ actions, disabled, triggerLoading, onChange }: React.PropsWithChildren) => { + + const triggerAction = React.useCallback((action: CustomScript) => { + if (triggerLoading) { + triggerLoading(localize(LocalizationKey.panelFieldsFieldCustomActionExecuting)); + } + + messageHandler.request(CommandToCode.runFieldAction, { + ...action + }).then((value: any) => { + onChange(value); + + if (triggerLoading) { + triggerLoading(); + } + }).catch(() => { + console.error('Error while running the custom action'); + + if (triggerLoading) { + triggerLoading(); + } + }); + }, [triggerLoading, onChange]); + + if (!actions) { + return null; + } + + if (actions.length === 1) { + const action = actions[0]; + return ( + + ); + } + return ( - - ); + + { + actions.map((action) => ( + triggerAction(action)}> + + {action.title} + + )) + } + + + ) }; \ No newline at end of file diff --git a/src/panelWebView/components/Fields/FieldTitle.tsx b/src/panelWebView/components/Fields/FieldTitle.tsx index 06fc2925..80999e50 100644 --- a/src/panelWebView/components/Fields/FieldTitle.tsx +++ b/src/panelWebView/components/Fields/FieldTitle.tsx @@ -10,7 +10,7 @@ export interface IFieldTitleProps { className?: string; required?: boolean; actionElement?: JSX.Element; - customAction?: CustomScript; + customActions?: CustomScript[]; isDisabled?: boolean; triggerLoading?: (message?: string) => void; onChange?: (value: any) => void; @@ -22,7 +22,7 @@ export const FieldTitle: React.FunctionComponent = ({ className, required, actionElement, - customAction, + customActions, isDisabled, triggerLoading, onChange, @@ -40,17 +40,17 @@ export const FieldTitle: React.FunctionComponent = ({
+ {actionElement} + { - customAction && onChange && ( + customActions && onChange && ( ) } - - {actionElement}
); diff --git a/src/panelWebView/components/Fields/PreviewImageField.tsx b/src/panelWebView/components/Fields/PreviewImageField.tsx index 555f3105..18a07569 100644 --- a/src/panelWebView/components/Fields/PreviewImageField.tsx +++ b/src/panelWebView/components/Fields/PreviewImageField.tsx @@ -3,7 +3,7 @@ import { PhotoIcon } from '@heroicons/react/24/outline'; import * as React from 'react'; import { useCallback, useEffect, useMemo } from 'react'; import { DefaultFieldValues } from '../../../constants'; -import { BaseFieldProps, BlockFieldData } from '../../../models'; +import { BaseFieldProps, BlockFieldData, CustomScript } from '../../../models'; import { CommandToCode } from '../../CommandToCode'; import { FieldTitle } from './FieldTitle'; import { PreviewImage } from './PreviewImage'; @@ -23,6 +23,7 @@ export interface IPreviewImageFieldProps parents?: string[]; multiple?: boolean; blockData?: BlockFieldData; + actions?: CustomScript[]; onChange: (value: string | string[] | null) => void; } @@ -36,8 +37,10 @@ export const PreviewImageField: React.FunctionComponent filePath, multiple, parents, + actions, required }: React.PropsWithChildren) => { + const [loading, setLoading] = React.useState(undefined); const [imageData, setImageData] = React.useState(null); const selectImage = useCallback(() => { @@ -95,7 +98,14 @@ export const PreviewImageField: React.FunctionComponent return (
- } required={required} /> + } + required={required} + isDisabled={!!loading} + customActions={actions} + triggerLoading={(message) => setLoading(message)} + onChange={(value: string) => onChange(value)} />
0 diff --git a/src/panelWebView/components/Fields/TagPicker.tsx b/src/panelWebView/components/Fields/TagPicker.tsx index df56ac18..bfa7a43e 100644 --- a/src/panelWebView/components/Fields/TagPicker.tsx +++ b/src/panelWebView/components/Fields/TagPicker.tsx @@ -36,7 +36,7 @@ export interface ITagPickerProps { limit?: number; required?: boolean; renderAsString?: boolean; - action?: CustomScript; + actions?: CustomScript[]; } const TagPicker: React.FunctionComponent = ({ @@ -57,7 +57,7 @@ const TagPicker: React.FunctionComponent = ({ limit, required, renderAsString, - action + actions }: React.PropsWithChildren) => { const [selected, setSelected] = React.useState([]); const [inputValue, setInputValue] = React.useState(''); @@ -393,7 +393,7 @@ const TagPicker: React.FunctionComponent = ({ icon={icon} required={required} isDisabled={!!loading} - customAction={action} + customActions={actions} triggerLoading={(message) => setLoading(message)} onChange={updateTaxonomy} /> diff --git a/src/panelWebView/components/Fields/TextField.tsx b/src/panelWebView/components/Fields/TextField.tsx index e4a14ec8..1b6252cb 100644 --- a/src/panelWebView/components/Fields/TextField.tsx +++ b/src/panelWebView/components/Fields/TextField.tsx @@ -22,7 +22,7 @@ export interface ITextFieldProps extends BaseFieldProps { name: string; placeholder?: string; settings: PanelSettings; - action?: CustomScript; + actions?: CustomScript[]; onChange: (txtValue: string) => void; } @@ -40,7 +40,7 @@ export const TextField: React.FunctionComponent = ({ name, settings, onChange, - action, + actions, required }: React.PropsWithChildren) => { const [, setRequiredFields] = useRecoilState(RequiredFieldsAtom); @@ -145,7 +145,7 @@ export const TextField: React.FunctionComponent = ({ )} ); - }, [settings?.aiEnabled, settings?.copilotEnabled, name, action, loading]); + }, [settings?.aiEnabled, settings?.copilotEnabled, name, actions, loading]); useEffect(() => { if (text !== value && (lastUpdated === null || Date.now() - DEBOUNCE_TIME > lastUpdated)) { @@ -168,7 +168,7 @@ export const TextField: React.FunctionComponent = ({ icon={} required={required} isDisabled={!!loading} - customAction={action} + customActions={actions} triggerLoading={(message) => setLoading(message)} onChange={onTextChange} /> diff --git a/src/panelWebView/components/Fields/WrapperField.tsx b/src/panelWebView/components/Fields/WrapperField.tsx index 35b45109..caf431a2 100644 --- a/src/panelWebView/components/Fields/WrapperField.tsx +++ b/src/panelWebView/components/Fields/WrapperField.tsx @@ -216,7 +216,7 @@ export const WrapperField: React.FunctionComponent = ({ value={(fieldValue as string) || null} required={!!field.required} settings={settings} - action={field.action} + actions={field.actions} /> ); @@ -252,6 +252,7 @@ export const WrapperField: React.FunctionComponent = ({ multiple={field.multiple} blockData={blockData} onChange={onFieldChange} + actions={field.actions} /> ); @@ -308,7 +309,7 @@ export const WrapperField: React.FunctionComponent = ({ limit={field.taxonomyLimit} renderAsString={field.singleValueAsString} required={!!field.required} - action={field.action} + actions={field.actions} /> );