refactor: audit logs block (#1517)
* refactor: audit-log * refactor: audit-log fix view action * refactor: audit-log view fix * refactor(audit-log): collection field fix * refactor: audit-log view field fix * refactor(audit-log): support fixedBlock * refactor(audit-log): i18n fix * refactor(audit-log): fixedTable and drag issue * refactor(audit-log): remove template support * refactor(audit-log): drag fix * refactor(audit-log): disableTemplate & DndContext --------- Co-authored-by: anuoua <anuoua@gmail.com>
This commit is contained in:
parent
e913af7f32
commit
07ec115904
@ -20,7 +20,7 @@ export const CollectionManagerProvider: React.FC<CollectionManagerOptions> = (pr
|
|||||||
service,
|
service,
|
||||||
interfaces: { ...defaultInterfaces, ...ctx.interfaces, ...interfaces },
|
interfaces: { ...defaultInterfaces, ...ctx.interfaces, ...interfaces },
|
||||||
templates: { ...defaultTemplates, ...templates },
|
templates: { ...defaultTemplates, ...templates },
|
||||||
collections,
|
collections: [...ctx.collections, ...collections],
|
||||||
refreshCM,
|
refreshCM,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@ -38,7 +38,7 @@ export const RemoteCollectionManagerProvider = (props: any) => {
|
|||||||
action: 'list',
|
action: 'list',
|
||||||
params: {
|
params: {
|
||||||
paginate: false,
|
paginate: false,
|
||||||
appends: ['fields', 'fields.uiSchema','category'],
|
appends: ['fields', 'fields.uiSchema', 'category'],
|
||||||
filter: {
|
filter: {
|
||||||
// inherit: false,
|
// inherit: false,
|
||||||
},
|
},
|
||||||
@ -75,13 +75,13 @@ export const RemoteCollectionManagerProvider = (props: any) => {
|
|||||||
|
|
||||||
export const CollectionCategroriesProvider = (props) => {
|
export const CollectionCategroriesProvider = (props) => {
|
||||||
const api = useAPIClient();
|
const api = useAPIClient();
|
||||||
const options={
|
const options = {
|
||||||
url: 'collectionCategories:list',
|
url: 'collectionCategories:list',
|
||||||
params: {
|
params: {
|
||||||
paginate: false,
|
paginate: false,
|
||||||
sort:['sort']
|
sort: ['sort'],
|
||||||
},
|
},
|
||||||
}
|
};
|
||||||
const result = useRequest(options);
|
const result = useRequest(options);
|
||||||
if (result.loading) {
|
if (result.loading) {
|
||||||
return <Spin />;
|
return <Spin />;
|
||||||
@ -91,11 +91,11 @@ export const CollectionCategroriesProvider = (props) => {
|
|||||||
value={{
|
value={{
|
||||||
...result,
|
...result,
|
||||||
data: result?.data?.data,
|
data: result?.data?.data,
|
||||||
refresh:async ()=>{
|
refresh: async () => {
|
||||||
const { data } = await api.request(options);
|
const { data } = await api.request(options);
|
||||||
result.mutate(data);
|
result.mutate(data);
|
||||||
return data?.data || [];
|
return data?.data || [];
|
||||||
}
|
},
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{props.children}
|
{props.children}
|
||||||
|
@ -4,7 +4,7 @@ import cls from 'classnames';
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useCollection } from '../../../collection-manager';
|
import { useCollection } from '../../../collection-manager';
|
||||||
import { useSchemaInitializer } from '../../../schema-initializer';
|
import { useSchemaInitializer } from '../../../schema-initializer';
|
||||||
import { SortableItem } from '../../common';
|
import { DndContext, SortableItem } from '../../common';
|
||||||
import { useDesigner } from '../../hooks';
|
import { useDesigner } from '../../hooks';
|
||||||
import { AssociationFilterInitializer } from './AssociationFilter.Initializer';
|
import { AssociationFilterInitializer } from './AssociationFilter.Initializer';
|
||||||
import { AssociationFilterItem } from './AssociationFilter.Item';
|
import { AssociationFilterItem } from './AssociationFilter.Item';
|
||||||
@ -17,59 +17,61 @@ export const AssociationFilter = (props) => {
|
|||||||
const { exists, render } = useSchemaInitializer(filedSchema['x-initializer']);
|
const { exists, render } = useSchemaInitializer(filedSchema['x-initializer']);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SortableItem
|
<DndContext>
|
||||||
className={cls(
|
<SortableItem
|
||||||
'nb-block-item',
|
className={cls(
|
||||||
props.className,
|
'nb-block-item',
|
||||||
css`
|
props.className,
|
||||||
position: relative;
|
css`
|
||||||
&:hover {
|
position: relative;
|
||||||
> .general-schema-designer {
|
&:hover {
|
||||||
display: block;
|
> .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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
&.nb-form-item:hover {
|
||||||
`,
|
> .general-schema-designer {
|
||||||
)}
|
background: rgba(241, 139, 98, 0.06) !important;
|
||||||
>
|
border: 0 !important;
|
||||||
<Designer />
|
top: -5px !important;
|
||||||
{props.children}
|
bottom: -5px !important;
|
||||||
{render()}
|
left: -5px !important;
|
||||||
</SortableItem>
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<Designer />
|
||||||
|
{props.children}
|
||||||
|
{render()}
|
||||||
|
</SortableItem>
|
||||||
|
</DndContext>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import { useTranslation } from 'react-i18next';
|
|||||||
import { useDesignable } from '../../hooks';
|
import { useDesignable } from '../../hooks';
|
||||||
import { useRecord } from '../../../record-provider';
|
import { useRecord } from '../../../record-provider';
|
||||||
import { useBlockTemplateContext } from '../../../schema-templates/BlockTemplate';
|
import { useBlockTemplateContext } from '../../../schema-templates/BlockTemplate';
|
||||||
|
import { uid } from '@formily/shared';
|
||||||
|
|
||||||
const FixedBlockContext = React.createContext({
|
const FixedBlockContext = React.createContext({
|
||||||
setFixedSchema: (schema: Schema) => {},
|
setFixedSchema: (schema: Schema) => {},
|
||||||
|
@ -23,6 +23,7 @@ export const TableBlockDesigner = () => {
|
|||||||
const defaultFilter = fieldSchema?.['x-decorator-props']?.params?.filter || {};
|
const defaultFilter = fieldSchema?.['x-decorator-props']?.params?.filter || {};
|
||||||
const defaultSort = fieldSchema?.['x-decorator-props']?.params?.sort || [];
|
const defaultSort = fieldSchema?.['x-decorator-props']?.params?.sort || [];
|
||||||
const defaultResource = fieldSchema?.['x-decorator-props']?.resource;
|
const defaultResource = fieldSchema?.['x-decorator-props']?.resource;
|
||||||
|
const supportTemplate = !fieldSchema?.['x-decorator-props']?.disableTemplate;
|
||||||
const sort = defaultSort?.map((item: string) => {
|
const sort = defaultSort?.map((item: string) => {
|
||||||
return item.startsWith('-')
|
return item.startsWith('-')
|
||||||
? {
|
? {
|
||||||
@ -211,8 +212,10 @@ export const TableBlockDesigner = () => {
|
|||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<SchemaSettings.Divider />
|
{supportTemplate && <SchemaSettings.Divider />}
|
||||||
<SchemaSettings.Template componentName={'Table'} collectionName={name} resourceName={defaultResource} />
|
{supportTemplate && (
|
||||||
|
<SchemaSettings.Template componentName={'Table'} collectionName={name} resourceName={defaultResource} />
|
||||||
|
)}
|
||||||
<SchemaSettings.Divider />
|
<SchemaSettings.Divider />
|
||||||
<SchemaSettings.Remove
|
<SchemaSettings.Remove
|
||||||
removeParentsIfNoChildren
|
removeParentsIfNoChildren
|
||||||
|
@ -10,7 +10,7 @@ import {
|
|||||||
SchemaInitializerButtonProps,
|
SchemaInitializerButtonProps,
|
||||||
SchemaInitializerItemComponent,
|
SchemaInitializerItemComponent,
|
||||||
SchemaInitializerItemOptions,
|
SchemaInitializerItemOptions,
|
||||||
SchemaInitializerItemProps
|
SchemaInitializerItemProps,
|
||||||
} from './types';
|
} from './types';
|
||||||
|
|
||||||
const defaultWrap = (s: ISchema) => s;
|
const defaultWrap = (s: ISchema) => s;
|
||||||
|
@ -6,7 +6,7 @@ import { SchemaInitializer, SchemaSettings } from '../..';
|
|||||||
import { useAPIClient } from '../../api-client';
|
import { useAPIClient } from '../../api-client';
|
||||||
import { createDesignable, useDesignable } from '../../schema-component';
|
import { createDesignable, useDesignable } from '../../schema-component';
|
||||||
|
|
||||||
const Resizable = (props) => {
|
export const Resizable = (props) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { dn } = useDesignable();
|
const { dn } = useDesignable();
|
||||||
const fieldSchema = useFieldSchema();
|
const fieldSchema = useFieldSchema();
|
||||||
|
@ -2,5 +2,13 @@ export * from './SchemaInitializer';
|
|||||||
export * from './SchemaInitializerProvider';
|
export * from './SchemaInitializerProvider';
|
||||||
export * from './types';
|
export * from './types';
|
||||||
export * from './items';
|
export * from './items';
|
||||||
export { gridRowColWrap, useRecordCollectionDataSourceItems } from './utils';
|
export {
|
||||||
|
gridRowColWrap,
|
||||||
|
useRecordCollectionDataSourceItems,
|
||||||
|
createTableBlockSchema,
|
||||||
|
useAssociatedTableColumnInitializerFields,
|
||||||
|
useInheritsTableColumnInitializerFields,
|
||||||
|
useTableColumnInitializerFields,
|
||||||
|
itemsMerge,
|
||||||
|
} from './utils';
|
||||||
export * from './buttons';
|
export * from './buttons';
|
||||||
|
@ -815,10 +815,20 @@ export const createReadPrettyFormBlockSchema = (options) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const createTableBlockSchema = (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 = {
|
const schema: ISchema = {
|
||||||
type: 'void',
|
type: 'void',
|
||||||
'x-decorator': 'TableBlockProvider',
|
'x-decorator': tableBlockProvider ?? 'TableBlockProvider',
|
||||||
'x-acl-action': `${resource || collection}:list`,
|
'x-acl-action': `${resource || collection}:list`,
|
||||||
'x-decorator-props': {
|
'x-decorator-props': {
|
||||||
collection,
|
collection,
|
||||||
@ -830,6 +840,7 @@ export const createTableBlockSchema = (options) => {
|
|||||||
rowKey,
|
rowKey,
|
||||||
showIndex: true,
|
showIndex: true,
|
||||||
dragSort: false,
|
dragSort: false,
|
||||||
|
disableTemplate: disableTemplate ?? false,
|
||||||
...others,
|
...others,
|
||||||
},
|
},
|
||||||
'x-designer': 'TableBlockDesigner',
|
'x-designer': 'TableBlockDesigner',
|
||||||
@ -837,7 +848,7 @@ export const createTableBlockSchema = (options) => {
|
|||||||
properties: {
|
properties: {
|
||||||
actions: {
|
actions: {
|
||||||
type: 'void',
|
type: 'void',
|
||||||
'x-initializer': 'TableActionInitializers',
|
'x-initializer': tableActionInitializers ?? 'TableActionInitializers',
|
||||||
'x-component': 'ActionBar',
|
'x-component': 'ActionBar',
|
||||||
'x-component-props': {
|
'x-component-props': {
|
||||||
style: {
|
style: {
|
||||||
@ -848,7 +859,7 @@ export const createTableBlockSchema = (options) => {
|
|||||||
},
|
},
|
||||||
[uid()]: {
|
[uid()]: {
|
||||||
type: 'array',
|
type: 'array',
|
||||||
'x-initializer': 'TableColumnInitializers',
|
'x-initializer': tableColumnInitializers ?? 'TableColumnInitializers',
|
||||||
'x-component': 'TableV2',
|
'x-component': 'TableV2',
|
||||||
'x-component-props': {
|
'x-component-props': {
|
||||||
rowKey: 'id',
|
rowKey: 'id',
|
||||||
@ -865,7 +876,7 @@ export const createTableBlockSchema = (options) => {
|
|||||||
'x-decorator': 'TableV2.Column.ActionBar',
|
'x-decorator': 'TableV2.Column.ActionBar',
|
||||||
'x-component': 'TableV2.Column',
|
'x-component': 'TableV2.Column',
|
||||||
'x-designer': 'TableV2.ActionColumnDesigner',
|
'x-designer': 'TableV2.ActionColumnDesigner',
|
||||||
'x-initializer': 'TableActionColumnInitializers',
|
'x-initializer': tableActionColumnInitializers ?? 'TableActionColumnInitializers',
|
||||||
properties: {
|
properties: {
|
||||||
actions: {
|
actions: {
|
||||||
type: 'void',
|
type: 'void',
|
||||||
|
@ -1,31 +1,29 @@
|
|||||||
import { TableOutlined } from '@ant-design/icons';
|
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 React from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
export const AuditLogsBlockInitializer = (props) => {
|
export const AuditLogsBlockInitializer = (props) => {
|
||||||
const { insert } = props;
|
const { insert } = props;
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const schema = createTableBlockSchema({
|
||||||
|
collection: 'auditLogs',
|
||||||
|
rowKey: 'id',
|
||||||
|
tableActionInitializers: 'AuditLogsTableActionInitializers',
|
||||||
|
tableColumnInitializers: 'AuditLogsTableColumnInitializers',
|
||||||
|
tableActionColumnInitializers: 'AuditLogsTableActionColumnInitializers',
|
||||||
|
tableBlockProvider: 'AuditLogsBlockProvider',
|
||||||
|
disableTemplate: true,
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SchemaInitializer.Item
|
<SchemaInitializer.Item
|
||||||
{...props}
|
{...props}
|
||||||
icon={<TableOutlined />}
|
icon={<TableOutlined />}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
insert({
|
insert(schema as ISchema);
|
||||||
type: 'void',
|
|
||||||
'x-designer': 'AuditLogs.Designer',
|
|
||||||
'x-decorator': 'AuditLogs.Decorator',
|
|
||||||
'x-decorator-props': {
|
|
||||||
params: {},
|
|
||||||
},
|
|
||||||
'x-component': 'CardItem',
|
|
||||||
properties: {
|
|
||||||
auditLogs: {
|
|
||||||
type: 'void',
|
|
||||||
'x-component': 'AuditLogs',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}}
|
}}
|
||||||
title={t('Audit Logs')}
|
title={t('Audit Logs')}
|
||||||
/>
|
/>
|
||||||
|
@ -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 (
|
||||||
|
<SchemaInitializerProvider
|
||||||
|
initializers={{
|
||||||
|
...initializers,
|
||||||
|
AuditLogsTableActionInitializers,
|
||||||
|
AuditLogsTableActionColumnInitializers,
|
||||||
|
AuditLogsTableColumnInitializers,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CollectionManagerProvider collections={[auditLogsCollection, auditChangesCollection, collectionsCollection]}>
|
||||||
|
<TableBlockProvider {...restProps}>{children}</TableBlockProvider>
|
||||||
|
</CollectionManagerProvider>
|
||||||
|
</SchemaInitializerProvider>
|
||||||
|
);
|
||||||
|
};
|
@ -1,11 +1,26 @@
|
|||||||
import { SchemaComponentOptions } from '@nocobase/client';
|
import { SchemaComponentOptions, SchemaInitializerContext, SchemaInitializerProvider } from '@nocobase/client';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { AuditLogs } from './AuditLogs';
|
|
||||||
import { AuditLogsBlockInitializer } from './AuditLogsBlockInitializer';
|
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) => {
|
export const AuditLogsProvider = (props: any) => {
|
||||||
return (
|
return (
|
||||||
<SchemaComponentOptions components={{ AuditLogs, AuditLogsBlockInitializer }}>
|
<SchemaComponentOptions
|
||||||
|
components={{
|
||||||
|
AuditLogs,
|
||||||
|
AuditLogsBlockProvider,
|
||||||
|
AuditLogsBlockInitializer,
|
||||||
|
AuditLogsValue,
|
||||||
|
AuditLogsField,
|
||||||
|
AuditLogsViewActionInitializer,
|
||||||
|
AuditLogsTableActionColumnInitializer,
|
||||||
|
}}
|
||||||
|
>
|
||||||
{props.children}
|
{props.children}
|
||||||
</SchemaComponentOptions>
|
</SchemaComponentOptions>
|
||||||
);
|
);
|
||||||
|
166
packages/plugins/audit-logs/src/client/collections.tsx
Normal file
166
packages/plugins/audit-logs/src/client/collections.tsx
Normal file
@ -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 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
};
|
@ -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<any>();
|
||||||
|
const compile = useCompile();
|
||||||
|
if (!field.value) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return <div>{field.value?.uiSchema?.title ? compile(field.value?.uiSchema?.title) : field.value.name}</div>;
|
||||||
|
});
|
@ -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<any>();
|
||||||
|
const record = useRecord();
|
||||||
|
if (record.field?.uiSchema) {
|
||||||
|
return (
|
||||||
|
<FormProvider>
|
||||||
|
<SchemaComponent
|
||||||
|
schema={{
|
||||||
|
name: record.field.name,
|
||||||
|
...record.field?.uiSchema,
|
||||||
|
default: field.value,
|
||||||
|
'x-read-pretty': true,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</FormProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return <div>{field.value ? JSON.stringify(field.value) : null}</div>;
|
||||||
|
});
|
@ -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 <ActionInitializer {...props} schema={schema} />;
|
||||||
|
};
|
@ -7,7 +7,8 @@ import {
|
|||||||
SchemaComponent,
|
SchemaComponent,
|
||||||
TableBlockProvider,
|
TableBlockProvider,
|
||||||
useCollection,
|
useCollection,
|
||||||
useCompile, useRecord
|
useCompile,
|
||||||
|
useRecord,
|
||||||
} from '@nocobase/client';
|
} from '@nocobase/client';
|
||||||
import React, { createContext, useContext } from 'react';
|
import React, { createContext, useContext } from 'react';
|
||||||
import { AuditLogsDesigner } from './AuditLogsDesigner';
|
import { AuditLogsDesigner } from './AuditLogsDesigner';
|
||||||
@ -106,7 +107,7 @@ export const AuditLogs: any = () => {
|
|||||||
'x-read-pretty': true,
|
'x-read-pretty': true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<SchemaComponent
|
<SchemaComponent
|
||||||
@ -454,10 +455,13 @@ AuditLogs.Decorator = observer((props: any) => {
|
|||||||
const filterByTk = record?.[parent.filterTargetKey || 'id'];
|
const filterByTk = record?.[parent.filterTargetKey || 'id'];
|
||||||
if (filter) {
|
if (filter) {
|
||||||
filter = {
|
filter = {
|
||||||
$and: [filter, {
|
$and: [
|
||||||
collectionName: parent.name,
|
filter,
|
||||||
recordId: `${filterByTk}`,
|
{
|
||||||
}],
|
collectionName: parent.name,
|
||||||
|
recordId: `${filterByTk}`,
|
||||||
|
},
|
||||||
|
],
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
filter = {
|
filter = {
|
@ -1,5 +1,13 @@
|
|||||||
import { ISchema, useField, useFieldSchema } from '@formily/react';
|
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 React from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
@ -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 <InitializerWithSwitch {...props} schema={schema} type={'x-action-column'} />;
|
||||||
|
};
|
@ -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 (
|
||||||
|
<SchemaInitializer.Button
|
||||||
|
insertPosition={'beforeEnd'}
|
||||||
|
insert={(schema) => {
|
||||||
|
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={<MenuOutlined style={{ cursor: 'pointer' }} />}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
@ -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;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
@ -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 (
|
||||||
|
<SchemaInitializer.Button
|
||||||
|
insertPosition={'beforeEnd'}
|
||||||
|
icon={'SettingOutlined'}
|
||||||
|
wrap={(s) => {
|
||||||
|
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')}
|
||||||
|
</SchemaInitializer.Button>
|
||||||
|
);
|
||||||
|
};
|
3
packages/plugins/audit-logs/src/client/locale/en-US.ts
Normal file
3
packages/plugins/audit-logs/src/client/locale/en-US.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export default {
|
||||||
|
'Details of changes': 'Details of changes',
|
||||||
|
};
|
12
packages/plugins/audit-logs/src/client/locale/index.ts
Normal file
12
packages/plugins/audit-logs/src/client/locale/index.ts
Normal file
@ -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);
|
||||||
|
}
|
1
packages/plugins/audit-logs/src/client/locale/ja-JP.ts
Normal file
1
packages/plugins/audit-logs/src/client/locale/ja-JP.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export default {};
|
1
packages/plugins/audit-logs/src/client/locale/ru-RU.ts
Normal file
1
packages/plugins/audit-logs/src/client/locale/ru-RU.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export default {};
|
1
packages/plugins/audit-logs/src/client/locale/tr-TR.ts
Normal file
1
packages/plugins/audit-logs/src/client/locale/tr-TR.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export default {};
|
3
packages/plugins/audit-logs/src/client/locale/zh-CN.ts
Normal file
3
packages/plugins/audit-logs/src/client/locale/zh-CN.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export default {
|
||||||
|
'Details of changes': '变更详情',
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user