diff --git a/packages/core/client/src/collection-manager/CollectionManagerProvider.tsx b/packages/core/client/src/collection-manager/CollectionManagerProvider.tsx index c4f65117b..0d93e6635 100644 --- a/packages/core/client/src/collection-manager/CollectionManagerProvider.tsx +++ b/packages/core/client/src/collection-manager/CollectionManagerProvider.tsx @@ -20,7 +20,7 @@ export const CollectionManagerProvider: React.FC = (pr service, interfaces: { ...defaultInterfaces, ...ctx.interfaces, ...interfaces }, templates: { ...defaultTemplates, ...templates }, - collections, + collections: [...ctx.collections, ...collections], refreshCM, }} > @@ -38,7 +38,7 @@ export const RemoteCollectionManagerProvider = (props: any) => { action: 'list', params: { paginate: false, - appends: ['fields', 'fields.uiSchema','category'], + appends: ['fields', 'fields.uiSchema', 'category'], filter: { // inherit: false, }, @@ -75,13 +75,13 @@ export const RemoteCollectionManagerProvider = (props: any) => { export const CollectionCategroriesProvider = (props) => { const api = useAPIClient(); - const options={ + const options = { url: 'collectionCategories:list', params: { paginate: false, - sort:['sort'] + sort: ['sort'], }, - } + }; const result = useRequest(options); if (result.loading) { return ; @@ -91,11 +91,11 @@ export const CollectionCategroriesProvider = (props) => { value={{ ...result, data: result?.data?.data, - refresh:async ()=>{ + refresh: async () => { const { data } = await api.request(options); result.mutate(data); return data?.data || []; - } + }, }} > {props.children} diff --git a/packages/core/client/src/schema-component/antd/association-filter/AssociationFilter.tsx b/packages/core/client/src/schema-component/antd/association-filter/AssociationFilter.tsx index b3b26e4a1..a1c808bd4 100644 --- a/packages/core/client/src/schema-component/antd/association-filter/AssociationFilter.tsx +++ b/packages/core/client/src/schema-component/antd/association-filter/AssociationFilter.tsx @@ -4,7 +4,7 @@ import cls from 'classnames'; import React from 'react'; import { useCollection } from '../../../collection-manager'; import { useSchemaInitializer } from '../../../schema-initializer'; -import { SortableItem } from '../../common'; +import { DndContext, SortableItem } from '../../common'; import { useDesigner } from '../../hooks'; import { AssociationFilterInitializer } from './AssociationFilter.Initializer'; import { AssociationFilterItem } from './AssociationFilter.Item'; @@ -17,59 +17,61 @@ export const AssociationFilter = (props) => { const { exists, render } = useSchemaInitializer(filedSchema['x-initializer']); return ( - .general-schema-designer { - display: block; - } - } - &.nb-form-item:hover { - > .general-schema-designer { - background: rgba(241, 139, 98, 0.06) !important; - border: 0 !important; - top: -5px !important; - bottom: -5px !important; - left: -5px !important; - right: -5px !important; - } - } - > .general-schema-designer { - position: absolute; - z-index: 999; - top: 0; - bottom: 0; - left: 0; - right: 0; - display: none; - border: 2px solid rgba(241, 139, 98, 0.3); - pointer-events: none; - > .general-schema-designer-icons { - position: absolute; - right: 2px; - top: 2px; - line-height: 16px; - pointer-events: all; - .ant-space-item { - background-color: #f18b62; - color: #fff; - line-height: 16px; - width: 16px; - padding-left: 1px; + + .general-schema-designer { + display: block; } } - } - `, - )} - > - - {props.children} - {render()} - + &.nb-form-item:hover { + > .general-schema-designer { + background: rgba(241, 139, 98, 0.06) !important; + border: 0 !important; + top: -5px !important; + bottom: -5px !important; + left: -5px !important; + right: -5px !important; + } + } + > .general-schema-designer { + position: absolute; + z-index: 999; + top: 0; + bottom: 0; + left: 0; + right: 0; + display: none; + border: 2px solid rgba(241, 139, 98, 0.3); + pointer-events: none; + > .general-schema-designer-icons { + position: absolute; + right: 2px; + top: 2px; + line-height: 16px; + pointer-events: all; + .ant-space-item { + background-color: #f18b62; + color: #fff; + line-height: 16px; + width: 16px; + padding-left: 1px; + } + } + } + `, + )} + > + + {props.children} + {render()} + + ); }; diff --git a/packages/core/client/src/schema-component/antd/page/FixedBlock.tsx b/packages/core/client/src/schema-component/antd/page/FixedBlock.tsx index 4b2847d9a..dfd79c367 100644 --- a/packages/core/client/src/schema-component/antd/page/FixedBlock.tsx +++ b/packages/core/client/src/schema-component/antd/page/FixedBlock.tsx @@ -6,6 +6,7 @@ import { useTranslation } from 'react-i18next'; import { useDesignable } from '../../hooks'; import { useRecord } from '../../../record-provider'; import { useBlockTemplateContext } from '../../../schema-templates/BlockTemplate'; +import { uid } from '@formily/shared'; const FixedBlockContext = React.createContext({ setFixedSchema: (schema: Schema) => {}, diff --git a/packages/core/client/src/schema-component/antd/table-v2/TableBlockDesigner.tsx b/packages/core/client/src/schema-component/antd/table-v2/TableBlockDesigner.tsx index 94c301d64..a7722b783 100644 --- a/packages/core/client/src/schema-component/antd/table-v2/TableBlockDesigner.tsx +++ b/packages/core/client/src/schema-component/antd/table-v2/TableBlockDesigner.tsx @@ -23,6 +23,7 @@ export const TableBlockDesigner = () => { const defaultFilter = fieldSchema?.['x-decorator-props']?.params?.filter || {}; const defaultSort = fieldSchema?.['x-decorator-props']?.params?.sort || []; const defaultResource = fieldSchema?.['x-decorator-props']?.resource; + const supportTemplate = !fieldSchema?.['x-decorator-props']?.disableTemplate; const sort = defaultSort?.map((item: string) => { return item.startsWith('-') ? { @@ -211,8 +212,10 @@ export const TableBlockDesigner = () => { }); }} /> - - + {supportTemplate && } + {supportTemplate && ( + + )} s; diff --git a/packages/core/client/src/schema-initializer/buttons/TableActionColumnInitializers.tsx b/packages/core/client/src/schema-initializer/buttons/TableActionColumnInitializers.tsx index 9acde7233..67efeeef8 100644 --- a/packages/core/client/src/schema-initializer/buttons/TableActionColumnInitializers.tsx +++ b/packages/core/client/src/schema-initializer/buttons/TableActionColumnInitializers.tsx @@ -6,7 +6,7 @@ import { SchemaInitializer, SchemaSettings } from '../..'; import { useAPIClient } from '../../api-client'; import { createDesignable, useDesignable } from '../../schema-component'; -const Resizable = (props) => { +export const Resizable = (props) => { const { t } = useTranslation(); const { dn } = useDesignable(); const fieldSchema = useFieldSchema(); diff --git a/packages/core/client/src/schema-initializer/index.ts b/packages/core/client/src/schema-initializer/index.ts index a587a2c0d..bd08edb76 100644 --- a/packages/core/client/src/schema-initializer/index.ts +++ b/packages/core/client/src/schema-initializer/index.ts @@ -2,5 +2,13 @@ export * from './SchemaInitializer'; export * from './SchemaInitializerProvider'; export * from './types'; export * from './items'; -export { gridRowColWrap, useRecordCollectionDataSourceItems } from './utils'; +export { + gridRowColWrap, + useRecordCollectionDataSourceItems, + createTableBlockSchema, + useAssociatedTableColumnInitializerFields, + useInheritsTableColumnInitializerFields, + useTableColumnInitializerFields, + itemsMerge, +} from './utils'; export * from './buttons'; diff --git a/packages/core/client/src/schema-initializer/utils.ts b/packages/core/client/src/schema-initializer/utils.ts index 8694e06a3..10ebd03b0 100644 --- a/packages/core/client/src/schema-initializer/utils.ts +++ b/packages/core/client/src/schema-initializer/utils.ts @@ -815,10 +815,20 @@ export const createReadPrettyFormBlockSchema = (options) => { }; export const createTableBlockSchema = (options) => { - const { collection, resource, rowKey, ...others } = options; + const { + collection, + resource, + rowKey, + tableActionInitializers, + tableColumnInitializers, + tableActionColumnInitializers, + tableBlockProvider, + disableTemplate, + ...others + } = options; const schema: ISchema = { type: 'void', - 'x-decorator': 'TableBlockProvider', + 'x-decorator': tableBlockProvider ?? 'TableBlockProvider', 'x-acl-action': `${resource || collection}:list`, 'x-decorator-props': { collection, @@ -830,6 +840,7 @@ export const createTableBlockSchema = (options) => { rowKey, showIndex: true, dragSort: false, + disableTemplate: disableTemplate ?? false, ...others, }, 'x-designer': 'TableBlockDesigner', @@ -837,7 +848,7 @@ export const createTableBlockSchema = (options) => { properties: { actions: { type: 'void', - 'x-initializer': 'TableActionInitializers', + 'x-initializer': tableActionInitializers ?? 'TableActionInitializers', 'x-component': 'ActionBar', 'x-component-props': { style: { @@ -848,7 +859,7 @@ export const createTableBlockSchema = (options) => { }, [uid()]: { type: 'array', - 'x-initializer': 'TableColumnInitializers', + 'x-initializer': tableColumnInitializers ?? 'TableColumnInitializers', 'x-component': 'TableV2', 'x-component-props': { rowKey: 'id', @@ -865,7 +876,7 @@ export const createTableBlockSchema = (options) => { 'x-decorator': 'TableV2.Column.ActionBar', 'x-component': 'TableV2.Column', 'x-designer': 'TableV2.ActionColumnDesigner', - 'x-initializer': 'TableActionColumnInitializers', + 'x-initializer': tableActionColumnInitializers ?? 'TableActionColumnInitializers', properties: { actions: { type: 'void', diff --git a/packages/plugins/audit-logs/src/client/AuditLogsBlockInitializer.tsx b/packages/plugins/audit-logs/src/client/AuditLogsBlockInitializer.tsx index 45bb683cb..a8ccbd350 100644 --- a/packages/plugins/audit-logs/src/client/AuditLogsBlockInitializer.tsx +++ b/packages/plugins/audit-logs/src/client/AuditLogsBlockInitializer.tsx @@ -1,31 +1,29 @@ import { TableOutlined } from '@ant-design/icons'; -import { SchemaInitializer } from '@nocobase/client'; +import { ISchema } from '@formily/react'; +import { createTableBlockSchema, SchemaInitializer } from '@nocobase/client'; import React from 'react'; import { useTranslation } from 'react-i18next'; export const AuditLogsBlockInitializer = (props) => { const { insert } = props; const { t } = useTranslation(); + + const schema = createTableBlockSchema({ + collection: 'auditLogs', + rowKey: 'id', + tableActionInitializers: 'AuditLogsTableActionInitializers', + tableColumnInitializers: 'AuditLogsTableColumnInitializers', + tableActionColumnInitializers: 'AuditLogsTableActionColumnInitializers', + tableBlockProvider: 'AuditLogsBlockProvider', + disableTemplate: true, + }); + return ( } onClick={() => { - insert({ - type: 'void', - 'x-designer': 'AuditLogs.Designer', - 'x-decorator': 'AuditLogs.Decorator', - 'x-decorator-props': { - params: {}, - }, - 'x-component': 'CardItem', - properties: { - auditLogs: { - type: 'void', - 'x-component': 'AuditLogs', - }, - }, - }); + insert(schema as ISchema); }} title={t('Audit Logs')} /> diff --git a/packages/plugins/audit-logs/src/client/AuditLogsBlockProvider.tsx b/packages/plugins/audit-logs/src/client/AuditLogsBlockProvider.tsx new file mode 100644 index 000000000..7aeafefc7 --- /dev/null +++ b/packages/plugins/audit-logs/src/client/AuditLogsBlockProvider.tsx @@ -0,0 +1,33 @@ +import { + CollectionManagerProvider, + SchemaInitializerContext, + SchemaInitializerProvider, + TableBlockProvider, +} from '@nocobase/client'; +import React, { useContext } from 'react'; +import { useAuditChangesCollection, useAuditLogsCollection, useCollectionsCollection } from './collections'; +import { AuditLogsTableActionColumnInitializers } from './initializers/AuditLogsTableActionColumnInitializers'; +import { AuditLogsTableActionInitializers } from './initializers/AuditLogsTableActionInitializers'; +import { AuditLogsTableColumnInitializers } from './initializers/AuditLogsTableColumnInitializers'; + +export const AuditLogsBlockProvider: React.FC = ({ children, ...restProps }) => { + const initializers = useContext(SchemaInitializerContext); + const auditChangesCollection = useAuditChangesCollection(); + const auditLogsCollection = useAuditLogsCollection(); + const collectionsCollection = useCollectionsCollection(); + + return ( + + + {children} + + + ); +}; diff --git a/packages/plugins/audit-logs/src/client/AuditLogsProvider.tsx b/packages/plugins/audit-logs/src/client/AuditLogsProvider.tsx index 9c0fad0ca..7587a930e 100644 --- a/packages/plugins/audit-logs/src/client/AuditLogsProvider.tsx +++ b/packages/plugins/audit-logs/src/client/AuditLogsProvider.tsx @@ -1,11 +1,26 @@ -import { SchemaComponentOptions } from '@nocobase/client'; +import { SchemaComponentOptions, SchemaInitializerContext, SchemaInitializerProvider } from '@nocobase/client'; import React from 'react'; -import { AuditLogs } from './AuditLogs'; import { AuditLogsBlockInitializer } from './AuditLogsBlockInitializer'; +import { AuditLogsValue } from './components/AuditLogsValue'; +import { AuditLogsField } from './components/AuditLogsField'; +import { AuditLogsBlockProvider } from './AuditLogsBlockProvider'; +import { AuditLogsTableActionColumnInitializer } from './initializers/AuditLogsTableActionColumnInitializer'; +import { AuditLogs } from './deplicated/AuditLogs'; +import { AuditLogsViewActionInitializer } from './components/AuditLogsViewActionInitializer'; export const AuditLogsProvider = (props: any) => { return ( - + {props.children} ); diff --git a/packages/plugins/audit-logs/src/client/collections.tsx b/packages/plugins/audit-logs/src/client/collections.tsx new file mode 100644 index 000000000..d22f40a1e --- /dev/null +++ b/packages/plugins/audit-logs/src/client/collections.tsx @@ -0,0 +1,166 @@ +import { useAuditLogsTranslation } from './locale'; + +export const useAuditLogsCollection = () => { + return { + name: 'auditLogs', + title: '{{t("Audit logs")}}', + fields: [ + { + name: 'createdAt', + type: 'date', + interface: 'createdAt', + uiSchema: { + type: 'datetime', + title: '{{t("Created at")}}', + 'x-component': 'DatePicker', + 'x-component-props': { + showTime: true, + ellipsis: true, + }, + 'x-read-pretty': true, + }, + }, + { + name: 'type', + type: 'string', + interface: 'select', + uiSchema: { + type: 'string', + title: '{{t("Action type")}}', + 'x-component': 'Select', + 'x-component-props': { ellipsis: true }, + 'x-read-pretty': true, + enum: [ + { label: '{{t("Create record")}}', value: 'create', color: 'lime' }, + { label: '{{t("Update record")}}', value: 'update', color: 'gold' }, + { label: '{{t("Delete record")}}', value: 'destroy', color: 'magenta' }, + ], + }, + }, + { + name: 'recordId', + type: 'string', + interface: 'input', + uiSchema: { + title: '{{t("Record ID")}}', + type: 'string', + 'x-component': 'Input', + 'x-component-props': { ellipsis: true }, + }, + }, + { + collectionName: 'auditLogs', + name: 'collection', + type: 'belongsTo', + interface: 'm2o', + target: 'collections', + targetKey: 'name', + sourceKey: 'id', + foreignKey: 'collectionName', + uiSchema: { + type: 'object', + title: '{{t("Collection")}}', + 'x-component': 'RecordPicker', + 'x-component-props': { fieldNames: { value: 'name', label: 'title' }, ellipsis: true }, + 'x-read-pretty': true, + }, + }, + { + name: 'user', + collectionName: 'auditLogs', + type: 'belongsTo', + interface: 'createdBy', + targetKey: 'id', + foreignKey: 'createdById', + target: 'users', + uiSchema: { + type: 'object', + title: '{{t("User")}}', + 'x-component': 'RecordPicker', + 'x-component-props': { fieldNames: { value: 'id', label: 'nickname' }, ellipsis: true }, + 'x-read-pretty': true, + }, + }, + { + name: 'changes', + collectionName: 'auditLogs', + type: 'hasMany', + interface: 'subTable', + target: 'auditChanges', + foreignKey: 'auditLogId', + targetKey: 'id', + uiSchema: { + type: 'object', + title: '{{t("Details of changes", { ns: "audit-logs" })}}', + }, + }, + ], + }; +}; + +export const useAuditChangesCollection = () => { + return { + name: 'auditChanges', + title: '{{t("Audit Changes")}}', + fields: [ + { + name: 'field', + type: 'json', + interface: 'input', + uiSchema: { + title: '{{t("Field")}}', + 'x-component': 'AuditLogsField', + }, + }, + { + type: 'json', + name: 'before', + interface: 'input', + uiSchema: { + title: '{{t("Before change")}}', + 'x-component': 'AuditLogsValue', + }, + }, + { + type: 'json', + name: 'after', + interface: 'input', + uiSchema: { + title: '{{t("After change")}}', + 'x-component': 'AuditLogsValue', + }, + }, + ], + }; +}; + +export const useCollectionsCollection = () => { + return { + name: 'collections', + title: '{{t("Collections")}}', + fields: [ + { + name: 'name', + type: 'string', + interface: 'input', + uiSchema: { + title: '{{t("Collection name")}}', + type: 'string', + 'x-component': 'Input', + 'x-component-props': { ellipsis: true }, + }, + }, + { + name: 'title', + type: 'string', + interface: 'input', + uiSchema: { + title: '{{t("Collection display name")}}', + type: 'string', + 'x-component': 'Input', + 'x-component-props': { ellipsis: true }, + }, + }, + ], + }; +}; diff --git a/packages/plugins/audit-logs/src/client/components/AuditLogsField.tsx b/packages/plugins/audit-logs/src/client/components/AuditLogsField.tsx new file mode 100644 index 000000000..5d5705588 --- /dev/null +++ b/packages/plugins/audit-logs/src/client/components/AuditLogsField.tsx @@ -0,0 +1,12 @@ +import { useCompile } from '@nocobase/client'; +import React from 'react'; +import { observer, useField } from '@formily/react'; + +export const AuditLogsField = observer(() => { + const field = useField(); + const compile = useCompile(); + if (!field.value) { + return null; + } + return
{field.value?.uiSchema?.title ? compile(field.value?.uiSchema?.title) : field.value.name}
; +}); diff --git a/packages/plugins/audit-logs/src/client/components/AuditLogsValue.tsx b/packages/plugins/audit-logs/src/client/components/AuditLogsValue.tsx new file mode 100644 index 000000000..b604b210f --- /dev/null +++ b/packages/plugins/audit-logs/src/client/components/AuditLogsValue.tsx @@ -0,0 +1,23 @@ +import { FormProvider, SchemaComponent, useRecord } from '@nocobase/client'; +import React from 'react'; +import { observer, useField } from '@formily/react'; + +export const AuditLogsValue = observer(() => { + const field = useField(); + const record = useRecord(); + if (record.field?.uiSchema) { + return ( + + + + ); + } + return
{field.value ? JSON.stringify(field.value) : null}
; +}); diff --git a/packages/plugins/audit-logs/src/client/components/AuditLogsViewActionInitializer.tsx b/packages/plugins/audit-logs/src/client/components/AuditLogsViewActionInitializer.tsx new file mode 100644 index 000000000..702255093 --- /dev/null +++ b/packages/plugins/audit-logs/src/client/components/AuditLogsViewActionInitializer.tsx @@ -0,0 +1,340 @@ +import { ActionInitializer } from '@nocobase/client'; +import React from 'react'; + +export const AuditLogsViewActionInitializer = (props) => { + const schema = { + type: 'void', + title: '{{ t("View") }}', + 'x-action': 'view', + 'x-designer': 'Action.Designer', + 'x-component': 'Action', + 'x-component-props': { + openMode: 'drawer', + }, + properties: { + drawer: { + type: 'void', + title: '{{ t("View record") }}', + 'x-component': 'Action.Container', + 'x-component-props': { + className: 'nb-action-popup', + }, + properties: { + tabs: { + type: 'void', + 'x-component': 'Tabs', + 'x-component-props': {}, + properties: { + tab1: { + type: 'void', + title: '{{t("Details")}}', + 'x-component': 'Tabs.TabPane', + 'x-designer': 'Tabs.Designer', + 'x-component-props': {}, + properties: { + grid: { + type: 'void', + 'x-component': 'Grid', + properties: { + '7ypqrxaqysp': { + type: 'void', + 'x-component': 'Grid.Row', + properties: { + '1fc2l8dwe7m': { + type: 'void', + 'x-component': 'Grid.Col', + properties: { + '5ley6xifrsb': { + type: 'void', + 'x-acl-action': 'auditLogs:get', + 'x-decorator': 'FormBlockProvider', + 'x-decorator-props': { + resource: 'auditLogs', + collection: 'auditLogs', + readPretty: true, + action: 'get', + useParams: '{{ useParamsFromRecord }}', + useSourceId: '{{ useSourceIdFromParentRecord }}', + }, + 'x-component': 'CardItem', + properties: { + bv710pbf9w6: { + type: 'void', + 'x-component': 'FormV2', + 'x-read-pretty': true, + 'x-component-props': { + useProps: '{{ useFormBlockProps }}', + }, + properties: { + grid: { + type: 'void', + 'x-component': 'Grid', + properties: { + g4c24abnbd9: { + type: 'void', + 'x-component': 'Grid.Row', + properties: { + fkt9dj5lu1k: { + type: 'void', + 'x-component': 'Grid.Col', + properties: { + createdAt: { + type: 'string', + 'x-component': 'CollectionField', + 'x-decorator': 'FormItem', + 'x-collection-field': 'auditLogs.createdAt', + 'x-component-props': {}, + 'x-read-pretty': true, + }, + }, + }, + }, + }, + l267bkv423v: { + type: 'void', + 'x-component': 'Grid.Row', + properties: { + tehaepm5xqy: { + type: 'void', + 'x-component': 'Grid.Col', + properties: { + type: { + type: 'string', + 'x-component': 'CollectionField', + 'x-decorator': 'FormItem', + 'x-collection-field': 'auditLogs.type', + 'x-component-props': {}, + 'x-read-pretty': true, + }, + }, + }, + }, + }, + zhmn2tkzdh2: { + type: 'void', + 'x-component': 'Grid.Row', + properties: { + yuwyej17i64: { + type: 'void', + 'x-component': 'Grid.Col', + properties: { + recordId: { + type: 'string', + 'x-component': 'CollectionField', + 'x-decorator': 'FormItem', + 'x-collection-field': 'auditLogs.recordId', + 'x-component-props': {}, + }, + }, + }, + }, + }, + '6q933ic06mj': { + type: 'void', + 'x-component': 'Grid.Row', + properties: { + nwtbkqd99zl2: { + type: 'void', + 'x-component': 'Grid.Col', + properties: { + 'collection.title': { + type: 'string', + 'x-component': 'CollectionField', + 'x-decorator': 'FormItem', + 'x-collection-field': 'auditLogs.collection.title', + 'x-component-props': {}, + }, + }, + }, + nwtbkqd99zl1: { + type: 'void', + 'x-component': 'Grid.Col', + properties: { + 'collection.name': { + type: 'string', + 'x-component': 'CollectionField', + 'x-decorator': 'FormItem', + 'x-collection-field': 'auditLogs.collection.name', + 'x-component-props': {}, + }, + }, + }, + }, + }, + xd4kzulndqk: { + type: 'void', + 'x-component': 'Grid.Row', + properties: { + k3sd72n83zd: { + type: 'void', + 'x-component': 'Grid.Col', + properties: { + user: { + type: 'string', + 'x-component': 'CollectionField', + 'x-decorator': 'FormItem', + 'x-collection-field': 'auditLogs.user', + 'x-component-props': {}, + 'x-read-pretty': true, + properties: { + viewer: { + type: 'void', + title: '{{ t("View record") }}', + 'x-component': 'RecordPicker.Viewer', + 'x-component-props': { + className: 'nb-action-popup', + }, + properties: { + tabs: { + type: 'void', + 'x-component': 'Tabs', + 'x-component-props': {}, + 'x-initializer': 'TabPaneInitializers', + properties: { + tab1: { + type: 'void', + title: '{{t("Details")}}', + 'x-component': 'Tabs.TabPane', + 'x-designer': 'Tabs.Designer', + 'x-component-props': {}, + properties: { + grid: { + type: 'void', + 'x-component': 'Grid', + 'x-initializer': 'RecordBlockInitializers', + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + '3lghgclbtcg': { + type: 'void', + 'x-component': 'Grid.Row', + properties: { + '8l1v1auwlx0': { + type: 'void', + 'x-component': 'Grid.Col', + properties: { + changes: { + type: 'void', + 'x-component': 'TableField', + 'x-decorator': 'FormItem', + 'x-collection-field': 'auditLogs.changes', + 'x-component-props': {}, + properties: { + block: { + type: 'void', + 'x-decorator': 'TableFieldProvider', + 'x-acl-action': 'auditChanges:list', + 'x-decorator-props': { + collection: 'auditChanges', + association: 'auditLogs.changes', + resource: 'auditLogs.changes', + action: 'list', + params: { + paginate: false, + }, + showIndex: true, + dragSort: false, + }, + properties: { + actions: { + type: 'void', + 'x-component': 'TableField.ActionBar', + 'x-component-props': {}, + }, + changes: { + type: 'array', + 'x-component': 'TableV2', + 'x-component-props': { + rowSelection: { + type: 'checkbox', + }, + useProps: '{{ useTableFieldProps }}', + }, + properties: { + '5uvv96u9ict': { + type: 'void', + 'x-decorator': 'TableV2.Column.Decorator', + 'x-component': 'TableV2.Column', + properties: { + field: { + 'x-collection-field': 'auditChanges.field', + 'x-component': 'CollectionField', + 'x-read-pretty': true, + 'x-component-props': { + ellipsis: true, + }, + }, + }, + }, + h7a4tgt11gd: { + type: 'void', + 'x-decorator': 'TableV2.Column.Decorator', + 'x-component': 'TableV2.Column', + properties: { + before: { + 'x-collection-field': 'auditChanges.before', + 'x-component': 'CollectionField', + 'x-read-pretty': true, + 'x-component-props': { + ellipsis: true, + }, + }, + }, + }, + m275z8rglzx: { + type: 'void', + 'x-decorator': 'TableV2.Column.Decorator', + 'x-component': 'TableV2.Column', + properties: { + after: { + 'x-collection-field': 'auditChanges.after', + 'x-component': 'CollectionField', + 'x-read-pretty': true, + 'x-component-props': { + ellipsis: true, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }; + return ; +}; diff --git a/packages/plugins/audit-logs/src/client/AuditLogs.tsx b/packages/plugins/audit-logs/src/client/deplicated/AuditLogs.tsx similarity index 99% rename from packages/plugins/audit-logs/src/client/AuditLogs.tsx rename to packages/plugins/audit-logs/src/client/deplicated/AuditLogs.tsx index d1523d1c5..a60d6c883 100644 --- a/packages/plugins/audit-logs/src/client/AuditLogs.tsx +++ b/packages/plugins/audit-logs/src/client/deplicated/AuditLogs.tsx @@ -7,7 +7,8 @@ import { SchemaComponent, TableBlockProvider, useCollection, - useCompile, useRecord + useCompile, + useRecord, } from '@nocobase/client'; import React, { createContext, useContext } from 'react'; import { AuditLogsDesigner } from './AuditLogsDesigner'; @@ -106,7 +107,7 @@ export const AuditLogs: any = () => { 'x-read-pretty': true, }, }, - } + }; } return ( { const filterByTk = record?.[parent.filterTargetKey || 'id']; if (filter) { filter = { - $and: [filter, { - collectionName: parent.name, - recordId: `${filterByTk}`, - }], + $and: [ + filter, + { + collectionName: parent.name, + recordId: `${filterByTk}`, + }, + ], }; } else { filter = { diff --git a/packages/plugins/audit-logs/src/client/AuditLogsDesigner.tsx b/packages/plugins/audit-logs/src/client/deplicated/AuditLogsDesigner.tsx similarity index 93% rename from packages/plugins/audit-logs/src/client/AuditLogsDesigner.tsx rename to packages/plugins/audit-logs/src/client/deplicated/AuditLogsDesigner.tsx index 05a9411b3..9a7daa8f9 100644 --- a/packages/plugins/audit-logs/src/client/AuditLogsDesigner.tsx +++ b/packages/plugins/audit-logs/src/client/deplicated/AuditLogsDesigner.tsx @@ -1,5 +1,13 @@ import { ISchema, useField, useFieldSchema } from '@formily/react'; -import { GeneralSchemaDesigner, SchemaSettings, useCollection, useCollectionFilterOptions, useDesignable, useSortFields, useTableBlockContext } from '@nocobase/client'; +import { + GeneralSchemaDesigner, + SchemaSettings, + useCollection, + useCollectionFilterOptions, + useDesignable, + useSortFields, + useTableBlockContext, +} from '@nocobase/client'; import React from 'react'; import { useTranslation } from 'react-i18next'; diff --git a/packages/plugins/audit-logs/src/client/initializers/AuditLogsTableActionColumnInitializer.tsx b/packages/plugins/audit-logs/src/client/initializers/AuditLogsTableActionColumnInitializer.tsx new file mode 100644 index 000000000..b77e6bce3 --- /dev/null +++ b/packages/plugins/audit-logs/src/client/initializers/AuditLogsTableActionColumnInitializer.tsx @@ -0,0 +1,26 @@ +import { InitializerWithSwitch } from '@nocobase/client'; +import React from 'react'; + +export const AuditLogsTableActionColumnInitializer = (props) => { + const schema = { + type: 'void', + title: '{{ t("Actions") }}', + 'x-decorator': 'TableV2.Column.ActionBar', + 'x-component': 'TableV2.Column', + 'x-designer': 'TableV2.ActionColumnDesigner', + 'x-initializer': 'AuditLogsTableActionColumnInitializers', + 'x-action-column': 'actions', + properties: { + actions: { + type: 'void', + 'x-decorator': 'DndContext', + 'x-component': 'Space', + 'x-component-props': { + split: '|', + }, + properties: {}, + }, + }, + }; + return ; +}; diff --git a/packages/plugins/audit-logs/src/client/initializers/AuditLogsTableActionColumnInitializers.tsx b/packages/plugins/audit-logs/src/client/initializers/AuditLogsTableActionColumnInitializers.tsx new file mode 100644 index 000000000..25fcec827 --- /dev/null +++ b/packages/plugins/audit-logs/src/client/initializers/AuditLogsTableActionColumnInitializers.tsx @@ -0,0 +1,63 @@ +import { MenuOutlined } from '@ant-design/icons'; +import { useFieldSchema } from '@formily/react'; +import { createDesignable, Resizable, SchemaInitializer, useAPIClient, useDesignable } from '@nocobase/client'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; + +export const AuditLogsTableActionColumnInitializers = (props: any) => { + const fieldSchema = useFieldSchema(); + const api = useAPIClient(); + const { refresh } = useDesignable(); + const { t } = useTranslation(); + return ( + { + const spaceSchema = fieldSchema.reduceProperties((buf, schema) => { + if (schema['x-component'] === 'Space') { + return schema; + } + return buf; + }, null); + if (!spaceSchema) { + return; + } + const dn = createDesignable({ + t, + api, + refresh, + current: spaceSchema, + }); + dn.loadAPIClientEvents(); + dn.insertBeforeEnd(schema); + }} + items={[ + { + type: 'itemGroup', + title: t('Enable actions'), + children: [ + { + type: 'item', + title: t('View'), + component: 'AuditLogsViewActionInitializer', + schema: { + 'x-component': 'Action.Link', + 'x-action': 'view', + 'x-decorator': 'ACLActionProvider', + }, + }, + ], + }, + { + type: 'divider', + }, + { + type: 'item', + title: t('Column width'), + component: Resizable, + }, + ]} + component={} + /> + ); +}; diff --git a/packages/plugins/audit-logs/src/client/initializers/AuditLogsTableActionInitializers.tsx b/packages/plugins/audit-logs/src/client/initializers/AuditLogsTableActionInitializers.tsx new file mode 100644 index 000000000..cc3454cba --- /dev/null +++ b/packages/plugins/audit-logs/src/client/initializers/AuditLogsTableActionInitializers.tsx @@ -0,0 +1,51 @@ +import { Schema } from '@formily/react'; + +// 操作记录表格操作配置 +export const AuditLogsTableActionInitializers = { + title: "{{t('Configure actions')}}", + icon: 'SettingOutlined', + style: { + marginLeft: 8, + }, + items: [ + { + type: 'itemGroup', + title: "{{t('Enable actions')}}", + children: [ + { + type: 'item', + title: "{{t('Filter')}}", + component: 'FilterActionInitializer', + schema: { + 'x-align': 'left', + }, + }, + { + type: 'item', + title: "{{t('Refresh')}}", + component: 'RefreshActionInitializer', + schema: { + 'x-align': 'right', + }, + }, + ], + }, + { + type: 'divider', + }, + { + type: 'item', + title: "{{t('Association fields filter')}}", + component: 'ActionBarAssociationFilterAction', + schema: { + 'x-align': 'left', + }, + find: (schema: Schema) => { + const resultSchema = Object.entries(schema.parent.properties).find( + ([, value]) => value['x-component'] === 'AssociationFilter', + )?.[1]; + return resultSchema; + }, + }, + ], +}; diff --git a/packages/plugins/audit-logs/src/client/initializers/AuditLogsTableColumnInitializers.tsx b/packages/plugins/audit-logs/src/client/initializers/AuditLogsTableColumnInitializers.tsx new file mode 100644 index 000000000..537c90d44 --- /dev/null +++ b/packages/plugins/audit-logs/src/client/initializers/AuditLogsTableColumnInitializers.tsx @@ -0,0 +1,88 @@ +import { + itemsMerge, + SchemaInitializer, + useAssociatedTableColumnInitializerFields, + useCompile, + useInheritsTableColumnInitializerFields, + useTableColumnInitializerFields, +} from '@nocobase/client'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; + +// 表格列配置 +export const AuditLogsTableColumnInitializers = (props: any) => { + const { items = [] } = props; + const { t } = useTranslation(); + const associatedFields = useAssociatedTableColumnInitializerFields(); + const inheritFields = useInheritsTableColumnInitializerFields(); + const compile = useCompile(); + const fieldItems: any[] = [ + { + type: 'itemGroup', + title: t('Display fields'), + children: useTableColumnInitializerFields(), + }, + ]; + if (inheritFields?.length > 0) { + inheritFields.forEach((inherit) => { + Object.values(inherit)[0].length && + fieldItems.push( + { + type: 'divider', + }, + { + type: 'itemGroup', + title: t(`Parent collection fields`) + '(' + compile(`${Object.keys(inherit)[0]}`) + ')', + children: Object.values(inherit)[0], + }, + ); + }); + } + if (associatedFields?.length > 0) { + fieldItems.push( + { + type: 'divider', + }, + { + type: 'itemGroup', + title: t('Display association fields'), + children: associatedFields, + }, + ); + } + fieldItems.push( + { + type: 'divider', + }, + { + type: 'item', + title: t('Action column'), + component: 'AuditLogsTableActionColumnInitializer', + }, + ); + return ( + { + if (s['x-action-column']) { + return s; + } + return { + type: 'void', + 'x-decorator': 'TableV2.Column.Decorator', + 'x-designer': 'TableV2.Column.Designer', + 'x-component': 'TableV2.Column', + properties: { + [s.name]: { + ...s, + }, + }, + }; + }} + items={itemsMerge(fieldItems, items)} + > + {t('Configure columns')} + + ); +}; diff --git a/packages/plugins/audit-logs/src/client/locale/en-US.ts b/packages/plugins/audit-logs/src/client/locale/en-US.ts new file mode 100644 index 000000000..4b43902c4 --- /dev/null +++ b/packages/plugins/audit-logs/src/client/locale/en-US.ts @@ -0,0 +1,3 @@ +export default { + 'Details of changes': 'Details of changes', +}; diff --git a/packages/plugins/audit-logs/src/client/locale/index.ts b/packages/plugins/audit-logs/src/client/locale/index.ts new file mode 100644 index 000000000..5784d89b6 --- /dev/null +++ b/packages/plugins/audit-logs/src/client/locale/index.ts @@ -0,0 +1,12 @@ +import { i18n } from '@nocobase/client'; +import { useTranslation } from 'react-i18next'; + +export const NAMESPACE = 'audit-logs'; + +export function lang(key: string) { + return i18n.t(key, { ns: NAMESPACE }); +} + +export function useAuditLogsTranslation() { + return useTranslation(NAMESPACE); +} diff --git a/packages/plugins/audit-logs/src/client/locale/ja-JP.ts b/packages/plugins/audit-logs/src/client/locale/ja-JP.ts new file mode 100644 index 000000000..ff8b4c563 --- /dev/null +++ b/packages/plugins/audit-logs/src/client/locale/ja-JP.ts @@ -0,0 +1 @@ +export default {}; diff --git a/packages/plugins/audit-logs/src/client/locale/ru-RU.ts b/packages/plugins/audit-logs/src/client/locale/ru-RU.ts new file mode 100644 index 000000000..ff8b4c563 --- /dev/null +++ b/packages/plugins/audit-logs/src/client/locale/ru-RU.ts @@ -0,0 +1 @@ +export default {}; diff --git a/packages/plugins/audit-logs/src/client/locale/tr-TR.ts b/packages/plugins/audit-logs/src/client/locale/tr-TR.ts new file mode 100644 index 000000000..ff8b4c563 --- /dev/null +++ b/packages/plugins/audit-logs/src/client/locale/tr-TR.ts @@ -0,0 +1 @@ +export default {}; diff --git a/packages/plugins/audit-logs/src/client/locale/zh-CN.ts b/packages/plugins/audit-logs/src/client/locale/zh-CN.ts new file mode 100644 index 000000000..22efb743c --- /dev/null +++ b/packages/plugins/audit-logs/src/client/locale/zh-CN.ts @@ -0,0 +1,3 @@ +export default { + 'Details of changes': '变更详情', +};