refactor: adjusting group block loading methods and folder structure
This commit is contained in:
parent
47e5892c61
commit
53bb505823
@ -12,6 +12,7 @@
|
||||
"@formily/react": "^2.2.27",
|
||||
"@formily/shared": "^2.2.27",
|
||||
"@react-pdf/renderer": "^3.3.2",
|
||||
"ahooks": "^3.7.2",
|
||||
"antd": "5.12.8",
|
||||
"copy-to-clipboard": "^3.3.3",
|
||||
"exceljs": "^4.4.0",
|
||||
|
@ -1,4 +1,3 @@
|
||||
export * from '../schema-components/blocks/GroupBlockConfigure/GroupBlockConfigure';
|
||||
export * from './PDFViewer';
|
||||
export * from './Sheet';
|
||||
export * from './SignatureInput';
|
||||
|
@ -40,24 +40,20 @@ import {
|
||||
CustomComponentStub,
|
||||
customComponentDispatcherSettings,
|
||||
Expression,
|
||||
GroupBlockConfigure,
|
||||
SignatureInput,
|
||||
} from './components';
|
||||
import { AutoComplete, DatePicker, GroupBlock, InternalPDFViewer, MenuDesigner } from './schema-components';
|
||||
import { AutoComplete, DatePicker, InternalPDFViewer, MenuDesigner } from './schema-components';
|
||||
import {
|
||||
CreateSubmitActionInitializer,
|
||||
FilterFormItem,
|
||||
FilterFormItemCustom,
|
||||
FilterItemCustomDesigner,
|
||||
GroupBlockInitializer,
|
||||
GroupBlockProvider,
|
||||
GroupBlockToolbar,
|
||||
GroupBlockPlugin,
|
||||
OutboundActionHelper,
|
||||
PDFViewerBlockInitializer,
|
||||
PDFViewerPrintActionInitializer,
|
||||
PDFViewerProvider,
|
||||
SettingBlockInitializer,
|
||||
groupBlockSettings,
|
||||
pdfViewActionInitializer,
|
||||
usePDFViewerPrintActionProps,
|
||||
} from './schema-initializer';
|
||||
@ -75,8 +71,11 @@ export * from './components/custom-components/custom-components';
|
||||
export class PluginCoreClient extends Plugin {
|
||||
locale: Locale;
|
||||
|
||||
async afterAdd() {
|
||||
await this.app.pm.add(GroupBlockPlugin);
|
||||
}
|
||||
|
||||
async registerSettings() {
|
||||
this.schemaSettingsManager.add(groupBlockSettings);
|
||||
this.schemaSettingsManager.add(sheetBlockSettings);
|
||||
this.schemaSettingsManager.add(customComponentDispatcherSettings);
|
||||
this.schemaSettingsManager.addItem('FilterFormItemSettings', 'formulatitleField', {
|
||||
@ -162,11 +161,6 @@ export class PluginCoreClient extends Plugin {
|
||||
FilterFormItem,
|
||||
FilterFormItemCustom,
|
||||
FilterItemCustomDesigner,
|
||||
GroupBlock,
|
||||
GroupBlockConfigure,
|
||||
GroupBlockInitializer,
|
||||
GroupBlockProvider,
|
||||
GroupBlockToolbar,
|
||||
FilterVariableInput,
|
||||
Menu: {
|
||||
...Menu,
|
||||
@ -231,10 +225,6 @@ export class PluginCoreClient extends Plugin {
|
||||
};
|
||||
this.schemaInitializerManager.add(pdfViewActionInitializer);
|
||||
this.app.schemaInitializerManager.addItem('page:addBlock', settingBlockItem.name, settingBlockItem);
|
||||
this.app.schemaInitializerManager.addItem('page:addBlock', 'dataBlocks.groupBlock', {
|
||||
title: tval('Group'),
|
||||
Component: 'GroupBlockInitializer',
|
||||
});
|
||||
this.app.schemaInitializerManager.addItem('page:addBlock', 'dataBlocks.sheetBlock', {
|
||||
title: tval('Sheet'),
|
||||
Component: 'SheetBlockInitializer',
|
||||
|
@ -1,28 +1,21 @@
|
||||
import React, { useState } from 'react';
|
||||
import { useField, useFieldSchema } from '@formily/react';
|
||||
import { findFilterTargets, useAPIClient, useBlockRequestContext, useFilterBlock } from '@nocobase/client';
|
||||
import { Descriptions, DescriptionsProps, Space, Spin } from 'antd';
|
||||
import { transformers } from './GroupBlockConfigure/transformers';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useAPIClient, useBlockRequestContext, useFilterBlock } from '@nocobase/client';
|
||||
import { Descriptions, DescriptionsProps, Spin, Table } from 'antd';
|
||||
import { transformers } from '../../schema-settings/GroupBlockConfigure';
|
||||
import { useAsyncEffect } from 'ahooks';
|
||||
import { GroupConfigure } from './GroupBlockConfigure/GroupConfigure';
|
||||
|
||||
type DataItem = {
|
||||
labels: string[];
|
||||
values: number[];
|
||||
};
|
||||
type requestData = {
|
||||
label: string;
|
||||
value: number | DataItem;
|
||||
type ReqData = {
|
||||
labels: any[];
|
||||
values: any[];
|
||||
};
|
||||
|
||||
export const GroupBlock = (props) => {
|
||||
const field = useField<any>();
|
||||
const fieldSchema = useFieldSchema();
|
||||
const params = fieldSchema.parent['x-decorator-props'].params;
|
||||
const { resource, service } = useBlockRequestContext();
|
||||
const { service } = useBlockRequestContext();
|
||||
const { getDataBlocks } = useFilterBlock();
|
||||
const Blocks = getDataBlocks();
|
||||
const [group, setGroup] = useState([]);
|
||||
if (!service.params.length) {
|
||||
getDataBlocks().map((block) => {
|
||||
if (Object.keys(block.defaultFilter).length) {
|
||||
@ -47,7 +40,7 @@ export const GroupBlock = (props) => {
|
||||
<p style={{ fontWeight: 600 }}>汇总:</p>
|
||||
{params?.config.map((configItem, index) => {
|
||||
if (configItem) {
|
||||
return <GroupConfigure {...props} configItem={configItem} service={service} key={index} />;
|
||||
return <InternalGroupBlock {...props} configItem={configItem} service={service} key={index} />;
|
||||
}
|
||||
})}
|
||||
</>
|
||||
@ -73,3 +66,123 @@ export const fieldTransformers = (item, data, api) => {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const InternalGroupBlock = (props) => {
|
||||
const { configItem, service } = props;
|
||||
const fieldSchema = useFieldSchema();
|
||||
const params = fieldSchema.parent['x-decorator-props'].params;
|
||||
const [result, setResult] = useState({});
|
||||
const { getDataBlocks } = useFilterBlock();
|
||||
const Blocks = getDataBlocks();
|
||||
const api = useAPIClient();
|
||||
useAsyncEffect(async () => {
|
||||
const filter = service?.params[0] ? service.params[0].filter : service?.params;
|
||||
if (configItem.reqUrl) {
|
||||
setResult(
|
||||
(await api.request({
|
||||
url: configItem.reqUrl,
|
||||
method: 'POST',
|
||||
data: {
|
||||
filter: { ...filter },
|
||||
collection: params.collection,
|
||||
},
|
||||
})) ?? {},
|
||||
);
|
||||
}
|
||||
}, [Blocks, service.params, service.params[0]]);
|
||||
if (configItem.style === 'describe') {
|
||||
const item: DescriptionsProps['items'] = describeItem(configItem, result, service, params, api);
|
||||
return <Descriptions style={{ marginBottom: '10px' }} items={item} />;
|
||||
} else if (configItem.style === 'table') {
|
||||
const { columns, options } = tableItem(configItem, result, service, params, api);
|
||||
return <Table style={{ marginBottom: '10px' }} columns={columns} dataSource={options} pagination={false} />;
|
||||
}
|
||||
};
|
||||
|
||||
const describeItem = (configItem, result, service, params, api) => {
|
||||
const item = [];
|
||||
if (configItem.type === 'field') {
|
||||
const measuresData = service.data?.data;
|
||||
if (measuresData) {
|
||||
let data = measuresData.map((value) => {
|
||||
return value[configItem.field];
|
||||
})[0];
|
||||
data = fieldTransformers(configItem, data, api);
|
||||
const label = params.measures.find((value) => value.field[0] === configItem.field).label;
|
||||
item.push({
|
||||
key: configItem.field,
|
||||
label,
|
||||
children: data,
|
||||
});
|
||||
}
|
||||
} else if (configItem.type === 'custom') {
|
||||
if (Object.keys(result).length && result?.['data']?.data) {
|
||||
const data: ReqData = { ...result?.['data']?.data };
|
||||
const label = data.labels;
|
||||
data.values.forEach((valueItem, index) => {
|
||||
let childrenText = '';
|
||||
label.forEach((value, index) => {
|
||||
if (index === 0) return;
|
||||
childrenText += `${value}${fieldTransformers(configItem, valueItem[index], api)} `;
|
||||
});
|
||||
item.push({
|
||||
key: index,
|
||||
label: valueItem[0],
|
||||
children: childrenText,
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
return item;
|
||||
};
|
||||
|
||||
const tableItem = (configItem, result, service, params, api) => {
|
||||
const columns = [];
|
||||
const options = [];
|
||||
if (configItem.type === 'custom') {
|
||||
if (Object.keys(result).length && result?.['data']?.data) {
|
||||
const data: ReqData = { ...result?.['data']?.data };
|
||||
data.labels.forEach((value, index) => {
|
||||
columns.push({ title: value, dataIndex: 'value' + index, key: index });
|
||||
});
|
||||
data.values.forEach((value, index) => {
|
||||
const item = {
|
||||
key: index,
|
||||
};
|
||||
columns.forEach((colItem, index) => {
|
||||
const data = isNaN(value[index]) ? value[index] : fieldTransformers(configItem, value[index], api);
|
||||
item[colItem.dataIndex] = data;
|
||||
});
|
||||
options.push(item);
|
||||
});
|
||||
}
|
||||
} else if (configItem.type === 'field') {
|
||||
const measuresData = service.data?.data;
|
||||
if (measuresData) {
|
||||
let data = measuresData.map((value) => {
|
||||
return value[configItem.field];
|
||||
})[0];
|
||||
data = fieldTransformers(configItem, data, api);
|
||||
const label = params.measures.find((value) => value.field[0] === configItem.field).label;
|
||||
columns.push(
|
||||
{
|
||||
title: '名称',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
},
|
||||
{
|
||||
title: '数量',
|
||||
dataIndex: 'number',
|
||||
key: 'number',
|
||||
},
|
||||
);
|
||||
options.push({
|
||||
key: label,
|
||||
name: label,
|
||||
number: data,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return { columns, options };
|
||||
};
|
||||
|
@ -1,132 +0,0 @@
|
||||
import { useField, useFieldSchema } from '@formily/react';
|
||||
import { useAPIClient, useFilterBlock, useRequest } from '@nocobase/client';
|
||||
import { Descriptions, DescriptionsProps, Spin, Table } from 'antd';
|
||||
import React, { useState } from 'react';
|
||||
import { useAsyncEffect } from 'ahooks';
|
||||
import { fieldTransformers } from '../GroupBlock';
|
||||
|
||||
type reqData = {
|
||||
labels: any[];
|
||||
values: any[];
|
||||
};
|
||||
|
||||
export const GroupConfigure = (props) => {
|
||||
const { configItem, service } = props;
|
||||
const fieldSchema = useFieldSchema();
|
||||
const field = useField<any>();
|
||||
const params = fieldSchema.parent['x-decorator-props'].params;
|
||||
const [result, setResult] = useState({});
|
||||
const { getDataBlocks } = useFilterBlock();
|
||||
const Blocks = getDataBlocks();
|
||||
const api = useAPIClient();
|
||||
useAsyncEffect(async () => {
|
||||
const filter = service?.params[0] ? service.params[0].filter : service?.params;
|
||||
if (configItem.reqUrl) {
|
||||
setResult(
|
||||
(await api.request({
|
||||
url: configItem.reqUrl,
|
||||
method: 'POST',
|
||||
data: {
|
||||
filter: { ...filter },
|
||||
collection: params.collection,
|
||||
},
|
||||
})) ?? {},
|
||||
);
|
||||
}
|
||||
}, [Blocks, service.params, service.params[0]]);
|
||||
if (configItem.style === 'describe') {
|
||||
const item: DescriptionsProps['items'] = describeItem(configItem, result, service, params, api);
|
||||
return <Descriptions style={{ marginBottom: '10px' }} items={item} />;
|
||||
} else if (configItem.style === 'table') {
|
||||
const { columns, options } = tableItem(configItem, result, service, params, api);
|
||||
return <Table style={{ marginBottom: '10px' }} columns={columns} dataSource={options} pagination={false} />;
|
||||
}
|
||||
};
|
||||
|
||||
const describeItem = (configItem, result, service, params, api) => {
|
||||
const item = [];
|
||||
if (configItem.type === 'field') {
|
||||
const measuresData = service.data?.data;
|
||||
if (measuresData) {
|
||||
let data = measuresData.map((value) => {
|
||||
return value[configItem.field];
|
||||
})[0];
|
||||
data = fieldTransformers(configItem, data, api);
|
||||
const label = params.measures.find((value) => value.field[0] === configItem.field).label;
|
||||
item.push({
|
||||
key: configItem.field,
|
||||
label,
|
||||
children: data,
|
||||
});
|
||||
}
|
||||
} else if (configItem.type === 'custom') {
|
||||
if (Object.keys(result).length && result?.['data']?.data) {
|
||||
const data: reqData = { ...result?.['data']?.data };
|
||||
const label = data.labels;
|
||||
data.values.forEach((valueItem, index) => {
|
||||
let childrenText = '';
|
||||
label.forEach((value, index) => {
|
||||
if (index === 0) return;
|
||||
childrenText += `${value}${fieldTransformers(configItem, valueItem[index], api)} `;
|
||||
});
|
||||
item.push({
|
||||
key: index,
|
||||
label: valueItem[0],
|
||||
children: childrenText,
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
return item;
|
||||
};
|
||||
|
||||
const tableItem = (configItem, result, service, params, api) => {
|
||||
const columns = [];
|
||||
const options = [];
|
||||
if (configItem.type === 'custom') {
|
||||
if (Object.keys(result).length && result?.['data']?.data) {
|
||||
const data: reqData = { ...result?.['data']?.data };
|
||||
data.labels.forEach((value, index) => {
|
||||
columns.push({ title: value, dataIndex: 'value' + index, key: index });
|
||||
});
|
||||
data.values.forEach((value, index) => {
|
||||
const item = {
|
||||
key: index,
|
||||
};
|
||||
columns.forEach((colItem, index) => {
|
||||
const data = isNaN(value[index]) ? value[index] : fieldTransformers(configItem, value[index], api);
|
||||
item[colItem.dataIndex] = data;
|
||||
});
|
||||
options.push(item);
|
||||
});
|
||||
}
|
||||
} else if (configItem.type === 'field') {
|
||||
const measuresData = service.data?.data;
|
||||
if (measuresData) {
|
||||
let data = measuresData.map((value) => {
|
||||
return value[configItem.field];
|
||||
})[0];
|
||||
data = fieldTransformers(configItem, data, api);
|
||||
const label = params.measures.find((value) => value.field[0] === configItem.field).label;
|
||||
columns.push(
|
||||
{
|
||||
title: '名称',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
},
|
||||
{
|
||||
title: '数量',
|
||||
dataIndex: 'number',
|
||||
key: 'number',
|
||||
},
|
||||
);
|
||||
options.push({
|
||||
key: label,
|
||||
name: label,
|
||||
number: data,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return { columns, options };
|
||||
};
|
@ -1,91 +0,0 @@
|
||||
export const transformers = {
|
||||
option: [
|
||||
{
|
||||
label: 'Percent',
|
||||
value: 'pertent',
|
||||
component: (val: number, locale = 'en-US') =>
|
||||
new Intl.NumberFormat(locale, { style: 'percent', minimumFractionDigits: 2, maximumFractionDigits: 2 }).format(
|
||||
val,
|
||||
),
|
||||
},
|
||||
{
|
||||
label: 'Currency',
|
||||
value: 'currency',
|
||||
component: (val: number, locale = 'en-US') => {
|
||||
const currency = {
|
||||
'zh-CN': 'CNY',
|
||||
'en-US': 'USD',
|
||||
'ja-JP': 'JPY',
|
||||
'ko-KR': 'KRW',
|
||||
'pt-BR': 'BRL',
|
||||
'ru-RU': 'RUB',
|
||||
'tr-TR': 'TRY',
|
||||
'es-ES': 'EUR',
|
||||
}[locale];
|
||||
return new Intl.NumberFormat(locale, { style: 'currency', currency }).format(val);
|
||||
},
|
||||
},
|
||||
{ label: 'Exponential', value: 'exponential', component: (val: number | string) => (+val)?.toExponential() },
|
||||
{
|
||||
label: 'Abbreviation',
|
||||
value: 'abbreviation',
|
||||
component: (val: number, locale = 'en-US') => new Intl.NumberFormat(locale, { notation: 'compact' }).format(val),
|
||||
},
|
||||
{
|
||||
label: 'Decimal',
|
||||
value: 'decimal',
|
||||
childrens: [
|
||||
{
|
||||
label: '1.0',
|
||||
value: 'OneDigits',
|
||||
component: (val: number) =>
|
||||
new Intl.NumberFormat('en-US', {
|
||||
style: 'decimal',
|
||||
minimumFractionDigits: 1,
|
||||
maximumFractionDigits: 1,
|
||||
}).format(val),
|
||||
},
|
||||
{
|
||||
label: '1.00',
|
||||
value: 'TwoDigits',
|
||||
component: (val: number) =>
|
||||
new Intl.NumberFormat('en-US', {
|
||||
style: 'decimal',
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
}).format(val),
|
||||
},
|
||||
{
|
||||
label: '1.000',
|
||||
value: 'ThreeDigits',
|
||||
component: (val: number) =>
|
||||
new Intl.NumberFormat('en-US', {
|
||||
style: 'decimal',
|
||||
minimumFractionDigits: 3,
|
||||
maximumFractionDigits: 3,
|
||||
}).format(val),
|
||||
},
|
||||
{
|
||||
label: '1.0000',
|
||||
value: 'FourDigits',
|
||||
component: (val: number) =>
|
||||
new Intl.NumberFormat('en-US', {
|
||||
style: 'decimal',
|
||||
minimumFractionDigits: 4,
|
||||
maximumFractionDigits: 4,
|
||||
}).format(val),
|
||||
},
|
||||
{
|
||||
label: '1.00000',
|
||||
value: 'FiveDigits',
|
||||
component: (val: number) =>
|
||||
new Intl.NumberFormat('en-US', {
|
||||
style: 'decimal',
|
||||
minimumFractionDigits: 5,
|
||||
maximumFractionDigits: 5,
|
||||
}).format(val),
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
@ -1,25 +1,58 @@
|
||||
import { TableOutlined } from '@ant-design/icons';
|
||||
import { ISchema, useField, useFieldSchema, useForm } from '@formily/react';
|
||||
import { ISchema, useField, useFieldSchema } from '@formily/react';
|
||||
import {
|
||||
useSchemaInitializer,
|
||||
useSchemaInitializerItem,
|
||||
SchemaSettings,
|
||||
SchemaToolbar,
|
||||
DataBlockInitializer,
|
||||
useCollectionManager_deprecated,
|
||||
useBlockRequestContext,
|
||||
BlockProvider,
|
||||
__UNSAFE__,
|
||||
SchemaSettingsSwitchItem,
|
||||
useDesignable,
|
||||
useCollectionManager,
|
||||
SchemaToolbarProps,
|
||||
Icon,
|
||||
Plugin,
|
||||
} from '@nocobase/client';
|
||||
import React, { createContext, useState } from 'react';
|
||||
import { uid } from '@nocobase/utils/client';
|
||||
import { Checkbox, Spin } from 'antd';
|
||||
import { GroupBlockConfigure } from '../../schema-components/blocks/GroupBlockConfigure/GroupBlockConfigure';
|
||||
import { Spin } from 'antd';
|
||||
import { GroupBlockConfigure } from '../../schema-settings/GroupBlockConfigure';
|
||||
import { GroupBlock } from '../../schema-components';
|
||||
import { tval } from '../../locale';
|
||||
|
||||
export class GroupBlockPlugin extends Plugin {
|
||||
async load() {
|
||||
this.app.schemaInitializerManager.addItem('page:addBlock', 'dataBlocks.groupBlock', {
|
||||
title: tval('Group'),
|
||||
Component: 'GroupBlockInitializer',
|
||||
});
|
||||
this.schemaSettingsManager.add(groupBlockSettings);
|
||||
this.app.addComponents({
|
||||
GroupBlock,
|
||||
GroupBlockConfigure,
|
||||
GroupBlockInitializer,
|
||||
GroupBlockProvider,
|
||||
GroupBlockToolbar,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export const GroupBlockContext = createContext<any>({});
|
||||
|
||||
const GroupSvg = () => (
|
||||
<svg viewBox="0 0 1024 1024" width="1em" height="1em" fill="currentColor">
|
||||
<path
|
||||
d="M833.179846 36.584242h-73.160824a36.516572 36.516572 0 0 0 0 73.160824h73.160824c20.173491 0 36.516572 16.343081 36.516572 36.580412v768.060967a36.580412 36.580412 0 0 1-36.516572 36.580412H174.860114a36.580412 36.580412 0 0 1-36.580412-36.580412V146.325478c0-20.173491 16.343081-36.580412 36.580412-36.580412h73.160824a36.516572 36.516572 0 1 0 0-73.160824H174.860114A109.805076 109.805076 0 0 0 65.118879 146.325478v768.060967c0 60.584312 49.156923 109.741235 109.741235 109.741235h658.383572a109.805076 109.805076 0 0 0 109.677395-109.741235V146.325478A109.805076 109.805076 0 0 0 833.179846 36.584242z"
|
||||
fill="#2C2C2C"
|
||||
></path>
|
||||
<path
|
||||
d="M357.826013 146.325478h292.451774a36.516572 36.516572 0 0 0 36.580412-36.580412V36.584242A36.516572 36.516572 0 0 0 650.277787 0.00383H357.826013a36.516572 36.516572 0 0 0-36.580412 36.580412v73.160824c0 20.173491 16.343081 36.580412 36.580412 36.580412z m-36.708092 622.888443a36.580412 36.580412 0 0 0 36.580412-36.580412V512.065755a36.516572 36.516572 0 1 0-73.096984 0v220.567754c0 20.173491 16.279241 36.580412 36.516572 36.580412z m146.321647-330.308989v293.728577a36.580412 36.580412 0 1 0 73.160824 0V438.904932a36.580412 36.580412 0 1 0-73.160824 0z m182.838219-146.321647v440.050224a36.644252 36.644252 0 0 0 73.160824 0V292.583285a36.644252 36.644252 0 0 0-73.160824 0z"
|
||||
fill="#2C2C2C"
|
||||
></path>
|
||||
</svg>
|
||||
);
|
||||
|
||||
const GroupIcon = (props: any) => <Icon type="" component={GroupSvg} {...props} />;
|
||||
|
||||
const InternalGroupBlockProvider = (props) => {
|
||||
const field = useField<any>();
|
||||
const { resource, service } = useBlockRequestContext();
|
||||
@ -98,14 +131,14 @@ const createGroupBlockSchema = (options) => {
|
||||
|
||||
export const GroupBlockInitializer = () => {
|
||||
const { insert } = useSchemaInitializer();
|
||||
const { getCollection } = useCollectionManager_deprecated();
|
||||
const cm = useCollectionManager();
|
||||
const itemConfig = useSchemaInitializerItem();
|
||||
return (
|
||||
<DataBlockInitializer
|
||||
{...itemConfig}
|
||||
icon={<TableOutlined />}
|
||||
icon={<GroupIcon />}
|
||||
onCreateBlockSchema={async ({ item }) => {
|
||||
const collection = getCollection(item.name);
|
||||
const collection = cm.getCollection(item.name);
|
||||
insert(
|
||||
createGroupBlockSchema({
|
||||
collection,
|
||||
@ -133,7 +166,9 @@ export const groupBlockSettings = new SchemaSettings({
|
||||
],
|
||||
});
|
||||
|
||||
export const GroupBlockToolbar = (props) => {
|
||||
export const GroupBlockToolbar = (
|
||||
props: React.JSX.IntrinsicAttributes & SchemaToolbarProps & { children?: React.ReactNode },
|
||||
) => {
|
||||
const fieldSchema = useFieldSchema();
|
||||
return <SchemaToolbar title={fieldSchema.title} settings={fieldSchema['x-settings']} {...props} />;
|
||||
};
|
||||
|
@ -1,14 +1,12 @@
|
||||
import {
|
||||
SchemaComponentOptions,
|
||||
SchemaSettingsItem,
|
||||
SchemaSettingsModalItem,
|
||||
useBlockRequestContext,
|
||||
useDesignable,
|
||||
} from '@nocobase/client';
|
||||
import React, { useContext } from 'react';
|
||||
import { useTranslation } from '../../../locale';
|
||||
import { GroupBlockContext } from '../../../schema-initializer/blocks/GroupBlockInitializer';
|
||||
import { transformers } from './transformers';
|
||||
import { useTranslation } from '../locale';
|
||||
import { GroupBlockContext } from '../schema-initializer/blocks/GroupBlockInitializer';
|
||||
import { ISchema, connect, useFieldSchema } from '@formily/react';
|
||||
import { ArrayItems, FormItem, Space } from '@formily/antd-v5';
|
||||
import { PullRequestOutlined } from '@ant-design/icons';
|
||||
@ -33,7 +31,7 @@ export const GroupBlockConfigure = connect((props) => {
|
||||
return (
|
||||
<SchemaComponentOptions scope={{ ...scope }} components={{ ArrayItems, FormItem, Space, PullRequestOutlined }}>
|
||||
<SchemaSettingsModalItem
|
||||
title="Configure"
|
||||
title={t('Configure')}
|
||||
key="configure"
|
||||
onSubmit={(fieldOptionItem) => {
|
||||
fieldSchema['x-decorator-props'].params['config'] = [...fieldOptionItem.configField];
|
||||
@ -203,3 +201,95 @@ const modalSchema = (t, params, valueOption, decimal) => {
|
||||
};
|
||||
return schema;
|
||||
};
|
||||
|
||||
export const transformers = {
|
||||
option: [
|
||||
{
|
||||
label: 'Percent',
|
||||
value: 'pertent',
|
||||
component: (val: number, locale = 'en-US') =>
|
||||
new Intl.NumberFormat(locale, { style: 'percent', minimumFractionDigits: 2, maximumFractionDigits: 2 }).format(
|
||||
val,
|
||||
),
|
||||
},
|
||||
{
|
||||
label: 'Currency',
|
||||
value: 'currency',
|
||||
component: (val: number, locale = 'en-US') => {
|
||||
const currency = {
|
||||
'zh-CN': 'CNY',
|
||||
'en-US': 'USD',
|
||||
'ja-JP': 'JPY',
|
||||
'ko-KR': 'KRW',
|
||||
'pt-BR': 'BRL',
|
||||
'ru-RU': 'RUB',
|
||||
'tr-TR': 'TRY',
|
||||
'es-ES': 'EUR',
|
||||
}[locale];
|
||||
return new Intl.NumberFormat(locale, { style: 'currency', currency }).format(val);
|
||||
},
|
||||
},
|
||||
{ label: 'Exponential', value: 'exponential', component: (val: number | string) => (+val)?.toExponential() },
|
||||
{
|
||||
label: 'Abbreviation',
|
||||
value: 'abbreviation',
|
||||
component: (val: number, locale = 'en-US') => new Intl.NumberFormat(locale, { notation: 'compact' }).format(val),
|
||||
},
|
||||
{
|
||||
label: 'Decimal',
|
||||
value: 'decimal',
|
||||
childrens: [
|
||||
{
|
||||
label: '1.0',
|
||||
value: 'OneDigits',
|
||||
component: (val: number) =>
|
||||
new Intl.NumberFormat('en-US', {
|
||||
style: 'decimal',
|
||||
minimumFractionDigits: 1,
|
||||
maximumFractionDigits: 1,
|
||||
}).format(val),
|
||||
},
|
||||
{
|
||||
label: '1.00',
|
||||
value: 'TwoDigits',
|
||||
component: (val: number) =>
|
||||
new Intl.NumberFormat('en-US', {
|
||||
style: 'decimal',
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
}).format(val),
|
||||
},
|
||||
{
|
||||
label: '1.000',
|
||||
value: 'ThreeDigits',
|
||||
component: (val: number) =>
|
||||
new Intl.NumberFormat('en-US', {
|
||||
style: 'decimal',
|
||||
minimumFractionDigits: 3,
|
||||
maximumFractionDigits: 3,
|
||||
}).format(val),
|
||||
},
|
||||
{
|
||||
label: '1.0000',
|
||||
value: 'FourDigits',
|
||||
component: (val: number) =>
|
||||
new Intl.NumberFormat('en-US', {
|
||||
style: 'decimal',
|
||||
minimumFractionDigits: 4,
|
||||
maximumFractionDigits: 4,
|
||||
}).format(val),
|
||||
},
|
||||
{
|
||||
label: '1.00000',
|
||||
value: 'FiveDigits',
|
||||
component: (val: number) =>
|
||||
new Intl.NumberFormat('en-US', {
|
||||
style: 'decimal',
|
||||
minimumFractionDigits: 5,
|
||||
maximumFractionDigits: 5,
|
||||
}).format(val),
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
@ -4,6 +4,7 @@
|
||||
"Configure": "Configure",
|
||||
"Custom filter": "Custom filter",
|
||||
"Custom option label": "Custom option label",
|
||||
"Group": "Group",
|
||||
"Group block": "Group block",
|
||||
"HomePage Config": "HomePage Config",
|
||||
"Mobile UI": "Mobile UI",
|
||||
|
@ -4,6 +4,7 @@
|
||||
"Configure": "配置",
|
||||
"Custom filter": "自定义筛选",
|
||||
"Custom option label": "自定义选项标签",
|
||||
"Group": "汇总",
|
||||
"Group block": "汇总区块",
|
||||
"HomePage Config": "主页配置",
|
||||
"Mobile UI": "移动端页面",
|
||||
|
78
yarn.lock
78
yarn.lock
@ -7,6 +7,11 @@
|
||||
resolved "https://registry.npmmirror.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf"
|
||||
integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==
|
||||
|
||||
"@adobe/css-tools@^4.3.2":
|
||||
version "4.3.3"
|
||||
resolved "https://registry.npmmirror.com/@adobe/css-tools/-/css-tools-4.3.3.tgz#90749bde8b89cd41764224f5aac29cd4138f75ff"
|
||||
integrity sha512-rE0Pygv0sEZ4vBWHlAgJLGDU7Pm8xoO6p3wsEceb7GYAjScrOHpEo8KK/eVkAcnSM+slAEtXjA2JpdjLp4fJQQ==
|
||||
|
||||
"@ahooksjs/use-url-state@3.5.1":
|
||||
version "3.5.1"
|
||||
resolved "https://registry.npmmirror.com/@ahooksjs/use-url-state/-/use-url-state-3.5.1.tgz#c3ad04e98cbcbc8f9eba476bcbd3237e9809aa5b"
|
||||
@ -6043,6 +6048,20 @@
|
||||
lz-string "^1.5.0"
|
||||
pretty-format "^27.0.2"
|
||||
|
||||
"@testing-library/jest-dom@^6.4.2":
|
||||
version "6.4.2"
|
||||
resolved "https://registry.npmmirror.com/@testing-library/jest-dom/-/jest-dom-6.4.2.tgz#38949f6b63722900e2d75ba3c6d9bf8cffb3300e"
|
||||
integrity sha512-CzqH0AFymEMG48CpzXFriYYkOjk6ZGPCLMhW9e9jg3KMCn5OfJecF8GtGW7yGfR/IgCe3SX8BSwjdzI6BBbZLw==
|
||||
dependencies:
|
||||
"@adobe/css-tools" "^4.3.2"
|
||||
"@babel/runtime" "^7.9.2"
|
||||
aria-query "^5.0.0"
|
||||
chalk "^3.0.0"
|
||||
css.escape "^1.5.1"
|
||||
dom-accessibility-api "^0.6.3"
|
||||
lodash "^4.17.15"
|
||||
redent "^3.0.0"
|
||||
|
||||
"@testing-library/react-hooks@^8.0.1":
|
||||
version "8.0.1"
|
||||
resolved "https://registry.npmmirror.com/@testing-library/react-hooks/-/react-hooks-8.0.1.tgz#0924bbd5b55e0c0c0502d1754657ada66947ca12"
|
||||
@ -8470,7 +8489,7 @@ aria-query@5.1.3:
|
||||
dependencies:
|
||||
deep-equal "^2.0.5"
|
||||
|
||||
aria-query@^5.3.0:
|
||||
aria-query@^5.0.0:
|
||||
version "5.3.0"
|
||||
resolved "https://registry.npmmirror.com/aria-query/-/aria-query-5.3.0.tgz#650c569e41ad90b51b3d7df5e5eed1c7549c103e"
|
||||
integrity sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==
|
||||
@ -9802,7 +9821,7 @@ chalk@3.0.0, chalk@^3.0.0, chalk@~3.0.0:
|
||||
ansi-styles "^4.1.0"
|
||||
supports-color "^7.1.0"
|
||||
|
||||
chalk@5.3.0, chalk@^5.3.0:
|
||||
chalk@5.3.0:
|
||||
version "5.3.0"
|
||||
resolved "https://registry.npmmirror.com/chalk/-/chalk-5.3.0.tgz#67c20a7ebef70e7f3970a01f90fa210cb6860385"
|
||||
integrity sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==
|
||||
@ -12153,7 +12172,7 @@ dom-accessibility-api@^0.5.9:
|
||||
resolved "https://registry.npmmirror.com/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz#5a7429e6066eb3664d911e33fb0e45de8eb08453"
|
||||
integrity sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==
|
||||
|
||||
dom-accessibility-api@^0.6.1:
|
||||
dom-accessibility-api@^0.6.3:
|
||||
version "0.6.3"
|
||||
resolved "https://registry.npmmirror.com/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz#993e925cc1d73f2c662e7d75dd5a5445259a8fd8"
|
||||
integrity sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==
|
||||
@ -15691,11 +15710,6 @@ indent-string@^4.0.0:
|
||||
resolved "https://registry.npmmirror.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251"
|
||||
integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==
|
||||
|
||||
indent-string@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.npmmirror.com/indent-string/-/indent-string-5.0.0.tgz#4fd2980fccaf8622d14c64d694f4cf33c81951a5"
|
||||
integrity sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==
|
||||
|
||||
infer-owner@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.npmmirror.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467"
|
||||
@ -18023,22 +18037,7 @@ matchdep@^2.0.0:
|
||||
resolve "^1.4.0"
|
||||
stack-trace "0.0.10"
|
||||
|
||||
"mathjs2@npm:mathjs@^10.6.0":
|
||||
version "10.6.4"
|
||||
resolved "https://registry.npmmirror.com/mathjs/-/mathjs-10.6.4.tgz#1b87a1268781d64f0c8b4e5e1b36cf7ecf58bb05"
|
||||
integrity sha512-omQyvRE1jIy+3k2qsqkWASOcd45aZguXZDckr3HtnTYyXk5+2xpVfC3kATgbO2Srjxlqww3TVdhD0oUdZ/hiFA==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.18.6"
|
||||
complex.js "^2.1.1"
|
||||
decimal.js "^10.3.1"
|
||||
escape-latex "^1.2.0"
|
||||
fraction.js "^4.2.0"
|
||||
javascript-natural-sort "^0.7.1"
|
||||
seedrandom "^3.0.5"
|
||||
tiny-emitter "^2.1.0"
|
||||
typed-function "^2.1.0"
|
||||
|
||||
mathjs@^10.6.0, mathjs@^10.6.1:
|
||||
"mathjs2@npm:mathjs@^10.6.0", mathjs@^10.6.0, mathjs@^10.6.1:
|
||||
version "10.6.4"
|
||||
resolved "https://registry.npmmirror.com/mathjs/-/mathjs-10.6.4.tgz#1b87a1268781d64f0c8b4e5e1b36cf7ecf58bb05"
|
||||
integrity sha512-omQyvRE1jIy+3k2qsqkWASOcd45aZguXZDckr3HtnTYyXk5+2xpVfC3kATgbO2Srjxlqww3TVdhD0oUdZ/hiFA==
|
||||
@ -18789,7 +18788,7 @@ mimic-response@^2.0.0:
|
||||
resolved "https://registry.npmmirror.com/mimic-response/-/mimic-response-2.1.0.tgz#d13763d35f613d09ec37ebb30bac0469c0ee8f43"
|
||||
integrity sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==
|
||||
|
||||
min-indent@^1.0.0, min-indent@^1.0.1:
|
||||
min-indent@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.npmmirror.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869"
|
||||
integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==
|
||||
@ -20816,7 +20815,7 @@ pg-types@^2.1.0:
|
||||
postgres-date "~1.0.4"
|
||||
postgres-interval "^1.1.0"
|
||||
|
||||
pg@^8.7.3:
|
||||
pg@^8.11.3, pg@^8.7.3:
|
||||
version "8.11.3"
|
||||
resolved "https://registry.npmmirror.com/pg/-/pg-8.11.3.tgz#d7db6e3fe268fcedd65b8e4599cda0b8b4bf76cb"
|
||||
integrity sha512-+9iuvG8QfaaUrrph+kpF24cXkH1YOOUeArRNYIxq1viYHZagBxrTno7cecY1Fa44tJeZvaoG+Djpkc3JwehN5g==
|
||||
@ -22886,14 +22885,6 @@ redent@^3.0.0:
|
||||
indent-string "^4.0.0"
|
||||
strip-indent "^3.0.0"
|
||||
|
||||
redent@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.npmmirror.com/redent/-/redent-4.0.0.tgz#0c0ba7caabb24257ab3bb7a4fd95dd1d5c5681f9"
|
||||
integrity sha512-tYkDkVVtYkSVhuQ4zBgfvciymHaeuel+zFKXShfDnFP5SyVEP7qo70Rf1jTOTCx3vGNAbnEi/xFkcfQVMIBWag==
|
||||
dependencies:
|
||||
indent-string "^5.0.0"
|
||||
strip-indent "^4.0.0"
|
||||
|
||||
redis@^4.6.10, redis@^4.6.7:
|
||||
version "4.6.11"
|
||||
resolved "https://registry.npmmirror.com/redis/-/redis-4.6.11.tgz#fad85e104545228f212259fd557c3e4f8eafcd3d"
|
||||
@ -24791,13 +24782,6 @@ strip-indent@^3.0.0:
|
||||
dependencies:
|
||||
min-indent "^1.0.0"
|
||||
|
||||
strip-indent@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.npmmirror.com/strip-indent/-/strip-indent-4.0.0.tgz#b41379433dd06f5eae805e21d631e07ee670d853"
|
||||
integrity sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==
|
||||
dependencies:
|
||||
min-indent "^1.0.1"
|
||||
|
||||
strip-json-comments@^2.0.0, strip-json-comments@~2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.npmmirror.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
|
||||
@ -26773,18 +26757,6 @@ vite@^5.0.0:
|
||||
optionalDependencies:
|
||||
fsevents "~2.3.3"
|
||||
|
||||
vitest-dom@^0.1.1:
|
||||
version "0.1.1"
|
||||
resolved "https://registry.npmmirror.com/vitest-dom/-/vitest-dom-0.1.1.tgz#a8e44a2662e557d86b84c916f62d9ce4b2eb90b1"
|
||||
integrity sha512-n/bonR2hcRHCE5hlzG/P0yTXTUXx/gPtsaeUWP86ADfwo/+dHDpnTTV14qY7+kevsUbOZFYECu77MXY7AA0QSA==
|
||||
dependencies:
|
||||
aria-query "^5.3.0"
|
||||
chalk "^5.3.0"
|
||||
css.escape "^1.5.1"
|
||||
dom-accessibility-api "^0.6.1"
|
||||
lodash-es "^4.17.21"
|
||||
redent "^4.0.0"
|
||||
|
||||
vitest@0.x:
|
||||
version "0.34.6"
|
||||
resolved "https://registry.npmmirror.com/vitest/-/vitest-0.34.6.tgz#44880feeeef493c04b7f795ed268f24a543250d7"
|
||||
|
Loading…
Reference in New Issue
Block a user