mirror of
https://gitee.com/nocobase/nocobase.git
synced 2025-05-08 15:09:27 +08:00
feat: introduce VariableProvider
This commit is contained in:
parent
bde404b540
commit
3f6cae33ec
@ -35,6 +35,7 @@ import { XButton } from './XButton';
|
||||
import { useStyles } from './style';
|
||||
import { Json } from '../input';
|
||||
import { Filters, Addition, FilterContext } from './VariableFilters';
|
||||
import { VariableProvider } from './VariableProvider';
|
||||
|
||||
const { Text } = Typography;
|
||||
const JT_VALUE_RE = /^\s*{{\s*([^{}]+)\s*}}\s*$/;
|
||||
@ -484,11 +485,13 @@ export function Input(props: VariableInputProps) {
|
||||
</React.Fragment>
|
||||
);
|
||||
})}
|
||||
<FilterContext.Provider value={{ updateFilterParams, deleteFilter }}>
|
||||
<Filters filters={filters} onFilterChange={onFilterAdd} />
|
||||
<VariableProvider variableName={fullVariable}>
|
||||
<FilterContext.Provider value={{ updateFilterParams, deleteFilter, variableName: fullVariable }}>
|
||||
<Filters filters={filters} onFilterChange={onFilterAdd} />
|
||||
|
||||
{variableText.length > 0 && <Addition variable={fullVariable} onFilterAdd={onFilterAdd} />}
|
||||
</FilterContext.Provider>
|
||||
{variableText.length > 0 && <Addition variable={fullVariable} onFilterAdd={onFilterAdd} />}
|
||||
</FilterContext.Provider>
|
||||
</VariableProvider>
|
||||
</Tag>
|
||||
</div>
|
||||
{!disabled ? (
|
||||
|
@ -17,6 +17,7 @@ import type { MenuProps } from 'antd';
|
||||
import { SchemaComponent } from '../../core/SchemaComponent';
|
||||
import { useApp } from '../../../application';
|
||||
import { useCompile } from '../../hooks';
|
||||
import { useVariable } from './VariableProvider';
|
||||
|
||||
export function Addition({ variable, onFilterAdd }) {
|
||||
const app = useApp();
|
||||
@ -59,15 +60,30 @@ export function Filters({ filters, onFilterChange }) {
|
||||
if (!filterConfig) {
|
||||
return null;
|
||||
}
|
||||
return <Filter key={index} filterId={index} config={filterConfig} filter={filter} />;
|
||||
const previousFilters = filters.slice(0, index);
|
||||
return (
|
||||
<Filter
|
||||
key={index}
|
||||
filterId={index}
|
||||
config={filterConfig}
|
||||
filter={filter}
|
||||
previousFilters={previousFilters}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export function Filter({ config, filter, filterId }) {
|
||||
export function Filter({ config, filter, filterId, previousFilters }) {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const { value } = useVariable();
|
||||
const inputValue = [...previousFilters].reduce((value, filter) => {
|
||||
return filter.handler(value, ...filter.args);
|
||||
}, value);
|
||||
const outputValue = [...previousFilters, filter].reduce((value, filter) => {
|
||||
return filter.handler(value, ...filter.args);
|
||||
}, value);
|
||||
const handleOpenChange = (newOpen: boolean) => {
|
||||
setOpen(newOpen);
|
||||
};
|
||||
@ -108,16 +124,28 @@ export function Filter({ config, filter, filterId }) {
|
||||
};
|
||||
|
||||
const useFormBlockProps = () => {
|
||||
return { form };
|
||||
return { form, layout: 'vertical' };
|
||||
};
|
||||
|
||||
const WithPropOver = ({ children }) => {
|
||||
const { value } = useVariable();
|
||||
const schema = {
|
||||
'x-uid': uid(),
|
||||
type: 'void',
|
||||
// 'x-component': 'FormV2',
|
||||
// 'x-use-component-props': 'useFormBlockProps',
|
||||
'x-component': 'FormV2',
|
||||
'x-use-component-props': 'useFormBlockProps',
|
||||
properties: {
|
||||
'$input-value': {
|
||||
type: 'void',
|
||||
'x-component': 'Input',
|
||||
'x-component-props': {
|
||||
defaultValue: '{{ inputValue }}',
|
||||
disabled: true,
|
||||
},
|
||||
'x-decorator': 'FormItem',
|
||||
title: tval('Input Value'),
|
||||
'x-read-pretty': true,
|
||||
},
|
||||
...Object.fromEntries(
|
||||
config.uiSchema.map((param) => [
|
||||
param.name,
|
||||
@ -127,6 +155,17 @@ export function Filter({ config, filter, filterId }) {
|
||||
},
|
||||
]),
|
||||
),
|
||||
'$return-value': {
|
||||
type: 'void',
|
||||
'x-component': 'Input',
|
||||
'x-component-props': {
|
||||
defaultValue: '{{ outputValue }}',
|
||||
disabled: true,
|
||||
},
|
||||
'x-decorator': 'FormItem',
|
||||
title: tval('Return Value'),
|
||||
'x-read-pretty': true,
|
||||
},
|
||||
actions: {
|
||||
type: 'void',
|
||||
title: tval('Save'),
|
||||
@ -153,13 +192,11 @@ export function Filter({ config, filter, filterId }) {
|
||||
open={open}
|
||||
onOpenChange={handleOpenChange}
|
||||
content={
|
||||
<FormContext.Provider value={form}>
|
||||
<SchemaComponent
|
||||
schema={schema}
|
||||
scope={{ useSaveActionProps, useFormBlockProps, useDeleteActionProps }}
|
||||
basePath={['']}
|
||||
/>
|
||||
</FormContext.Provider>
|
||||
<SchemaComponent
|
||||
schema={schema}
|
||||
scope={{ useSaveActionProps, useFormBlockProps, useDeleteActionProps, outputValue, inputValue }}
|
||||
basePath={['']}
|
||||
/>
|
||||
}
|
||||
trigger={'hover'}
|
||||
>
|
||||
@ -171,19 +208,19 @@ export function Filter({ config, filter, filterId }) {
|
||||
return (
|
||||
<>
|
||||
<span style={{ color: '#bfbfbf', margin: '0 5px' }}>|</span>
|
||||
<FormContext.Provider value={form}>
|
||||
{config.uiSchema ? <WithPropOver>{Label}</WithPropOver> : Label}
|
||||
</FormContext.Provider>
|
||||
{config.uiSchema ? <WithPropOver>{Label}</WithPropOver> : Label}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
type FilterContextType = {
|
||||
variableName: string;
|
||||
updateFilterParams: (args: { filterId: number; params: any[] }) => any;
|
||||
deleteFilter: (args: { filterId: number }) => any;
|
||||
};
|
||||
|
||||
export const FilterContext = React.createContext<FilterContextType>({
|
||||
variableName: '',
|
||||
updateFilterParams: (params: any) => {},
|
||||
deleteFilter: (params: any) => {},
|
||||
});
|
||||
|
@ -0,0 +1,47 @@
|
||||
/**
|
||||
* This file is part of the NocoBase (R) project.
|
||||
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
||||
* Authors: NocoBase Team.
|
||||
*
|
||||
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
||||
* For more information, please refer to: https://www.nocobase.com/agreement.
|
||||
*/
|
||||
|
||||
import React, { createContext, useContext, useEffect, useMemo, useState } from 'react';
|
||||
import { useVariables, useLocalVariables } from '../../../variables';
|
||||
import { getPath } from '../../../variables/utils/getPath';
|
||||
import { isArray } from 'lodash';
|
||||
interface VariableContextValue {
|
||||
value: any;
|
||||
}
|
||||
|
||||
interface VariableProviderProps {
|
||||
variableName: string;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
const VariableContext = createContext<VariableContextValue>({ value: null });
|
||||
|
||||
export const useVariable = () => {
|
||||
const context = useContext(VariableContext);
|
||||
if (!context) {
|
||||
throw new Error('useVariable must be used within a VariableProvider');
|
||||
}
|
||||
return context;
|
||||
};
|
||||
|
||||
export const VariableProvider: React.FC<VariableProviderProps> = ({ variableName, children }) => {
|
||||
const [value, setValue] = useState();
|
||||
const variables = useVariables();
|
||||
const localVariables = useLocalVariables();
|
||||
isArray(localVariables) ? localVariables : [localVariables];
|
||||
useEffect(() => {
|
||||
async function fetchValue() {
|
||||
const result = await variables.getVariableValue(variableName, localVariables);
|
||||
setValue(result.value);
|
||||
}
|
||||
fetchValue();
|
||||
}, [localVariables, variableName, variables]);
|
||||
|
||||
return <VariableContext.Provider value={{ value }}>{children}</VariableContext.Provider>;
|
||||
};
|
@ -347,11 +347,12 @@ const VariablesProvider = ({ children, filterVariables }: any) => {
|
||||
parseVariable,
|
||||
registerVariable,
|
||||
getVariable,
|
||||
getVariableValue: getResult,
|
||||
getCollectionField,
|
||||
removeVariable,
|
||||
filterVariables,
|
||||
}) as VariablesContextType,
|
||||
[getCollectionField, getVariable, parseVariable, registerVariable, removeVariable, setCtx],
|
||||
[getCollectionField, getVariable, parseVariable, registerVariable, removeVariable, setCtx, getResult],
|
||||
);
|
||||
|
||||
return <VariablesContext.Provider value={value}>{children}</VariablesContext.Provider>;
|
||||
|
@ -82,6 +82,26 @@ export interface VariablesContextType {
|
||||
* @returns 变量的配置
|
||||
*/
|
||||
getVariable: (variableName: string) => VariableOption;
|
||||
|
||||
/**
|
||||
* 获取变量的值
|
||||
* @param variableName 变量的名称,例如:`$user`
|
||||
* @returns 变量的配置
|
||||
*/
|
||||
getVariableValue: (
|
||||
variablePath: string,
|
||||
localVariables?: VariableOption[],
|
||||
options?: {
|
||||
/** Related fields that need to be included in the first request */
|
||||
appends?: string[];
|
||||
/** Do not request when the association field is empty */
|
||||
doNotRequest?: boolean;
|
||||
/**
|
||||
* The operator related to the current field, provided when parsing the default value of the field
|
||||
*/
|
||||
fieldOperator?: string | void;
|
||||
},
|
||||
) => Promise<any>;
|
||||
getCollectionField: (
|
||||
variableString: string,
|
||||
localVariables?: VariableOption | VariableOption[],
|
||||
|
@ -7,4 +7,4 @@
|
||||
* For more information, please refer to: https://www.nocobase.com/agreement.
|
||||
*/
|
||||
|
||||
export { createJSONTemplateParser, JSONTemplateParser } from './json-template-parser';
|
||||
export { createJSONTemplateParser, JSONTemplateParser, parse } from './json-template-parser';
|
||||
|
@ -256,3 +256,5 @@ const parser = new JSONTemplateParser();
|
||||
export function createJSONTemplateParser() {
|
||||
return parser;
|
||||
}
|
||||
|
||||
export const parse = parser.parse;
|
||||
|
@ -9,11 +9,8 @@
|
||||
|
||||
import lodash from 'lodash';
|
||||
import { dayjs } from './dayjs';
|
||||
import { createJSONTemplateParser } from '@nocobase/json-template-parser';
|
||||
const parser = createJSONTemplateParser();
|
||||
const parse = parser.parse;
|
||||
export { parse };
|
||||
|
||||
export { parse } from '@nocobase/json-template-parser';
|
||||
export * from './assign';
|
||||
export * from './collections-graph';
|
||||
export * from './common';
|
||||
|
Loading…
x
Reference in New Issue
Block a user