feat: refactor helper configuration and enhance date formatting component

This commit is contained in:
Sheldon Guo 2025-03-28 16:24:54 +08:00
parent 2116f2d424
commit f93029e990
6 changed files with 61 additions and 34 deletions

View File

@ -9,7 +9,7 @@
import { createForm, onFormValuesChange } from '@formily/core'; import { createForm, onFormValuesChange } from '@formily/core';
import { observer, useForm } from '@formily/react'; import { observer, useForm } from '@formily/react';
import { dayjs, tval, uid } from '@nocobase/utils/client'; import { dayjs, tval, uid } from '@nocobase/utils/client';
import { Tag } from 'antd'; import { Button, Card, Space, Tag } from 'antd';
import { createMemoryHistory } from 'history'; import { createMemoryHistory } from 'history';
import debounce from 'lodash/debounce'; import debounce from 'lodash/debounce';
import minimatch from 'minimatch'; import minimatch from 'minimatch';
@ -72,8 +72,9 @@ const Configurator = observer(
const { helpersObs, rawHelpersObs, removeHelper } = helperObservables; const { helpersObs, rawHelpersObs, removeHelper } = helperObservables;
const helper = helpersObs.value[index]; const helper = helpersObs.value[index];
const rawHelper = rawHelpersObs.value[index]; const rawHelper = rawHelpersObs.value[index];
const helperConfigs = app.jsonTemplateParser.filters; const helperConfigs = app.jsonTemplateParser.helpers;
const helperConfig = helperConfigs.find((item) => item.name === helper.name); const helperConfig = helperConfigs.find((item) => item.name === helper.name);
const HelperComponent = helperConfig.Component;
const previousHelpers = helpersObs.value.slice(0, index); const previousHelpers = helpersObs.value.slice(0, index);
const inputValue = previousHelpers.reduce((value, helper) => { const inputValue = previousHelpers.reduce((value, helper) => {
return helper.handler(value, ...helper.args); return helper.handler(value, ...helper.args);
@ -184,7 +185,16 @@ const Configurator = observer(
}, },
}; };
return ( return HelperComponent ? (
<>
<HelperComponent
value={helper.argsMap}
onChange={(values) => (rawHelper.argsMap = values)}
inputValue={inputValue}
/>
<MyButtons onDelete={() => removeHelper({ index: index })} onClose={close} />
</>
) : (
<SchemaComponent <SchemaComponent
components={{ InputValue, OuputValue }} components={{ InputValue, OuputValue }}
schema={schema} schema={schema}
@ -201,6 +211,23 @@ const Configurator = observer(
{ displayName: 'Configurator' }, { displayName: 'Configurator' },
); );
// Add a new component for custom delete and close buttons
export const MyButtons = observer(
({ onDelete, onClose }: { onDelete: () => void; onClose: () => void }) => {
const app = useApp();
const t = app.i18n.t;
return (
<Space style={{ display: 'flex', justifyContent: 'flex-end', marginTop: '16px' }}>
<Button type="primary" danger onClick={onDelete}>
{t('Delete', { ns: 'client' })}
</Button>
<Button onClick={onClose}>{t('Close', { ns: 'client' })}</Button>
</Space>
);
},
{ displayName: 'MyButtons' },
);
const WithRouter = observer( const WithRouter = observer(
({ children }: { children: React.ReactNode }) => { ({ children }: { children: React.ReactNode }) => {
const history = createMemoryHistory(); const history = createMemoryHistory();

View File

@ -22,7 +22,7 @@ type RawHelper = {
const parser = createJSONTemplateParser(); const parser = createJSONTemplateParser();
export const allHelpersConfigObs = observable<{ value: any[] }>({ value: parser.filters }); export const allHelpersConfigObs = observable<{ value: any[] }>({ value: parser.helpers });
export const createHelperObservables = () => { export const createHelperObservables = () => {
const rawHelpersObs = observable<{ value: RawHelper[] }>({ value: [] }); const rawHelpersObs = observable<{ value: RawHelper[] }>({ value: [] });
@ -38,6 +38,7 @@ export const createHelperObservables = () => {
config, config,
args, args,
handler: config.handler, handler: config.handler,
Component: config.Component,
}; };
}); });
}) as { value: Helper[] }; }) as { value: Helper[] };

View File

@ -10,21 +10,13 @@
import { Liquid, TokenKind } from 'liquidjs'; import { Liquid, TokenKind } from 'liquidjs';
import { get } from 'lodash'; import { get } from 'lodash';
import { escape, revertEscape } from '../escape'; import { escape, revertEscape } from '../escape';
import { Helper } from '../types';
type FilterGroup = { type FilterGroup = {
name: string; name: string;
title: string; title: string;
sort: number; sort: number;
}; };
type Helper = {
name: string;
title: string;
handler: (...args: any[]) => any;
group: string;
uiSchema?: any;
sort: number;
};
type ScopeFnWrapperResult = { type ScopeFnWrapperResult = {
getValue: (params: { field: string[]; keys: string[] }) => any; getValue: (params: { field: string[]; keys: string[] }) => any;
afterApplyHelpers: (params: { field: string[]; keys: string[]; value: any }) => any; afterApplyHelpers: (params: { field: string[]; keys: string[]; value: any }) => any;
@ -48,7 +40,7 @@ export class JSONTemplateParser {
this._filters = []; this._filters = [];
} }
get filters(): Array<Helper> { get helpers(): Array<Helper> {
return this._filters; return this._filters;
} }

View File

@ -18,5 +18,5 @@ export type Helper = {
sort: number; sort: number;
args: string[]; args: string[];
uiSchema?: any[]; uiSchema?: any[];
Component?: React.FC<{ value: any; onChange: (value: any) => void }>; Component?: React.FC<{ value: any; onChange: (value: any) => void; inputValue: any }>;
}; };

View File

@ -10,11 +10,11 @@
import { css } from '@emotion/css'; import { css } from '@emotion/css';
import { Checkbox, Input, Radio, Space } from 'antd'; import { Checkbox, Input, Radio, Space } from 'antd';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import React, { useEffect, useState } from 'react'; import React, { useCallback, useEffect, useState } from 'react';
// Component for displaying a date format preview // Component for displaying a date format preview
const DateFormatPreview = ({ format }) => { const DateFormatPreview = ({ format, date }) => {
const content = format ? dayjs().format(format) : null; const content = format ? date.format(format) : null;
if (!content) return null; if (!content) return null;
@ -38,16 +38,24 @@ const DateFormatPreview = ({ format }) => {
const DateFormat = ({ const DateFormat = ({
value, value,
onChange, onChange,
inputValue,
picker = 'date', picker = 'date',
showTimeToggle = true, showTimeToggle = true,
defaultShowTime = false, defaultShowTime = false,
timeFormat: initialTimeFormat = 'HH:mm:ss', timeFormat: initialTimeFormat = 'HH:mm:ss',
dateFormat: initialDateFormat = 'YYYY-MM-DD', dateFormat: initialDateFormat = 'YYYY-MM-DD',
}) => { }) => {
const [selectedFormat, setSelectedFormat] = useState(value || initialDateFormat); const [selectedFormat, setSelectedFormat] = useState(value.format || initialDateFormat);
const [isCustom, setIsCustom] = useState(false); const [isCustom, setIsCustom] = useState(false);
const [showTime, setShowTime] = useState(defaultShowTime); const [showTime, setShowTime] = useState(defaultShowTime);
const [timeFormat, setTimeFormat] = useState(initialTimeFormat); const [timeFormat, setTimeFormat] = useState(initialTimeFormat);
const date = dayjs.isDayjs(inputValue) ? inputValue : dayjs(inputValue);
const onFormatChange = useCallback(
(format) => {
onChange?.({ format });
},
[onChange],
);
// Date format options // Date format options
const dateFormatOptions = [ const dateFormatOptions = [
@ -55,7 +63,7 @@ const DateFormat = ({
label: ( label: (
<> <>
<span>MMMM Do YYYY</span> <span>MMMM Do YYYY</span>
<DateFormatPreview format="MMMM Do YYYY" /> <DateFormatPreview date={date} format="MMMM Do YYYY" />
</> </>
), ),
value: 'MMMM Do YYYY', value: 'MMMM Do YYYY',
@ -64,7 +72,7 @@ const DateFormat = ({
label: ( label: (
<> <>
<span>YYYY-MM-DD</span> <span>YYYY-MM-DD</span>
<DateFormatPreview format="YYYY-MM-DD" /> <DateFormatPreview date={date} format="YYYY-MM-DD" />
</> </>
), ),
value: 'YYYY-MM-DD', value: 'YYYY-MM-DD',
@ -73,7 +81,7 @@ const DateFormat = ({
label: ( label: (
<> <>
<span>MM/DD/YY</span> <span>MM/DD/YY</span>
<DateFormatPreview format="MM/DD/YY" /> <DateFormatPreview date={date} format="MM/DD/YY" />
</> </>
), ),
value: 'MM/DD/YY', value: 'MM/DD/YY',
@ -82,7 +90,7 @@ const DateFormat = ({
label: ( label: (
<> <>
<span>YYYY/MM/DD</span> <span>YYYY/MM/DD</span>
<DateFormatPreview format="YYYY/MM/DD" /> <DateFormatPreview date={date} format="YYYY/MM/DD" />
</> </>
), ),
value: 'YYYY/MM/DD', value: 'YYYY/MM/DD',
@ -91,7 +99,7 @@ const DateFormat = ({
label: ( label: (
<> <>
<span>DD/MM/YYYY</span> <span>DD/MM/YYYY</span>
<DateFormatPreview format="DD/MM/YYYY" /> <DateFormatPreview date={date} format="DD/MM/YYYY" />
</> </>
), ),
value: 'DD/MM/YYYY', value: 'DD/MM/YYYY',
@ -105,7 +113,7 @@ const DateFormat = ({
label: ( label: (
<> <>
<span>hh:mm:ss a</span> <span>hh:mm:ss a</span>
<DateFormatPreview format="hh:mm:ss a" /> <DateFormatPreview date={date} format="hh:mm:ss a" />
</> </>
), ),
value: 'hh:mm:ss a', value: 'hh:mm:ss a',
@ -114,7 +122,7 @@ const DateFormat = ({
label: ( label: (
<> <>
<span>HH:mm:ss</span> <span>HH:mm:ss</span>
<DateFormatPreview format="HH:mm:ss" /> <DateFormatPreview date={date} format="HH:mm:ss" />
</> </>
), ),
value: 'HH:mm:ss', value: 'HH:mm:ss',
@ -143,10 +151,10 @@ const DateFormat = ({
if (picker !== 'date') { if (picker !== 'date') {
const newFormat = getPickerFormat(picker); const newFormat = getPickerFormat(picker);
setSelectedFormat(newFormat); setSelectedFormat(newFormat);
onChange?.(newFormat); onFormatChange(newFormat);
setShowTime(false); setShowTime(false);
} }
}, [picker]); }, [picker, onFormatChange]);
// Update parent component with combined format // Update parent component with combined format
useEffect(() => { useEffect(() => {
@ -156,8 +164,8 @@ const DateFormat = ({
finalFormat = `${selectedFormat} ${timeFormat}`; finalFormat = `${selectedFormat} ${timeFormat}`;
} }
onChange?.(finalFormat); onFormatChange(finalFormat);
}, [selectedFormat, showTime, timeFormat]); }, [selectedFormat, showTime, timeFormat, onFormatChange, picker]);
// Handle date format change // Handle date format change
const handleDateFormatChange = (e) => { const handleDateFormatChange = (e) => {
@ -209,7 +217,7 @@ const DateFormat = ({
onChange={handleCustomFormatChange} onChange={handleCustomFormatChange}
onClick={(e) => e.stopPropagation()} onClick={(e) => e.stopPropagation()}
/> />
<DateFormatPreview format={selectedFormat} /> <DateFormatPreview date={date} format={selectedFormat} />
</> </>
) : ( ) : (
option.label option.label
@ -251,7 +259,7 @@ const DateFormat = ({
onChange={(e) => setTimeFormat(e.target.value)} onChange={(e) => setTimeFormat(e.target.value)}
onClick={(e) => e.stopPropagation()} onClick={(e) => e.stopPropagation()}
/> />
<DateFormatPreview format={timeFormat} /> <DateFormatPreview date={date} format={timeFormat} />
</> </>
) : ( ) : (
option.label option.label

View File

@ -77,8 +77,7 @@ export function dateOffset(initialValue: any, action: 'add' | 'subtract', number
return dayjs.isDayjs(value) ? value.add(number, unit) : dayjs(value).add(number, unit); return dayjs.isDayjs(value) ? value.add(number, unit) : dayjs(value).add(number, unit);
} else if (action === 'subtract') { } else if (action === 'subtract') {
return dayjs.isDayjs(value) ? value.subtract(number, unit) : dayjs(value).subtract(number, unit); return dayjs.isDayjs(value) ? value.subtract(number, unit) : dayjs(value).subtract(number, unit);
} } else return initialValue;
throw new Error('Invalid action');
}; };
return handler(initialValue); return handler(initialValue);
} }