diff --git a/packages/plugins/@hera/plugin-core/src/client/schema-components/association-cascader/AssociationCascader.tsx b/packages/plugins/@hera/plugin-core/src/client/schema-components/association-cascader/AssociationCascader.tsx
index 1dace2bc0..2cf535b15 100644
--- a/packages/plugins/@hera/plugin-core/src/client/schema-components/association-cascader/AssociationCascader.tsx
+++ b/packages/plugins/@hera/plugin-core/src/client/schema-components/association-cascader/AssociationCascader.tsx
@@ -24,38 +24,88 @@ const AssociationCascader = connect((props) => {
});
const options = useMemo(() => {
- const dict: { [key: string]: string[] } =
- data?.data.reduce((acc, item) => {
- if (item[associationField]) {
- const key = item[associationField][joinTitleField];
- acc[key] ??= [];
- acc[key].push(item[titleField]);
+ if (props.chartCascader) {
+ const dataOptions = {};
+ const options = [];
+ data?.data.forEach((item) => {
+ if (item?.[associationField]) {
+ const field = [];
+ if (Array.isArray(item[associationField]) && item[associationField].length) {
+ field.push(...item[associationField]);
+ } else {
+ field.push({ ...item[associationField] });
+ }
+ field.forEach((fieldItem) => {
+ if (!Object.keys(fieldItem).length) return;
+ if (dataOptions[fieldItem[joinTitleField]]) {
+ dataOptions[fieldItem[joinTitleField]].push({
+ label: item[titleField],
+ value: item[titleField],
+ });
+ } else {
+ dataOptions[fieldItem[joinTitleField]] = [
+ {
+ label: item[titleField],
+ value: item[titleField],
+ },
+ ];
+ }
+ });
}
- return acc;
- }, {}) || {};
- const options = Object.entries(dict).map(([key, values]) => ({
- [fieldNames.label]: key,
- [fieldNames.value]: key,
- children: values.map((value) => ({ [fieldNames.label]: value, [fieldNames.value]: value })),
- }));
- return options;
+ });
+ for (const key in dataOptions) {
+ options.push({
+ label: key,
+ value: key,
+ children: [...dataOptions[key]],
+ });
+ }
+ return options;
+ } else {
+ const dict: { [key: string]: string[] } =
+ data?.data.reduce((acc, item) => {
+ if (item[associationField]) {
+ const key = item[associationField][joinTitleField];
+ acc[key] ??= [];
+ acc[key].push(item[titleField]);
+ }
+ return acc;
+ }, {}) || {};
+ const options = Object.entries(dict).map(([key, values]) => ({
+ [fieldNames.label]: key,
+ [fieldNames.value]: key,
+ children: values.map((value) => ({ [fieldNames.label]: value, [fieldNames.value]: value })),
+ }));
+ return options;
+ }
}, [associationField, joinTitleField, titleField, data?.data]);
- return ;
+
+ return (
+
+ );
});
const SingleValueCascader = (props) => {
- const { value, options, onChange, fieldNames } = props;
+ const { value, options, onChange, fieldNames, chartCascader, titleField, joinTitleField } = props;
+ const fieldLabel = fieldNames ? fieldNames.value : titleField;
+ const joinFieldLabel = fieldNames ? fieldNames.value : 'value';
const arrayValue = value && options ? [] : undefined;
if (arrayValue) {
for (const option of options) {
- if (option[fieldNames.value] === value) {
- arrayValue.push(option[fieldNames.value]);
+ if (option[fieldLabel] === value) {
+ arrayValue.push(option[fieldLabel]);
break;
}
for (const subOption of option.children) {
- if (subOption[fieldNames.value] === value) {
- arrayValue.push(option[fieldNames.value]);
- arrayValue.push(subOption[fieldNames.value]);
+ if (subOption[joinFieldLabel] === value) {
+ arrayValue.push(option[joinFieldLabel]);
+ arrayValue.push(subOption[joinFieldLabel]);
break;
}
}
diff --git a/packages/plugins/@nocobase/plugin-data-visualization/src/client/filter/FilterItemInitializers.tsx b/packages/plugins/@nocobase/plugin-data-visualization/src/client/filter/FilterItemInitializers.tsx
index 9534a7558..ab6a1ddde 100644
--- a/packages/plugins/@nocobase/plugin-data-visualization/src/client/filter/FilterItemInitializers.tsx
+++ b/packages/plugins/@nocobase/plugin-data-visualization/src/client/filter/FilterItemInitializers.tsx
@@ -22,6 +22,7 @@ import {
useDesignable,
useGlobalTheme,
useSchemaInitializerItem,
+ useCompile,
} from '@nocobase/client';
import { useMemoizedFn } from 'ahooks';
import { Alert, ConfigProvider, Typography } from 'antd';
@@ -35,7 +36,7 @@ const { Paragraph, Text } = Typography;
const FieldComponentProps: React.FC = observer(
(props) => {
const form = useForm();
- const schema = getPropsSchemaByComponent(form.values.component);
+ const schema = getPropsSchemaByComponent(form.values.component, props['allCollection']);
return schema ? : null;
},
{ displayName: 'FieldComponentProps' },
@@ -127,12 +128,31 @@ export const ChartFilterCustomItemInitializer: React.FC<{
const dm = useDataSourceManager();
const sourceFields = useChartFilterSourceFields();
const { options: fieldComponents, values: fieldComponentValues } = useFieldComponents();
+ const { collections, getCollectionFields } = useCollectionManager_deprecated();
+ const compile = useCompile();
+ const allCollection = collections.map((collection) => {
+ return {
+ label: collection.getOption('title'),
+ value: collection.getOption('name'),
+ };
+ });
const handleClick = useCallback(async () => {
const values = await FormDialog(
t('Add custom field'),
() => (
{
+ return {
+ label: compile(field.uiSchema.title),
+ value: field.name,
+ };
+ });
+ },
+ }}
components={{ ...components, FieldComponentProps }}
>
@@ -176,6 +196,9 @@ export const ChartFilterCustomItemInitializer: React.FC<{
type: 'object',
title: t('Component properties'),
'x-component': 'FieldComponentProps',
+ 'x-component-props': {
+ allCollection,
+ },
},
},
}}
@@ -242,6 +265,7 @@ export const ChartFilterCustomItemInitializer: React.FC<{
'x-component-props': {
...(defaultSchema['x-component-props'] || {}),
...props,
+ chartCascader: true,
},
}),
);
diff --git a/packages/plugins/@nocobase/plugin-data-visualization/src/client/filter/utils.ts b/packages/plugins/@nocobase/plugin-data-visualization/src/client/filter/utils.ts
index d018de38a..37a0288eb 100644
--- a/packages/plugins/@nocobase/plugin-data-visualization/src/client/filter/utils.ts
+++ b/packages/plugins/@nocobase/plugin-data-visualization/src/client/filter/utils.ts
@@ -55,7 +55,7 @@ export const getOptionsSchema = () => {
return options;
};
-export const getPropsSchemaByComponent = (component: string) => {
+export const getPropsSchemaByComponent = (component: string, allCollection) => {
const showTime = {
type: 'boolean',
'x-content': '{{ t("Show time") }}',
@@ -135,6 +135,34 @@ export const getPropsSchemaByComponent = (component: string) => {
options,
},
},
+ AssociationCascader: {
+ type: 'object',
+ properties: {
+ collection: {
+ type: 'string',
+ title: '{{t("Field collection")}}',
+ 'x-decorator': 'FormItem',
+ 'x-component': 'Select',
+ enum: allCollection,
+ },
+ associationField: {
+ type: 'string',
+ title: '{{t("Field Association")}}',
+ 'x-visible': false,
+ 'x-decorator': 'FormItem',
+ 'x-component': 'Select',
+ 'x-reactions': {
+ dependencies: ['component', '.collection'],
+ fulfill: {
+ schema: {
+ 'x-visible': "{{$deps[0]=== 'AssociationCascader' && $deps[1]}}",
+ enum: '{{useCollectionField($deps[1])}}',
+ },
+ },
+ },
+ },
+ },
+ },
};
return propsSchema[component];
};
diff --git a/packages/plugins/@nocobase/plugin-data-visualization/src/client/hooks/filter.ts b/packages/plugins/@nocobase/plugin-data-visualization/src/client/hooks/filter.ts
index ea29411a4..d4d83dcd5 100644
--- a/packages/plugins/@nocobase/plugin-data-visualization/src/client/hooks/filter.ts
+++ b/packages/plugins/@nocobase/plugin-data-visualization/src/client/hooks/filter.ts
@@ -507,6 +507,7 @@ export const useFieldComponents = () => {
{ label: t('Select'), value: 'Select' },
{ label: t('Radio group'), value: 'Radio.Group' },
{ label: t('Checkbox group'), value: 'Checkbox.Group' },
+ { label: t('AssociationCascader'), value: 'AssociationCascader' },
// { label: t('China region'), value: 'chinaRegion' },
];
return {