From 28eb2632d07908f9a0de6960bcc6a71cb83b2319 Mon Sep 17 00:00:00 2001 From: Tshepo Date: Wed, 26 Mar 2025 23:01:40 +0200 Subject: [PATCH 01/21] chore: changing the settings of the file component --- .../designer-components/fileUpload/index.tsx | 2 +- .../fileUpload/settingsForm.ts | 836 ++++++++++++++++++ 2 files changed, 837 insertions(+), 1 deletion(-) create mode 100644 shesha-reactjs/src/designer-components/fileUpload/settingsForm.ts diff --git a/shesha-reactjs/src/designer-components/fileUpload/index.tsx b/shesha-reactjs/src/designer-components/fileUpload/index.tsx index 302f3c8925..4ffaf085b1 100644 --- a/shesha-reactjs/src/designer-components/fileUpload/index.tsx +++ b/shesha-reactjs/src/designer-components/fileUpload/index.tsx @@ -10,10 +10,10 @@ import { evaluateValue, validateConfigurableComponentSettings, } from '@/providers/form/utils'; -import { getSettings } from './settings'; import { migrateCustomFunctions, migratePropertyName, migrateReadOnly } from '@/designer-components/_common-migrations/migrateSettings'; import { migrateVisibility } from '@/designer-components/_common-migrations/migrateVisibility'; import { migrateFormApi } from '../_common-migrations/migrateFormApi1'; +import { getSettings } from './settingsForm'; export interface IFileUploadProps extends IConfigurableFormComponent, Omit { ownerId: string; diff --git a/shesha-reactjs/src/designer-components/fileUpload/settingsForm.ts b/shesha-reactjs/src/designer-components/fileUpload/settingsForm.ts new file mode 100644 index 0000000000..30e0ada56f --- /dev/null +++ b/shesha-reactjs/src/designer-components/fileUpload/settingsForm.ts @@ -0,0 +1,836 @@ +import { DesignerToolbarSettings } from '@/interfaces/toolbarSettings'; +import { fontTypes, fontWeights, textAlign } from '../_settings/utils/font/utils'; +import { getBorderInputs } from '../_settings/utils/border/utils'; +import { getCornerInputs } from '../_settings/utils/border/utils'; +import { + backgroundTypeOptions, + positionOptions, + repeatOptions, + sizeOptions, +} from '../_settings/utils/background/utils'; +import { nanoid } from '@/utils/uuid'; +import { FormLayout } from 'antd/es/form/Form'; + +export const getSettings = () => { + return { + components: new DesignerToolbarSettings() + .addSearchableTabs({ + id: 'W_m7doMyCpCYwAYDfRh6I', + propertyName: 'settingsTabs', + parentId: 'root', + label: 'Settings', + hideLabel: true, + labelAlign: 'right', + size: 'small', + tabs: [ + { + key: '1', + title: 'Display', + id: '11114bf6-f76d-4139-a850-c99bf06c8b69', + components: [ + ...new DesignerToolbarSettings() + .addSettingsInput({ + id: '5c813b1a-04c5-4658-ac0f-cbcbae6b3bd4', + propertyName: 'propertyName', + label: 'Property name', + inputType: 'propertyAutocomplete', + validate: { required: true }, + jsSetting: false, + }) + .addLabelConfigurator({ + id: '46d07439-4c18-468c-89e1-60c002ce96c5', + propertyName: 'hideLabel', + label: 'Label', + }) + .addSettingsInput({ + id: '2d32fe70-99a0-4825-ae6c-8b933004e119', + propertyName: 'description', + label: 'Tooltip', + inputType: 'textArea', + }) + .addSettingsInputRow({ + id: 'b920ef96-ae27-4a01-bfad-list-type', + readOnly: { _code: 'return getSettingValue(data?.readOnly);', _mode: 'code', _value: false } as any, + parentId: '11114bf6-f76d-4139-a850-c99bf06c8b69', + hidden: { _code: 'return getSettingValue(data?.isDragger);', _mode: 'code', _value: false } as any, + inputs: [ + { + id: 'b920ef96-ae27-4a01-bfad-bob7d07218da', + propertyName: 'listType', + label: 'List Type', + type: 'dropdown', + defaultValue: 'text', + dropdownOptions: [ + { label: 'File Name', value: 'text' }, + { label: 'Thumbnail', value: 'thumbnail' }, + ], + }, + { + id: 'cfd7d45e-c7e3-4a27-987b-dc525c412447', + propertyName: 'isDragger', + label: 'Is Dragger', + type: 'switch', + description: 'Where the uploader should show a dragger instead of a button', + hidden: { + _code: 'return getSettingValue(data?.listType) === "thumbnail";', + _mode: 'code', + _value: false, + } as any, + }, + ], + }) + .addSettingsInputRow({ + id: 'display-row-1', + readOnly: { _code: 'return getSettingValue(data?.readOnly);', _mode: 'code', _value: false } as any, + parentId: '11114bf6-f76d-4139-a850-c99bf06c8b69', + inputs: [ + { + id: '24a8be15-98eb-40f7-99ea-ebb602693e9c', + propertyName: 'editMode', + label: 'Edit Mode', + type: 'editModeSelector', + }, + { + id: 'b920ef96-ae27-4a01-bfad-b5b7d0xc18da', + propertyName: 'hideFileName', + label: 'Hide File Name', + type: 'switch', + hidden: { + _code: 'return getSettingValue(data?.listType) !== "thumbnail";', + _mode: 'code', + _value: false, + } as any, + }, + ], + }) + .addSettingsInputRow({ + id: 'b920ef96-ae27-hidefile-name-bfad-b5b7d0xc18da', + readOnly: { _code: 'return getSettingValue(data?.readOnly);', _mode: 'code', _value: false } as any, + inputs: [ + { + id: 'cfd7d45e-c7e3-4a27-987b-dc525c412448', + propertyName: 'hidden', + label: 'Hide', + type: 'switch', + }, + { + id: '40024b1c-edd4-4b5d-9c85-1dda6fb8db6c', + propertyName: 'allowUpload', + label: 'Allow Upload', + type: 'switch', + defaultValue: true, + hidden: { + _code: 'const r = getSettingValue(data?.readOnly); return r === true || r === "readOnly";', + _mode: 'code', + _value: false, + } as any, + }, + + ], + }) + .addSettingsInputRow({ + id: 'display-row-2', + readOnly: { _code: 'return getSettingValue(data?.readOnly);', _mode: 'code', _value: false } as any, + parentId: '11114bf6-f76d-4139-a850-c99bf06c8b69', + inputs: [ + { + id: '6b3d298a-0e82-4420-ae3c-38bf5a2246d4', + propertyName: 'allowReplace', + label: 'Allow Replace', + type: 'switch', + hidden: { + _code: 'const r = getSettingValue(data?.readOnly); return r === true || r === "readOnly";', + _mode: 'code', + _value: false, + } as any, + }, + { + id: '332d298a-0e82-4420-ae3c-38bf5a2246d4', + propertyName: 'allowDelete', + label: 'Allow Delete', + type: 'switch', + hidden: { + _code: 'const r = getSettingValue(data?.readOnly); return r === true || r === "readOnly";', + _mode: 'code', + _value: false, + } as any, + }, + ], + }) + .toJson(), + ], + }, + { + key: '2', + title: 'Data', + id: '9b302942-a0a6-4805-ac47-8f45486a69d4', + components: [ + ...new DesignerToolbarSettings() + .addSettingsInput({ + id: '3fe73b1a-04c5-4658-ac0f-cbcbae6b3bd4', + propertyName: 'useSync', + label: 'Synchronous Upload', + inputType: 'switch', + }) + .addSettingsInput({ + id: '1c03863c-880d-4308-8667-c3d996619cb7', + propertyName: 'ownerId', + label: 'Owner Id', + inputType: 'textField', + }) + .addSettingsInput({ + id: '0009bf13-04a3-49d5-a9d8-1b23df20b97c', + propertyName: 'ownerType', + label: 'Owner Type', + inputType: 'autocomplete', + dataSourceType: 'url', + dataSourceUrl: '/api/services/app/Metadata/EntityTypeAutocomplete', + useRawValues: true, + }) + .addSettingsInput({ + id: nanoid(), + propertyName: 'allowedFileTypes', + label: 'Allowed File Types', + inputType: 'editableTagGroupProps', + description: 'File types that can be accepted.', + }) + .toJson(), + ], + }, + { + key: '3', + title: 'Validation', + id: 'd675bfe4-ee69-431e-931b-b0e0b9ceee6f', + components: [ + ...new DesignerToolbarSettings() + .addSettingsInput({ + id: '3be9da3f-f47e-48ae-b4c3-f5cc36e534d9', + propertyName: 'validate.required', + label: 'Required', + inputType: 'switch', + }) + .toJson(), + ], + }, + { + key: '4', + title: 'Appearance', + id: 'elgrlievlfwehhh848r8hsdnflsdnclurbd', + components: [ + ...new DesignerToolbarSettings() + .addPropertyRouter({ + id: 'styleRouter', + propertyName: 'propertyRouter1', + componentName: 'propertyRouter', + label: 'Property router1', + labelAlign: 'right', + parentId: 'elgrlievlfwehhh848r8hsdnflsdnclurbd', + hidden: false, + propertyRouteName: { + _mode: 'code', + _code: " return contexts.canvasContext?.designerDevice || 'desktop';", + _value: '', + }, + components: [ + ...new DesignerToolbarSettings() + .addCollapsiblePanel({ + id: 'fontStyleCollapsiblePanel', + propertyName: 'pnlFontStyle', + label: 'Font', + labelAlign: 'right', + parentId: 'styleRouter', + ghost: true, + collapsible: 'header', + content: { + id: 'fontStylePnl', + components: [ + ...new DesignerToolbarSettings() + .addSettingsInputRow({ + id: 'try26voxhs-HxJ5k5ngYE', + parentId: 'fontStylePnl', + inline: true, + propertyName: 'font', + readOnly: { + _code: 'return getSettingValue(data?.readOnly);', + _mode: 'code', + _value: false, + } as any, + inputs: [ + { + type: 'dropdown', + id: 'fontFamily-s4gmBg31azZC0UjZjpfTm', + label: 'Family', + propertyName: 'font.type', + hideLabel: true, + dropdownOptions: fontTypes, + }, + { + type: 'numberField', + id: 'fontSize-s4gmBg31azZC0UjZjpfTm', + label: 'Size', + propertyName: 'font.size', + hideLabel: true, + width: 50, + }, + { + type: 'dropdown', + id: 'fontWeight-s4gmBg31azZC0UjZjpfTm', + label: 'Weight', + propertyName: 'font.weight', + hideLabel: true, + tooltip: 'Controls text thickness (light, normal, bold, etc.)', + dropdownOptions: fontWeights, + width: 100, + }, + { + type: 'colorPicker', + id: 'fontColor-s4gmBg31azZC0UjZjpfTm', + label: 'Color', + hideLabel: true, + propertyName: 'font.color', + }, + { + type: 'dropdown', + id: 'fontAlign-s4gmBg31azZC0UjZjpfTm', + label: 'Align', + propertyName: 'font.align', + hideLabel: true, + width: 60, + dropdownOptions: textAlign, + }, + ], + }) + .toJson(), + ], + }, + }) + .addCollapsiblePanel({ + id: 'dimensionsStyleCollapsiblePanel', + propertyName: 'pnlDimensions', + label: 'Dimensions', + parentId: 'styleRouter', + labelAlign: 'right', + ghost: true, + collapsible: 'header', + content: { + id: 'dimensionsStylePnl', + components: [ + ...new DesignerToolbarSettings() + .addSettingsInputRow({ + id: 'dimensionsStyleRowWidth', + parentId: 'dimensionsStylePnl', + inline: true, + readOnly: { + _code: 'return getSettingValue(data?.readOnly);', + _mode: 'code', + _value: false, + } as any, + inputs: [ + { + type: 'textField', + id: 'width-s4gmBg31azZC0UjZjpfTm', + label: 'Width', + width: 85, + propertyName: 'dimensions.width', + icon: 'widthIcon', + tooltip: 'You can use any unit (%, px, em, etc). px by default if without unit', + }, + { + type: 'textField', + id: 'minWidth-s4gmBg31azZC0UjZjpfTm', + label: 'Min Width', + width: 85, + hideLabel: true, + propertyName: 'dimensions.minWidth', + icon: 'minWidthIcon', + }, + { + type: 'textField', + id: 'maxWidth-s4gmBg31azZC0UjZjpfTm', + label: 'Max Width', + width: 85, + hideLabel: true, + propertyName: 'dimensions.maxWidth', + icon: 'maxWidthIcon', + }, + ], + }) + .addSettingsInputRow({ + id: 'dimensionsStyleRowHeight', + parentId: 'dimensionsStylePnl', + inline: true, + readOnly: { + _code: 'return getSettingValue(data?.readOnly);', + _mode: 'code', + _value: false, + } as any, + inputs: [ + { + type: 'textField', + id: 'height-s4gmBg31azZC0UjZjpfTm', + label: 'Height', + width: 85, + propertyName: 'dimensions.height', + icon: 'heightIcon', + tooltip: 'You can use any unit (%, px, em, etc). px by default if without unit', + }, + { + type: 'textField', + id: 'minHeight-s4gmBg31azZC0UjZjpfTm', + label: 'Min Height', + width: 85, + hideLabel: true, + propertyName: 'dimensions.minHeight', + icon: 'minHeightIcon', + }, + { + type: 'textField', + id: 'maxHeight-s4gmBg31azZC0UjZjpfTm', + label: 'Max Height', + width: 85, + hideLabel: true, + propertyName: 'dimensions.maxHeight', + icon: 'maxHeightIcon', + }, + ], + }) + .toJson(), + ], + }, + }) + .addCollapsiblePanel({ + id: 'borderStyleCollapsiblePanel', + propertyName: 'pnlBorderStyle', + label: 'Border', + labelAlign: 'right', + ghost: true, + parentId: 'styleRouter', + collapsible: 'header', + content: { + id: 'borderStylePnl', + components: [ + ...new DesignerToolbarSettings() + .addSettingsInputRow({ + id: `borderStyleRow`, + parentId: 'borderStylePnl', + hidden: { + _code: + 'return !getSettingValue(data[`${contexts.canvasContext?.designerDevice || "desktop"}`]?.border?.hideBorder);', + _mode: 'code', + _value: false, + } as any, + readOnly: { + _code: 'return getSettingValue(data?.readOnly);', + _mode: 'code', + _value: false, + } as any, + inputs: [ + { + type: 'button', + id: 'borderStyleRow-hideBorder', + label: 'Border', + hideLabel: true, + propertyName: 'border.hideBorder', + icon: 'EyeOutlined', + iconAlt: 'EyeInvisibleOutlined', + }, + ], + }) + .addContainer({ + id: 'borderStyleRow', + parentId: 'borderStylePnl', + components: getBorderInputs() as any, + }) + .addContainer({ + id: 'borderRadiusStyleRow', + parentId: 'borderStylePnl', + components: getCornerInputs() as any, + }) + .toJson(), + ], + }, + }) + .addCollapsiblePanel({ + id: 'backgroundStyleCollapsiblePanel', + propertyName: 'pnlBackgroundStyle', + label: 'Background', + labelAlign: 'right', + ghost: true, + parentId: 'styleRouter', + collapsible: 'header', + content: { + id: 'backgroundStylePnl', + components: [ + ...new DesignerToolbarSettings() + .addSettingsInput({ + id: 'backgroundStyleRow-selectType', + parentId: 'backgroundStylePnl', + label: 'Type', + jsSetting: false, + propertyName: 'background.type', + inputType: 'radio', + tooltip: 'Select a type of background', + buttonGroupOptions: backgroundTypeOptions, + readOnly: { + _code: 'return getSettingValue(data?.readOnly);', + _mode: 'code', + _value: false, + } as any, + }) + .addSettingsInputRow({ + id: 'backgroundStyleRow-color', + parentId: 'backgroundStylePnl', + inputs: [ + { + type: 'colorPicker', + id: 'backgroundStyleRow-color', + label: 'Color', + propertyName: 'background.color', + hideLabel: true, + jsSetting: false, + }, + ], + hidden: { + _code: + 'return getSettingValue(data[`${contexts.canvasContext?.designerDevice || "desktop"}`]?.background?.type) !== "color";', + _mode: 'code', + _value: false, + } as any, + readOnly: { + _code: 'return getSettingValue(data?.readOnly);', + _mode: 'code', + _value: false, + } as any, + }) + .addSettingsInputRow({ + id: 'backgroundStyle-gradientColors', + parentId: 'backgroundStylePnl', + inputs: [ + { + type: 'multiColorPicker', + id: 'backgroundStyle-gradientColors', + propertyName: 'background.gradient.colors', + label: 'Colors', + jsSetting: false, + }, + ], + hidden: { + _code: + 'return getSettingValue(data[`${contexts.canvasContext?.designerDevice || "desktop"}`]?.background?.type) !== "gradient";', + _mode: 'code', + _value: false, + } as any, + hideLabel: true, + readOnly: { + _code: 'return getSettingValue(data?.readOnly);', + _mode: 'code', + _value: false, + } as any, + }) + .addSettingsInputRow({ + id: 'backgroundStyle-url', + parentId: 'backgroundStylePnl', + inputs: [ + { + type: 'textField', + id: 'backgroundStyle-url', + propertyName: 'background.url', + jsSetting: false, + label: 'URL', + }, + ], + hidden: { + _code: + 'return getSettingValue(data[`${contexts.canvasContext?.designerDevice || "desktop"}`]?.background?.type) !== "url";', + _mode: 'code', + _value: false, + } as any, + readOnly: { + _code: 'return getSettingValue(data?.readOnly);', + _mode: 'code', + _value: false, + } as any, + }) + .addSettingsInputRow({ + id: 'backgroundStyle-image', + parentId: 'backgroundStylePnl', + inputs: [ + { + type: 'imageUploader', + id: 'backgroundStyle-image', + propertyName: 'background.uploadFile', + label: 'Image', + jsSetting: false, + }, + ], + hidden: { + _code: + 'return getSettingValue(data[`${contexts.canvasContext?.designerDevice || "desktop"}`]?.background?.type) !== "image";', + _mode: 'code', + _value: false, + } as any, + readOnly: { + _code: 'return getSettingValue(data?.readOnly);', + _mode: 'code', + _value: false, + } as any, + }) + .addSettingsInputRow({ + id: 'backgroundStyleRow-storedFile', + parentId: 'backgroundStylePnl', + hidden: { + _code: + 'return getSettingValue(data[`${contexts.canvasContext?.designerDevice || "desktop"}`]?.background?.type) !== "storedFile";', + _mode: 'code', + _value: false, + } as any, + readOnly: { + _code: 'return getSettingValue(data?.readOnly);', + _mode: 'code', + _value: false, + } as any, + inputs: [ + { + type: 'textField', + id: 'backgroundStyle-storedFile', + jsSetting: false, + propertyName: 'background.storedFile.id', + label: 'File ID', + }, + ], + }) + .addSettingsInputRow({ + id: 'backgroundStyleRow-controls', + parentId: 'backgroundStyleRow', + inline: true, + hidden: { + _code: + 'return getSettingValue(data[`${contexts.canvasContext?.designerDevice || "desktop"}`]?.background?.type) === "color";', + _mode: 'code', + _value: false, + } as any, + readOnly: { + _code: 'return getSettingValue(data?.readOnly);', + _mode: 'code', + _value: false, + } as any, + inputs: [ + { + type: 'customDropdown', + id: 'backgroundStyleRow-size', + label: 'Size', + hideLabel: true, + propertyName: 'background.size', + customTooltip: + 'Size of the background image, two space separated values with units e.g "100% 100px"', + dropdownOptions: sizeOptions, + hidden: { + _code: + 'return getSettingValue(data[`${contexts.canvasContext?.designerDevice || "desktop"}`]?.background?.type) === "color";', + _mode: 'code', + _value: false, + } as any, + }, + { + type: 'customDropdown', + id: 'backgroundStyleRow-position', + label: 'Position', + hideLabel: true, + customTooltip: + 'Position of the background image, two space separated values with units e.g "5em 100px"', + propertyName: 'background.position', + dropdownOptions: positionOptions, + }, + ], + }) + .addSettingsInputRow({ + id: 'backgroundStyleRow-repeat', + parentId: 'backgroundStyleRow', + readOnly: { + _code: 'return getSettingValue(data?.readOnly);', + _mode: 'code', + _value: false, + } as any, + inputs: [ + { + type: 'radio', + id: 'backgroundStyleRow-repeat-radio', + label: 'Repeat', + hideLabel: true, + propertyName: 'background.repeat', + inputType: 'radio', + buttonGroupOptions: repeatOptions, + }, + ], + hidden: { + _code: + 'return getSettingValue(data[`${contexts.canvasContext?.designerDevice || "desktop"}`]?.background?.type) === "color";', + _mode: 'code', + _value: false, + } as any, + }) + .toJson(), + ], + }, + }) + .addCollapsiblePanel({ + id: 'shadowStyleCollapsiblePanel', + propertyName: 'pnlShadowStyle', + label: 'Shadow', + labelAlign: 'right', + ghost: true, + parentId: 'styleRouter', + collapsible: 'header', + content: { + id: 'shadowStylePnl', + components: [ + ...new DesignerToolbarSettings() + .addSettingsInputRow({ + id: 'shadowStyleRow', + parentId: 'shadowStylePnl', + inline: true, + readOnly: { + _code: 'return getSettingValue(data?.readOnly);', + _mode: 'code', + _value: false, + } as any, + inputs: [ + { + type: 'numberField', + id: 'shadowStyleRow-offsetX', + label: 'Offset X', + hideLabel: true, + tooltip: 'Offset X', + width: 80, + icon: 'offsetHorizontalIcon', + propertyName: 'shadow.offsetX', + }, + { + type: 'numberField', + id: 'shadowStyleRow-offsetY', + label: 'Offset Y', + hideLabel: true, + tooltip: 'Offset Y', + width: 80, + icon: 'offsetVerticalIcon', + propertyName: 'shadow.offsetY', + }, + { + type: 'numberField', + id: 'shadowStyleRow-blurRadius', + label: 'Blur', + hideLabel: true, + tooltip: 'Blur radius', + width: 80, + icon: 'blurIcon', + propertyName: 'shadow.blurRadius', + }, + { + type: 'numberField', + id: 'shadowStyleRow-spreadRadius', + label: 'Spread', + hideLabel: true, + tooltip: 'Spread radius', + width: 80, + icon: 'spreadIcon', + propertyName: 'shadow.spreadRadius', + }, + { + type: 'colorPicker', + id: 'shadowStyleRow-color', + label: 'Color', + hideLabel: true, + propertyName: 'shadow.color', + }, + ], + }) + .toJson(), + ], + }, + }) + .addCollapsiblePanel({ + id: 'styleCollapsiblePanel', + propertyName: 'stylingBox', + label: 'Margin & Padding', + labelAlign: 'right', + ghost: true, + collapsible: 'header', + content: { + id: 'stylePnl-M5-911', + components: [ + ...new DesignerToolbarSettings() + .addStyleBox({ + id: 'styleBoxPnl', + label: 'Margin Padding', + hideLabel: true, + propertyName: 'stylingBox', + }) + .toJson(), + ], + }, + }) + .addCollapsiblePanel({ + id: 'customStyleCollapsiblePanel', + propertyName: 'customStyle', + label: 'Custom Styles', + labelAlign: 'right', + ghost: true, + parentId: 'styleRouter', + collapsible: 'header', + content: { + id: 'stylePnl-M500-911MFR', + components: [ + ...new DesignerToolbarSettings() + .addSettingsInput({ + readOnly: { + _code: 'return getSettingValue(data?.readOnly);', + _mode: 'code', + _value: false, + } as any, + id: 'custom-css-412c-8461-4c8d55e5c073', + inputType: 'codeEditor', + propertyName: 'style', + hideLabel: false, + label: 'Style', + description: + 'A script that returns the style of the element as an object. This should conform to CSSProperties', + }) + .toJson(), + ], + }, + }) + .toJson(), + ], + }) + .toJson(), + ], + }, + { + key: '5', + title: 'Security', + id: '6Vw9iiDw9d0MD_Rh5cbIn', + components: [ + ...new DesignerToolbarSettings() + .addSettingsInput({ + readOnly: { _code: 'return getSettingValue(data?.readOnly);', _mode: 'code', _value: false } as any, + id: '1adea529-1f0c-4def-bd41-ee166a5dfcd7', + inputType: 'permissions', + propertyName: 'permissions', + label: 'Permissions', + size: 'small', + parentId: '6Vw9iiDw9d0MD_Rh5cbIn', + }) + .toJson(), + ], + }, + ], + }) + .toJson(), + formSettings: { + colon: false, + layout: 'vertical' as FormLayout, + labelCol: { span: 24 }, + wrapperCol: { span: 24 }, + }, + }; +}; From eb70cd47ee67e75d347781488753f0e3f38dfce9 Mon Sep 17 00:00:00 2001 From: Tshepo Date: Thu, 27 Mar 2025 15:45:24 +0200 Subject: [PATCH 02/21] chore: changing the file to show thumbnail --- .../src/components/fileUpload/index.tsx | 32 +++-- .../designer-components/fileUpload/index.tsx | 3 + .../fileUpload/settingsForm.ts | 111 ++++++++++-------- .../designer-components/link/settingsForm.ts | 39 +++--- .../designer-components/text/settingsForm.ts | 40 +++++++ .../src/designer-components/text/utils.ts | 2 +- 6 files changed, 146 insertions(+), 81 deletions(-) diff --git a/shesha-reactjs/src/components/fileUpload/index.tsx b/shesha-reactjs/src/components/fileUpload/index.tsx index d67993a5bb..c1ecc78615 100644 --- a/shesha-reactjs/src/components/fileUpload/index.tsx +++ b/shesha-reactjs/src/components/fileUpload/index.tsx @@ -1,20 +1,21 @@ -import React, { FC, useRef } from 'react'; +import { listType } from '@/designer-components/attachmentsEditor/attachmentsEditor'; import { useStoredFile } from '@/providers'; -import { Upload, App, Button } from 'antd'; -import { UploadRequestOption as RcCustomRequestOptions } from 'rc-upload/lib/interface'; import { - InfoCircleOutlined, - SyncOutlined, DeleteOutlined, + InfoCircleOutlined, LoadingOutlined, + SyncOutlined, UploadOutlined, } from '@ant-design/icons'; +import { App, Button, Upload } from 'antd'; import { UploadProps } from 'antd/lib/upload/Upload'; +import classNames from 'classnames'; import filesize from 'filesize'; +import { UploadRequestOption as RcCustomRequestOptions } from 'rc-upload/lib/interface'; +import React, { FC, useRef } from 'react'; import { FileVersionsPopup } from './fileVersionsPopup'; import { DraggerStub } from './stubs'; import { useStyles } from './styles/styles'; -import classNames from 'classnames'; const { Dragger } = Upload; @@ -29,6 +30,13 @@ export interface IFileUploadProps { isStub?: boolean; allowedFileTypes?: string[]; isDragger?: boolean; + listType?: listType; + thumbnailWidth?: string; + thumbnailHeight?: string; + borderRadius?: number; + hideFileName?: boolean; + readonly?: boolean; + } export const FileUpload: FC = ({ @@ -40,6 +48,8 @@ export const FileUpload: FC = ({ isStub = false, allowedFileTypes = [], isDragger = false, + listType = 'text', + readonly, }) => { const { fileInfo, @@ -108,9 +118,10 @@ export const FileUpload: FC = ({ const fileProps: UploadProps = { name: 'file', - disabled: false, + disabled: readonly && allowUpload, accept: allowedFileTypes?.join(','), multiple: false, + listType: listType === 'text' ? 'text' : 'picture-card', fileList: fileInfo ? [fileInfo] : [], customRequest: onCustomRequest, onChange(info) { @@ -149,7 +160,7 @@ export const FileUpload: FC = ({ ref={uploadButtonRef} style={{ display: !showUploadButton ? 'none' : '' }} > - (press to upload) + {listType ==='text' ?`(press to upload)`: null} ); @@ -170,10 +181,9 @@ export const FileUpload: FC = ({ ); } - return ( - - {/* {allowUpload && uploadButton} */} + + {allowUpload && uploadButton} ); }; diff --git a/shesha-reactjs/src/designer-components/fileUpload/index.tsx b/shesha-reactjs/src/designer-components/fileUpload/index.tsx index 4ffaf085b1..f0e980eb91 100644 --- a/shesha-reactjs/src/designer-components/fileUpload/index.tsx +++ b/shesha-reactjs/src/designer-components/fileUpload/index.tsx @@ -46,6 +46,7 @@ const FileUploadComponent: IToolboxComponent = { return ( {(value, onChange) => { + console.log('model', model); return ( = { uploadMode={model.useSync ? 'sync' : 'async'} > = { ownerId: '', ownerType: '', isDragger: false, + editMode: 'inherited', }; return customModel; }, diff --git a/shesha-reactjs/src/designer-components/fileUpload/settingsForm.ts b/shesha-reactjs/src/designer-components/fileUpload/settingsForm.ts index 30e0ada56f..36d1c5ca4a 100644 --- a/shesha-reactjs/src/designer-components/fileUpload/settingsForm.ts +++ b/shesha-reactjs/src/designer-components/fileUpload/settingsForm.ts @@ -29,18 +29,19 @@ export const getSettings = () => { id: '11114bf6-f76d-4139-a850-c99bf06c8b69', components: [ ...new DesignerToolbarSettings() - .addSettingsInput({ + .addContextPropertyAutocomplete({ id: '5c813b1a-04c5-4658-ac0f-cbcbae6b3bd4', propertyName: 'propertyName', label: 'Property name', - inputType: 'propertyAutocomplete', validate: { required: true }, + styledLabel: true, jsSetting: false, }) .addLabelConfigurator({ id: '46d07439-4c18-468c-89e1-60c002ce96c5', propertyName: 'hideLabel', label: 'Label', + hideLabel: true, }) .addSettingsInput({ id: '2d32fe70-99a0-4825-ae6c-8b933004e119', @@ -52,7 +53,6 @@ export const getSettings = () => { id: 'b920ef96-ae27-4a01-bfad-list-type', readOnly: { _code: 'return getSettingValue(data?.readOnly);', _mode: 'code', _value: false } as any, parentId: '11114bf6-f76d-4139-a850-c99bf06c8b69', - hidden: { _code: 'return getSettingValue(data?.isDragger);', _mode: 'code', _value: false } as any, inputs: [ { id: 'b920ef96-ae27-4a01-bfad-bob7d07218da', @@ -61,9 +61,14 @@ export const getSettings = () => { type: 'dropdown', defaultValue: 'text', dropdownOptions: [ - { label: 'File Name', value: 'text' }, + { label: 'File name', value: 'text' }, { label: 'Thumbnail', value: 'thumbnail' }, ], + hidden: { + _code: 'return getSettingValue(data?.isDragger);', + _mode: 'code', + _value: false, + } as any, }, { id: 'cfd7d45e-c7e3-4a27-987b-dc525c412447', @@ -89,6 +94,7 @@ export const getSettings = () => { propertyName: 'editMode', label: 'Edit Mode', type: 'editModeSelector', + defaultValue: 'inherited', }, { id: 'b920ef96-ae27-4a01-bfad-b5b7d0xc18da', @@ -108,24 +114,23 @@ export const getSettings = () => { readOnly: { _code: 'return getSettingValue(data?.readOnly);', _mode: 'code', _value: false } as any, inputs: [ { - id: 'cfd7d45e-c7e3-4a27-987b-dc525c412448', - propertyName: 'hidden', - label: 'Hide', - type: 'switch', + id: 'cfd7d45e-c7e3-4a27-987b-dc525c412448', + propertyName: 'hidden', + label: 'Hide', + type: 'switch', }, { - id: '40024b1c-edd4-4b5d-9c85-1dda6fb8db6c', - propertyName: 'allowUpload', - label: 'Allow Upload', - type: 'switch', - defaultValue: true, - hidden: { - _code: 'const r = getSettingValue(data?.readOnly); return r === true || r === "readOnly";', - _mode: 'code', - _value: false, - } as any, - }, - + id: '40024b1c-edd4-4b5d-9c85-1dda6fb8db6c', + propertyName: 'allowUpload', + label: 'Allow Upload', + type: 'switch', + defaultValue: true, + hidden: { + _code: 'const r = getSettingValue(data?.readOnly); return r === true || r === "readOnly";', + _mode: 'code', + _value: false, + } as any, + }, ], }) .addSettingsInputRow({ @@ -166,33 +171,47 @@ export const getSettings = () => { id: '9b302942-a0a6-4805-ac47-8f45486a69d4', components: [ ...new DesignerToolbarSettings() - .addSettingsInput({ - id: '3fe73b1a-04c5-4658-ac0f-cbcbae6b3bd4', - propertyName: 'useSync', - label: 'Synchronous Upload', - inputType: 'switch', - }) - .addSettingsInput({ - id: '1c03863c-880d-4308-8667-c3d996619cb7', - propertyName: 'ownerId', - label: 'Owner Id', - inputType: 'textField', - }) - .addSettingsInput({ - id: '0009bf13-04a3-49d5-a9d8-1b23df20b97c', - propertyName: 'ownerType', - label: 'Owner Type', - inputType: 'autocomplete', - dataSourceType: 'url', - dataSourceUrl: '/api/services/app/Metadata/EntityTypeAutocomplete', - useRawValues: true, + .addSettingsInputRow({ + id: 'display-row-2', + readOnly: { _code: 'return getSettingValue(data?.readOnly);', _mode: 'code', _value: false } as any, + parentId: '9b302942-a0a6-4805-ac47-8f45486a69d4', + inputs: [ + { + id: '3fe73b1a-04c5-4658-ac0f-cbcbae6b3bd4', + propertyName: 'useSync', + label: 'Synchronous Upload', + type: 'switch', + }, + { + id: '3fe73b1a-04c5-4658-ac0f-cbcbae6b3bd4', + propertyName: 'allowedFileTypes', + label: 'Allowed File Types', + type: 'editableTagGroupProps', + description: 'File types that can be accepted.', + }, + ], }) - .addSettingsInput({ - id: nanoid(), - propertyName: 'allowedFileTypes', - label: 'Allowed File Types', - inputType: 'editableTagGroupProps', - description: 'File types that can be accepted.', + .addSettingsInputRow({ + id: 'display-row-3', + readOnly: { _code: 'return getSettingValue(data?.readOnly);', _mode: 'code', _value: false } as any, + parentId: '9b302942-a0a6-4805-ac47-8f45486a69d4', + inputs: [ + { + id: '1c03863c-880d-4308-8667-c3d996619cb7', + propertyName: 'ownerId', + label: 'Owner Id', + type: 'textField', + }, + { + id: '1c03863c-880d-4308-8667-c3d996619cb7', + propertyName: 'ownerType', + label: 'Owner Type', + type: 'autocomplete', + dataSourceType: 'url', + dataSourceUrl: '/api/services/app/Metadata/EntityTypeAutocomplete', + useRawValues: true, + }, + ], }) .toJson(), ], diff --git a/shesha-reactjs/src/designer-components/link/settingsForm.ts b/shesha-reactjs/src/designer-components/link/settingsForm.ts index a2bae895cf..2b75f8a28d 100644 --- a/shesha-reactjs/src/designer-components/link/settingsForm.ts +++ b/shesha-reactjs/src/designer-components/link/settingsForm.ts @@ -110,13 +110,6 @@ export const getSettings = (data: any) => { }, ], }, - ], - }) - .addSettingsInputRow({ - id: 'type-default-value-s4gmBg31azZC0UjZjpfTm', - parentId: 's4gmBg31azZC0UjZjpfTm', - readOnly: { _code: 'return getSettingValue(data?.readOnly);', _mode: 'code', _value: false } as any, - inputs: [ { type: 'dropdown', id: 'type-s4gmBg31azZC0UjZjpfTm', @@ -375,6 +368,22 @@ export const getSettings = (data: any) => { }, ], }, + ], + }) + .addSettingsInputRow({ + id: 'type-default-value-s4gmBg31azZC0UjZjpfTm', + parentId: 's4gmBg31azZC0UjZjpfTm', + hidden: { + _code: 'return !getSettingValue(data?.hasChildren);', + _mode: 'code', + _value: false, + } as any, + readOnly: { + _code: 'return getSettingValue(data?.readOnly);', + _mode: 'code', + _value: false, + } as any, + inputs: [ { type: 'dropdown', id: 'justifyItems-s4gmBg31azZC0UjZjpfTm', @@ -453,22 +462,6 @@ export const getSettings = (data: any) => { }, ], }, - ], - }) - .addSettingsInputRow({ - id: 'type-default-value-s4gmBg31azZC0UjZjpfTm', - parentId: 's4gmBg31azZC0UjZjpfTm', - hidden: { - _code: 'return !getSettingValue(data?.hasChildren);', - _mode: 'code', - _value: false, - } as any, - readOnly: { - _code: 'return getSettingValue(data?.readOnly);', - _mode: 'code', - _value: false, - } as any, - inputs: [ { type: 'textField', id: 'customCss-s4gmBg31azZC0UjZjpfTm', diff --git a/shesha-reactjs/src/designer-components/text/settingsForm.ts b/shesha-reactjs/src/designer-components/text/settingsForm.ts index 7e819ee0cd..4cc1c65369 100644 --- a/shesha-reactjs/src/designer-components/text/settingsForm.ts +++ b/shesha-reactjs/src/designer-components/text/settingsForm.ts @@ -4,6 +4,8 @@ import { DEFAULT_CONTENT_TYPE } from './utils'; import { getBorderInputs, getCornerInputs } from '../_settings/utils/border/utils'; import { fontTypes, fontWeights, textAlign } from '../_settings/utils/font/utils'; import { positionOptions, repeatOptions, sizeOptions } from '../_settings/utils/background/utils'; +import { FONT_SIZES } from './models'; +import { nanoid } from '@/utils/uuid'; export const getSettings = (data: any) => { return { @@ -329,6 +331,44 @@ export const getSettings = (data: any) => { propertyName: 'font.size', hideLabel: true, width: 50, + hidden: {_code: 'return getSettingValue(data?.textType) === "title";', _mode: 'code', _value: false} as any, + }, + { + id: 'ccea671b-9144-4266-9cd7-64495cbc6910', + propertyName: 'level', + type: 'dropdown', + parentId: '4pnl54bf6-f76d-4139-a850-c99bf06c8b69', + label: 'Size', + dropdownOptions: [ + { + label: 'H1', + value: '1', + id: '81f0cd35-45b0-4d3e-8960-b6c9c3f7fb6f', + }, + { + label: 'H2', + value: '2', + id: 'a19ccf4a-27f0-45ae-819a-779668370639', + }, + { + label: 'H3', + value: '3', + id: '6a755f46-09a6-4e5e-b9fe-8617be7ef8e1', + }, + { + label: 'H4', + value: '4', + id: '3f8460ca-f50a-4cba-9b5d-6a2b02be14d2', + }, + { + label: 'H5', + value: '5', + id: '186a71a8-ead4-4bed-8a3b-bc197faac998', + }, + ...Object.keys(FONT_SIZES).map(key => ({ id: nanoid(), value: key, label: key })), + ], + hideLabel: true, + hidden: {_code: 'return getSettingValue(data?.textType) !== "title";', _mode: 'code', _value: false} as any, }, { type: 'dropdown', diff --git a/shesha-reactjs/src/designer-components/text/utils.ts b/shesha-reactjs/src/designer-components/text/utils.ts index af780f306c..9749fd6e19 100644 --- a/shesha-reactjs/src/designer-components/text/utils.ts +++ b/shesha-reactjs/src/designer-components/text/utils.ts @@ -92,7 +92,7 @@ export const defaultStyles = (): IStyleType => { color: '#000', type: 'Segoe UI', }, - background: { type: 'color', color: 'transparent' }, + background: { type: 'color' }, border: { border: { all: { From 5c82948289a76e6cb613b082b6afb534c3a262fd Mon Sep 17 00:00:00 2001 From: Tshepo Date: Fri, 28 Mar 2025 07:57:42 +0200 Subject: [PATCH 03/21] chore: adding styling to the thumbnail --- .../src/components/fileUpload/index.tsx | 22 +- .../components/fileUpload/styles/styles.ts | 340 +++++- .../dataList/dataListSettings.tsx | 21 +- .../dataList/settingsForm.ts | 39 +- .../designer-components/dataList/utils.tsx | 72 ++ .../designer-components/fileUpload/index.tsx | 80 +- .../fileUpload/settingsForm.ts | 1045 ++++++++--------- .../designer-components/fileUpload/utils.ts | 34 + .../inputComponent/index.tsx | 4 + .../settingsInput/interfaces.ts | 5 +- 10 files changed, 983 insertions(+), 679 deletions(-) create mode 100644 shesha-reactjs/src/designer-components/dataList/utils.tsx create mode 100644 shesha-reactjs/src/designer-components/fileUpload/utils.ts diff --git a/shesha-reactjs/src/components/fileUpload/index.tsx b/shesha-reactjs/src/components/fileUpload/index.tsx index c1ecc78615..dc2a99a294 100644 --- a/shesha-reactjs/src/components/fileUpload/index.tsx +++ b/shesha-reactjs/src/components/fileUpload/index.tsx @@ -97,18 +97,18 @@ export const FileUpload: FC = ({ return ( {fileInfo && ( - + {false && } )} {allowReplace && ( - + )} {allowDelete && ( - + )} @@ -136,9 +136,9 @@ export const FileUpload: FC = ({ }, itemRender: (_originNode, file, _currFileList) => { return ( -
-
- {isUploading && } +
+
+ {isUploading && } {file.name} ({filesize(file.size)}) @@ -151,7 +151,7 @@ export const FileUpload: FC = ({ }; const showUploadButton = allowUpload && !fileInfo && !isUploading; - const classes = classNames(styles.shaUpload, { [styles.shaUploadHasFile]: fileInfo || isUploading }); + // const classes = classNames(styles.shaUpload, { [styles.shaUploadHasFile]: fileInfo || isUploading }); const uploadButton = ( ); @@ -183,13 +208,29 @@ export const FileUpload: FC = ({ } return ( - {allowUpload && uploadButton} + {allowUpload && !fileInfo && uploadButton} ); }; - return {isStub ? renderStub() : renderUploader()}; + return <> + {isStub ? renderStub() : renderUploader()} + {previewOpen && ( + setPreviewOpen(visible), + afterOpenChange: (visible) => !visible, + toolbarRender: (original) => { + return
downloadFile({ fileId: previewImage.uid, fileName: previewImage.name })} />{original}
; + }, + }} + src={imageUrl} + /> + )} + ; }; export default FileUpload; diff --git a/shesha-reactjs/src/components/fileUpload/styles/styles.ts b/shesha-reactjs/src/components/fileUpload/styles/styles.ts index 703da1dc65..6af15e97c1 100644 --- a/shesha-reactjs/src/components/fileUpload/styles/styles.ts +++ b/shesha-reactjs/src/components/fileUpload/styles/styles.ts @@ -1,12 +1,47 @@ import { createStyles } from '@/styles'; export const useStyles = createStyles(({ token, css, cx, prefixCls }, { style, model }) => { - const { background, backgroundImage, borderRadius, borderWidth, borderTopWidth, width, minWidth, maxWidth, - borderBottomWidth, borderLeftWidth, borderLeftColor, borderLeftStyle, borderRightColor, borderRightStyle, borderColor, borderTopStyle, borderTopColor, - borderTop, boxShadow, borderBottom, borderBottomColor, borderBottomStyle, borderRight, borderRightWidth, backgroundColor, backgroundPosition, - backgroundRepeat, backgroundSize, borderStyle, color, fontFamily, fontSize, fontWeight, height, maxHeight, minHeight, textAlign, + + const { + background = 'transparent', + backgroundImage, + borderRadius = '8px', + borderWidth = '0', + borderTopWidth, + width, + minWidth, + maxWidth, + borderBottomWidth, + borderLeftWidth, + borderLeftColor, + borderLeftStyle, + borderRightColor, + borderRightStyle, + borderColor = 'transparent', + borderTopStyle, + borderTopColor, + borderTop, + boxShadow, + borderBottom, + borderBottomColor, + borderBottomStyle, + borderRight, + borderRightWidth, + backgroundColor = '#fff', + backgroundPosition, + backgroundRepeat, + backgroundSize, + borderStyle = 'solid', + color, + fontFamily = 'Segoe UI', + fontSize = '14px', + fontWeight = '400', + height, + maxHeight, + minHeight, + textAlign = 'center', ...rest - } = style; + } = style || {}; const { gap, layout, hideFileName, isDragger } = model; @@ -53,7 +88,7 @@ export const useStyles = createStyles(({ token, css, cx, prefixCls }, { style, m .ant-upload-list-item-thumbnail { border-radius: ${borderRadius ?? '8px'} !important; padding: 0 !important; - background: ${backgroundImage ?? (backgroundColor || '#fff')} !important; + background: ${background ?? (backgroundImage ?? (backgroundColor || '#fff'))} !important; border: ${borderWidth} ${borderStyle} ${borderColor}; border-top: ${borderTopWidth || borderWidth} ${borderTopStyle || borderStyle} ${borderTopColor || borderColor}; border-right: ${borderRightWidth || borderWidth} ${borderRightStyle || borderStyle} ${borderRightColor || borderColor}; @@ -170,123 +205,124 @@ export const useStyles = createStyles(({ token, css, cx, prefixCls }, { style, m color: #fff; } `); - const shaStoredFilesRendererHorizontal = cx("sha-stored-files-renderer-horizontal", css` - height: var(--container-height) !important; - width: var(--container-width) !important; - max-height: var(--container-max-height) !important; - max-width: var(--container-max-width) !important; - min-height: var(--container-min-height) !important; - .${prefixCls}-upload-list { - display: flex !important; - flex-wrap: nowrap !important; - flex-direction: row !important; - flex-shrink: 0 !important; - overflow-x: auto; - overflow-y: clip !important; - align-items: center !important; - padding: 0 ${borderWidth ?? '2px'} !important; - height: max-content !important; - width: var(--container-width) !important; - min-width: var(--container-min-width) !important; - max-width: var(--container-max-width) !important; - } - .ant-upload-list-item-container { - display: inline-block !important; - max-width: var(--thumbnail-width) !important; - height: var(--thumbnail-height) !important; - border-radius: ${borderRadius ?? '8px'} !important; - &.ant-upload-animate-inline-appear, - &.ant-upload-animate-inline-appear-active, - &.ant-upload-animate-inline { - display: none !important; - animation: none !important; - transition: none !important; - } - } - `); + // const shaStoredFilesRendererHorizontal = cx("sha-stored-files-renderer-horizontal", css` + // height: var(--container-height) !important; + // width: var(--container-width) !important; + // max-height: var(--container-max-height) !important; + // max-width: var(--container-max-width) !important; + // min-height: var(--container-min-height) !important; + // .${prefixCls}-upload-list { + // display: flex !important; + // flex-wrap: nowrap !important; + // flex-direction: row !important; + // flex-shrink: 0 !important; + // overflow-x: auto; + // overflow-y: clip !important; + // align-items: center !important; + // padding: 0 ${borderWidth ?? '2px'} !important; + // height: max-content !important; + // width: var(--container-width) !important; + // min-width: var(--container-min-width) !important; + // max-width: var(--container-max-width) !important; + // } - const shaStoredFilesRendererVertical = cx("sha-stored-files-renderer-vertical", css` - width: max-content; - max-width: var(--container-max-width) !important; - padding: ${borderWidth ?? '2px'} !important; - width: max-content !important; - height: var(--container-height) !important; - max-height: var(--container-max-height) !important; - min-height: var(--container-min-height) !important; - .${prefixCls}-upload-list { - display: flex !important; - flex-direction: column !important; - flex-wrap: nowrap !important; - padding: 2px ${borderWidth ?? '2px'} !important; - height: var(--container-height) !important; - width: 100% !important; - max-height: calc(var(--container-max-height) - 32px) !important; - min-height: calc(var(--container-min-height) - 32px) !important; - min-height: calc(var(--container-min-height) - 32px) !important; - } + // .ant-upload-list-item-container { + // display: inline-block !important; + // max-width: var(--thumbnail-width) !important; + // height: var(--thumbnail-height) !important; + // border-radius: ${borderRadius ?? '8px'} !important; + // &.ant-upload-animate-inline-appear, + // &.ant-upload-animate-inline-appear-active, + // &.ant-upload-animate-inline { + // display: none !important; + // animation: none !important; + // transition: none !important; + // } + // } + // `); - .stored-files-renderer-btn-container { - justify-content: flex-start; - .ant-btn { - padding: 0; - } - } + // const shaStoredFilesRendererVertical = cx("sha-stored-files-renderer-vertical", css` + // width: max-content; + // max-width: var(--container-max-width) !important; + // padding: ${borderWidth ?? '2px'} !important; + // width: max-content !important; + // height: var(--container-height) !important; + // max-height: var(--container-max-height) !important; + // min-height: var(--container-min-height) !important; + // .${prefixCls}-upload-list { + // display: flex !important; + // flex-direction: column !important; + // flex-wrap: nowrap !important; + // padding: 2px ${borderWidth ?? '2px'} !important; + // height: var(--container-height) !important; + // width: 100% !important; + // max-height: calc(var(--container-max-height) - 32px) !important; + // min-height: calc(var(--container-min-height) - 32px) !important; + // min-height: calc(var(--container-min-height) - 32px) !important; + // } - .ant-upload-list-item-container { - display: inline-block !important; - width: var(--thumbnail-width) !important; - height: var(--thumbnail-height) !important; - border-radius: ${borderRadius ?? '8px'} !important; - &.ant-upload-animate-inline-appear, - &.ant-upload-animate-inline-appear-active, - &.ant-upload-animate-inline { - display: none !important; - animation: none !important; - transition: none !important; - } - } - `); + // .stored-files-renderer-btn-container { + // justify-content: flex-start; + // .ant-btn { + // padding: 0; + // } + // } - const shaStoredFilesRendererGrid = cx("sha-stored-files-renderer-grid", css` - max-width: var(--container-width) !important; - max-height: var(--container-height) !important; + // .ant-upload-list-item-container { + // display: inline-block !important; + // width: var(--thumbnail-width) !important; + // height: var(--thumbnail-height) !important; + // border-radius: ${borderRadius ?? '8px'} !important; + // &.ant-upload-animate-inline-appear, + // &.ant-upload-animate-inline-appear-active, + // &.ant-upload-animate-inline { + // display: none !important; + // animation: none !important; + // transition: none !important; + // } + // } + // `); - .${prefixCls}-upload-list { - align-items: center; - padding: 2px; - height: var(--container-height) !important; - width: var(--container-width) !important; - max-height: var(--container-max-height) !important; - max-width: var(--container-max-width) !important; - min-height: var(--container-min-height) !important; - min-width: var(--container-min-width) !important; - .${prefixCls}-upload-list-item { - width: 100% !important; - height: 100% !important; - } - } + // const shaStoredFilesRendererGrid = cx("sha-stored-files-renderer-grid", css` + // max-width: var(--container-width) !important; + // max-height: var(--container-height) !important; - .ant-upload-list-item-container { - display: inline-block !important; - width: var(--thumbnail-width) !important; - height: var(--thumbnail-height) !important; - border-radius: ${borderRadius ?? '8px'} !important; - &.ant-upload-animate-inline-appear, - &.ant-upload-animate-inline-appear-active, - &.ant-upload-animate-inline { - display: none !important; - animation: none !important; - transition: none !important; - } - } - `); + // .${prefixCls}-upload-list { + // align-items: center; + // padding: 2px; + // height: var(--container-height) !important; + // width: var(--container-width) !important; + // max-height: var(--container-max-height) !important; + // max-width: var(--container-max-width) !important; + // min-height: var(--container-min-height) !important; + // min-width: var(--container-min-width) !important; + // .${prefixCls}-upload-list-item { + // width: 100% !important; + // height: 100% !important; + // } + // } + + // .ant-upload-list-item-container { + // display: inline-block !important; + // width: var(--thumbnail-width) !important; + // height: var(--thumbnail-height) !important; + // border-radius: ${borderRadius ?? '8px'} !important; + // &.ant-upload-animate-inline-appear, + // &.ant-upload-animate-inline-appear-active, + // &.ant-upload-animate-inline { + // display: none !important; + // animation: none !important; + // transition: none !important; + // } + // } + // `); return { shaStoredFilesRenderer, - shaStoredFilesRendererHorizontal, - shaStoredFilesRendererVertical, - shaStoredFilesRendererGrid, + // shaStoredFilesRendererHorizontal, + // shaStoredFilesRendererVertical, + // shaStoredFilesRendererGrid, storedFilesRendererBtnContainer, storedFilesRendererNoFiles, antUploadDragIcon, diff --git a/shesha-reactjs/src/designer-components/fileUpload/index.tsx b/shesha-reactjs/src/designer-components/fileUpload/index.tsx index cb0baa6544..ec53bfab8a 100644 --- a/shesha-reactjs/src/designer-components/fileUpload/index.tsx +++ b/shesha-reactjs/src/designer-components/fileUpload/index.tsx @@ -23,9 +23,7 @@ import { getSizeStyle } from '../_settings/utils/dimensions/utils'; import { getFontStyle } from '../_settings/utils/font/utils'; import { getShadowStyle } from '../_settings/utils/shadow/utils'; import { getBackgroundStyle } from '../_settings/utils/background/utils'; -import { addPx } from '../_settings/utils'; import { listType } from '../attachmentsEditor/attachmentsEditor'; -import { useStyles } from '@/components/fileUpload/styles/styles'; export interface IFileUploadProps extends IConfigurableFormComponent, Omit, IStyleType { ownerId: string; @@ -36,11 +34,11 @@ export interface IFileUploadProps extends IConfigurableFormComponent, Omit = { @@ -50,61 +48,55 @@ const FileUploadComponent: IToolboxComponent = { isInput: true, isOutput: true, Factory: ({ model }) => { - const { backendUrl, httpHeaders } = useSheshaApplication(); - - const dimensions = model?.dimensions; - const border = model?.border; - const font = model?.font; - const shadow = model?.shadow; - const background = model?.background; - const jsStyle = getStyle(model.style, model); - - const dimensionsStyles = useMemo(() => getSizeStyle(dimensions), [dimensions]); - const borderStyles = useMemo(() => getBorderStyle(border, jsStyle), [border, jsStyle]); - const fontStyles = useMemo(() => getFontStyle(font), [font]); - const [backgroundStyles, setBackgroundStyles] = useState({}); - const shadowStyles = useMemo(() => getShadowStyle(shadow), [shadow]); - - useEffect(() => { - - const fetchStyles = async () => { - const storedImageUrl = background?.storedFile?.id && background?.type === 'storedFile' - ? await fetch(`${backendUrl}/api/StoredFile/Download?id=${background?.storedFile?.id}`, - { headers: { ...httpHeaders, "Content-Type": "application/octet-stream" } }) - .then((response) => { - return response.blob(); - }) - .then((blob) => { - return URL.createObjectURL(blob); - }) : ''; - - const style = await getBackgroundStyle(background, jsStyle, storedImageUrl); - setBackgroundStyles(style); - }; - - fetchStyles(); - }, [background, backendUrl, httpHeaders, jsStyle]); - - const styling = JSON.parse(model.stylingBox || '{}'); - const stylingBoxAsCSS = pickStyleFromModel(styling); - - const additionalStyles: CSSProperties = removeUndefinedProps({ - ...stylingBoxAsCSS, - ...dimensionsStyles, - ...borderStyles, - ...fontStyles, - ...backgroundStyles, - ...shadowStyles - }); - - - const finalStyle = removeUndefinedProps(additionalStyles); - - const { styles } = useStyles({ - style: finalStyle, model: { hideFileName: model.hideFileName && model.listType === 'thumbnail', isDragger: model.isDragger } - }); - - console.log(styles, 'styles'); + const { backendUrl, httpHeaders } = useSheshaApplication(); + + const dimensions = model?.dimensions; + const border = model?.border; + const font = model?.font; + const shadow = model?.shadow; + const background = model?.background; + const jsStyle = getStyle(model.style, model); + + const dimensionsStyles = useMemo(() => getSizeStyle(dimensions), [dimensions]); + const borderStyles = useMemo(() => getBorderStyle(border, jsStyle), [border, jsStyle]); + const fontStyles = useMemo(() => getFontStyle(font), [font]); + const [backgroundStyles, setBackgroundStyles] = useState({}); + const shadowStyles = useMemo(() => getShadowStyle(shadow), [shadow]); + + useEffect(() => { + + const fetchStyles = async () => { + const storedImageUrl = background?.storedFile?.id && background?.type === 'storedFile' + ? await fetch(`${backendUrl}/api/StoredFile/Download?id=${background?.storedFile?.id}`, + { headers: { ...httpHeaders, "Content-Type": "application/octet-stream" } }) + .then((response) => { + return response.blob(); + }) + .then((blob) => { + return URL.createObjectURL(blob); + }) : ''; + + const style = getBackgroundStyle(background, jsStyle, storedImageUrl); + setBackgroundStyles(style); + }; + + fetchStyles(); + }, [background, backendUrl, httpHeaders, jsStyle]); + + const styling = JSON.parse(model.stylingBox || '{}'); + const stylingBoxAsCSS = pickStyleFromModel(styling); + + const additionalStyles: CSSProperties = removeUndefinedProps({ + ...stylingBoxAsCSS, + ...dimensionsStyles, + ...borderStyles, + ...fontStyles, + ...backgroundStyles, + ...shadowStyles + }); + + const finalStyle = removeUndefinedProps(additionalStyles); + // TODO: refactor and implement a generic way for values evaluation const { formSettings, formMode } = useForm(); const { data } = useFormData(); @@ -116,7 +108,6 @@ const FileUploadComponent: IToolboxComponent = { return ( {(value, onChange) => { - console.log('model', model); return ( = { allowReplace={enabled && model.allowReplace} allowedFileTypes={model?.allowedFileTypes} isDragger={model?.isDragger} + styles={finalStyle} /> + ); }} @@ -180,7 +173,7 @@ const FileUploadComponent: IToolboxComponent = { .add(3, (prev) => migrateVisibility(prev)) .add(4, (prev) => migrateReadOnly(prev)) .add(5, (prev) => ({ ...migrateFormApi.eventsAndProperties(prev) })) - .add(6, (prev) => ({ ...prev, desktop: { ...defaultStyles() }, mobile: { ...defaultStyles() }, tablet: { ...defaultStyles() } })), + .add(6, (prev) => ({ ...prev, ...defaultStyles(), desktop: { ...defaultStyles() }, mobile: { ...defaultStyles() }, tablet: { ...defaultStyles() } })), settingsFormMarkup: getSettings(), validateSettings: (model) => validateConfigurableComponentSettings(getSettings(), model), }; diff --git a/shesha-starter/intent/ShaCompanyName.ShaProjectName/Intent.Metadata/Visual Studio/ShaCompanyName.ShaProjectName/Elements/ASP.NET Core Web Application/ShaCompanyName.ShaProjectName.Web.Host__d06tm1hb.xml b/shesha-starter/intent/ShaCompanyName.ShaProjectName/Intent.Metadata/Visual Studio/ShaCompanyName.ShaProjectName/Elements/ASP.NET Core Web Application/ShaCompanyName.ShaProjectName.Web.Host__d06tm1hb.xml deleted file mode 100644 index 961d9b8d3e..0000000000 --- a/shesha-starter/intent/ShaCompanyName.ShaProjectName/Intent.Metadata/Visual Studio/ShaCompanyName.ShaProjectName/Elements/ASP.NET Core Web Application/ShaCompanyName.ShaProjectName.Web.Host__d06tm1hb.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - ShaCompanyName.ShaProjectName.Web.Host - ShaCompanyName.ShaProjectName.Web.Host - false - by-type-then-by-name - - false - 3f941b57-60ee-435b-b447-f8787966b1af - 3f941b57-60ee-435b-b447-f8787966b1af - ShaCompanyName.ShaProjectName - - - true - Intent.VisualStudio.Projects - a0636ab7-d3a1-430b-9609-11a18aa3cc7f - - - - - - - - - - - - - - - - true - Intent.VisualStudio.Projects - a0636ab7-d3a1-430b-9609-11a18aa3cc7f - - - - - - - - - - - - Startup - Startup - false - - false - 4686bbad-b46a-49bd-b2c8-727271bea4e5 - 3f941b57-60ee-435b-b447-f8787966b1af - ShaCompanyName.ShaProjectName - - - - - - \ No newline at end of file diff --git a/shesha-starter/intent/ShaCompanyName.ShaProjectName/Intent.Metadata/Visual Studio/ShaCompanyName.ShaProjectName/Elements/Class Library (.NET Core)/ShaCompanyName.ShaProjectName.Application__ht499nxl.xml b/shesha-starter/intent/ShaCompanyName.ShaProjectName/Intent.Metadata/Visual Studio/ShaCompanyName.ShaProjectName/Elements/Class Library (.NET Core)/ShaCompanyName.ShaProjectName.Application__ht499nxl.xml deleted file mode 100644 index 08c7374877..0000000000 --- a/shesha-starter/intent/ShaCompanyName.ShaProjectName/Intent.Metadata/Visual Studio/ShaCompanyName.ShaProjectName/Elements/Class Library (.NET Core)/ShaCompanyName.ShaProjectName.Application__ht499nxl.xml +++ /dev/null @@ -1,104 +0,0 @@ - - - ShaCompanyName.ShaProjectName.Application - ShaCompanyName.ShaProjectName.Application - false - by-type-then-by-name - - false - 3f941b57-60ee-435b-b447-f8787966b1af - 3f941b57-60ee-435b-b447-f8787966b1af - ShaCompanyName.ShaProjectName - - - true - Intent.VisualStudio.Projects - a0636ab7-d3a1-430b-9609-11a18aa3cc7f - - - - - - - - - - - - - - - - true - Intent.VisualStudio.Projects - a0636ab7-d3a1-430b-9609-11a18aa3cc7f - - - - - - - - - - - - Boxfusion.Modules.Application.AutoMapper.MapProfile - Boxfusion.Modules.Application.AutoMapper.MapProfile - false - - false - 3145c5e4-a968-45c3-9afa-7f3883beb67d - 3f941b57-60ee-435b-b447-f8787966b1af - ShaCompanyName.ShaProjectName - - - - - - - - Boxfusion.Modules.Application.Services.AppService - Boxfusion.Modules.Application.Services.AppService - false - - false - 3145c5e4-a968-45c3-9afa-7f3883beb67d - 3f941b57-60ee-435b-b447-f8787966b1af - ShaCompanyName.ShaProjectName - - - - - - - - Boxfusion.Modules.Application.Services.Dto - Boxfusion.Modules.Application.Services.Dto - false - - false - 3145c5e4-a968-45c3-9afa-7f3883beb67d - 3f941b57-60ee-435b-b447-f8787966b1af - ShaCompanyName.ShaProjectName - - - - - - - - Application - Application - false - - false - 3145c5e4-a968-45c3-9afa-7f3883beb67d - 3f941b57-60ee-435b-b447-f8787966b1af - ShaCompanyName.ShaProjectName - - - - - - \ No newline at end of file diff --git a/shesha-starter/intent/ShaCompanyName.ShaProjectName/Intent.Metadata/Visual Studio/ShaCompanyName.ShaProjectName/Elements/Class Library (.NET Core)/ShaCompanyName.ShaProjectName.Domain__1stf96vf.xml b/shesha-starter/intent/ShaCompanyName.ShaProjectName/Intent.Metadata/Visual Studio/ShaCompanyName.ShaProjectName/Elements/Class Library (.NET Core)/ShaCompanyName.ShaProjectName.Domain__1stf96vf.xml deleted file mode 100644 index e319352e4b..0000000000 --- a/shesha-starter/intent/ShaCompanyName.ShaProjectName/Intent.Metadata/Visual Studio/ShaCompanyName.ShaProjectName/Elements/Class Library (.NET Core)/ShaCompanyName.ShaProjectName.Domain__1stf96vf.xml +++ /dev/null @@ -1,171 +0,0 @@ - - - ShaCompanyName.ShaProjectName.Domain - ShaCompanyName.ShaProjectName.Domain - false - by-type-then-by-name - - false - 3f941b57-60ee-435b-b447-f8787966b1af - 3f941b57-60ee-435b-b447-f8787966b1af - ShaCompanyName.ShaProjectName - - - true - Intent.VisualStudio.Projects - a0636ab7-d3a1-430b-9609-11a18aa3cc7f - - - - - - - - - - - - - - - - true - Intent.VisualStudio.Projects - a0636ab7-d3a1-430b-9609-11a18aa3cc7f - - - - - - - - - - - - Boxfusion.Modules.Domain.Entity - Boxfusion.Modules.Domain.Entity - Boxfusion.Modules.Domain - false - - false - 64ce0d1a-eb19-4611-91c9-73a3392ed9b7 - 3f941b57-60ee-435b-b447-f8787966b1af - ShaCompanyName.ShaProjectName - - - - - - - - Boxfusion.Modules.Domain.Enum - Boxfusion.Modules.Domain.Enum - Boxfusion.Modules.Domain - false - - false - 64ce0d1a-eb19-4611-91c9-73a3392ed9b7 - 3f941b57-60ee-435b-b447-f8787966b1af - ShaCompanyName.ShaProjectName - - - - - - - - Boxfusion.Modules.Domain.Module - Boxfusion.Modules.Domain.Module - Boxfusion.Modules.Domain - false - - false - 64ce0d1a-eb19-4611-91c9-73a3392ed9b7 - 3f941b57-60ee-435b-b447-f8787966b1af - ShaCompanyName.ShaProjectName - - - - - - - - Boxfusion.Modules.FluentMigrator.EnumMigration - Boxfusion.Modules.FluentMigrator.EnumMigration - Boxfusion.Modules.FluentMigrator - false - - false - 64ce0d1a-eb19-4611-91c9-73a3392ed9b7 - 3f941b57-60ee-435b-b447-f8787966b1af - ShaCompanyName.ShaProjectName - - - - - - - - Boxfusion.Modules.FluentMigrator.EnumMigrationMetadata - Boxfusion.Modules.FluentMigrator.EnumMigrationMetadata - Boxfusion.Modules.FluentMigrator - false - - false - 64ce0d1a-eb19-4611-91c9-73a3392ed9b7 - 3f941b57-60ee-435b-b447-f8787966b1af - ShaCompanyName.ShaProjectName - - - - - - - - Boxfusion.Modules.FluentMigrator.Migration - Boxfusion.Modules.FluentMigrator.Migration - Boxfusion.Modules.FluentMigrator - false - - false - 64ce0d1a-eb19-4611-91c9-73a3392ed9b7 - 3f941b57-60ee-435b-b447-f8787966b1af - ShaCompanyName.ShaProjectName - - - - - - - - Boxfusion.Modules.FluentMigrator.MigrationMetadata - Boxfusion.Modules.FluentMigrator.MigrationMetadata - Boxfusion.Modules.FluentMigrator - false - - false - 64ce0d1a-eb19-4611-91c9-73a3392ed9b7 - 3f941b57-60ee-435b-b447-f8787966b1af - ShaCompanyName.ShaProjectName - - - - - - - - Domain - Domain - false - - false - 64ce0d1a-eb19-4611-91c9-73a3392ed9b7 - 3f941b57-60ee-435b-b447-f8787966b1af - ShaCompanyName.ShaProjectName - - - - - - \ No newline at end of file diff --git a/shesha-starter/intent/ShaCompanyName.ShaProjectName/Intent.Metadata/Visual Studio/ShaCompanyName.ShaProjectName/Elements/Class Library (.NET Core)/ShaCompanyName.ShaProjectName.Web.Core__k5ykvd6l.xml b/shesha-starter/intent/ShaCompanyName.ShaProjectName/Intent.Metadata/Visual Studio/ShaCompanyName.ShaProjectName/Elements/Class Library (.NET Core)/ShaCompanyName.ShaProjectName.Web.Core__k5ykvd6l.xml deleted file mode 100644 index 4328b65779..0000000000 --- a/shesha-starter/intent/ShaCompanyName.ShaProjectName/Intent.Metadata/Visual Studio/ShaCompanyName.ShaProjectName/Elements/Class Library (.NET Core)/ShaCompanyName.ShaProjectName.Web.Core__k5ykvd6l.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - ShaCompanyName.ShaProjectName.Web.Core - ShaCompanyName.ShaProjectName.Web.Core - false - - false - 3f941b57-60ee-435b-b447-f8787966b1af - 3f941b57-60ee-435b-b447-f8787966b1af - ShaCompanyName.ShaProjectName - - - true - Intent.VisualStudio.Projects - a0636ab7-d3a1-430b-9609-11a18aa3cc7f - - - - - - - - - - - - - - - - true - Intent.VisualStudio.Projects - a0636ab7-d3a1-430b-9609-11a18aa3cc7f - - - - - - - - - - - \ No newline at end of file From 46e8b307e8d7f7e2b72e3e1159f43d353a950c33 Mon Sep 17 00:00:00 2001 From: Tshepo Date: Wed, 2 Apr 2025 21:07:50 +0200 Subject: [PATCH 05/21] fix: importing the download icon --- .../src/components/fileUpload/index.tsx | 125 ++++++++++-------- 1 file changed, 73 insertions(+), 52 deletions(-) diff --git a/shesha-reactjs/src/components/fileUpload/index.tsx b/shesha-reactjs/src/components/fileUpload/index.tsx index a67d4040b5..a749295200 100644 --- a/shesha-reactjs/src/components/fileUpload/index.tsx +++ b/shesha-reactjs/src/components/fileUpload/index.tsx @@ -2,6 +2,7 @@ import { listType } from '@/designer-components/attachmentsEditor/attachmentsEdi import { useSheshaApplication, useStoredFile } from '@/providers'; import { DeleteOutlined, + DownloadOutlined, InfoCircleOutlined, LoadingOutlined, SyncOutlined, @@ -65,12 +66,21 @@ export const FileUpload: FC = ({ } = useStoredFile(); const { backendUrl, httpHeaders } = useSheshaApplication(); - const { styles } = useStyles({ styles: stylesProp, model: { layout: listType === 'thumbnail' && !isDragger, hideFileName: hideFileName && listType === 'thumbnail', isDragger } }); + const { styles } = useStyles({ + styles: stylesProp, + model: { + layout: listType === 'thumbnail' && !isDragger, + hideFileName: hideFileName && listType === 'thumbnail', + isDragger, + }, + }); const uploadButtonRef = useRef(null); const uploadDraggerSpanRef = useRef(null); const { message } = App.useApp(); const [imageUrl, setImageUrl] = useState(''); const [previewOpen, setPreviewOpen] = useState(false); + const [previewImage, setPreviewImage] = useState({ url: '', uid: '', name: '' }); + const onCustomRequest = ({ file /*, onError, onSuccess*/ }: RcCustomRequestOptions) => { // call action from context uploadFile({ file: file as File }, callback); @@ -98,32 +108,32 @@ export const FileUpload: FC = ({ deleteFile(); }; - const fileControls = () => { - return ( - - {fileInfo && ( - - {false && } - - - )} - {allowReplace && ( - - - - )} - {allowDelete && ( - - - - )} - - ); - }; + // const fileControls = () => { + // return ( + // + // {fileInfo && ( + // + // {false && } + // + // + // )} + // {allowReplace && ( + // + // + // + // )} + // {allowDelete && ( + // + // + // + // )} + // + // ); + // }; + const url = `${backendUrl}${fileInfo?.url}`; useEffect(() => { - fetch(`${backendUrl}${fileInfo?.url}`, - { headers: { ...httpHeaders, "Content-Type": "application/octet-stream" } }) + fetch(url, { headers: { ...httpHeaders, 'Content-Type': 'application/octet-stream' } }) .then((response) => { return response.blob(); }) @@ -133,7 +143,6 @@ export const FileUpload: FC = ({ .then((url) => { setImageUrl(url); }); - }, [fileInfo]); const iconRender = (fileInfo) => { @@ -155,7 +164,10 @@ export const FileUpload: FC = ({ listType: listType === 'text' ? 'text' : 'picture-card', fileList: fileInfo ? [fileInfo] : [], customRequest: onCustomRequest, - onPreview: () => setPreviewOpen(true), + onPreview: () => { + setPreviewImage({ url, uid: fileInfo.id, name: fileInfo.name }); + setPreviewOpen(true); + }, onChange(info) { if (info.file.status !== 'uploading') { // @@ -191,7 +203,11 @@ export const FileUpload: FC = ({ const renderStub = () => { if (isDragger) { - return ; + return ( + + + + ); } return
{uploadButton}
; @@ -200,37 +216,42 @@ export const FileUpload: FC = ({ const renderUploader = () => { if (isDragger && allowUpload) { return ( - + ); } - return ( - - {allowUpload && !fileInfo && uploadButton} - - ); + return {allowUpload && !fileInfo && uploadButton}; }; - - return <> - {isStub ? renderStub() : renderUploader()} - {previewOpen && ( - setPreviewOpen(visible), - afterOpenChange: (visible) => !visible, - toolbarRender: (original) => { - return
downloadFile({ fileId: previewImage.uid, fileName: previewImage.name })} />{original}
; - }, - }} - src={imageUrl} - /> - )} - ; + return ( + <> + {isStub ? renderStub() : renderUploader()} + {previewOpen && ( + setPreviewOpen(visible), + afterOpenChange: (visible) => !visible, + toolbarRender: (original) => { + return ( +
+ downloadFile({ fileId: previewImage.uid, fileName: previewImage.name })} + /> + {original} +
+ ); + }, + }} + src={imageUrl} + /> + )} + + ); }; export default FileUpload; From 67612899460b3b2fcac72c62054127d0d6a39513 Mon Sep 17 00:00:00 2001 From: Tshepo Date: Fri, 4 Apr 2025 09:33:06 +0200 Subject: [PATCH 06/21] chore: dynamically showing file controls --- .../src/components/fileUpload/index.tsx | 136 ++++++++++++------ 1 file changed, 89 insertions(+), 47 deletions(-) diff --git a/shesha-reactjs/src/components/fileUpload/index.tsx b/shesha-reactjs/src/components/fileUpload/index.tsx index a749295200..3f21783205 100644 --- a/shesha-reactjs/src/components/fileUpload/index.tsx +++ b/shesha-reactjs/src/components/fileUpload/index.tsx @@ -3,6 +3,7 @@ import { useSheshaApplication, useStoredFile } from '@/providers'; import { DeleteOutlined, DownloadOutlined, + EyeOutlined, InfoCircleOutlined, LoadingOutlined, SyncOutlined, @@ -10,14 +11,14 @@ import { } from '@ant-design/icons'; import { App, Button, Upload } from 'antd'; import { UploadProps } from 'antd/lib/upload/Upload'; -import filesize from 'filesize'; import { UploadRequestOption as RcCustomRequestOptions } from 'rc-upload/lib/interface'; import React, { FC, useEffect, useRef, useState } from 'react'; -import { FileVersionsPopup } from './fileVersionsPopup'; import { DraggerStub } from './stubs'; import { useStyles } from './styles/styles'; import { isImageType, getFileIcon } from '@/icons/fileIcons'; import { Image } from 'antd/lib'; +import filesize from 'filesize'; +import FileVersionsPopup from './fileVersionsPopup'; const { Dragger } = Upload; export interface IFileUploadProps { @@ -91,11 +92,11 @@ export const FileUpload: FC = ({ downloadFile({ fileId: fileInfo.id, fileName: fileInfo.name }); }; - const onReplaceClick = (e: React.MouseEvent) => { + const onReplaceClick = (e) => { e.preventDefault(); if (!isDragger) { - uploadButtonRef.current.click(); + uploadButtonRef?.current?.click(); } else { if (uploadDraggerSpanRef.current) { uploadDraggerSpanRef.current.click(); @@ -108,28 +109,71 @@ export const FileUpload: FC = ({ deleteFile(); }; - // const fileControls = () => { - // return ( - // - // {fileInfo && ( - // - // {false && } - // - // - // )} - // {allowReplace && ( - // - // - // - // )} - // {allowDelete && ( - // - // - // - // )} - // - // ); - // }; + const onPreview = () => { + setPreviewImage({ url, uid: fileInfo.id, name: fileInfo.name }); + setPreviewOpen(true); + }; + + const fileControls = () => { + return ( + <> + + {false && } + + + {allowReplace && ( + onReplaceClick(e)} style={{ color: '#000' }}> + + + )} + {allowDelete && ( + onDeleteClick(e)} style={{ color: '#000' }}> + + + )} + { + + + + } + + ); + }; + const styledfileControls = () => { + return ( + fileInfo && ( +
+ {fileInfo.name} +
+ {fileControls()} +
+
+ ) + ); + }; const url = `${backendUrl}${fileInfo?.url}`; useEffect(() => { @@ -145,29 +189,24 @@ export const FileUpload: FC = ({ }); }, [fileInfo]); - const iconRender = (fileInfo) => { - const { type, name } = fileInfo; - if (isImageType(type)) { - if (listType === 'thumbnail' && !isDragger) { - return {name}; - } - } + // const iconRender = (fileInfo) => { + // const { type, name } = fileInfo; + // if (isImageType(type)) { + // if (listType === 'thumbnail' && !isDragger) { + // return {name}; + // } + // } - return getFileIcon(type); - }; + // return getFileIcon(type); + // }; const fileProps: UploadProps = { name: 'file', - disabled: readonly && allowUpload, + disabled: !allowUpload, accept: allowedFileTypes?.join(','), multiple: false, - listType: listType === 'text' ? 'text' : 'picture-card', fileList: fileInfo ? [fileInfo] : [], customRequest: onCustomRequest, - onPreview: () => { - setPreviewImage({ url, uid: fileInfo.id, name: fileInfo.name }); - setPreviewOpen(true); - }, onChange(info) { if (info.file.status !== 'uploading') { // @@ -178,13 +217,16 @@ export const FileUpload: FC = ({ message.error(`${info.file.name} file upload failed.`); } }, - onRemove: () => deleteFile(), - onDownload: (e) => onDownloadClick(e), - showUploadList: { - showRemoveIcon: allowDelete, - showDownloadIcon: true, + itemRender: (_originNode, file, _currFileList) => { + return ( +
+ {!isUploading && listType === 'thumbnail' ? styledfileControls() : null} + + {file.name} ({filesize(file.size)}){listType === 'text' ? fileControls(): null} + +
+ ); }, - iconRender: iconRender, }; const showUploadButton = allowUpload && !fileInfo && !isUploading; From a56b2f468a36ba371d5738993119b43fdd48aa5a Mon Sep 17 00:00:00 2001 From: Tshepo Date: Fri, 4 Apr 2025 11:35:13 +0200 Subject: [PATCH 07/21] chore: started code refactoring --- .../src/components/fileUpload/index.tsx | 130 +++++++--------- .../components/fileUpload/styles/styles.ts | 140 ++++-------------- 2 files changed, 81 insertions(+), 189 deletions(-) diff --git a/shesha-reactjs/src/components/fileUpload/index.tsx b/shesha-reactjs/src/components/fileUpload/index.tsx index 3f21783205..fb645bfbb4 100644 --- a/shesha-reactjs/src/components/fileUpload/index.tsx +++ b/shesha-reactjs/src/components/fileUpload/index.tsx @@ -1,5 +1,5 @@ import { listType } from '@/designer-components/attachmentsEditor/attachmentsEditor'; -import { useSheshaApplication, useStoredFile } from '@/providers'; +import { useSheshaApplication, useStoredFile, useTheme } from '@/providers'; import { DeleteOutlined, DownloadOutlined, @@ -9,7 +9,7 @@ import { SyncOutlined, UploadOutlined, } from '@ant-design/icons'; -import { App, Button, Upload } from 'antd'; +import { App, Button, Flex, Space, Upload } from 'antd'; import { UploadProps } from 'antd/lib/upload/Upload'; import { UploadRequestOption as RcCustomRequestOptions } from 'rc-upload/lib/interface'; import React, { FC, useEffect, useRef, useState } from 'react'; @@ -75,6 +75,7 @@ export const FileUpload: FC = ({ isDragger, }, }); + const { theme } = useTheme(); const uploadButtonRef = useRef(null); const uploadDraggerSpanRef = useRef(null); const { message } = App.useApp(); @@ -82,16 +83,25 @@ export const FileUpload: FC = ({ const [previewOpen, setPreviewOpen] = useState(false); const [previewImage, setPreviewImage] = useState({ url: '', uid: '', name: '' }); + const url = `${backendUrl}${fileInfo?.url}`; + useEffect(() => { + fetch(url, { headers: { ...httpHeaders, 'Content-Type': 'application/octet-stream' } }) + .then((response) => { + return response.blob(); + }) + .then((blob) => { + return URL.createObjectURL(blob); + }) + .then((url) => { + setImageUrl(url); + }); + }, [fileInfo]); + const onCustomRequest = ({ file /*, onError, onSuccess*/ }: RcCustomRequestOptions) => { // call action from context uploadFile({ file: file as File }, callback); }; - const onDownloadClick = (e) => { - e.preventDefault(); - downloadFile({ fileId: fileInfo.id, fileName: fileInfo.name }); - }; - const onReplaceClick = (e) => { e.preventDefault(); @@ -99,7 +109,7 @@ export const FileUpload: FC = ({ uploadButtonRef?.current?.click(); } else { if (uploadDraggerSpanRef.current) { - uploadDraggerSpanRef.current.click(); + uploadDraggerSpanRef?.current?.click(); } } }; @@ -114,91 +124,70 @@ export const FileUpload: FC = ({ setPreviewOpen(true); }; - const fileControls = () => { + const fileControls = (color: string) => { return ( - <> - + //space between the icons + + {false && } {allowReplace && ( - onReplaceClick(e)} style={{ color: '#000' }}> + onReplaceClick(e)} style={{ color: color }}> )} {allowDelete && ( - onDeleteClick(e)} style={{ color: '#000' }}> + onDeleteClick(e)} style={{ color: color }}> )} { - + } - + ); }; + + const iconRender = (fileInfo) => { + const { type, name } = fileInfo; + if (isImageType(type)) { + if (listType === 'thumbnail' && !isDragger) { + return {name}; + } + } + + return getFileIcon(type); + }; + const styledfileControls = () => { return ( fileInfo && (
- {fileInfo.name} -
- {fileControls()} -
+ {iconRender(fileInfo)} +
{fileControls('#fff')}
) ); }; - const url = `${backendUrl}${fileInfo?.url}`; - useEffect(() => { - fetch(url, { headers: { ...httpHeaders, 'Content-Type': 'application/octet-stream' } }) - .then((response) => { - return response.blob(); - }) - .then((blob) => { - return URL.createObjectURL(blob); - }) - .then((url) => { - setImageUrl(url); - }); - }, [fileInfo]); - - // const iconRender = (fileInfo) => { - // const { type, name } = fileInfo; - // if (isImageType(type)) { - // if (listType === 'thumbnail' && !isDragger) { - // return {name}; - // } - // } + const renderFileItem = (file: any) => { + const showThumbnailControls = !isUploading && listType === 'thumbnail'; + const showTextControls = listType === 'text'; - // return getFileIcon(type); - // }; + return ( + + ); + }; const fileProps: UploadProps = { name: 'file', @@ -217,16 +206,7 @@ export const FileUpload: FC = ({ message.error(`${info.file.name} file upload failed.`); } }, - itemRender: (_originNode, file, _currFileList) => { - return ( -
- {!isUploading && listType === 'thumbnail' ? styledfileControls() : null} - - {file.name} ({filesize(file.size)}){listType === 'text' ? fileControls(): null} - -
- ); - }, + itemRender: (_originNode, file) => renderFileItem(file), }; const showUploadButton = allowUpload && !fileInfo && !isUploading; diff --git a/shesha-reactjs/src/components/fileUpload/styles/styles.ts b/shesha-reactjs/src/components/fileUpload/styles/styles.ts index 6af15e97c1..440b2bc911 100644 --- a/shesha-reactjs/src/components/fileUpload/styles/styles.ts +++ b/shesha-reactjs/src/components/fileUpload/styles/styles.ts @@ -206,126 +206,38 @@ export const useStyles = createStyles(({ token, css, cx, prefixCls }, { style, m } `); - // const shaStoredFilesRendererHorizontal = cx("sha-stored-files-renderer-horizontal", css` - // height: var(--container-height) !important; - // width: var(--container-width) !important; - // max-height: var(--container-max-height) !important; - // max-width: var(--container-max-width) !important; - // min-height: var(--container-min-height) !important; - // .${prefixCls}-upload-list { - // display: flex !important; - // flex-wrap: nowrap !important; - // flex-direction: row !important; - // flex-shrink: 0 !important; - // overflow-x: auto; - // overflow-y: clip !important; - // align-items: center !important; - // padding: 0 ${borderWidth ?? '2px'} !important; - // height: max-content !important; - // width: var(--container-width) !important; - // min-width: var(--container-min-width) !important; - // max-width: var(--container-max-width) !important; - // } - - // .ant-upload-list-item-container { - // display: inline-block !important; - // max-width: var(--thumbnail-width) !important; - // height: var(--thumbnail-height) !important; - // border-radius: ${borderRadius ?? '8px'} !important; - // &.ant-upload-animate-inline-appear, - // &.ant-upload-animate-inline-appear-active, - // &.ant-upload-animate-inline { - // display: none !important; - // animation: none !important; - // transition: none !important; - // } - // } - // `); - - // const shaStoredFilesRendererVertical = cx("sha-stored-files-renderer-vertical", css` - // width: max-content; - // max-width: var(--container-max-width) !important; - // padding: ${borderWidth ?? '2px'} !important; - // width: max-content !important; - // height: var(--container-height) !important; - // max-height: var(--container-max-height) !important; - // min-height: var(--container-min-height) !important; - // .${prefixCls}-upload-list { - // display: flex !important; - // flex-direction: column !important; - // flex-wrap: nowrap !important; - // padding: 2px ${borderWidth ?? '2px'} !important; - // height: var(--container-height) !important; - // width: 100% !important; - // max-height: calc(var(--container-max-height) - 32px) !important; - // min-height: calc(var(--container-min-height) - 32px) !important; - // min-height: calc(var(--container-min-height) - 32px) !important; - // } - - // .stored-files-renderer-btn-container { - // justify-content: flex-start; - // .ant-btn { - // padding: 0; - // } - // } - - // .ant-upload-list-item-container { - // display: inline-block !important; - // width: var(--thumbnail-width) !important; - // height: var(--thumbnail-height) !important; - // border-radius: ${borderRadius ?? '8px'} !important; - // &.ant-upload-animate-inline-appear, - // &.ant-upload-animate-inline-appear-active, - // &.ant-upload-animate-inline { - // display: none !important; - // animation: none !important; - // transition: none !important; - // } - // } - // `); - - // const shaStoredFilesRendererGrid = cx("sha-stored-files-renderer-grid", css` - // max-width: var(--container-width) !important; - // max-height: var(--container-height) !important; - - // .${prefixCls}-upload-list { - // align-items: center; - // padding: 2px; - // height: var(--container-height) !important; - // width: var(--container-width) !important; - // max-height: var(--container-max-height) !important; - // max-width: var(--container-max-width) !important; - // min-height: var(--container-min-height) !important; - // min-width: var(--container-min-width) !important; - // .${prefixCls}-upload-list-item { - // width: 100% !important; - // height: 100% !important; - // } - // } + const thumbnailControls = cx("thumbnail-controls", css` + width: 90px !important; + height: 90px !important; + object-fit: cover; + border-radius: 8px; + `); - // .ant-upload-list-item-container { - // display: inline-block !important; - // width: var(--thumbnail-width) !important; - // height: var(--thumbnail-height) !important; - // border-radius: ${borderRadius ?? '8px'} !important; - // &.ant-upload-animate-inline-appear, - // &.ant-upload-animate-inline-appear-active, - // &.ant-upload-animate-inline { - // display: none !important; - // animation: none !important; - // transition: none !important; - // } - // } - // `); + const overlayThumbnailControls = cx("overlay-thumbnail-controls", css` + position: absolute; + top: 0; + right: 0; + background: rgba(0, 0, 0, 0.6); + height: 100%; + width:100%; + opacity: 0; + border-radius: 8px; + transition: opacity 0.3s ease; + display: flex; + justify-content: center; + align-items: center; + &:hover { + opacity: 1; + } + `); return { shaStoredFilesRenderer, - // shaStoredFilesRendererHorizontal, - // shaStoredFilesRendererVertical, - // shaStoredFilesRendererGrid, storedFilesRendererBtnContainer, storedFilesRendererNoFiles, antUploadDragIcon, - antPreviewDownloadIcon + antPreviewDownloadIcon, + thumbnailControls, + overlayThumbnailControls }; }); \ No newline at end of file From fd900b2a03c98b94634e97ffa0737c8ace019375 Mon Sep 17 00:00:00 2001 From: Tshepo Date: Fri, 4 Apr 2025 14:18:18 +0200 Subject: [PATCH 08/21] fix: fix the dragger stub --- .../src/components/fileUpload/index.tsx | 23 ++++++++++--------- .../src/components/fileUpload/stubs.tsx | 7 ++---- .../components/fileUpload/styles/styles.ts | 10 +++++--- .../storedFilesRendererBase/index.tsx | 4 ++-- .../fileUpload/settingsForm.ts | 2 -- 5 files changed, 23 insertions(+), 23 deletions(-) diff --git a/shesha-reactjs/src/components/fileUpload/index.tsx b/shesha-reactjs/src/components/fileUpload/index.tsx index fb645bfbb4..a0af0af5db 100644 --- a/shesha-reactjs/src/components/fileUpload/index.tsx +++ b/shesha-reactjs/src/components/fileUpload/index.tsx @@ -1,24 +1,23 @@ import { listType } from '@/designer-components/attachmentsEditor/attachmentsEditor'; +import { getFileIcon, isImageType } from '@/icons/fileIcons'; import { useSheshaApplication, useStoredFile, useTheme } from '@/providers'; import { DeleteOutlined, DownloadOutlined, EyeOutlined, InfoCircleOutlined, - LoadingOutlined, SyncOutlined, UploadOutlined, } from '@ant-design/icons'; -import { App, Button, Flex, Space, Upload } from 'antd'; +import { App, Button, Space, Upload } from 'antd'; +import { Image } from 'antd/lib'; import { UploadProps } from 'antd/lib/upload/Upload'; +import filesize from 'filesize'; import { UploadRequestOption as RcCustomRequestOptions } from 'rc-upload/lib/interface'; import React, { FC, useEffect, useRef, useState } from 'react'; +import FileVersionsPopup from './fileVersionsPopup'; import { DraggerStub } from './stubs'; import { useStyles } from './styles/styles'; -import { isImageType, getFileIcon } from '@/icons/fileIcons'; -import { Image } from 'antd/lib'; -import filesize from 'filesize'; -import FileVersionsPopup from './fileVersionsPopup'; const { Dragger } = Upload; export interface IFileUploadProps { @@ -67,14 +66,16 @@ export const FileUpload: FC = ({ } = useStoredFile(); const { backendUrl, httpHeaders } = useSheshaApplication(); - const { styles } = useStyles({ - styles: stylesProp, + + const props = { + style: stylesProp, model: { layout: listType === 'thumbnail' && !isDragger, hideFileName: hideFileName && listType === 'thumbnail', isDragger, }, - }); + }; + const { styles } = useStyles(props); const { theme } = useTheme(); const uploadButtonRef = useRef(null); const uploadDraggerSpanRef = useRef(null); @@ -227,7 +228,7 @@ export const FileUpload: FC = ({ if (isDragger) { return ( - + ); } @@ -240,7 +241,7 @@ export const FileUpload: FC = ({ return ( - + ); } diff --git a/shesha-reactjs/src/components/fileUpload/stubs.tsx b/shesha-reactjs/src/components/fileUpload/stubs.tsx index 5c2b505cd8..4b36e43469 100644 --- a/shesha-reactjs/src/components/fileUpload/stubs.tsx +++ b/shesha-reactjs/src/components/fileUpload/stubs.tsx @@ -1,10 +1,7 @@ -import React, { FC } from 'react'; +import React from 'react'; import { InboxOutlined } from '@ant-design/icons'; -import { useStyles } from './styles/styles'; - -export const DraggerStub: FC = () => { - const { styles } = useStyles(); +export const DraggerStub = ({styles}) => { return (

diff --git a/shesha-reactjs/src/components/fileUpload/styles/styles.ts b/shesha-reactjs/src/components/fileUpload/styles/styles.ts index 440b2bc911..b9e0f59b7a 100644 --- a/shesha-reactjs/src/components/fileUpload/styles/styles.ts +++ b/shesha-reactjs/src/components/fileUpload/styles/styles.ts @@ -1,7 +1,6 @@ import { createStyles } from '@/styles'; export const useStyles = createStyles(({ token, css, cx, prefixCls }, { style, model }) => { - const { background = 'transparent', backgroundImage, @@ -45,10 +44,13 @@ export const useStyles = createStyles(({ token, css, cx, prefixCls }, { style, m const { gap, layout, hideFileName, isDragger } = model; + const antUploadDragIcon = `${prefixCls}-upload-drag-icon`; + const antUploadText = `${prefixCls}-upload-text`; + const antUploadHint = `${prefixCls}-upload-hint`; + const storedFilesRendererBtnContainer = "stored-files-renderer-btn-container"; const storedFilesRendererNoFiles = "stored-files-renderer-no-files"; - const antUploadDragIcon = `${prefixCls}-upload-drag-icon`; const shaStoredFilesRenderer = cx("sha-stored-files-renderer", css` --thumbnail-width: ${layout ? (width ?? height ?? '54px') : '100%'}; --thumbnail-height: ${layout ? (height ?? width ?? '54px') : '100%'}; @@ -238,6 +240,8 @@ export const useStyles = createStyles(({ token, css, cx, prefixCls }, { style, m antUploadDragIcon, antPreviewDownloadIcon, thumbnailControls, - overlayThumbnailControls + overlayThumbnailControls, + antUploadText, + antUploadHint, }; }); \ No newline at end of file diff --git a/shesha-reactjs/src/components/storedFilesRendererBase/index.tsx b/shesha-reactjs/src/components/storedFilesRendererBase/index.tsx index 26b4bccea8..315f832b87 100644 --- a/shesha-reactjs/src/components/storedFilesRendererBase/index.tsx +++ b/shesha-reactjs/src/components/storedFilesRendererBase/index.tsx @@ -307,12 +307,12 @@ export const StoredFilesRendererBase: FC = ({ > {isStub ? (isDragger - ? + ? :

{renderUploadContent()}
) : (props.disabled ? : isDragger - ? + ? : {!disabled ? renderUploadContent() : null}) } diff --git a/shesha-reactjs/src/designer-components/fileUpload/settingsForm.ts b/shesha-reactjs/src/designer-components/fileUpload/settingsForm.ts index f694fee746..2b8b3abefd 100644 --- a/shesha-reactjs/src/designer-components/fileUpload/settingsForm.ts +++ b/shesha-reactjs/src/designer-components/fileUpload/settingsForm.ts @@ -3,12 +3,10 @@ import { fontTypes, fontWeights, textAlign } from '../_settings/utils/font/utils import { getBorderInputs } from '../_settings/utils/border/utils'; import { getCornerInputs } from '../_settings/utils/border/utils'; import { - backgroundTypeOptions, positionOptions, repeatOptions, sizeOptions, } from '../_settings/utils/background/utils'; -import { nanoid } from '@/utils/uuid'; import { FormLayout } from 'antd/es/form/Form'; export const getSettings = () => { From 5b3b4ba86d8263c730834fac0228d0c35982bff0 Mon Sep 17 00:00:00 2001 From: Tshepo Date: Sun, 6 Apr 2025 11:20:31 +0200 Subject: [PATCH 09/21] chore: passing down styles into the Dragger stub component --- shesha-reactjs/src/components/fileUpload/index.tsx | 13 +++++++------ .../components/storedFilesRendererBase/index.tsx | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/shesha-reactjs/src/components/fileUpload/index.tsx b/shesha-reactjs/src/components/fileUpload/index.tsx index a0af0af5db..a99ed2f98d 100644 --- a/shesha-reactjs/src/components/fileUpload/index.tsx +++ b/shesha-reactjs/src/components/fileUpload/index.tsx @@ -103,14 +103,14 @@ export const FileUpload: FC = ({ uploadFile({ file: file as File }, callback); }; - const onReplaceClick = (e) => { + const onReplaceClick = (e: React.MouseEvent) => { e.preventDefault(); if (!isDragger) { - uploadButtonRef?.current?.click(); + uploadButtonRef.current.click(); } else { if (uploadDraggerSpanRef.current) { - uploadDraggerSpanRef?.current?.click(); + uploadDraggerSpanRef.current.click(); } } }; @@ -134,10 +134,11 @@ export const FileUpload: FC = ({ {allowReplace && ( - onReplaceClick(e)} style={{ color: color }}> + )} + {allowDelete && ( onDeleteClick(e)} style={{ color: color }}> @@ -211,7 +212,7 @@ export const FileUpload: FC = ({ }; const showUploadButton = allowUpload && !fileInfo && !isUploading; - // const classes = classNames(styles.shaUpload, { [styles.shaUploadHasFile]: fileInfo || isUploading }); + // const classes = classNames(styles.shaUpload, { [styles.shaUploadHasFile]: fileInfo || isUploading }); const uploadButton = ( ); + const renderStub = () => { if (isDragger) { return ( @@ -242,7 +248,7 @@ export const FileUpload: FC = ({ ); } - return
{uploadButton}
; + return
{uploadButton}
; }; const renderUploader = () => { diff --git a/shesha-reactjs/src/components/fileUpload/styles/styles.ts b/shesha-reactjs/src/components/fileUpload/styles/styles.ts index 75bbbf97dd..bec91d9bba 100644 --- a/shesha-reactjs/src/components/fileUpload/styles/styles.ts +++ b/shesha-reactjs/src/components/fileUpload/styles/styles.ts @@ -1,323 +1,318 @@ -import { createStyles } from '@/styles'; - -export const useStyles = createStyles(({ token, css, cx, prefixCls }, { style, model }) => { - const { - background = 'transparent', - backgroundImage, - borderRadius = '8px', - borderWidth = '0', - borderTopWidth, - width, - minWidth, - maxWidth, - borderBottomWidth, - borderLeftWidth, - borderLeftColor, - borderLeftStyle, - borderRightColor, - borderRightStyle, - borderColor = 'transparent', - borderTopStyle, - borderTopColor, - borderTop, - boxShadow, - borderBottom, - borderBottomColor, - borderBottomStyle, - borderRight, - borderRightWidth, - backgroundColor = '#fff', - backgroundPosition, - backgroundRepeat, - backgroundSize, - borderStyle = 'solid', - color, - fontFamily = 'Segoe UI', - fontSize = '14px', - fontWeight = '400', - height, - maxHeight, - minHeight, - textAlign = 'center', - ...rest - } = style || {}; - - const { gap, layout, hideFileName, isDragger } = model; - - const antUploadDragIcon = `${prefixCls}-upload-drag-icon`; - const antUploadText = `${prefixCls}-upload-text`; - const antUploadHint = `${prefixCls}-upload-hint`; - - const storedFilesRendererBtnContainer = 'stored-files-renderer-btn-container'; - const storedFilesRendererNoFiles = 'stored-files-renderer-no-files'; - - const shaStoredFilesRenderer = cx( - 'sha-stored-files-renderer', - css` - --thumbnail-width: ${layout ? (width ?? height ?? '60px') : '100%'}; - --thumbnail-height: ${layout ? (height ?? width ?? '60px') : '100%'}; - --ant-margin-xs: ${gap ?? '8px'} !important; - --ant-border-radius-xs: ${borderRadius ?? '8px'} !important; - --ant-border-radius-sm: ${borderRadius ?? '8px'} !important; - --ant-border-radius-lg: ${borderRadius ?? '8px'} !important; - --ant-button-content-font-size: ${fontSize ?? '14px'} !important; - --ant-button-font-weight: ${fontWeight ?? '400'} !important; - --ant-font-family: ${fontFamily ?? 'Segoe UI'} !important; - --ant-button-font-weight: ${fontWeight ?? '400'} !important; - ${rest} - max-height: auto; - - .ant-upload-select-picture-card { - width: var(--thumbnail-width) !important; - height: var(--thumbnail-height) !important; - } - - .ant-upload-list-picture-card-container { - width: var(--thumbnail-width) !important; - height: var(--thumbnail-height) !important; - } - - .ant-upload-list-picture-card .ant-upload-list-item { - width: var(--thumbnail-width) !important; - height: var(--thumbnail-height) !important; - - img { - width: 100% !important; - height: 100% !important; - object-fit: contain !important; - } - } - - .ant-upload-list-picture-card .ant-upload-list-item-thumbnail { - img { - width: 100% !important; - height: 100% !important; - object-fit: contain !important; - } - } - - .ant-upload-list-item-image { - object-fit: contain !important; - width: 100% !important; - height: 100% !important; - } - - .ant-upload:not(.ant-upload-disabled) { - .icon { - color: ${token.colorPrimary} !important; - } - } - - .ant-upload-list-item { - --ant-line-width: 0px !important; - --ant-padding-xs: 0px !important; - --font-size: ${fontSize ?? '14px'} !important; - --ant-font-size: ${fontSize ?? '14px'} !important; - border-radius: ${borderRadius ?? '8px'} !important; - display: flex; - - :before { - top: 0; - width: 100% !important; - border-radius: ${borderRadius ?? '8px'} !important; - height: 100% !important; - } - } - - .ant-upload-list-item-thumbnail { - border-radius: ${borderRadius ?? '8px'} !important; - padding: 0 !important; - background: ${background ?? backgroundImage ?? (backgroundColor || '#fff')} !important; - border: ${borderWidth} ${borderStyle} ${borderColor}; - border-top: ${borderTopWidth || borderWidth} ${borderTopStyle || borderStyle} ${borderTopColor || borderColor}; - border-right: ${borderRightWidth || borderWidth} ${borderRightStyle || borderStyle} - ${borderRightColor || borderColor}; - border-left: ${borderLeftWidth || borderWidth} ${borderLeftStyle || borderStyle} - ${borderLeftColor || borderColor}; - border-bottom: ${borderBottomWidth || borderWidth} ${borderBottomStyle || borderStyle} - ${borderBottomColor || borderColor}; - box-shadow: ${boxShadow}; - - img { - width: var(--thumbnail-width, 54px) !important; - height: var(--thumbnail-height, 54px) !important; - border-radius: ${borderRadius ?? '8px'} !important; - object-fit: cover !important; - display: flex !important; - justify-content: center !important; - } - .ant-image .anticon { - border-radius: ${borderRadius ?? '8px'} !important; - display: block !important; - } - } - - .ant-upload-list-item-name { - display: ${hideFileName ? 'none !important' : 'block'}; - color: ${color ?? token.colorPrimary}; - font-family: ${fontFamily ?? 'Segoe UI'}; - font-size: ${fontSize ?? '14px'}; - font-weight: ${fontWeight ?? '400'}; - text-align: ${textAlign ?? 'center'}; - padding: 0 8px !important; - width: ${(layout && width) ?? '54px'} !important; - font-size: var(--font-size, 14px) !important; - } - - .ant-upload-list-text { - height: calc(var(--container-height) - 32px) !important; - max-height: calc(var(--container-max-height) - calc(${fontSize} * 4)) !important; - min-height: calc(var(--container-min-height) - 32px) !important; - width: calc(var(--container-width) - 32px) !important; - max-width: calc(var(--container-max-width) - 32px) !important; - min-width: calc(var(--container-min-width) - 32px) !important; - } - - .ant-upload-drag:hover:not(.ant-upload-disabled) { - border-color: ${token.colorPrimary} !important; - } - - .${prefixCls}-upload { - ${layout && !isDragger && 'width: var(--thumbnail-width) !important;'}; - ${layout && !isDragger && 'height: var(--thumbnail-height) !important'}; - border-radius: ${borderRadius ?? '8px'} !important; - align-items: center; - - &.${prefixCls}-upload-btn { - .${prefixCls}-upload-drag-icon { - margin: unset; - } - - .${storedFilesRendererNoFiles} { - margin-bottom: 6px; - } - - .ant-upload-select { - align-content: center; - } - } - } - - .ant-btn { - padding: 0; - * { - font-size: ${fontSize ?? '14px'} !important; - font-weight: ${fontWeight ?? '400'} !important; - font-family: ${fontFamily ?? 'Segoe UI'} !important; - } - } - .${storedFilesRendererBtnContainer} { - display: flex; - margin-top: 4px; - justify-content: flex-end; - } - - .${prefixCls}-upload-list { - padding: 2px !important; /*to remove scroller*/ - --ant-margin-xs: ${gap ?? '8px'} !important; - overflow-y: auto; - } - - .ant-upload-list-item-uploading { - display: none; - } - - .ant-upload-list-item-container { - display: inline-block !important; - width: var(--thumbnail-width) !important; - height: var(--thumbnail-height) !important; - border-radius: ${borderRadius ?? '8px'} !important; - &.ant-upload-animate-inline-appear, - &.ant-upload-animate-inline-appear-active, - &.ant-upload-animate-inline { - display: none !important; - animation: none !important; - transition: none !important; - } - } - ` - ); - - const antPreviewDownloadIcon = cx( - 'ant-preview-download-icon', - css` - background: #0000001a; - font-size: 24px; - padding: 8px; - border-radius: 100px; - :hover { - color: #fff; - } - ` - ); - - const thumbnailControls = cx( - 'thumbnail-controls', - css` - width: var(--thumbnail-width, 54px) !important; - height: var(--thumbnail-height, 54px) !important; - border-radius: ${borderRadius ?? '8px'} !important; - object-fit: cover !important; - display: flex !important; - justify-content: center !important; - border-radius: 8px; - ` - ); - - const overlayThumbnailControls = cx( - 'overlay-thumbnail-controls', - css` - position: absolute; - top: 0; - right: 0; - background: rgba(0, 0, 0, 0.6); - height: 100%; - width: 100%; - opacity: 0; - border-radius: 8px; - transition: opacity 0.3s ease; - display: flex; - justify-content: center; - align-items: center; - padding: 4px; - - .ant-space { - display: grid !important; - grid-template-columns: repeat(2, minmax(24px, auto)) !important; - gap: 4px !important; - place-items: center !important; - place-content: center !important; - } - - .ant-space-item { - display: flex; - justify-content: center; - align-items: center; - } - - a { - display: flex; - justify-content: center; - align-items: center; - width: 24px; - height: 24px; - } - - &:hover { - opacity: 1; - } - ` - ); - - return { - shaStoredFilesRenderer, - storedFilesRendererBtnContainer, - storedFilesRendererNoFiles, - antUploadDragIcon, - antPreviewDownloadIcon, - thumbnailControls, - overlayThumbnailControls, - antUploadText, - antUploadHint, - }; -}); +import { createStyles } from '@/styles'; + +export const useStyles = createStyles(({ token, css, cx, prefixCls }, { style, model }) => { + const { + background = 'transparent', + backgroundImage, + borderRadius = '8px', + borderWidth = '0', + borderTopWidth, + width, + minWidth, + maxWidth, + borderBottomWidth, + borderLeftWidth, + borderLeftColor, + borderLeftStyle, + borderRightColor, + borderRightStyle, + borderColor = 'transparent', + borderTopStyle, + borderTopColor, + borderTop, + boxShadow, + borderBottom, + borderBottomColor, + borderBottomStyle, + borderRight, + borderRightWidth, + backgroundColor = '#fff', + backgroundPosition, + backgroundRepeat, + backgroundSize, + borderStyle = 'solid', + color, + fontFamily = 'Segoe UI', + fontSize = '14px', + fontWeight = '400', + height, + maxHeight, + minHeight, + textAlign = 'center', + ...rest + } = style || {}; + + const { layout, isDragger } = model; + + const antUploadDragIcon = `${prefixCls}-upload-drag-icon`; + const antUploadText = `${prefixCls}-upload-text`; + const antUploadHint = `${prefixCls}-upload-hint`; + + const storedFilesRendererBtnContainer = 'stored-files-renderer-btn-container'; + const storedFilesRendererNoFiles = 'stored-files-renderer-no-files'; + + const shaStoredFilesRenderer = cx( + 'sha-stored-files-renderer', + css` + --thumbnail-width: ${layout ? (width ?? height ?? '54px') : '100%'}; + --thumbnail-height: ${layout ? (height ?? width ?? '54px') : '100%'}; + --ant-border-radius-xs: ${borderRadius ?? '8px'} !important; + --ant-border-radius-sm: ${borderRadius ?? '8px'} !important; + --ant-border-radius-lg: ${borderRadius ?? '8px'} !important; + --ant-button-content-font-size: ${fontSize ?? '14px'} !important; + --ant-button-font-weight: ${fontWeight ?? '400'} !important; + --ant-font-family: ${fontFamily ?? 'Segoe UI'} !important; + --ant-button-font-weight: ${fontWeight ?? '400'} !important; + ${rest} + max-height: auto; + height: ${height ?? '54px'} !important; + width: ${width ?? '54px'} !important; + + .ant-upload-select-picture-card { + width: var(--thumbnail-width) !important; + height: var(--thumbnail-height) !important; + } + + .ant-upload-list-picture-card-container { + width: var(--thumbnail-width) !important; + height: var(--thumbnail-height) !important; + } + + .ant-upload-list-picture-card .ant-upload-list-item { + width: var(--thumbnail-width) !important; + height: var(--thumbnail-height) !important; + + img { + width: 100% !important; + height: 100% !important; + object-fit: contain !important; + } + .ant-image .anticon { + border-radius: ${borderRadius ?? '8px'} !important; + display: block !important; + + } + } + + .ant-upload-list-picture-card .ant-upload-list-item-thumbnail { + img { + width: 100% !important; + height: 100% !important; + object-fit: contain !important; + } + } + + .ant-upload-list-item-image { + object-fit: contain !important; + width: 100% !important; + height: 100% !important; + } + + .ant-upload:not(.ant-upload-disabled) { + .icon { + color: ${token.colorPrimary} !important; + } + } + + .ant-upload-list-item { + --ant-line-width: 0px !important; + --ant-padding-xs: 0px !important; + --font-size: ${fontSize ?? '14px'} !important; + --ant-font-size: ${fontSize ?? '14px'} !important; + border-radius: ${borderRadius ?? '8px'} !important; + display: flex; + + :before { + top: 0; + width: 100% !important; + border-radius: ${borderRadius ?? '8px'} !important; + height: 100% !important; + } + } + + .ant-upload-list-item-thumbnail { + border-radius: ${borderRadius ?? '8px'} !important; + padding: 0 !important; + background: ${background ?? backgroundImage ?? (backgroundColor || '#fff')} !important; + border: ${borderWidth} ${borderStyle} ${borderColor}; + border-top: ${borderTopWidth || borderWidth} ${borderTopStyle || borderStyle} ${borderTopColor || borderColor}; + border-right: ${borderRightWidth || borderWidth} ${borderRightStyle || borderStyle} + ${borderRightColor || borderColor}; + border-left: ${borderLeftWidth || borderWidth} ${borderLeftStyle || borderStyle} + ${borderLeftColor || borderColor}; + border-bottom: ${borderBottomWidth || borderWidth} ${borderBottomStyle || borderStyle} + ${borderBottomColor || borderColor}; + box-shadow: ${boxShadow}; + + img { + width: var(--thumbnail-width, 54px) !important; + height: var(--thumbnail-height, 54px) !important; + border-radius: ${borderRadius ?? '8px'} !important; + object-fit: cover !important; + display: flex !important; + justify-content: center !important; + } + .ant-image .anticon { + border-radius: ${borderRadius ?? '8px'} !important; + display: block !important; + } + } + + .ant-upload-list-item-name { + display: 'block'; + color: ${color ?? token.colorPrimary}; + font-family: ${fontFamily ?? 'Segoe UI'}; + font-size: ${fontSize ?? '14px'}; + font-weight: ${fontWeight ?? '400'}; + text-align: ${textAlign ?? 'center'}; + padding: 0 8px !important; + width: ${(layout && width) ?? '54px'} !important; + font-size: var(--font-size, 14px) !important; + } + + .thumbnail-stub { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + ${style} + } + + .ant-upload-list-text { + height: calc(var(--container-height) - 32px) !important; + max-height: calc(var(--container-max-height) - calc(${fontSize} * 4)) !important; + min-height: calc(var(--container-min-height) - 32px) !important; + width: calc(var(--container-width) - 32px) !important; + max-width: calc(var(--container-max-width) - 32px) !important; + min-width: calc(var(--container-min-width) - 32px) !important; + } + + .ant-upload-drag:hover:not(.ant-upload-disabled) { + border-color: ${token.colorPrimary} !important; + } + + .${prefixCls}-upload { + ${layout && !isDragger && 'width: var(--thumbnail-width) !important;'}; + ${layout && !isDragger && 'height: var(--thumbnail-height) !important'}; + border-radius: ${borderRadius ?? '8px'} !important; + align-items: center; + + &.${prefixCls}-upload-btn { + .${prefixCls}-upload-drag-icon { + margin: unset; + } + + + .ant-upload-select { + align-content: center; + } + } + } + + .ant-btn { + padding: 0; + * { + font-size: ${fontSize ?? '14px'} !important; + font-weight: ${fontWeight ?? '400'} !important; + font-family: ${fontFamily ?? 'Segoe UI'} !important; + } + } + + .ant-upload-list-item-container { + width: var(--thumbnail-width) !important; + height: var(--thumbnail-height) !important; + border-radius: ${borderRadius ?? '8px'} !important; + &.ant-upload-animate-inline-appear, + &.ant-upload-animate-inline-appear-active, + &.ant-upload-animate-inline { + display: none !important; + animation: none !important; + transition: none !important; + } + } + ` + ); + + const antPreviewDownloadIcon = cx( + 'ant-preview-download-icon', + css` + background: #0000001a; + font-size: 24px; + padding: 8px; + border-radius: 100px; + :hover { + color: #fff; + } + ` + ); + + const thumbnailControls = cx( + 'thumbnail-controls', + css` + width: var(--thumbnail-width, 54px) !important; + height: var(--thumbnail-height, 54px) !important; + border-radius: ${borderRadius ?? '8px'} !important; + object-fit: cover !important; + display: flex !important; + justify-content: center !important; + border-radius: 8px; + ` + ); + + const overlayThumbnailControls = cx( + 'overlay-thumbnail-controls', + css` + position: absolute; + top: 0; + left: 0; + background: rgba(0, 0, 0, 0.6); + height: ${height ?? '54px'} !important; + width: ${width ?? '54px'} !important; + opacity: 0; + border-radius: 8px; + transition: opacity 0.3s ease; + display: flex; + justify-content: center; + align-items: center; + padding: 4px; + + .ant-space { + display: grid !important; + grid-template-columns: repeat(2, minmax(24px, auto)) !important; + gap: 4px !important; + place-items: center !important; + place-content: center !important; + } + + .ant-space-item { + display: flex; + justify-content: center; + align-items: center; + } + + a { + display: flex; + justify-content: center; + align-items: center; + width: 24px; + height: 24px; + } + + &:hover { + opacity: 1; + } + ` + ); + + return { + shaStoredFilesRenderer, + storedFilesRendererBtnContainer, + storedFilesRendererNoFiles, + antUploadDragIcon, + antPreviewDownloadIcon, + thumbnailControls, + overlayThumbnailControls, + antUploadText, + antUploadHint, + }; +}); From 49e2641e28edc2f5981456f3941a471bf818d9f1 Mon Sep 17 00:00:00 2001 From: Tshepo Date: Wed, 9 Apr 2025 06:36:11 +0200 Subject: [PATCH 13/21] fix: fixing the style of the thumbnail --- .../src/components/fileUpload/index.tsx | 37 +++-- .../components/fileUpload/styles/styles.ts | 157 +++++++++--------- 2 files changed, 97 insertions(+), 97 deletions(-) diff --git a/shesha-reactjs/src/components/fileUpload/index.tsx b/shesha-reactjs/src/components/fileUpload/index.tsx index 20a3c1e900..a238a6b3eb 100644 --- a/shesha-reactjs/src/components/fileUpload/index.tsx +++ b/shesha-reactjs/src/components/fileUpload/index.tsx @@ -150,15 +150,11 @@ export const FileUpload: FC = ({ )} - {isImageType(fileInfo?.type) ? ( + { - ) : ( - downloadFile({ fileId: fileInfo?.id, fileName: fileInfo?.name })} style={{ color: color }}> - - - )} + } ); }; @@ -177,28 +173,33 @@ export const FileUpload: FC = ({ const styledfileControls = () => { return ( fileInfo && ( -
+
{iconRender(fileInfo)}
{fileControls('#fff')}
) ); }; + const renderFileItem = (file: any) => { const showThumbnailControls = !isUploading && listType === 'thumbnail'; const showTextControls = listType === 'text'; return ( -
-
- {showThumbnailControls && styledfileControls()} -
- {!hideFileName && ( -
- {file.name} ({filesize(file.size)}) -
- )} - {showTextControls && fileControls(theme.application.primaryColor)} + ); }; @@ -248,7 +249,7 @@ export const FileUpload: FC = ({ ); } - return
{uploadButton}
; + return
{uploadButton}
; }; const renderUploader = () => { diff --git a/shesha-reactjs/src/components/fileUpload/styles/styles.ts b/shesha-reactjs/src/components/fileUpload/styles/styles.ts index bec91d9bba..7c69416899 100644 --- a/shesha-reactjs/src/components/fileUpload/styles/styles.ts +++ b/shesha-reactjs/src/components/fileUpload/styles/styles.ts @@ -33,13 +33,13 @@ export const useStyles = createStyles(({ token, css, cx, prefixCls }, { style, m borderStyle = 'solid', color, fontFamily = 'Segoe UI', - fontSize = '14px', + fontSize = '25px', fontWeight = '400', height, maxHeight, minHeight, textAlign = 'center', - ...rest + } = style || {}; const { layout, isDragger } = model; @@ -51,55 +51,60 @@ export const useStyles = createStyles(({ token, css, cx, prefixCls }, { style, m const storedFilesRendererBtnContainer = 'stored-files-renderer-btn-container'; const storedFilesRendererNoFiles = 'stored-files-renderer-no-files'; + const commonBorderStyles = css` + border: ${borderWidth} ${borderStyle} ${borderColor}; + border-top: ${borderTopWidth || borderWidth} ${borderTopStyle || borderStyle} ${borderTopColor || borderColor}; + border-right: ${borderRightWidth || borderWidth} ${borderRightStyle || borderStyle} ${borderRightColor || borderColor}; + border-left: ${borderLeftWidth || borderWidth} ${borderLeftStyle || borderStyle} ${borderLeftColor || borderColor}; + border-bottom: ${borderBottomWidth || borderWidth} ${borderBottomStyle || borderStyle} ${borderBottomColor || borderColor}; + box-shadow: ${boxShadow}; + `; + + const commonTextStyles = css` + color: ${color || token.colorPrimary}; + font-family: ${fontFamily}; + font-size: ${fontSize}; + font-weight: ${fontWeight}; + text-align: ${textAlign}; + `; + const shaStoredFilesRenderer = cx( 'sha-stored-files-renderer', css` --thumbnail-width: ${layout ? (width ?? height ?? '54px') : '100%'}; --thumbnail-height: ${layout ? (height ?? width ?? '54px') : '100%'}; - --ant-border-radius-xs: ${borderRadius ?? '8px'} !important; - --ant-border-radius-sm: ${borderRadius ?? '8px'} !important; - --ant-border-radius-lg: ${borderRadius ?? '8px'} !important; - --ant-button-content-font-size: ${fontSize ?? '14px'} !important; - --ant-button-font-weight: ${fontWeight ?? '400'} !important; - --ant-font-family: ${fontFamily ?? 'Segoe UI'} !important; - --ant-button-font-weight: ${fontWeight ?? '400'} !important; - ${rest} - max-height: auto; + --ant-border-radius-xs: ${borderRadius} !important; + --ant-border-radius-sm: ${borderRadius} !important; + --ant-border-radius-lg: ${borderRadius} !important; + --ant-button-content-font-size: ${fontSize} !important; + --ant-button-font-weight: ${fontWeight} !important; + --ant-font-family: ${fontFamily} !important; height: ${height ?? '54px'} !important; width: ${width ?? '54px'} !important; + max-height: ${maxHeight ?? 'auto'} !important; + min-height: ${minHeight} !important; + max-width: ${maxWidth} !important; + min-width: ${minWidth} !important; .ant-upload-select-picture-card { width: var(--thumbnail-width) !important; height: var(--thumbnail-height) !important; + background-position: ${backgroundPosition} !important; + background-repeat: ${backgroundRepeat} !important; + background-size: ${backgroundSize} !important; } - .ant-upload-list-picture-card-container { - width: var(--thumbnail-width) !important; - height: var(--thumbnail-height) !important; - } - - .ant-upload-list-picture-card .ant-upload-list-item { + .ant-upload-list-item { width: var(--thumbnail-width) !important; - height: var(--thumbnail-height) !important; - - img { - width: 100% !important; - height: 100% !important; - object-fit: contain !important; - } - .ant-image .anticon { - border-radius: ${borderRadius ?? '8px'} !important; - display: block !important; - - } + height: calc(var(--thumbnail-height) + 32px) !important; + border-top: ${borderTop} !important; + border-bottom: ${borderBottom} !important; + border-right: ${borderRight} !important; } - .ant-upload-list-picture-card .ant-upload-list-item-thumbnail { - img { - width: 100% !important; - height: 100% !important; - object-fit: contain !important; - } + .ant-upload-list-picture-card { + height: calc(var(--thumbnail-height) + ${fontSize} * 2 + 32px) !important; + padding-bottom: 1rem; } .ant-upload-list-item-image { @@ -110,64 +115,42 @@ export const useStyles = createStyles(({ token, css, cx, prefixCls }, { style, m .ant-upload:not(.ant-upload-disabled) { .icon { - color: ${token.colorPrimary} !important; + color: ${color || token.colorPrimary} !important; } } .ant-upload-list-item { --ant-line-width: 0px !important; --ant-padding-xs: 0px !important; - --font-size: ${fontSize ?? '14px'} !important; - --ant-font-size: ${fontSize ?? '14px'} !important; - border-radius: ${borderRadius ?? '8px'} !important; + --font-size: ${fontSize} !important; + --ant-font-size: ${fontSize} !important; + border-radius: ${borderRadius} !important; display: flex; :before { top: 0; width: 100% !important; - border-radius: ${borderRadius ?? '8px'} !important; + border-radius: ${borderRadius} !important; height: 100% !important; } } .ant-upload-list-item-thumbnail { - border-radius: ${borderRadius ?? '8px'} !important; + border-radius: ${borderRadius} !important; padding: 0 !important; - background: ${background ?? backgroundImage ?? (backgroundColor || '#fff')} !important; - border: ${borderWidth} ${borderStyle} ${borderColor}; - border-top: ${borderTopWidth || borderWidth} ${borderTopStyle || borderStyle} ${borderTopColor || borderColor}; - border-right: ${borderRightWidth || borderWidth} ${borderRightStyle || borderStyle} - ${borderRightColor || borderColor}; - border-left: ${borderLeftWidth || borderWidth} ${borderLeftStyle || borderStyle} - ${borderLeftColor || borderColor}; - border-bottom: ${borderBottomWidth || borderWidth} ${borderBottomStyle || borderStyle} - ${borderBottomColor || borderColor}; - box-shadow: ${boxShadow}; - - img { - width: var(--thumbnail-width, 54px) !important; - height: var(--thumbnail-height, 54px) !important; - border-radius: ${borderRadius ?? '8px'} !important; - object-fit: cover !important; - display: flex !important; - justify-content: center !important; - } - .ant-image .anticon { - border-radius: ${borderRadius ?? '8px'} !important; - display: block !important; - } + background: ${background ?? backgroundImage ?? backgroundColor} !important; + ${commonBorderStyles} } .ant-upload-list-item-name { - display: 'block'; - color: ${color ?? token.colorPrimary}; - font-family: ${fontFamily ?? 'Segoe UI'}; - font-size: ${fontSize ?? '14px'}; - font-weight: ${fontWeight ?? '400'}; - text-align: ${textAlign ?? 'center'}; + display: block; + ${commonTextStyles} padding: 0 8px !important; width: ${(layout && width) ?? '54px'} !important; - font-size: var(--font-size, 14px) !important; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + max-width: 100%; } .thumbnail-stub { @@ -194,7 +177,7 @@ export const useStyles = createStyles(({ token, css, cx, prefixCls }, { style, m .${prefixCls}-upload { ${layout && !isDragger && 'width: var(--thumbnail-width) !important;'}; ${layout && !isDragger && 'height: var(--thumbnail-height) !important'}; - border-radius: ${borderRadius ?? '8px'} !important; + border-radius: ${borderRadius} !important; align-items: center; &.${prefixCls}-upload-btn { @@ -202,7 +185,6 @@ export const useStyles = createStyles(({ token, css, cx, prefixCls }, { style, m margin: unset; } - .ant-upload-select { align-content: center; } @@ -212,16 +194,16 @@ export const useStyles = createStyles(({ token, css, cx, prefixCls }, { style, m .ant-btn { padding: 0; * { - font-size: ${fontSize ?? '14px'} !important; - font-weight: ${fontWeight ?? '400'} !important; - font-family: ${fontFamily ?? 'Segoe UI'} !important; + font-size: ${fontSize} !important; + font-weight: ${fontWeight} !important; + font-family: ${fontFamily} !important; } } .ant-upload-list-item-container { width: var(--thumbnail-width) !important; height: var(--thumbnail-height) !important; - border-radius: ${borderRadius ?? '8px'} !important; + border-radius: ${borderRadius} !important; &.ant-upload-animate-inline-appear, &.ant-upload-animate-inline-appear-active, &.ant-upload-animate-inline { @@ -251,11 +233,10 @@ export const useStyles = createStyles(({ token, css, cx, prefixCls }, { style, m css` width: var(--thumbnail-width, 54px) !important; height: var(--thumbnail-height, 54px) !important; - border-radius: ${borderRadius ?? '8px'} !important; + border-radius: ${borderRadius} !important; object-fit: cover !important; display: flex !important; justify-content: center !important; - border-radius: 8px; ` ); @@ -304,6 +285,23 @@ export const useStyles = createStyles(({ token, css, cx, prefixCls }, { style, m ` ); + const styledFileControls = cx( + 'styled-file-controls', + css` + ${commonBorderStyles} + ${commonTextStyles} + border-radius: ${borderRadius} !important; + padding: 0 !important; + background: ${background ?? backgroundImage ?? backgroundColor} !important; + width: ${width || '90px'} !important; + height: ${height || '90px'} !important; + display: flex !important; + align-items: center !important; + justify-content: center !important; + font-size: ${fontSize || '14px'} !important; + ` + ); + return { shaStoredFilesRenderer, storedFilesRendererBtnContainer, @@ -314,5 +312,6 @@ export const useStyles = createStyles(({ token, css, cx, prefixCls }, { style, m overlayThumbnailControls, antUploadText, antUploadHint, + styledFileControls, }; }); From 4ccdda4111578ca9c25391d3b87222b6c82428b8 Mon Sep 17 00:00:00 2001 From: Tshepo Date: Thu, 10 Apr 2025 11:18:21 +0200 Subject: [PATCH 14/21] chore: changed the order of the settings --- .../fileUpload/settingsForm.ts | 45 ++++++++++--------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/shesha-reactjs/src/designer-components/fileUpload/settingsForm.ts b/shesha-reactjs/src/designer-components/fileUpload/settingsForm.ts index 2b8b3abefd..34b003f24b 100644 --- a/shesha-reactjs/src/designer-components/fileUpload/settingsForm.ts +++ b/shesha-reactjs/src/designer-components/fileUpload/settingsForm.ts @@ -169,26 +169,6 @@ export const getSettings = () => { id: '9b302942-a0a6-4805-ac47-8f45486a69d4', components: [ ...new DesignerToolbarSettings() - .addSettingsInputRow({ - id: 'display-row-2', - readOnly: { _code: 'return getSettingValue(data?.readOnly);', _mode: 'code', _value: false } as any, - parentId: '9b302942-a0a6-4805-ac47-8f45486a69d4', - inputs: [ - { - id: '3fe73b1a-04c5-4658-ac0f-cbcbae6b3bd4', - propertyName: 'useSync', - label: 'Synchronous Upload', - type: 'switch', - }, - { - id: '3fe73b1a-04c5-4658-ac0f-cbcbae6b3bd4', - propertyName: 'allowedFileTypes', - label: 'Allowed File Types', - type: 'editableTagGroupProps', - description: 'File types that can be accepted.', - }, - ], - }) .addSettingsInputRow({ id: 'display-row-3', readOnly: { _code: 'return getSettingValue(data?.readOnly);', _mode: 'code', _value: false } as any, @@ -211,6 +191,26 @@ export const getSettings = () => { }, ], }) + .addSettingsInputRow({ + id: 'display-row-2', + readOnly: { _code: 'return getSettingValue(data?.readOnly);', _mode: 'code', _value: false } as any, + parentId: '9b302942-a0a6-4805-ac47-8f45486a69d4', + inputs: [ + { + id: '3fe73b1a-04c5-4658-ac0f-cbcbae6b3bd4', + propertyName: 'useSync', + label: 'Synchronous Upload', + type: 'switch', + }, + { + id: '3fe73b1a-04c5-4658-ac0f-cbcbae6b3bd4', + propertyName: 'allowedFileTypes', + label: 'Allowed File Types', + type: 'editableTagGroupProps', + description: 'File types that can be accepted.', + }, + ], + }) .toJson(), ], }, @@ -307,6 +307,7 @@ export const getSettings = () => { propertyName: 'font.align', hideLabel: true, width: 60, + hidden: { _code: 'return getSettingValue(data.listType) !== "thumbnail";', _mode: 'code', _value: false } as any, dropdownOptions: textAlign, }, ], @@ -323,6 +324,7 @@ export const getSettings = () => { labelAlign: 'right', ghost: true, collapsible: 'header', + hidden: { _code: 'return getSettingValue(data.listType) !== "thumbnail";', _mode: 'code', _value: false } as any, content: { id: 'dimensionsStylePnl', components: [...new DesignerToolbarSettings() @@ -409,6 +411,7 @@ export const getSettings = () => { ghost: true, parentId: 'styleRouter', collapsible: 'header', + hidden: { _code: 'return getSettingValue(data.listType) !== "thumbnail";', _mode: 'code', _value: false } as any, content: { id: 'borderStylePnl', components: [...new DesignerToolbarSettings() @@ -451,6 +454,7 @@ export const getSettings = () => { ghost: true, parentId: 'styleRouter', collapsible: 'header', + hidden: { _code: 'return getSettingValue(data.listType) !== "thumbnail";', _mode: 'code', _value: false } as any, content: { id: 'backgroundStylePnl', components: [ @@ -616,6 +620,7 @@ export const getSettings = () => { ghost: true, parentId: 'styleRouter', collapsible: 'header', + hidden: { _code: 'return getSettingValue(data.listType) !== "thumbnail";', _mode: 'code', _value: false } as any, content: { id: 'shadowStylePnl', components: [...new DesignerToolbarSettings() From 62e867e68baed538a935350c22178b0681cfc1ad Mon Sep 17 00:00:00 2001 From: Tshepo Date: Thu, 10 Apr 2025 11:43:06 +0200 Subject: [PATCH 15/21] chore: changing the download to be on the label --- .../src/components/fileUpload/index.tsx | 43 ++++++++++++++----- .../components/fileUpload/styles/styles.ts | 22 ++++++---- .../src/designer-components/link/index.tsx | 2 +- 3 files changed, 46 insertions(+), 21 deletions(-) diff --git a/shesha-reactjs/src/components/fileUpload/index.tsx b/shesha-reactjs/src/components/fileUpload/index.tsx index a238a6b3eb..0a52c234ba 100644 --- a/shesha-reactjs/src/components/fileUpload/index.tsx +++ b/shesha-reactjs/src/components/fileUpload/index.tsx @@ -70,6 +70,7 @@ export const FileUpload: FC = ({ model: { layout: listType === 'thumbnail' && !isDragger, isDragger, + hideFileName, }, }; const { styles } = useStyles(props); @@ -150,11 +151,17 @@ export const FileUpload: FC = ({ )} - { + {isImageType(fileInfo?.type) ? ( - } + ) : ( + hideFileName && ( + downloadFile({ fileId: fileInfo?.id, fileName: fileInfo?.name })} style={{ color: color }}> + + + ) + )} ); }; @@ -163,7 +170,7 @@ export const FileUpload: FC = ({ const { type, name } = fileInfo; if (isImageType(type)) { if (listType === 'thumbnail' && !isDragger) { - return {name}; + return {name}; } } @@ -175,7 +182,9 @@ export const FileUpload: FC = ({ fileInfo && (
{iconRender(fileInfo)} -
{fileControls('#fff')}
+
+ {fileControls('#fff')} +
) ); @@ -191,12 +200,14 @@ export const FileUpload: FC = ({ {isUploading ? ( - + + + ) : ( - <> - {(listType === 'text' || !hideFileName) && `${file.name} (${filesize(file.size)})`} + )} @@ -239,7 +250,6 @@ export const FileUpload: FC = ({ ); - const renderStub = () => { if (isDragger) { return ( @@ -249,11 +259,22 @@ export const FileUpload: FC = ({ ); } - return
{uploadButton}
; + return ( + <> +
+ {uploadButton} +
+ {listType === 'thumbnail' ?
File name
: null} + + ); }; const renderUploader = () => { - const antListType = listType === 'thumbnail' ? 'picture-card' : 'text'; + const antListType = listType === 'thumbnail' ? 'picture-card' : 'text'; if (isDragger && allowUpload) { return ( diff --git a/shesha-reactjs/src/components/fileUpload/styles/styles.ts b/shesha-reactjs/src/components/fileUpload/styles/styles.ts index 7c69416899..cf6e08dd1e 100644 --- a/shesha-reactjs/src/components/fileUpload/styles/styles.ts +++ b/shesha-reactjs/src/components/fileUpload/styles/styles.ts @@ -42,7 +42,7 @@ export const useStyles = createStyles(({ token, css, cx, prefixCls }, { style, m } = style || {}; - const { layout, isDragger } = model; + const { layout, isDragger, hideFileName } = model; const antUploadDragIcon = `${prefixCls}-upload-drag-icon`; const antUploadText = `${prefixCls}-upload-text`; @@ -67,7 +67,6 @@ export const useStyles = createStyles(({ token, css, cx, prefixCls }, { style, m font-weight: ${fontWeight}; text-align: ${textAlign}; `; - const shaStoredFilesRenderer = cx( 'sha-stored-files-renderer', css` @@ -103,7 +102,7 @@ export const useStyles = createStyles(({ token, css, cx, prefixCls }, { style, m } .ant-upload-list-picture-card { - height: calc(var(--thumbnail-height) + ${fontSize} * 2 + 32px) !important; + height: ${hideFileName ? 'var(--thumbnail-height) )' : `calc(var(--thumbnail-height) + ${fontSize} * 2 + 32px)`} !important; padding-bottom: 1rem; } @@ -138,12 +137,10 @@ export const useStyles = createStyles(({ token, css, cx, prefixCls }, { style, m .ant-upload-list-item-thumbnail { border-radius: ${borderRadius} !important; padding: 0 !important; - background: ${background ?? backgroundImage ?? backgroundColor} !important; ${commonBorderStyles} } .ant-upload-list-item-name { - display: block; ${commonTextStyles} padding: 0 8px !important; width: ${(layout && width) ?? '54px'} !important; @@ -153,6 +150,10 @@ export const useStyles = createStyles(({ token, css, cx, prefixCls }, { style, m max-width: 100%; } + .thumbnail-item-name{ + ${commonTextStyles} + } + .thumbnail-stub { display: flex; flex-direction: column; @@ -201,6 +202,7 @@ export const useStyles = createStyles(({ token, css, cx, prefixCls }, { style, m } .ant-upload-list-item-container { + background: ${backgroundImage ?? (backgroundColor || '#fff')} !important; width: var(--thumbnail-width) !important; height: var(--thumbnail-height) !important; border-radius: ${borderRadius} !important; @@ -258,17 +260,19 @@ export const useStyles = createStyles(({ token, css, cx, prefixCls }, { style, m padding: 4px; .ant-space { - display: grid !important; - grid-template-columns: repeat(2, minmax(24px, auto)) !important; + display: flex !important; + flex-wrap: wrap !important; + justify-content: center !important; + align-items: center !important; gap: 4px !important; - place-items: center !important; - place-content: center !important; + width: 100% !important; } .ant-space-item { display: flex; justify-content: center; align-items: center; + flex: 0 0 auto; } a { diff --git a/shesha-reactjs/src/designer-components/link/index.tsx b/shesha-reactjs/src/designer-components/link/index.tsx index 2e2a1dce95..4713015602 100644 --- a/shesha-reactjs/src/designer-components/link/index.tsx +++ b/shesha-reactjs/src/designer-components/link/index.tsx @@ -114,7 +114,7 @@ const LinkComponent: IToolboxComponent = { return containerHolder(); } return ( - + {containerHolder()} ); From 734c3f24a0cc8f38d755b414b87ff1ded3eba2dc Mon Sep 17 00:00:00 2001 From: Tshepo Date: Thu, 10 Apr 2025 21:33:30 +0200 Subject: [PATCH 16/21] chore: removing the white background on default styles --- shesha-reactjs/src/components/fileUpload/index.tsx | 12 ++++++++++-- .../src/components/fileUpload/styles/styles.ts | 4 ++-- .../src/designer-components/fileUpload/utils.ts | 2 +- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/shesha-reactjs/src/components/fileUpload/index.tsx b/shesha-reactjs/src/components/fileUpload/index.tsx index 0a52c234ba..38803b483f 100644 --- a/shesha-reactjs/src/components/fileUpload/index.tsx +++ b/shesha-reactjs/src/components/fileUpload/index.tsx @@ -157,7 +157,10 @@ export const FileUpload: FC = ({ ) : ( hideFileName && ( - downloadFile({ fileId: fileInfo?.id, fileName: fileInfo?.name })} style={{ color: color }}> + downloadFile({ fileId: fileInfo?.id, fileName: fileInfo?.name })} + style={{ color: color }} + > ) @@ -205,7 +208,12 @@ export const FileUpload: FC = ({ ) : (
- {(listType === 'text' || !hideFileName) && downloadFile({ fileId: file.id, fileName: file.name })}>{`${file.name} (${filesize(file.size)})`}} + {(listType === 'text' || !hideFileName) && ( + downloadFile({ fileId: file.id, fileName: file.name })} + >{`${file.name} (${filesize(file.size)})`} + )} {showTextControls && fileControls(theme.application.primaryColor)}
)} diff --git a/shesha-reactjs/src/components/fileUpload/styles/styles.ts b/shesha-reactjs/src/components/fileUpload/styles/styles.ts index cf6e08dd1e..134f007ee6 100644 --- a/shesha-reactjs/src/components/fileUpload/styles/styles.ts +++ b/shesha-reactjs/src/components/fileUpload/styles/styles.ts @@ -26,7 +26,7 @@ export const useStyles = createStyles(({ token, css, cx, prefixCls }, { style, m borderBottomStyle, borderRight, borderRightWidth, - backgroundColor = '#fff', + backgroundColor, backgroundPosition, backgroundRepeat, backgroundSize, @@ -202,7 +202,7 @@ export const useStyles = createStyles(({ token, css, cx, prefixCls }, { style, m } .ant-upload-list-item-container { - background: ${backgroundImage ?? (backgroundColor || '#fff')} !important; + background: ${backgroundImage ?? (backgroundColor)} !important; width: var(--thumbnail-width) !important; height: var(--thumbnail-height) !important; border-radius: ${borderRadius} !important; diff --git a/shesha-reactjs/src/designer-components/fileUpload/utils.ts b/shesha-reactjs/src/designer-components/fileUpload/utils.ts index 04e58e7654..565f0d049c 100644 --- a/shesha-reactjs/src/designer-components/fileUpload/utils.ts +++ b/shesha-reactjs/src/designer-components/fileUpload/utils.ts @@ -7,7 +7,7 @@ export const defaultStyles = (): IStyleType => { dimensions: { width: '54px', height: '54px', minHeight: '0px', maxHeight: 'auto', minWidth: '0px', maxWidth: 'auto' }, background: { type: 'color', - color: '#fff', + color: '', repeat: 'no-repeat', size: 'cover', position: 'center', From 6e93b31abef4240a0cfa6a441d19b6269111a0e1 Mon Sep 17 00:00:00 2001 From: Tshepo Date: Thu, 10 Apr 2025 22:46:07 +0200 Subject: [PATCH 17/21] chore: adding a grid template --- .../components/fileUpload/styles/styles.ts | 24 ++++--------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/shesha-reactjs/src/components/fileUpload/styles/styles.ts b/shesha-reactjs/src/components/fileUpload/styles/styles.ts index 134f007ee6..0f90e36afa 100644 --- a/shesha-reactjs/src/components/fileUpload/styles/styles.ts +++ b/shesha-reactjs/src/components/fileUpload/styles/styles.ts @@ -260,27 +260,11 @@ export const useStyles = createStyles(({ token, css, cx, prefixCls }, { style, m padding: 4px; .ant-space { - display: flex !important; - flex-wrap: wrap !important; - justify-content: center !important; - align-items: center !important; + display: grid !important; + grid-template-columns: repeat(2, minmax(24px, auto)) !important; gap: 4px !important; - width: 100% !important; - } - - .ant-space-item { - display: flex; - justify-content: center; - align-items: center; - flex: 0 0 auto; - } - - a { - display: flex; - justify-content: center; - align-items: center; - width: 24px; - height: 24px; + place-items: center !important; + place-content: center !important; } &:hover { From acd1eb1063a6c33419f6ba244b92ec8bc0a53efd Mon Sep 17 00:00:00 2001 From: Tshepo Date: Sun, 13 Apr 2025 16:23:36 +0200 Subject: [PATCH 18/21] chore: changing the casing of API URL --- shesha-reactjs/src/components/fileUpload/styles/styles.ts | 6 ++++++ .../src/designer-components/checkboxGroup/settingsForm.ts | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/shesha-reactjs/src/components/fileUpload/styles/styles.ts b/shesha-reactjs/src/components/fileUpload/styles/styles.ts index 0f90e36afa..2eb9184eda 100644 --- a/shesha-reactjs/src/components/fileUpload/styles/styles.ts +++ b/shesha-reactjs/src/components/fileUpload/styles/styles.ts @@ -287,6 +287,12 @@ export const useStyles = createStyles(({ token, css, cx, prefixCls }, { style, m align-items: center !important; justify-content: center !important; font-size: ${fontSize || '14px'} !important; + + .anticon { + font-size: ${fontSize || '14px'} !important; + width: 100% !important; + height: 100% !important; + } ` ); diff --git a/shesha-reactjs/src/designer-components/checkboxGroup/settingsForm.ts b/shesha-reactjs/src/designer-components/checkboxGroup/settingsForm.ts index fe16e832c4..e941a694c0 100644 --- a/shesha-reactjs/src/designer-components/checkboxGroup/settingsForm.ts +++ b/shesha-reactjs/src/designer-components/checkboxGroup/settingsForm.ts @@ -120,7 +120,7 @@ export const getSettings = (data: any) => { value: 'referenceList', }, { - label: 'Api url', + label: 'Api URL', value: 'url', }, ], From ad0c74ac93112c17fbaff44ad29dafaf3440aa2a Mon Sep 17 00:00:00 2001 From: Tshepo Date: Sun, 13 Apr 2025 22:21:22 +0200 Subject: [PATCH 19/21] chore: hiding the file name by default --- shesha-reactjs/src/components/fileUpload/index.tsx | 2 +- shesha-reactjs/src/components/fileUpload/styles/styles.ts | 8 ++++---- .../src/designer-components/fileUpload/index.tsx | 2 ++ 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/shesha-reactjs/src/components/fileUpload/index.tsx b/shesha-reactjs/src/components/fileUpload/index.tsx index 38803b483f..524ee0de31 100644 --- a/shesha-reactjs/src/components/fileUpload/index.tsx +++ b/shesha-reactjs/src/components/fileUpload/index.tsx @@ -276,7 +276,7 @@ export const FileUpload: FC = ({ > {uploadButton}
- {listType === 'thumbnail' ?
File name
: null} + {listType === 'thumbnail' && !hideFileName ?
File name
: null} ); }; diff --git a/shesha-reactjs/src/components/fileUpload/styles/styles.ts b/shesha-reactjs/src/components/fileUpload/styles/styles.ts index 2eb9184eda..764edaf580 100644 --- a/shesha-reactjs/src/components/fileUpload/styles/styles.ts +++ b/shesha-reactjs/src/components/fileUpload/styles/styles.ts @@ -286,12 +286,12 @@ export const useStyles = createStyles(({ token, css, cx, prefixCls }, { style, m display: flex !important; align-items: center !important; justify-content: center !important; - font-size: ${fontSize || '14px'} !important; .anticon { - font-size: ${fontSize || '14px'} !important; - width: 100% !important; - height: 100% !important; + img{ + object-fit: cover !important; + } + } ` ); diff --git a/shesha-reactjs/src/designer-components/fileUpload/index.tsx b/shesha-reactjs/src/designer-components/fileUpload/index.tsx index ec53bfab8a..9ced0ec494 100644 --- a/shesha-reactjs/src/designer-components/fileUpload/index.tsx +++ b/shesha-reactjs/src/designer-components/fileUpload/index.tsx @@ -144,6 +144,7 @@ const FileUploadComponent: IToolboxComponent = { allowReplace: true, allowDelete: true, allowUpload: true, + hideFileName: true, ownerId: '', ownerType: '', isDragger: false, @@ -158,6 +159,7 @@ const FileUploadComponent: IToolboxComponent = { allowReplace: true, allowDelete: true, allowUpload: true, + hideFileName: true, ownerId: prev['ownerId'], ownerType: prev['ownerType'], owner: prev['owner'], From f88644610e6edcf8ce39d14296f40f2f1bf22826 Mon Sep 17 00:00:00 2001 From: Tshepo Date: Mon, 14 Apr 2025 06:33:04 +0200 Subject: [PATCH 20/21] chore: removing the download button when file name is visible --- shesha-reactjs/src/components/fileUpload/index.tsx | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/shesha-reactjs/src/components/fileUpload/index.tsx b/shesha-reactjs/src/components/fileUpload/index.tsx index 524ee0de31..78742d7a74 100644 --- a/shesha-reactjs/src/components/fileUpload/index.tsx +++ b/shesha-reactjs/src/components/fileUpload/index.tsx @@ -309,14 +309,15 @@ export const FileUpload: FC = ({ preview={{ visible: previewOpen, onVisibleChange: (visible) => setPreviewOpen(visible), - afterOpenChange: (visible) => !visible, toolbarRender: (original) => { return (
- downloadFile({ fileId: previewImage?.uid, fileName: previewImage?.name })} - /> + {hideFileName && ( + downloadFile({ fileId: previewImage?.uid, fileName: previewImage?.name })} + /> + )} {original}
); From e38aa35f83d2a63bb7c26db569f0542a7b6194ad Mon Sep 17 00:00:00 2001 From: Tshepo Date: Mon, 14 Apr 2025 07:04:45 +0200 Subject: [PATCH 21/21] chore: cleaning up the code with error handling --- .../src/components/fileUpload/index.tsx | 4 + .../components/fileUpload/styles/styles.ts | 2 +- .../designer-components/fileUpload/index.tsx | 108 ++++++++++++------ 3 files changed, 75 insertions(+), 39 deletions(-) diff --git a/shesha-reactjs/src/components/fileUpload/index.tsx b/shesha-reactjs/src/components/fileUpload/index.tsx index 78742d7a74..2e5e72e909 100644 --- a/shesha-reactjs/src/components/fileUpload/index.tsx +++ b/shesha-reactjs/src/components/fileUpload/index.tsx @@ -127,6 +127,10 @@ export const FileUpload: FC = ({ const onPreview = () => { if (fileInfo) { + if (!url) { + message.error('Preview URL not available'); + return; + } setPreviewImage({ url, uid: fileInfo?.id, name: fileInfo?.name }); setPreviewOpen(true); } diff --git a/shesha-reactjs/src/components/fileUpload/styles/styles.ts b/shesha-reactjs/src/components/fileUpload/styles/styles.ts index 764edaf580..2a1b9ae368 100644 --- a/shesha-reactjs/src/components/fileUpload/styles/styles.ts +++ b/shesha-reactjs/src/components/fileUpload/styles/styles.ts @@ -102,7 +102,7 @@ export const useStyles = createStyles(({ token, css, cx, prefixCls }, { style, m } .ant-upload-list-picture-card { - height: ${hideFileName ? 'var(--thumbnail-height) )' : `calc(var(--thumbnail-height) + ${fontSize} * 2 + 32px)`} !important; + height: ${hideFileName ? 'var(--thumbnail-height)' : `calc(var(--thumbnail-height) + ${fontSize} * 2 + 32px)`} !important; padding-bottom: 1rem; } diff --git a/shesha-reactjs/src/designer-components/fileUpload/index.tsx b/shesha-reactjs/src/designer-components/fileUpload/index.tsx index 9ced0ec494..490a7ef08e 100644 --- a/shesha-reactjs/src/designer-components/fileUpload/index.tsx +++ b/shesha-reactjs/src/designer-components/fileUpload/index.tsx @@ -12,7 +12,11 @@ import { pickStyleFromModel, validateConfigurableComponentSettings, } from '@/providers/form/utils'; -import { migrateCustomFunctions, migratePropertyName, migrateReadOnly } from '@/designer-components/_common-migrations/migrateSettings'; +import { + migrateCustomFunctions, + migratePropertyName, + migrateReadOnly, +} from '@/designer-components/_common-migrations/migrateSettings'; import { migrateVisibility } from '@/designer-components/_common-migrations/migrateVisibility'; import { migrateFormApi } from '../_common-migrations/migrateFormApi1'; import { getSettings } from './settingsForm'; @@ -64,23 +68,41 @@ const FileUploadComponent: IToolboxComponent = { const shadowStyles = useMemo(() => getShadowStyle(shadow), [shadow]); useEffect(() => { + let objectUrl = ''; const fetchStyles = async () => { - const storedImageUrl = background?.storedFile?.id && background?.type === 'storedFile' - ? await fetch(`${backendUrl}/api/StoredFile/Download?id=${background?.storedFile?.id}`, - { headers: { ...httpHeaders, "Content-Type": "application/octet-stream" } }) - .then((response) => { - return response.blob(); - }) - .then((blob) => { - return URL.createObjectURL(blob); - }) : ''; + let storedImageUrl = ''; + + try { + if (background?.storedFile?.id && background?.type === 'storedFile') { + const response = await fetch(`${backendUrl}/api/StoredFile/Download?id=${background?.storedFile?.id}`, { + headers: { ...httpHeaders, 'Content-Type': 'application/octet-stream' }, + }); + + if (!response.ok) { + throw new Error(`Failed to fetch background: ${response.status} ${response.statusText}`); + } + + const blob = await response.blob(); + objectUrl = URL.createObjectURL(blob); + storedImageUrl = objectUrl; + } + } catch (error) { + console.error('Error fetching background image:', error); + } const style = getBackgroundStyle(background, jsStyle, storedImageUrl); setBackgroundStyles(style); }; fetchStyles(); + + // Cleanup function to revoke the object URL when component unmounts or when dependencies change + return () => { + if (objectUrl) { + URL.revokeObjectURL(objectUrl); + } + }; }, [background, backendUrl, httpHeaders, jsStyle]); const styling = JSON.parse(model.stylingBox || '{}'); @@ -92,7 +114,7 @@ const FileUploadComponent: IToolboxComponent = { ...borderStyles, ...fontStyles, ...backgroundStyles, - ...shadowStyles + ...shadowStyles, }); const finalStyle = removeUndefinedProps(additionalStyles); @@ -116,7 +138,11 @@ const FileUploadComponent: IToolboxComponent = { baseUrl={backendUrl} ownerId={Boolean(ownerId) ? ownerId : Boolean(data?.id) ? data?.id : ''} ownerType={ - Boolean(model.ownerType) ? model.ownerType : Boolean(formSettings?.modelType) ? formSettings?.modelType : '' + Boolean(model.ownerType) + ? model.ownerType + : Boolean(formSettings?.modelType) + ? formSettings?.modelType + : '' } propertyName={model.propertyName} uploadMode={model.useSync ? 'sync' : 'async'} @@ -131,14 +157,13 @@ const FileUploadComponent: IToolboxComponent = { isDragger={model?.isDragger} styles={finalStyle} /> - ); }} ); }, - initModel: model => { + initModel: (model) => { const customModel: IFileUploadProps = { ...model, allowReplace: true, @@ -152,32 +177,39 @@ const FileUploadComponent: IToolboxComponent = { }; return customModel; }, - migrator: (m) => m - .add(0, prev => { - return { + migrator: (m) => + m + .add(0, (prev) => { + return { + ...prev, + allowReplace: true, + allowDelete: true, + allowUpload: true, + hideFileName: true, + ownerId: prev['ownerId'], + ownerType: prev['ownerType'], + owner: prev['owner'], + } as IFileUploadProps; + }) + .add(1, (prev, context) => ({ ...prev, useSync: !Boolean(context.formSettings?.modelType) })) + .add(2, (prev) => { + const pn = prev['name'] ?? prev.propertyName; + const model = migratePropertyName(migrateCustomFunctions(prev)); + model.propertyName = pn; + return model; + }) + .add(3, (prev) => migrateVisibility(prev)) + .add(4, (prev) => migrateReadOnly(prev)) + .add(5, (prev) => ({ ...migrateFormApi.eventsAndProperties(prev) })) + .add(6, (prev) => ({ ...prev, - allowReplace: true, - allowDelete: true, - allowUpload: true, - hideFileName: true, - ownerId: prev['ownerId'], - ownerType: prev['ownerType'], - owner: prev['owner'], - } as IFileUploadProps; - }) - .add(1, (prev, context) => ({ ...prev, useSync: !Boolean(context.formSettings?.modelType) })) - .add(2, (prev) => { - const pn = prev['name'] ?? prev.propertyName; - const model = migratePropertyName(migrateCustomFunctions(prev)); - model.propertyName = pn; - return model; - }) - .add(3, (prev) => migrateVisibility(prev)) - .add(4, (prev) => migrateReadOnly(prev)) - .add(5, (prev) => ({ ...migrateFormApi.eventsAndProperties(prev) })) - .add(6, (prev) => ({ ...prev, ...defaultStyles(), desktop: { ...defaultStyles() }, mobile: { ...defaultStyles() }, tablet: { ...defaultStyles() } })), + ...defaultStyles(), + desktop: { ...defaultStyles() }, + mobile: { ...defaultStyles() }, + tablet: { ...defaultStyles() }, + })), settingsFormMarkup: getSettings(), validateSettings: (model) => validateConfigurableComponentSettings(getSettings(), model), }; -export default FileUploadComponent; \ No newline at end of file +export default FileUploadComponent;