mirror of
https://gitee.com/nocobase/nocobase.git
synced 2025-05-07 14:39:25 +08:00
Merge branch 'next' into develop
This commit is contained in:
commit
1c6b1916bc
@ -151,7 +151,6 @@ const InternalAssociationSelect = observer(
|
||||
</div>
|
||||
);
|
||||
};
|
||||
console.log(fieldSchema);
|
||||
return (
|
||||
<div key={fieldSchema.name}>
|
||||
<Space.Compact style={{ display: 'flex' }}>
|
||||
|
@ -20,6 +20,11 @@ import React from 'react';
|
||||
import { useChartsTranslation } from '../locale';
|
||||
import { useField, useFieldSchema } from '@formily/react';
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* use `chartBlockSettings` instead
|
||||
*/
|
||||
|
||||
export const ChartV2BlockDesigner: React.FC = () => {
|
||||
const { t } = useChartsTranslation();
|
||||
const field = useField();
|
||||
|
@ -112,7 +112,7 @@ export const ChartV2BlockInitializer: React.FC = () => {
|
||||
type: 'void',
|
||||
'x-component': 'ChartCardItem',
|
||||
'x-use-component-props': 'useChartBlockCardProps',
|
||||
'x-designer': 'ChartV2BlockDesigner',
|
||||
'x-settings': 'chart:block',
|
||||
'x-decorator': 'ChartBlockProvider',
|
||||
properties: {
|
||||
actions: {
|
||||
|
@ -11,6 +11,10 @@ import { GeneralSchemaDesigner, SchemaSettingsRemove } from '@nocobase/client';
|
||||
import React from 'react';
|
||||
import { useChartsTranslation } from '../locale';
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* use `chartFilterBlockSettings` instead
|
||||
*/
|
||||
export const ChartFilterBlockDesigner: React.FC = () => {
|
||||
const { t } = useChartsTranslation();
|
||||
return (
|
||||
|
@ -31,7 +31,8 @@ const createFilterSchema = () => {
|
||||
'x-component-props': {
|
||||
size: 'small',
|
||||
},
|
||||
'x-designer': 'ChartFilterBlockDesigner',
|
||||
'x-toolbar': 'ChartFilterBlockToolbar',
|
||||
'x-settings': 'chart:filterForm:block',
|
||||
properties: {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
|
@ -353,6 +353,10 @@ const EditDataScope: React.FC = () => {
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* use `chartFilterItemSettings` instead
|
||||
*/
|
||||
export const ChartFilterItemDesigner: React.FC = () => {
|
||||
const { getCollectionJoinField } = useCollectionManager_deprecated();
|
||||
const { getField } = useCollection_deprecated();
|
||||
|
@ -240,7 +240,8 @@ export const ChartFilterCustomItemInitializer: React.FC<{
|
||||
title: title,
|
||||
name: `custom.${name}`,
|
||||
required: false,
|
||||
'x-designer': 'ChartFilterItemDesigner',
|
||||
'x-toolbar': 'ChartFilterItemToolbar',
|
||||
'x-settings': 'chart:filterForm:item',
|
||||
'x-decorator': 'ChartFilterFormItem',
|
||||
'x-component-props': {
|
||||
...(defaultSchema['x-component-props'] || {}),
|
||||
|
@ -129,18 +129,21 @@ export const useChartFilter = () => {
|
||||
title,
|
||||
name: `${name}.${field.name}`,
|
||||
required: false,
|
||||
'x-designer': 'ChartFilterItemDesigner',
|
||||
'x-toolbar': 'ChartFilterItemToolbar',
|
||||
'x-settings': 'chart:filterForm:item',
|
||||
'x-component': 'CollectionField',
|
||||
'x-decorator': 'ChartFilterFormItem',
|
||||
'x-data-source': dataSource,
|
||||
'x-collection-field': `${fieldName}.${field.name}`,
|
||||
...defaultOperator?.schema,
|
||||
'x-component-props': {
|
||||
utc: false,
|
||||
underFilter: true,
|
||||
...field.uiSchema?.['x-component-props'],
|
||||
'filter-operator': defaultOperator,
|
||||
'data-source': dataSource,
|
||||
'collection-field': `${fieldName}.${field.name}`,
|
||||
},
|
||||
'x-filter-operators': defaultOperator?.value,
|
||||
};
|
||||
if (field.interface === 'formula') {
|
||||
const component = getFormulaComponent(field.dataType) || 'Input';
|
||||
@ -189,18 +192,21 @@ export const useChartFilter = () => {
|
||||
type: 'string',
|
||||
name: `${name}.${child.name}`,
|
||||
required: false,
|
||||
'x-designer': 'ChartFilterItemDesigner',
|
||||
'x-settings': 'chart:filterForm:item',
|
||||
'x-toolbar': 'ChartFilterItemToolbar',
|
||||
'x-decorator': 'ChartFilterFormItem',
|
||||
'x-data-source': dataSource,
|
||||
'x-collection-field': `${fieldName}.${child.name}`,
|
||||
...child.schema,
|
||||
title,
|
||||
...defaultOperator?.schema,
|
||||
'x-component-props': {
|
||||
utc: false,
|
||||
underFilter: true,
|
||||
'filter-operator': defaultOperator,
|
||||
'data-source': dataSource,
|
||||
'collection-field': `${fieldName}.${child.name}`,
|
||||
},
|
||||
'x-filter-operators': defaultOperator?.value,
|
||||
};
|
||||
if (defaultOperator?.noValue) {
|
||||
schema = {
|
||||
|
@ -26,13 +26,20 @@ import {
|
||||
chartFilterItemInitializers_deprecated,
|
||||
} from './filter';
|
||||
import { lang } from './locale';
|
||||
import { chartActionsInitializer } from './initializers/chartActions';
|
||||
import { chartActionRefreshSettings } from './settings/chartActionRefresh';
|
||||
import { useChartRefreshActionProps } from './initializers/RefreshAction';
|
||||
import { chartBlockActionsInitializer } from './initializers/chartBlockActions';
|
||||
import { useChartBlockRefreshActionProps } from './initializers/BlockRefreshAction';
|
||||
import { chartBlockActionRefreshSettings } from './settings/chartBlockActionRefresh';
|
||||
import { useChartBlockCardProps } from './block/ChartBlock';
|
||||
import { chartActionsInitializer } from './initializers/chartActions';
|
||||
import {
|
||||
chartActionRefreshSettings,
|
||||
chartBlockActionRefreshSettings,
|
||||
chartBlockSettings,
|
||||
chartFilterBlockSettings,
|
||||
chartFilterItemSettings,
|
||||
chartRendererSettings,
|
||||
} from './settings';
|
||||
import { chartBlockActionsInitializer } from './initializers/chartBlockActions';
|
||||
import { useChartRefreshActionProps } from './initializers/RefreshAction';
|
||||
import { useChartBlockRefreshActionProps } from './initializers/BlockRefreshAction';
|
||||
import { ChartRendererToolbar, ChartFilterBlockToolbar, ChartFilterItemToolbar } from './toolbar';
|
||||
import { ChartCardItem } from './block/CardItem';
|
||||
|
||||
class PluginDataVisualiztionClient extends Plugin {
|
||||
@ -48,6 +55,9 @@ class PluginDataVisualiztionClient extends Plugin {
|
||||
ChartV2Block,
|
||||
ChartCardItem,
|
||||
ChartBlockProvider,
|
||||
ChartRendererToolbar,
|
||||
ChartFilterBlockToolbar,
|
||||
ChartFilterItemToolbar,
|
||||
});
|
||||
this.app.addScopes({
|
||||
useChartBlockCardProps,
|
||||
@ -55,16 +65,24 @@ class PluginDataVisualiztionClient extends Plugin {
|
||||
useChartBlockRefreshActionProps,
|
||||
});
|
||||
|
||||
this.app.schemaInitializerManager.add(chartInitializers_deprecated);
|
||||
this.app.schemaInitializerManager.add(chartInitializers);
|
||||
this.app.schemaInitializerManager.add(chartFilterItemInitializers_deprecated);
|
||||
this.app.schemaInitializerManager.add(chartFilterItemInitializers);
|
||||
this.app.schemaInitializerManager.add(chartFilterActionInitializers_deprecated);
|
||||
this.app.schemaInitializerManager.add(chartFilterActionInitializers);
|
||||
this.app.schemaInitializerManager.add(chartActionsInitializer);
|
||||
this.app.schemaInitializerManager.add(chartBlockActionsInitializer);
|
||||
this.app.schemaSettingsManager.add(chartActionRefreshSettings);
|
||||
this.app.schemaSettingsManager.add(chartBlockActionRefreshSettings);
|
||||
this.app.schemaInitializerManager.add(
|
||||
chartInitializers_deprecated,
|
||||
chartInitializers,
|
||||
chartFilterItemInitializers_deprecated,
|
||||
chartFilterItemInitializers,
|
||||
chartFilterActionInitializers_deprecated,
|
||||
chartFilterActionInitializers,
|
||||
chartActionsInitializer,
|
||||
chartBlockActionsInitializer,
|
||||
);
|
||||
this.app.schemaSettingsManager.add(
|
||||
chartActionRefreshSettings,
|
||||
chartBlockActionRefreshSettings,
|
||||
chartBlockSettings,
|
||||
chartRendererSettings,
|
||||
chartFilterBlockSettings,
|
||||
chartFilterItemSettings,
|
||||
);
|
||||
|
||||
const blockInitializers = this.app.schemaInitializerManager.get('page:addBlock');
|
||||
blockInitializers?.add('dataBlocks.chartV2', {
|
||||
|
@ -25,6 +25,10 @@ import { useChartsTranslation } from '../locale';
|
||||
import { createRendererSchema } from '../utils';
|
||||
import { ChartRendererContext } from './ChartRendererProvider';
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* use `chartRendererSettings` instead
|
||||
*/
|
||||
export function ChartRendererDesigner() {
|
||||
const { t } = useChartsTranslation();
|
||||
const { setVisible, setCurrent } = useContext(ChartConfigContext);
|
||||
|
@ -0,0 +1,103 @@
|
||||
/**
|
||||
* 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 from 'react';
|
||||
import {
|
||||
SchemaSettings,
|
||||
SchemaSettingsBlockTitleItem,
|
||||
SchemaSettingsSwitchItem,
|
||||
useDesignable,
|
||||
useToken,
|
||||
} from '@nocobase/client';
|
||||
import { useChartsTranslation } from '../locale';
|
||||
import { useField, useFieldSchema } from '@formily/react';
|
||||
|
||||
export const chartBlockSettings = new SchemaSettings({
|
||||
name: 'chart:block',
|
||||
items: [
|
||||
{
|
||||
name: 'title',
|
||||
Component: SchemaSettingsBlockTitleItem,
|
||||
},
|
||||
{
|
||||
name: 'background',
|
||||
Component: () => {
|
||||
const { t } = useChartsTranslation();
|
||||
const field = useField();
|
||||
const fieldSchema = useFieldSchema();
|
||||
const { dn } = useDesignable();
|
||||
const { token } = useToken();
|
||||
|
||||
return (
|
||||
<SchemaSettingsSwitchItem
|
||||
title={t('Show background')}
|
||||
checked={field.componentProps.style?.background !== 'none'}
|
||||
onChange={(v) => {
|
||||
const style = {
|
||||
...field.componentProps.style,
|
||||
background: v ? token.colorBgContainer : 'none',
|
||||
boxShadow: v ? token.boxShadowTertiary : 'none',
|
||||
};
|
||||
field.componentProps.style = style;
|
||||
field.componentProps.bordered = v;
|
||||
fieldSchema['x-component-props'] = field.componentProps;
|
||||
dn.emit('patch', {
|
||||
schema: {
|
||||
['x-uid']: fieldSchema['x-uid'],
|
||||
'x-component-props': field.componentProps,
|
||||
},
|
||||
});
|
||||
dn.refresh();
|
||||
}}
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'padding',
|
||||
Component: () => {
|
||||
const { t } = useChartsTranslation();
|
||||
const field = useField();
|
||||
const fieldSchema = useFieldSchema();
|
||||
const { dn } = useDesignable();
|
||||
const { token } = useToken();
|
||||
|
||||
return (
|
||||
<SchemaSettingsSwitchItem
|
||||
title={t('Show padding')}
|
||||
checked={field.componentProps.bodyStyle?.padding !== '5px 0 0'}
|
||||
onChange={(v) => {
|
||||
const style = {
|
||||
...field.componentProps.bodyStyle,
|
||||
padding: v ? `${token.paddingLG}px ${token.paddingLG}px 0` : '5px 0 0',
|
||||
};
|
||||
field.componentProps.bodyStyle = style;
|
||||
fieldSchema['x-component-props'] = field.componentProps;
|
||||
dn.emit('patch', {
|
||||
schema: {
|
||||
['x-uid']: fieldSchema['x-uid'],
|
||||
'x-component-props': field.componentProps,
|
||||
},
|
||||
});
|
||||
dn.refresh();
|
||||
}}
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'divider',
|
||||
type: 'divider',
|
||||
},
|
||||
{
|
||||
name: 'remove',
|
||||
type: 'remove',
|
||||
},
|
||||
],
|
||||
});
|
@ -0,0 +1,29 @@
|
||||
/**
|
||||
* 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 from 'react';
|
||||
import { SchemaSettings, SchemaSettingsRemove } from '@nocobase/client';
|
||||
|
||||
export const chartFilterBlockSettings = new SchemaSettings({
|
||||
name: 'chart:filterForm:block',
|
||||
items: [
|
||||
{
|
||||
name: 'remove',
|
||||
Component: () => {
|
||||
return (
|
||||
<SchemaSettingsRemove
|
||||
breakRemoveOn={{
|
||||
'x-component': 'ChartV2Block',
|
||||
}}
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
@ -0,0 +1,574 @@
|
||||
/**
|
||||
* 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, { useContext } from 'react';
|
||||
import {
|
||||
EditDescription,
|
||||
GeneralSchemaDesigner,
|
||||
SchemaSettingsItem,
|
||||
SchemaSettingsDivider,
|
||||
SchemaSettingsModalItem,
|
||||
SchemaSettingsRemove,
|
||||
VariablesContext,
|
||||
useCollection_deprecated,
|
||||
useCollectionManager_deprecated,
|
||||
useCompile,
|
||||
useDesignable,
|
||||
SchemaSettingsSelectItem,
|
||||
CollectionFieldOptions_deprecated,
|
||||
DEFAULT_DATA_SOURCE_KEY,
|
||||
useIsAssociationField,
|
||||
SchemaSettingsDataScope,
|
||||
removeNullCondition,
|
||||
useFormBlockContext,
|
||||
useLocalVariables,
|
||||
SchemaSettings,
|
||||
useApp,
|
||||
useIsFileField,
|
||||
} from '@nocobase/client';
|
||||
import { useChartsTranslation } from '../locale';
|
||||
import { Schema, useField, useFieldSchema, ISchema } from '@formily/react';
|
||||
import { Field } from '@formily/core';
|
||||
import _ from 'lodash';
|
||||
import { ChartFilterContext } from '../filter/FilterProvider';
|
||||
import { getPropsSchemaByComponent, setDefaultValue } from '../filter/utils';
|
||||
import { ChartFilterVariableInput } from '../filter/FilterVariableInput';
|
||||
import { useChartDataSource, useChartFilter, useCollectionJoinFieldTitle } from '../hooks';
|
||||
import { Typography } from 'antd';
|
||||
import { getFormulaInterface } from '../utils';
|
||||
const { Text } = Typography;
|
||||
|
||||
function useFieldComponentName(): string {
|
||||
const field = useField<Field>();
|
||||
const isFileField = useIsFileField();
|
||||
const { getCollectionJoinField } = useCollectionManager_deprecated();
|
||||
const { getField } = useCollection_deprecated();
|
||||
const fieldSchema = useFieldSchema();
|
||||
const fieldName = fieldSchema.name as string;
|
||||
const collectionField = getField(fieldName) || getCollectionJoinField(fieldSchema['x-collection-field']);
|
||||
|
||||
const map = {
|
||||
// AssociationField 的 mode 默认值是 Select
|
||||
AssociationField: 'Select',
|
||||
};
|
||||
const fieldComponentName =
|
||||
fieldSchema?.['x-component-props']?.['mode'] ||
|
||||
field?.componentProps?.['mode'] ||
|
||||
(isFileField ? 'FileManager' : '') ||
|
||||
fieldSchema?.['x-component-props']?.['component'] ||
|
||||
collectionField?.uiSchema?.['x-component'];
|
||||
return map[fieldComponentName] || fieldComponentName;
|
||||
}
|
||||
|
||||
const EditTitle = () => {
|
||||
const field = useField<Field>();
|
||||
const fieldSchema = useFieldSchema();
|
||||
const { t } = useChartsTranslation();
|
||||
const { dn } = useDesignable();
|
||||
const { setField } = useContext(ChartFilterContext);
|
||||
|
||||
return (
|
||||
<SchemaSettingsModalItem
|
||||
key="edit-field-title"
|
||||
title={t('Edit field title')}
|
||||
schema={{
|
||||
type: 'object',
|
||||
title: t('Edit field title'),
|
||||
properties: {
|
||||
title: {
|
||||
title: t('Field title'),
|
||||
default: field?.title,
|
||||
required: true,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
'x-component-props': {},
|
||||
},
|
||||
},
|
||||
}}
|
||||
onSubmit={({ title }) => {
|
||||
if (title) {
|
||||
field.title = title;
|
||||
fieldSchema.title = title;
|
||||
dn.emit('patch', {
|
||||
schema: {
|
||||
'x-uid': fieldSchema['x-uid'],
|
||||
title: fieldSchema.title,
|
||||
},
|
||||
});
|
||||
setField(fieldSchema.name as string, { title });
|
||||
}
|
||||
dn.refresh();
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const EditOperator = () => {
|
||||
const compile = useCompile();
|
||||
const fieldSchema = useFieldSchema();
|
||||
const field = useField<Field>();
|
||||
const { t } = useChartsTranslation();
|
||||
const { dn } = useDesignable();
|
||||
const { setField } = useContext(ChartFilterContext);
|
||||
const fieldName = fieldSchema['x-collection-field'];
|
||||
const dataSource = fieldSchema['x-data-source'] || DEFAULT_DATA_SOURCE_KEY;
|
||||
const { cm, fim } = useChartDataSource(dataSource);
|
||||
if (!cm) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const getOperators = (props: CollectionFieldOptions_deprecated) => {
|
||||
let fieldInterface = props?.interface;
|
||||
if (fieldInterface === 'formula') {
|
||||
fieldInterface = getFormulaInterface(props.dataType) || props.dataType;
|
||||
}
|
||||
const interfaceConfig = fim.getFieldInterface(fieldInterface);
|
||||
const operatorList = interfaceConfig?.filterable?.operators || [];
|
||||
return { operatorList, interfaceConfig };
|
||||
};
|
||||
|
||||
let props = cm.getCollectionField(fieldName);
|
||||
let { operatorList, interfaceConfig } = getOperators(props);
|
||||
if (!operatorList.length) {
|
||||
const names = fieldName.split('.');
|
||||
const name = names.pop();
|
||||
if (names.length < 2) {
|
||||
return null;
|
||||
}
|
||||
props = cm.getCollectionField(names.join('.'));
|
||||
if (!props) {
|
||||
return null;
|
||||
}
|
||||
const res = getOperators(props);
|
||||
operatorList = res.operatorList;
|
||||
interfaceConfig = res.interfaceConfig;
|
||||
if (!interfaceConfig) {
|
||||
return null;
|
||||
}
|
||||
const children = interfaceConfig?.filterable.children || [];
|
||||
const child = children.find((item: any) => item.name === name);
|
||||
operatorList = child?.operators || [];
|
||||
}
|
||||
if (!operatorList.length) {
|
||||
return null;
|
||||
}
|
||||
const defaultComponent = interfaceConfig?.default?.uiSchema?.['x-component'] || 'Input';
|
||||
const operator = fieldSchema['x-component-props']?.['filter-operator'];
|
||||
|
||||
const setOperatorComponent = (operator: any, component: any, props = {}) => {
|
||||
const componentProps = field.componentProps || {};
|
||||
field.component = component;
|
||||
field.componentProps = {
|
||||
...componentProps,
|
||||
'filter-operator': operator,
|
||||
...props,
|
||||
};
|
||||
fieldSchema['x-component'] = component;
|
||||
fieldSchema['x-component-props'] = {
|
||||
...fieldSchema['x-component-props'],
|
||||
'filter-operator': operator,
|
||||
...props,
|
||||
};
|
||||
fieldSchema['x-filter-operator'] = operator?.value;
|
||||
dn.emit('patch', {
|
||||
schema: {
|
||||
'x-uid': fieldSchema['x-uid'],
|
||||
'x-component': component,
|
||||
'x-component-props': {
|
||||
...fieldSchema['x-component-props'],
|
||||
'filter-operator': operator,
|
||||
...props,
|
||||
},
|
||||
'x-filter-operator': operator?.value,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<SchemaSettingsSelectItem
|
||||
key="operator"
|
||||
title={t('Operator')}
|
||||
value={operator?.value || operatorList[0]?.value}
|
||||
options={compile(operatorList)}
|
||||
onChange={(op: string) => {
|
||||
const operator = operatorList.find((item: any) => item.value === op);
|
||||
if (operator.noValue) {
|
||||
setOperatorComponent(operator, 'ChartFilterCheckbox', {
|
||||
content: Schema.compile(operator.label, { t }),
|
||||
});
|
||||
} else if (operator.schema?.['x-component']) {
|
||||
setOperatorComponent(operator, operator.schema['x-component']);
|
||||
} else {
|
||||
setOperatorComponent(operator, defaultComponent);
|
||||
}
|
||||
|
||||
setField(fieldSchema.name as string, { operator });
|
||||
dn.refresh();
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const EditProps = () => {
|
||||
const { t } = useChartsTranslation();
|
||||
const { dn } = useDesignable();
|
||||
const field = useField<Field>();
|
||||
const fieldSchema = useFieldSchema();
|
||||
const propsSchema = getPropsSchemaByComponent(fieldSchema['x-component']);
|
||||
return (
|
||||
<SchemaSettingsModalItem
|
||||
key="edit-field-props"
|
||||
title={t('Edit field properties')}
|
||||
schema={{
|
||||
title: t('Edit field properties'),
|
||||
...propsSchema,
|
||||
}}
|
||||
initialValues={field.componentProps}
|
||||
onSubmit={(props) => {
|
||||
field.reset();
|
||||
field.componentProps = props;
|
||||
fieldSchema['x-component-props'] = props;
|
||||
dn.emit('patch', {
|
||||
schema: {
|
||||
'x-uid': fieldSchema['x-uid'],
|
||||
'x-component-props': props,
|
||||
},
|
||||
});
|
||||
dn.refresh();
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const EditDefaultValue = () => {
|
||||
const { t } = useChartsTranslation();
|
||||
const { dn } = useDesignable();
|
||||
const variables = useContext(VariablesContext);
|
||||
const localVariables = useLocalVariables();
|
||||
const field = useField<Field>();
|
||||
const fieldSchema = useFieldSchema();
|
||||
const { getTranslatedTitle } = useChartFilter();
|
||||
const title = getTranslatedTitle(fieldSchema.title);
|
||||
return (
|
||||
<SchemaSettingsModalItem
|
||||
key="set field default value"
|
||||
title={t('Set default value')}
|
||||
components={{
|
||||
ChartFilterVariableInput,
|
||||
}}
|
||||
schema={{
|
||||
type: 'void',
|
||||
title: t('Set default value'),
|
||||
properties: {
|
||||
default: {
|
||||
title,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'ChartFilterVariableInput',
|
||||
'x-component-props': {
|
||||
fieldSchema,
|
||||
},
|
||||
},
|
||||
},
|
||||
}}
|
||||
onSubmit={({ default: { value } }) => {
|
||||
field.setInitialValue(value);
|
||||
fieldSchema.default = value;
|
||||
dn.emit('patch', {
|
||||
schema: {
|
||||
'x-uid': fieldSchema['x-uid'],
|
||||
default: value,
|
||||
},
|
||||
});
|
||||
dn.refresh();
|
||||
setDefaultValue(field, variables, localVariables);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const EditTitleField = () => {
|
||||
const { getCollectionFields, getCollectionJoinField, getInterface } = useCollectionManager_deprecated();
|
||||
const field = useField<Field>();
|
||||
const fieldSchema = useFieldSchema();
|
||||
const { t } = useChartsTranslation();
|
||||
const { dn } = useDesignable();
|
||||
const compile = useCompile();
|
||||
const collectionField = getCollectionJoinField(fieldSchema['x-collection-field']);
|
||||
const targetFields = collectionField?.target
|
||||
? getCollectionFields(collectionField?.target)
|
||||
: getCollectionFields(collectionField?.targetCollection) ?? [];
|
||||
const options = targetFields
|
||||
.filter((field) => {
|
||||
if (field?.target || field.type === 'boolean') {
|
||||
return false;
|
||||
}
|
||||
const fieldInterface = getInterface(field?.interface);
|
||||
return fieldInterface?.titleUsable;
|
||||
})
|
||||
.map((field) => ({
|
||||
value: field?.name,
|
||||
label: compile(field?.uiSchema?.title) || field?.name,
|
||||
}));
|
||||
|
||||
return options.length > 0 && fieldSchema['x-component'] === 'CollectionField' ? (
|
||||
<SchemaSettingsSelectItem
|
||||
key="title-field"
|
||||
title={t('Title field')}
|
||||
options={options}
|
||||
value={field?.componentProps?.fieldNames?.label}
|
||||
onChange={(label: string) => {
|
||||
const schema = {
|
||||
['x-uid']: fieldSchema['x-uid'],
|
||||
};
|
||||
const fieldNames = {
|
||||
...collectionField?.uiSchema?.['x-component-props']?.['fieldNames'],
|
||||
...field.componentProps.fieldNames,
|
||||
label,
|
||||
};
|
||||
fieldSchema['x-component-props'] = fieldSchema['x-component-props'] || {};
|
||||
fieldSchema['x-component-props']['fieldNames'] = fieldNames;
|
||||
schema['x-component-props'] = fieldSchema['x-component-props'];
|
||||
field.componentProps.fieldNames = fieldSchema['x-component-props'].fieldNames;
|
||||
dn.emit('patch', {
|
||||
schema,
|
||||
});
|
||||
dn.refresh();
|
||||
}}
|
||||
/>
|
||||
) : null;
|
||||
};
|
||||
|
||||
const EditDataScope: React.FC = () => {
|
||||
const { dn } = useDesignable();
|
||||
const field = useField<Field>();
|
||||
const fieldSchema = useFieldSchema();
|
||||
const dataSource = fieldSchema['x-data-source'] || DEFAULT_DATA_SOURCE_KEY;
|
||||
const { form } = useFormBlockContext();
|
||||
const { cm } = useChartDataSource(dataSource);
|
||||
const collectionField = cm.getCollectionField(fieldSchema['x-collection-field']);
|
||||
if (!collectionField) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<SchemaSettingsDataScope
|
||||
form={form}
|
||||
defaultFilter={fieldSchema?.['x-component-props']?.service?.params?.filter || {}}
|
||||
collectionName={collectionField.target}
|
||||
onSubmit={({ filter }) => {
|
||||
filter = removeNullCondition(filter);
|
||||
_.set(field.componentProps, 'service.params.filter', filter);
|
||||
fieldSchema['x-component-props'] = field.componentProps;
|
||||
dn.emit('patch', {
|
||||
schema: {
|
||||
['x-uid']: fieldSchema['x-uid'],
|
||||
'x-component-props': field.componentProps,
|
||||
},
|
||||
});
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export const chartFilterItemSettings = new SchemaSettings({
|
||||
name: 'chart:filterForm:item',
|
||||
items: [
|
||||
{
|
||||
name: 'originalTitle',
|
||||
Component: () => {
|
||||
const { t } = useChartsTranslation();
|
||||
const fieldSchema = useFieldSchema();
|
||||
const fieldName = fieldSchema.name as string;
|
||||
const isCustom = fieldName.startsWith('custom.');
|
||||
const dataSource = fieldSchema['x-data-source'] || DEFAULT_DATA_SOURCE_KEY;
|
||||
|
||||
const originalTitle = useCollectionJoinFieldTitle(dataSource, fieldName);
|
||||
if (isCustom) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<SchemaSettingsItem title={fieldName}>
|
||||
<Text type="secondary">
|
||||
{t('Original field')}: {originalTitle}
|
||||
</Text>
|
||||
</SchemaSettingsItem>
|
||||
<SchemaSettingsDivider />
|
||||
</>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'decoratorOptions',
|
||||
type: 'itemGroup',
|
||||
hideIfNoChildren: true,
|
||||
useComponentProps() {
|
||||
const { t } = useChartsTranslation();
|
||||
return {
|
||||
title: t('Generic properties'),
|
||||
};
|
||||
},
|
||||
useChildren() {
|
||||
return [
|
||||
{
|
||||
name: 'title',
|
||||
Component: EditTitle,
|
||||
},
|
||||
{
|
||||
name: 'displayTitle',
|
||||
type: 'switch',
|
||||
useComponentProps() {
|
||||
const { t } = useChartsTranslation();
|
||||
const { dn } = useDesignable();
|
||||
const field = useField<Field>();
|
||||
const fieldSchema = useFieldSchema();
|
||||
|
||||
return {
|
||||
title: t('Display title'),
|
||||
checked: fieldSchema['x-decorator-props']?.['showTitle'] ?? true,
|
||||
onChange(checked) {
|
||||
fieldSchema['x-decorator-props'] = fieldSchema['x-decorator-props'] || {};
|
||||
fieldSchema['x-decorator-props']['showTitle'] = checked;
|
||||
field.decoratorProps.showTitle = checked;
|
||||
dn.emit('patch', {
|
||||
schema: {
|
||||
'x-uid': fieldSchema['x-uid'],
|
||||
'x-decorator-props': {
|
||||
...fieldSchema['x-decorator-props'],
|
||||
showTitle: checked,
|
||||
},
|
||||
},
|
||||
});
|
||||
dn.refresh();
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'description',
|
||||
Component: EditDescription,
|
||||
},
|
||||
{
|
||||
name: 'editTooltip',
|
||||
type: 'modal',
|
||||
useComponentProps() {
|
||||
const { t } = useChartsTranslation();
|
||||
const { dn } = useDesignable();
|
||||
const field = useField<Field>();
|
||||
const fieldSchema = useFieldSchema();
|
||||
|
||||
return {
|
||||
title: t('Edit tooltip'),
|
||||
schema: {
|
||||
type: 'object',
|
||||
title: t('Edit tooltip'),
|
||||
properties: {
|
||||
tooltip: {
|
||||
default: fieldSchema?.['x-decorator-props']?.tooltip,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input.TextArea',
|
||||
'x-component-props': {},
|
||||
},
|
||||
},
|
||||
} as ISchema,
|
||||
onSubmit({ tooltip }) {
|
||||
field.decoratorProps.tooltip = tooltip;
|
||||
fieldSchema['x-decorator-props'] = fieldSchema['x-decorator-props'] || {};
|
||||
fieldSchema['x-decorator-props']['tooltip'] = tooltip;
|
||||
dn.emit('patch', {
|
||||
schema: {
|
||||
'x-uid': fieldSchema['x-uid'],
|
||||
'x-decorator-props': fieldSchema['x-decorator-props'],
|
||||
},
|
||||
});
|
||||
dn.refresh();
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'defaultValue',
|
||||
Component: EditDefaultValue,
|
||||
},
|
||||
{
|
||||
name: 'operator',
|
||||
Component: () => {
|
||||
const fieldSchema = useFieldSchema();
|
||||
const fieldName = fieldSchema.name as string;
|
||||
const isCustom = fieldName.startsWith('custom.');
|
||||
if (isCustom) {
|
||||
return null;
|
||||
}
|
||||
return <EditOperator />;
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'props',
|
||||
Component: () => {
|
||||
const fieldSchema = useFieldSchema();
|
||||
const fieldName = fieldSchema.name as string;
|
||||
const isCustom = fieldName.startsWith('custom.');
|
||||
const hasProps = getPropsSchemaByComponent(fieldSchema['x-component']);
|
||||
if (hasProps && isCustom) {
|
||||
return <EditProps />;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
},
|
||||
];
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'componentOptions',
|
||||
type: 'itemGroup',
|
||||
hideIfNoChildren: true,
|
||||
useComponentProps() {
|
||||
const { t } = useChartsTranslation();
|
||||
return {
|
||||
title: t('Specific properties'),
|
||||
};
|
||||
},
|
||||
useChildren() {
|
||||
const fieldComponentNameMap = {
|
||||
Select: 'FilterSelect',
|
||||
};
|
||||
const app = useApp();
|
||||
const fieldComponentName = useFieldComponentName();
|
||||
const componentSettings = app.schemaSettingsManager.get(
|
||||
`fieldSettings:component:${fieldComponentNameMap[fieldComponentName] || fieldComponentName}`,
|
||||
);
|
||||
return componentSettings?.items || [];
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'divider',
|
||||
Component: () => {
|
||||
return <SchemaSettingsDivider />;
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'remove',
|
||||
Component: () => {
|
||||
const { t } = useChartsTranslation();
|
||||
|
||||
return (
|
||||
<SchemaSettingsRemove
|
||||
key="remove"
|
||||
confirm={{
|
||||
title: t('Delete field'),
|
||||
}}
|
||||
breakRemoveOn={{
|
||||
'x-component': 'Grid',
|
||||
}}
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
@ -0,0 +1,102 @@
|
||||
/**
|
||||
* 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, { useContext } from 'react';
|
||||
import { useField, useFieldSchema } from '@formily/react';
|
||||
import {
|
||||
SchemaSettings,
|
||||
SchemaSettingsItem,
|
||||
SchemaSettingsRemove,
|
||||
gridRowColWrap,
|
||||
useDataSource,
|
||||
useCollection,
|
||||
useDesignable,
|
||||
} from '@nocobase/client';
|
||||
import { ChartDataContext } from '../block/ChartDataProvider';
|
||||
import { ChartConfigContext } from '../configure';
|
||||
import { useChartsTranslation } from '../locale';
|
||||
import { createRendererSchema } from '../utils';
|
||||
import { ChartRendererContext } from '../renderer/ChartRendererProvider';
|
||||
|
||||
export const chartRendererSettings = new SchemaSettings({
|
||||
name: 'chart:renderer',
|
||||
items: [
|
||||
{
|
||||
name: 'configure',
|
||||
Component: () => {
|
||||
const { t } = useChartsTranslation();
|
||||
const { setVisible, setCurrent } = useContext(ChartConfigContext);
|
||||
const { service } = useContext(ChartRendererContext);
|
||||
const field = useField();
|
||||
const schema = useFieldSchema();
|
||||
const dataSource = useDataSource();
|
||||
const { name } = useCollection();
|
||||
|
||||
return (
|
||||
<SchemaSettingsItem
|
||||
title="Configure"
|
||||
key="configure"
|
||||
onClick={async () => {
|
||||
setCurrent({ schema, field, dataSource: dataSource.key, collection: name, service, data: service.data });
|
||||
setVisible(true);
|
||||
}}
|
||||
>
|
||||
{t('Configure')}
|
||||
</SchemaSettingsItem>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'duplicate',
|
||||
Component: () => {
|
||||
const { t } = useChartsTranslation();
|
||||
const { insertAdjacent, refresh } = useDesignable();
|
||||
const schema = useFieldSchema();
|
||||
|
||||
return (
|
||||
<SchemaSettingsItem
|
||||
title="Duplicate"
|
||||
key="duplicate"
|
||||
onClick={() => {
|
||||
insertAdjacent('afterEnd', gridRowColWrap(createRendererSchema(schema?.['x-decorator-props'])));
|
||||
refresh({ refreshParentSchema: true });
|
||||
}}
|
||||
>
|
||||
{t('Duplicate')}
|
||||
</SchemaSettingsItem>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'divider',
|
||||
type: 'divider',
|
||||
},
|
||||
{
|
||||
name: 'remove',
|
||||
Component: () => {
|
||||
const { removeChart } = useContext(ChartDataContext);
|
||||
const schema = useFieldSchema();
|
||||
|
||||
return (
|
||||
<SchemaSettingsRemove
|
||||
// removeParentsIfNoChildren
|
||||
breakRemoveOn={{
|
||||
'x-component': 'ChartV2Block',
|
||||
}}
|
||||
confirm={{
|
||||
onOk: () => {
|
||||
removeChart(schema['x-uid']);
|
||||
},
|
||||
}}
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
@ -0,0 +1,15 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export { chartActionRefreshSettings } from './chartActionRefresh';
|
||||
export { chartBlockActionRefreshSettings } from './chartBlockActionRefresh';
|
||||
export { chartBlockSettings } from './chartBlock';
|
||||
export { chartRendererSettings } from './chartRenderer';
|
||||
export { chartFilterBlockSettings } from './chartFilterBlock';
|
||||
export { chartFilterItemSettings } from './chartFilterItem';
|
@ -0,0 +1,18 @@
|
||||
/**
|
||||
* 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 { SchemaToolbar } from '@nocobase/client';
|
||||
import React from 'react';
|
||||
import { useChartsTranslation } from '../locale';
|
||||
|
||||
export const ChartFilterBlockToolbar = () => {
|
||||
const { t } = useChartsTranslation();
|
||||
|
||||
return <SchemaToolbar title={t('Filter')} />;
|
||||
};
|
@ -0,0 +1,15 @@
|
||||
/**
|
||||
* 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 { SchemaToolbar } from '@nocobase/client';
|
||||
import React from 'react';
|
||||
|
||||
export const ChartFilterItemToolbar = () => {
|
||||
return <SchemaToolbar showBackground={true} showBorder={false} />;
|
||||
};
|
@ -0,0 +1,17 @@
|
||||
/**
|
||||
* 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 { SchemaToolbar, useCollection } from '@nocobase/client';
|
||||
import React from 'react';
|
||||
|
||||
export const ChartRendererToolbar = () => {
|
||||
const { name, title } = useCollection();
|
||||
|
||||
return <SchemaToolbar title={title || name} />;
|
||||
};
|
@ -0,0 +1,12 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export * from './ChartRenderer';
|
||||
export * from './ChartFilterBlock';
|
||||
export * from './ChartFilterItem';
|
@ -12,8 +12,7 @@ import { uid } from '@formily/shared';
|
||||
import lodash from 'lodash';
|
||||
import { SelectedField } from './configure';
|
||||
import { FieldOption } from './hooks';
|
||||
import { ChartRendererContext, QueryProps } from './renderer';
|
||||
import { useContext } from 'react';
|
||||
import { QueryProps } from './renderer';
|
||||
|
||||
export const createRendererSchema = (decoratorProps: any, componentProps = {}) => {
|
||||
const { collection, config } = decoratorProps;
|
||||
@ -23,7 +22,8 @@ export const createRendererSchema = (decoratorProps: any, componentProps = {}) =
|
||||
'x-decorator': 'ChartRendererProvider',
|
||||
'x-decorator-props': decoratorProps,
|
||||
'x-acl-action': `${collection}:list`,
|
||||
'x-designer': 'ChartRenderer.Designer',
|
||||
'x-toolbar': 'ChartRendererToolbar',
|
||||
'x-settings': 'chart:renderer',
|
||||
'x-component': 'CardItem',
|
||||
'x-component-props': {
|
||||
size: 'small',
|
||||
|
Loading…
x
Reference in New Issue
Block a user