mirror of
https://github.com/nocobase/nocobase.git
synced 2026-09-01 14:57:36 +08:00
4f87de7da5
* test: create view collection * feat: view collection class * feat: list view * chore: skip sync view collection * test: should create view collection in difference schema * test: create view collection in collection manager * feat: create view collection by user sql * test: view resourcer * feat: view collection * feat: view collection cannot be added, deleted, or modified * feat: view collection cannot be added, deleted, or modified * feat: view collection cannot be added, deleted, or modified * feat: view collection cannot be added, deleted, or modified * refactor: connect to database view * refactor: sync from database * chore: rename list view sql * chore: list view fields api * chore: create collection without viewName * feat: bring out fields when selecting a view * chore: bring out fields when selecting a view * feat: view field inference class * chore: bring out fields when selecting a view * chore: sync form database view * chore: sync form database view * refactor: view collection local * feat: view get api * feat: database type infer * feat: integer map * chore: remove from in view list * chore: build error * chore: uniq collection * fix: typo * chore: replace collection list source field * fix: destroy view collection * chore: timestamp field map * refactor: interface avalableTypes * refactor: interface avalableTypes * chore: list fields test * refactor: interface avalableTypes * chore: uiSchema response in field source * fix: view query * chore: collection snippet * refactor: view collection support preview * fix: handle field source * fix: typo * fix: configure fileds title * fix: configure fileds title * fix: configure fileds title * fix: sync from databse interface * fix: sync from databse interface * feat: set fields api * fix: sync from databse fix * feat: possibleTypes * chore: fields get * fix: sync from databse * fix: list view test * fix: view test in difference schema * chore: comment * feat: when there is only one source collection, the view is a subset of a Collection * feat: view collection add field * fix: inherit query with schema * fix: test * fix: ci test * fix: test with schema * chore: set pg default search path * chore: mysql test * fix: test with schema * chore: test * chore: action test * chore: view column usage return type * feat: mysql field inference * fix: tableName * chore: node sql parser * fix: sql build * fix: database build * fix: mysql test * feat: view collection uiSchema title * fix: incorrect field source display when switching views * refactor: view collection not allow modify * fix: view collection is allow add, delete, and modify * fix: mysql test * fix: sqlite test * fix: sqlite test * fix: sqlite test * fix: sqlite test * chore: add id field as default target key * style: style improve * feat: load source field options * style: style improve * chore: disable remove column in view collection * chore: support creating view collection with different schemas with the same name * chore: support creating view collection with different schemas with the same name * fix: query view in difference schema * refactor: view collection viewname * fix: query view collection in difference schema * fix: field load * chore: field options * fix: mysql test * fix: uiSchema component error when using a view field in a block * fix: sqlite test * chore: test * fix: dump user views * fix: view collection can be updated and edited in table block * chore: sync from database display last field configuration * chore: loadCollections * chore: sync from database display last field configuration * fix: field options merge issues * style: preview table * fix: view collection is allow using in kanban blocks * refactor: code improve * fix: view collection can be updated an edited in calendar block * chore: disable infer field without interface * feat: preview only shows source or interface fields * fix: test * refactor: locale * feat: sql parser * chore: remove node-sql-parser * fix: yarn.lock * test: view repository * fix: view repository test * chore: console.log * chore: console.log * fix: mysql without schema * fix: mysql without schema * chore: preview with field schema * chore: tableActionInitializers * style: preview style improve * chore: parameter is filter when there is no filterByTk * fix: preview pagination * fix: preview pagination * style: preview table style improve * fix: sync from database loading * chore: preview performance optimization * chore: preview performance optimization * feat: limit & offset * chore: preview performance optimization * test: field with dot column * fix: datetime interface display * fix: missing boolean type * fix: sync * fix: sync from database * style: style improve * style: style improve * style: style improve * chore: preview table * chore: preview table * chore: preview table * fix: styling --------- Co-authored-by: katherinehhh <katherine_15995@163.com> Co-authored-by: chenos <chenlinxh@gmail.com>
1407 lines
43 KiB
TypeScript
1407 lines
43 KiB
TypeScript
import { ISchema, Schema, useFieldSchema, useForm } from '@formily/react';
|
|
import { uid } from '@formily/shared';
|
|
import React, { useContext, useState } from 'react';
|
|
import { useTranslation } from 'react-i18next';
|
|
import { BlockRequestContext, SchemaInitializerItemOptions } from '../';
|
|
import { FieldOptions, useCollection, useCollectionManager } from '../collection-manager';
|
|
import { isAssocField } from '../filter-provider/utils';
|
|
import { useActionContext, useDesignable } from '../schema-component';
|
|
import { useSchemaTemplateManager } from '../schema-templates';
|
|
import { SelectCollection } from './SelectCollection';
|
|
|
|
export const itemsMerge = (items1) => {
|
|
return items1;
|
|
};
|
|
|
|
export const gridRowColWrap = (schema: ISchema) => {
|
|
return {
|
|
type: 'void',
|
|
'x-component': 'Grid.Row',
|
|
properties: {
|
|
[uid()]: {
|
|
type: 'void',
|
|
'x-component': 'Grid.Col',
|
|
properties: {
|
|
[schema.name || uid()]: schema,
|
|
},
|
|
},
|
|
},
|
|
};
|
|
};
|
|
|
|
export const removeTableColumn = (schema, cb) => {
|
|
cb(schema.parent);
|
|
};
|
|
|
|
export const removeGridFormItem = (schema, cb) => {
|
|
cb(schema, {
|
|
removeParentsIfNoChildren: true,
|
|
breakRemoveOn: {
|
|
'x-component': 'Grid',
|
|
},
|
|
});
|
|
};
|
|
|
|
export const useRemoveGridFormItem = () => {
|
|
const form = useForm();
|
|
return (schema, cb) => {
|
|
cb(schema, {
|
|
removeParentsIfNoChildren: true,
|
|
breakRemoveOn: {
|
|
'x-component': 'Grid',
|
|
},
|
|
});
|
|
delete form.values?.[schema.name];
|
|
};
|
|
};
|
|
|
|
export const findTableColumn = (schema: Schema, key: string, action: string, deepth: number = 0) => {
|
|
return schema.reduceProperties((buf, s) => {
|
|
if (s[key] === action) {
|
|
return s;
|
|
}
|
|
const c = s.reduceProperties((buf, s) => {
|
|
if (s[key] === action) {
|
|
return s;
|
|
}
|
|
return buf;
|
|
});
|
|
if (c) {
|
|
return c;
|
|
}
|
|
return buf;
|
|
});
|
|
};
|
|
|
|
export const useTableColumnInitializerFields = () => {
|
|
const { name, currentFields = [] } = useCollection();
|
|
const { getInterface } = useCollectionManager();
|
|
return currentFields
|
|
.filter(
|
|
(field) => field?.interface && field?.interface !== 'subTable' && !field?.isForeignKey && !field?.treeChildren,
|
|
)
|
|
.map((field) => {
|
|
const interfaceConfig = getInterface(field.interface);
|
|
const schema = {
|
|
name: field.name,
|
|
'x-collection-field': `${name}.${field.name}`,
|
|
'x-component': 'CollectionField',
|
|
'x-read-pretty': true,
|
|
'x-component-props': {},
|
|
};
|
|
// interfaceConfig?.schemaInitialize?.(schema, { field, readPretty: true, block: 'Table' });
|
|
return {
|
|
type: 'item',
|
|
title: field?.uiSchema?.title || field.name,
|
|
component: 'TableCollectionFieldInitializer',
|
|
find: findTableColumn,
|
|
remove: removeTableColumn,
|
|
schemaInitialize: (s) => {
|
|
interfaceConfig?.schemaInitialize?.(s, { field, readPretty: true, block: 'Table' });
|
|
},
|
|
field,
|
|
schema,
|
|
} as SchemaInitializerItemOptions;
|
|
});
|
|
};
|
|
|
|
export const useAssociatedTableColumnInitializerFields = () => {
|
|
const { name, fields } = useCollection();
|
|
const { getInterface, getCollectionFields } = useCollectionManager();
|
|
const groups = fields
|
|
?.filter((field) => {
|
|
return ['o2o', 'oho', 'obo', 'm2o'].includes(field.interface);
|
|
})
|
|
?.map((field) => {
|
|
const subFields = getCollectionFields(field.target);
|
|
const items = subFields
|
|
// ?.filter((subField) => subField?.interface && !['o2o', 'oho', 'obo', 'o2m', 'm2o', 'subTable', 'linkTo'].includes(subField?.interface))
|
|
?.filter(
|
|
(subField) => subField?.interface && !['subTable'].includes(subField?.interface) && !subField?.treeChildren,
|
|
)
|
|
?.map((subField) => {
|
|
const interfaceConfig = getInterface(subField.interface);
|
|
const schema = {
|
|
// type: 'string',
|
|
name: `${field.name}.${subField.name}`,
|
|
// title: subField?.uiSchema?.title || subField.name,
|
|
|
|
'x-component': 'CollectionField',
|
|
'x-read-pretty': true,
|
|
'x-collection-field': `${name}.${field.name}.${subField.name}`,
|
|
'x-component-props': {},
|
|
};
|
|
|
|
return {
|
|
type: 'item',
|
|
title: subField?.uiSchema?.title || subField.name,
|
|
component: 'TableCollectionFieldInitializer',
|
|
find: findTableColumn,
|
|
remove: removeTableColumn,
|
|
schemaInitialize: (s) => {
|
|
interfaceConfig?.schemaInitialize?.(s, { field: subField, readPretty: true, block: 'Table' });
|
|
},
|
|
field: subField,
|
|
schema,
|
|
} as SchemaInitializerItemOptions;
|
|
});
|
|
return {
|
|
type: 'subMenu',
|
|
title: field.uiSchema?.title,
|
|
children: items,
|
|
} as SchemaInitializerItemOptions;
|
|
});
|
|
|
|
return groups;
|
|
};
|
|
|
|
export const useInheritsTableColumnInitializerFields = () => {
|
|
const { name } = useCollection();
|
|
const { getInterface, getInheritCollections, getCollection, getParentCollectionFields } = useCollectionManager();
|
|
const inherits = getInheritCollections(name);
|
|
return inherits?.map((v) => {
|
|
const fields = getParentCollectionFields(v, name);
|
|
const targetCollection = getCollection(v);
|
|
return {
|
|
[targetCollection?.title]: fields
|
|
?.filter((field) => {
|
|
return field?.interface;
|
|
})
|
|
.map((k) => {
|
|
const interfaceConfig = getInterface(k.interface);
|
|
const schema = {
|
|
name: `${k.name}`,
|
|
'x-component': 'CollectionField',
|
|
'x-read-pretty': true,
|
|
'x-collection-field': `${name}.${k.name}`,
|
|
'x-component-props': {},
|
|
};
|
|
return {
|
|
type: 'item',
|
|
title: k?.uiSchema?.title || k.name,
|
|
component: 'TableCollectionFieldInitializer',
|
|
find: findTableColumn,
|
|
remove: removeTableColumn,
|
|
schemaInitialize: (s) => {
|
|
interfaceConfig?.schemaInitialize?.(s, { field: k, readPretty: true, block: 'Table' });
|
|
},
|
|
field: k,
|
|
schema,
|
|
} as SchemaInitializerItemOptions;
|
|
}),
|
|
};
|
|
});
|
|
};
|
|
|
|
export const useFormItemInitializerFields = (options?: any) => {
|
|
const { name, currentFields } = useCollection();
|
|
const { getInterface } = useCollectionManager();
|
|
const form = useForm();
|
|
const { readPretty = form.readPretty, block = 'Form' } = options || {};
|
|
const { snapshot, fieldSchema } = useActionContext();
|
|
const action = fieldSchema?.['x-action'];
|
|
|
|
return currentFields
|
|
?.filter((field) => field?.interface && !field?.isForeignKey && !field?.treeChildren)
|
|
?.map((field) => {
|
|
const interfaceConfig = getInterface(field.interface);
|
|
const schema = {
|
|
type: 'string',
|
|
name: field.name,
|
|
'x-designer': 'FormItem.Designer',
|
|
'x-component': field.interface === 'o2m' && !snapshot ? 'TableField' : 'CollectionField',
|
|
'x-decorator': 'FormItem',
|
|
'x-collection-field': `${name}.${field.name}`,
|
|
'x-component-props': {},
|
|
'x-read-pretty': field?.uiSchema?.['x-read-pretty'],
|
|
};
|
|
// interfaceConfig?.schemaInitialize?.(schema, { field, block: 'Form', readPretty: form.readPretty });
|
|
const resultItem = {
|
|
type: 'item',
|
|
title: field?.uiSchema?.title || field.name,
|
|
component: 'CollectionFieldInitializer',
|
|
remove: removeGridFormItem,
|
|
schemaInitialize: (s) => {
|
|
interfaceConfig?.schemaInitialize?.(s, { field, block, readPretty, action });
|
|
},
|
|
schema,
|
|
} as SchemaInitializerItemOptions;
|
|
if (block == 'Kanban') {
|
|
resultItem['find'] = (schema: Schema, key: string, action: string) => {
|
|
const s = findSchema(schema, 'x-component', block);
|
|
return findSchema(s, key, action);
|
|
};
|
|
}
|
|
|
|
return resultItem;
|
|
});
|
|
};
|
|
|
|
// 筛选表单相关
|
|
export const useFilterFormItemInitializerFields = (options?: any) => {
|
|
const { name, currentFields } = useCollection();
|
|
const { getInterface } = useCollectionManager();
|
|
const form = useForm();
|
|
const { readPretty = form.readPretty, block = 'FilterForm' } = options || {};
|
|
const { snapshot, fieldSchema } = useActionContext();
|
|
const action = fieldSchema?.['x-action'];
|
|
|
|
return currentFields
|
|
?.filter((field) => field?.interface && !field?.isForeignKey && getInterface(field.interface)?.filterable)
|
|
?.map((field) => {
|
|
const interfaceConfig = getInterface(field.interface);
|
|
let schema = {
|
|
type: 'string',
|
|
name: field.name,
|
|
required: false,
|
|
'x-designer': 'FormItem.FilterFormDesigner',
|
|
'x-component': field.interface === 'o2m' && !snapshot ? 'TableField' : 'CollectionField',
|
|
'x-decorator': 'FormItem',
|
|
'x-collection-field': `${name}.${field.name}`,
|
|
'x-component-props': {},
|
|
};
|
|
if (isAssocField(field)) {
|
|
schema = {
|
|
type: 'string',
|
|
name: field.name,
|
|
required: false,
|
|
'x-designer': 'AssociationSelect.FilterDesigner',
|
|
'x-component': 'AssociationSelect',
|
|
'x-decorator': 'FormItem',
|
|
'x-collection-field': `${name}.${field.name}`,
|
|
'x-component-props': field.uiSchema?.['x-component-props'],
|
|
};
|
|
}
|
|
const resultItem = {
|
|
type: 'item',
|
|
title: field?.uiSchema?.title || field.name,
|
|
component: 'CollectionFieldInitializer',
|
|
remove: removeGridFormItem,
|
|
schemaInitialize: (s) => {
|
|
interfaceConfig?.schemaInitialize?.(s, { field, block, readPretty, action });
|
|
},
|
|
schema,
|
|
} as SchemaInitializerItemOptions;
|
|
|
|
return resultItem;
|
|
});
|
|
};
|
|
|
|
export const useAssociatedFormItemInitializerFields = (options?: any) => {
|
|
const { name, fields } = useCollection();
|
|
const { getInterface, getCollectionFields } = useCollectionManager();
|
|
const form = useForm();
|
|
const { readPretty = form.readPretty, block = 'Form' } = options || {};
|
|
const interfaces = block === 'Form' ? ['m2o'] : ['o2o', 'oho', 'obo', 'm2o'];
|
|
const groups = fields
|
|
?.filter((field) => {
|
|
return interfaces.includes(field.interface);
|
|
})
|
|
?.map((field) => {
|
|
const subFields = getCollectionFields(field.target);
|
|
const items = subFields
|
|
?.filter(
|
|
(subField) => subField?.interface && !['subTable'].includes(subField?.interface) && !subField.treeChildren,
|
|
)
|
|
?.map((subField) => {
|
|
const interfaceConfig = getInterface(subField.interface);
|
|
const schema = {
|
|
type: 'string',
|
|
name: `${field.name}.${subField.name}`,
|
|
'x-designer': 'FormItem.Designer',
|
|
'x-component': 'CollectionField',
|
|
'x-read-pretty': readPretty,
|
|
'x-component-props': {
|
|
'pattern-disable': block === 'Form' && readPretty,
|
|
},
|
|
'x-decorator': 'FormItem',
|
|
'x-collection-field': `${name}.${field.name}.${subField.name}`,
|
|
};
|
|
return {
|
|
type: 'item',
|
|
title: subField?.uiSchema?.title || subField.name,
|
|
component: 'CollectionFieldInitializer',
|
|
remove: removeGridFormItem,
|
|
schemaInitialize: (s) => {
|
|
interfaceConfig?.schemaInitialize?.(s, { field: subField, block, readPretty });
|
|
},
|
|
schema,
|
|
} as SchemaInitializerItemOptions;
|
|
});
|
|
|
|
return {
|
|
type: 'subMenu',
|
|
title: field.uiSchema?.title,
|
|
children: items,
|
|
} as SchemaInitializerItemOptions;
|
|
});
|
|
return groups;
|
|
};
|
|
|
|
const getItem = (
|
|
field: FieldOptions,
|
|
schemaName: string,
|
|
collectionName: string,
|
|
getCollectionFields,
|
|
processedCollections: string[],
|
|
) => {
|
|
if (field.interface === 'm2o') {
|
|
if (processedCollections.includes(field.target)) return null;
|
|
|
|
const subFields = getCollectionFields(field.target);
|
|
|
|
return {
|
|
type: 'subMenu',
|
|
title: field.uiSchema?.title,
|
|
children: subFields
|
|
.map((subField) =>
|
|
getItem(subField, `${schemaName}.${subField.name}`, collectionName, getCollectionFields, [
|
|
...processedCollections,
|
|
field.target,
|
|
]),
|
|
)
|
|
.filter(Boolean),
|
|
} as SchemaInitializerItemOptions;
|
|
}
|
|
|
|
if (isAssocField(field)) return null;
|
|
|
|
const schema = {
|
|
type: 'string',
|
|
name: schemaName,
|
|
'x-designer': 'FormItem.FilterFormDesigner',
|
|
'x-designer-props': {
|
|
// 在 useOperatorList 中使用,用于获取对应的操作符列表
|
|
interface: field.interface,
|
|
},
|
|
'x-component': 'CollectionField',
|
|
'x-read-pretty': false,
|
|
'x-decorator': 'FormItem',
|
|
'x-collection-field': `${collectionName}.${schemaName}`,
|
|
};
|
|
|
|
return {
|
|
type: 'item',
|
|
title: field.uiSchema?.title || field.name,
|
|
component: 'CollectionFieldInitializer',
|
|
remove: removeGridFormItem,
|
|
schema,
|
|
} as SchemaInitializerItemOptions;
|
|
};
|
|
|
|
// 筛选表单相关
|
|
export const useFilterAssociatedFormItemInitializerFields = () => {
|
|
const { name, fields } = useCollection();
|
|
const { getCollectionFields } = useCollectionManager();
|
|
const interfaces = ['m2o'];
|
|
const groups = fields
|
|
?.filter((field) => {
|
|
return interfaces.includes(field.interface);
|
|
})
|
|
?.map((field) => getItem(field, field.name, name, getCollectionFields, []));
|
|
return groups;
|
|
};
|
|
|
|
export const useInheritsFormItemInitializerFields = (options?) => {
|
|
const { name } = useCollection();
|
|
const { getInterface, getInheritCollections, getCollection, getParentCollectionFields } = useCollectionManager();
|
|
const inherits = getInheritCollections(name);
|
|
const { snapshot } = useActionContext();
|
|
|
|
return inherits?.map((v) => {
|
|
const fields = getParentCollectionFields(v, name);
|
|
const form = useForm();
|
|
const { readPretty = form.readPretty, block = 'Form' } = options || {};
|
|
const targetCollection = getCollection(v);
|
|
return {
|
|
[targetCollection.title]: fields
|
|
?.filter((field) => field?.interface && !field?.isForeignKey)
|
|
?.map((field) => {
|
|
const interfaceConfig = getInterface(field.interface);
|
|
const schema = {
|
|
type: 'string',
|
|
name: field.name,
|
|
title: field?.uiSchema?.title || field.name,
|
|
'x-designer': 'FormItem.Designer',
|
|
'x-component': field.interface === 'o2m' && !snapshot ? 'TableField' : 'CollectionField',
|
|
'x-decorator': 'FormItem',
|
|
'x-collection-field': `${name}.${field.name}`,
|
|
'x-component-props': {},
|
|
'x-read-pretty': field?.uiSchema?.['x-read-pretty'],
|
|
};
|
|
return {
|
|
type: 'item',
|
|
title: field?.uiSchema?.title || field.name,
|
|
component: 'CollectionFieldInitializer',
|
|
remove: removeGridFormItem,
|
|
schemaInitialize: (s) => {
|
|
interfaceConfig?.schemaInitialize?.(s, { field, block, readPretty });
|
|
},
|
|
schema,
|
|
} as SchemaInitializerItemOptions;
|
|
}),
|
|
};
|
|
});
|
|
};
|
|
|
|
// 筛选表单相关
|
|
export const useFilterInheritsFormItemInitializerFields = (options?) => {
|
|
const { name } = useCollection();
|
|
const { getInterface, getInheritCollections, getCollection, getParentCollectionFields } = useCollectionManager();
|
|
const inherits = getInheritCollections(name);
|
|
const { snapshot } = useActionContext();
|
|
|
|
return inherits?.map((v) => {
|
|
const fields = getParentCollectionFields(v, name);
|
|
const form = useForm();
|
|
const { readPretty = form.readPretty, block = 'Form' } = options || {};
|
|
const targetCollection = getCollection(v);
|
|
return {
|
|
[targetCollection.title]: fields
|
|
?.filter((field) => field?.interface && !field?.isForeignKey && getInterface(field.interface)?.filterable)
|
|
?.map((field) => {
|
|
const interfaceConfig = getInterface(field.interface);
|
|
const schema = {
|
|
type: 'string',
|
|
name: field.name,
|
|
title: field?.uiSchema?.title || field.name,
|
|
required: false,
|
|
'x-designer': 'FormItem.FilterFormDesigner',
|
|
'x-component': field.interface === 'o2m' && !snapshot ? 'TableField' : 'CollectionField',
|
|
'x-decorator': 'FormItem',
|
|
'x-collection-field': `${name}.${field.name}`,
|
|
'x-component-props': {},
|
|
'x-read-pretty': field?.uiSchema?.['x-read-pretty'],
|
|
};
|
|
return {
|
|
type: 'item',
|
|
title: field?.uiSchema?.title || field.name,
|
|
component: 'CollectionFieldInitializer',
|
|
remove: removeGridFormItem,
|
|
schemaInitialize: (s) => {
|
|
interfaceConfig?.schemaInitialize?.(s, { field, block, readPretty });
|
|
},
|
|
schema,
|
|
} as SchemaInitializerItemOptions;
|
|
}),
|
|
};
|
|
});
|
|
};
|
|
export const useCustomFormItemInitializerFields = (options?: any) => {
|
|
const { name, currentFields } = useCollection();
|
|
const { getInterface } = useCollectionManager();
|
|
const form = useForm();
|
|
const { readPretty = form.readPretty, block = 'Form' } = options || {};
|
|
const remove = useRemoveGridFormItem();
|
|
return currentFields
|
|
?.filter((field) => {
|
|
return field?.interface && !field?.uiSchema?.['x-read-pretty'] && field.interface !== 'snapshot';
|
|
})
|
|
?.map((field) => {
|
|
const interfaceConfig = getInterface(field.interface);
|
|
const schema = {
|
|
type: 'string',
|
|
name: field.name,
|
|
title: field?.uiSchema?.title || field.name,
|
|
'x-designer': 'FormItem.Designer',
|
|
'x-component': 'AssignedField',
|
|
'x-decorator': 'FormItem',
|
|
'x-collection-field': `${name}.${field.name}`,
|
|
};
|
|
return {
|
|
type: 'item',
|
|
title: field?.uiSchema?.title || field.name,
|
|
component: 'CollectionFieldInitializer',
|
|
remove: remove,
|
|
schemaInitialize: (s) => {
|
|
interfaceConfig?.schemaInitialize?.(s, { field, block, readPretty });
|
|
},
|
|
schema,
|
|
} as SchemaInitializerItemOptions;
|
|
});
|
|
};
|
|
|
|
export const useCustomBulkEditFormItemInitializerFields = (options?: any) => {
|
|
const { name, fields } = useCollection();
|
|
const { getInterface } = useCollectionManager();
|
|
const form = useForm();
|
|
const { readPretty = form.readPretty, block = 'Form' } = options || {};
|
|
const remove = useRemoveGridFormItem();
|
|
return fields
|
|
?.filter((field) => {
|
|
return field?.interface && !field?.uiSchema?.['x-read-pretty'] && field.interface !== 'snapshot';
|
|
})
|
|
?.map((field) => {
|
|
const interfaceConfig = getInterface(field.interface);
|
|
const schema = {
|
|
type: 'string',
|
|
name: field.name,
|
|
title: field?.uiSchema?.title || field.name,
|
|
'x-designer': 'FormItem.Designer',
|
|
'x-component': 'BulkEditField',
|
|
'x-decorator': 'FormItem',
|
|
'x-collection-field': `${name}.${field.name}`,
|
|
};
|
|
return {
|
|
type: 'item',
|
|
title: field?.uiSchema?.title || field.name,
|
|
component: 'CollectionFieldInitializer',
|
|
remove: remove,
|
|
schemaInitialize: (s) => {
|
|
interfaceConfig?.schemaInitialize?.(s, { field, block, readPretty });
|
|
},
|
|
schema,
|
|
} as SchemaInitializerItemOptions;
|
|
});
|
|
};
|
|
|
|
const findSchema = (schema: Schema, key: string, action: string) => {
|
|
if (!Schema.isSchemaInstance(schema)) return null;
|
|
return schema.reduceProperties((buf, s) => {
|
|
if (s[key] === action) {
|
|
return s;
|
|
}
|
|
const c = findSchema(s, key, action);
|
|
if (c) {
|
|
return c;
|
|
}
|
|
return buf;
|
|
});
|
|
};
|
|
|
|
const removeSchema = (schema, cb) => {
|
|
return cb(schema);
|
|
};
|
|
|
|
const recursiveParent = (schema: Schema) => {
|
|
if (!schema.parent) return null;
|
|
|
|
if (schema.parent['x-initializer']) return schema.parent;
|
|
|
|
return recursiveParent(schema.parent);
|
|
};
|
|
|
|
export const useCurrentSchema = (action: string, key: string, find = findSchema, rm = removeSchema) => {
|
|
let fieldSchema = useFieldSchema();
|
|
if (!fieldSchema?.['x-initializer']) {
|
|
const recursiveInitializerSchema = recursiveParent(fieldSchema);
|
|
if (recursiveInitializerSchema) {
|
|
fieldSchema = recursiveInitializerSchema;
|
|
}
|
|
}
|
|
const { remove } = useDesignable();
|
|
const schema = find(fieldSchema, key, action);
|
|
const ctx = useContext(BlockRequestContext);
|
|
|
|
return {
|
|
schema,
|
|
exists: !!schema,
|
|
remove() {
|
|
if (ctx.field) {
|
|
ctx.field.data = ctx.field.data || {};
|
|
ctx.field.data.activeFields = ctx.field.data.activeFields || new Set();
|
|
ctx.field.data.activeFields.delete(schema.name);
|
|
}
|
|
schema && rm(schema, remove);
|
|
},
|
|
};
|
|
};
|
|
|
|
export const useRecordCollectionDataSourceItems = (
|
|
componentName,
|
|
item = null,
|
|
collectionName = null,
|
|
resourceName = null,
|
|
) => {
|
|
const { t } = useTranslation();
|
|
const collection = useCollection();
|
|
const { getTemplatesByCollection } = useSchemaTemplateManager();
|
|
const templates = getTemplatesByCollection(collectionName || collection.name)
|
|
.filter((template) => {
|
|
return componentName && template.componentName === componentName;
|
|
})
|
|
.filter((template) => {
|
|
return ['FormItem', 'ReadPrettyFormItem'].includes(componentName) || template.resourceName === resourceName;
|
|
});
|
|
if (!templates.length) {
|
|
return [];
|
|
}
|
|
const index = 0;
|
|
return [
|
|
{
|
|
key: `${collectionName || componentName}_table_blank`,
|
|
type: 'item',
|
|
name: collection.name,
|
|
title: t('Blank block'),
|
|
item,
|
|
},
|
|
{
|
|
type: 'divider',
|
|
},
|
|
{
|
|
key: `${collectionName || componentName}_table_subMenu_${index}_copy`,
|
|
type: 'subMenu',
|
|
name: 'copy',
|
|
title: t('Duplicate template'),
|
|
children: templates.map((template) => {
|
|
const templateName = ['FormItem', 'ReadPrettyFormItem'].includes(template?.componentName)
|
|
? `${template?.name} ${t('(Fields only)')}`
|
|
: template?.name;
|
|
return {
|
|
type: 'item',
|
|
mode: 'copy',
|
|
name: collection.name,
|
|
template,
|
|
item,
|
|
title: templateName || t('Untitled'),
|
|
};
|
|
}),
|
|
},
|
|
{
|
|
key: `${collectionName || componentName}_table_subMenu_${index}_ref`,
|
|
type: 'subMenu',
|
|
name: 'ref',
|
|
title: t('Reference template'),
|
|
children: templates.map((template) => {
|
|
const templateName = ['FormItem', 'ReadPrettyFormItem'].includes(template?.componentName)
|
|
? `${template?.name} ${t('(Fields only)')}`
|
|
: template?.name;
|
|
return {
|
|
type: 'item',
|
|
mode: 'reference',
|
|
name: collection.name,
|
|
template,
|
|
item,
|
|
title: templateName || t('Untitled'),
|
|
};
|
|
}),
|
|
},
|
|
];
|
|
};
|
|
|
|
export const useCollectionDataSourceItems = (componentName) => {
|
|
const { t } = useTranslation();
|
|
const { collections } = useCollectionManager();
|
|
const { getTemplatesByCollection } = useSchemaTemplateManager();
|
|
const [selected, setSelected] = useState([]);
|
|
const [value, onChange] = useState(null);
|
|
const clearKeywords = () => {
|
|
setSelected([]);
|
|
onChange(null);
|
|
};
|
|
return [
|
|
{
|
|
key: 'tableBlock',
|
|
type: 'itemGroup',
|
|
title: React.createElement(SelectCollection, {
|
|
value,
|
|
onChange,
|
|
setSelected,
|
|
}),
|
|
children: collections
|
|
?.filter((item) => {
|
|
const b = !value || selected.includes(item.name);
|
|
if (item.inherit) {
|
|
return false;
|
|
} else if (item.autoGenId === false && !item.fields.find((v) => v.primaryKey)) {
|
|
return false;
|
|
} else if (['Kanban', 'FormItem'].includes(componentName) && item.template === 'view') {
|
|
return false;
|
|
} else {
|
|
return b && !(item?.isThrough && item?.autoCreate);
|
|
}
|
|
})
|
|
?.map((item, index) => {
|
|
const templates = getTemplatesByCollection(item.name).filter((template) => {
|
|
return (
|
|
componentName &&
|
|
template.componentName === componentName &&
|
|
(!template.resourceName || template.resourceName === item.name)
|
|
);
|
|
});
|
|
if (!templates.length) {
|
|
return {
|
|
type: 'item',
|
|
name: item.name,
|
|
title: item.title,
|
|
clearKeywords,
|
|
};
|
|
}
|
|
return {
|
|
key: `${componentName}_table_subMenu_${index}`,
|
|
type: 'subMenu',
|
|
name: `${item.name}_${index}`,
|
|
title: item.title,
|
|
children: [
|
|
{
|
|
type: 'item',
|
|
name: item.name,
|
|
title: t('Blank block'),
|
|
clearKeywords,
|
|
},
|
|
{
|
|
type: 'divider',
|
|
},
|
|
{
|
|
key: `${componentName}_table_subMenu_${index}_copy`,
|
|
type: 'subMenu',
|
|
name: 'copy',
|
|
title: t('Duplicate template'),
|
|
children: templates.map((template) => {
|
|
const templateName =
|
|
template?.componentName === 'FormItem' ? `${template?.name} ${t('(Fields only)')}` : template?.name;
|
|
return {
|
|
type: 'item',
|
|
mode: 'copy',
|
|
name: item.name,
|
|
template,
|
|
clearKeywords,
|
|
title: templateName || t('Untitled'),
|
|
};
|
|
}),
|
|
},
|
|
{
|
|
key: `${componentName}_table_subMenu_${index}_ref`,
|
|
type: 'subMenu',
|
|
name: 'ref',
|
|
title: t('Reference template'),
|
|
children: templates.map((template) => {
|
|
const templateName =
|
|
template?.componentName === 'FormItem' ? `${template?.name} ${t('(Fields only)')}` : template?.name;
|
|
return {
|
|
type: 'item',
|
|
mode: 'reference',
|
|
clearKeywords,
|
|
name: item.name,
|
|
template,
|
|
title: templateName || t('Untitled'),
|
|
};
|
|
}),
|
|
},
|
|
],
|
|
};
|
|
}),
|
|
},
|
|
];
|
|
};
|
|
|
|
export const createDetailsBlockSchema = (options) => {
|
|
const {
|
|
formItemInitializers = 'ReadPrettyFormItemInitializers',
|
|
actionInitializers = 'DetailsActionInitializers',
|
|
collection,
|
|
association,
|
|
resource,
|
|
template,
|
|
...others
|
|
} = options;
|
|
const resourceName = resource || association || collection;
|
|
const schema: ISchema = {
|
|
type: 'void',
|
|
'x-acl-action': `${resourceName}:view`,
|
|
'x-decorator': 'DetailsBlockProvider',
|
|
'x-decorator-props': {
|
|
resource: resourceName,
|
|
collection,
|
|
association,
|
|
readPretty: true,
|
|
action: 'list',
|
|
params: {
|
|
pageSize: 1,
|
|
},
|
|
// useParams: '{{ useParamsFromRecord }}',
|
|
...others,
|
|
},
|
|
'x-designer': 'DetailsDesigner',
|
|
'x-component': 'CardItem',
|
|
properties: {
|
|
[uid()]: {
|
|
type: 'void',
|
|
'x-component': 'Details',
|
|
'x-read-pretty': true,
|
|
'x-component-props': {
|
|
useProps: '{{ useDetailsBlockProps }}',
|
|
},
|
|
properties: {
|
|
[uid()]: {
|
|
type: 'void',
|
|
'x-initializer': actionInitializers,
|
|
'x-component': 'ActionBar',
|
|
'x-component-props': {
|
|
style: {
|
|
marginBottom: 24,
|
|
},
|
|
},
|
|
properties: {},
|
|
},
|
|
grid: template || {
|
|
type: 'void',
|
|
'x-component': 'Grid',
|
|
'x-initializer': formItemInitializers,
|
|
properties: {},
|
|
},
|
|
pagination: {
|
|
type: 'void',
|
|
'x-component': 'Pagination',
|
|
'x-component-props': {
|
|
useProps: '{{ useDetailsPaginationProps }}',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
};
|
|
console.log(JSON.stringify(schema, null, 2));
|
|
return schema;
|
|
};
|
|
|
|
export const createFormBlockSchema = (options) => {
|
|
const {
|
|
formItemInitializers = 'FormItemInitializers',
|
|
actionInitializers = 'FormActionInitializers',
|
|
collection,
|
|
resource,
|
|
association,
|
|
action,
|
|
template,
|
|
...others
|
|
} = options;
|
|
const resourceName = resource || association || collection;
|
|
const schema: ISchema = {
|
|
type: 'void',
|
|
'x-acl-action-props': {
|
|
skipScopeCheck: !action,
|
|
},
|
|
'x-acl-action': action ? `${resourceName}:update` : `${resourceName}:create`,
|
|
'x-decorator': 'FormBlockProvider',
|
|
'x-decorator-props': {
|
|
...others,
|
|
action,
|
|
resource: resourceName,
|
|
collection,
|
|
association,
|
|
// action: 'get',
|
|
// useParams: '{{ useParamsFromRecord }}',
|
|
},
|
|
'x-designer': 'FormV2.Designer',
|
|
'x-component': 'CardItem',
|
|
properties: {
|
|
[uid()]: {
|
|
type: 'void',
|
|
'x-component': 'FormV2',
|
|
'x-component-props': {
|
|
useProps: '{{ useFormBlockProps }}',
|
|
},
|
|
properties: {
|
|
grid: template || {
|
|
type: 'void',
|
|
'x-component': 'Grid',
|
|
'x-initializer': formItemInitializers,
|
|
properties: {},
|
|
},
|
|
actions: {
|
|
type: 'void',
|
|
'x-initializer': actionInitializers,
|
|
'x-component': 'ActionBar',
|
|
'x-component-props': {
|
|
layout: 'one-column',
|
|
style: {
|
|
marginTop: 24,
|
|
},
|
|
},
|
|
properties: {},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
};
|
|
console.log(JSON.stringify(schema, null, 2));
|
|
return schema;
|
|
};
|
|
|
|
export const createFilterFormBlockSchema = (options) => {
|
|
const {
|
|
formItemInitializers = 'FilterFormItemInitializers',
|
|
actionInitializers = 'FilterFormActionInitializers',
|
|
collection,
|
|
resource,
|
|
association,
|
|
action,
|
|
template,
|
|
...others
|
|
} = options;
|
|
const resourceName = resource || association || collection;
|
|
const schema: ISchema = {
|
|
type: 'void',
|
|
'x-decorator': 'FilterFormBlockProvider',
|
|
'x-decorator-props': {
|
|
...others,
|
|
action,
|
|
resource: resourceName,
|
|
collection,
|
|
association,
|
|
},
|
|
'x-designer': 'FormV2.FilterDesigner',
|
|
'x-component': 'CardItem',
|
|
// 保存当前筛选区块所能过滤的数据区块
|
|
'x-filter-targets': [],
|
|
// 用于存储用户设置的每个字段的运算符,目前仅筛选表单区块支持自定义
|
|
'x-filter-operators': {},
|
|
properties: {
|
|
[uid()]: {
|
|
type: 'void',
|
|
'x-component': 'FormV2',
|
|
'x-component-props': {
|
|
useProps: '{{ useFormBlockProps }}',
|
|
},
|
|
properties: {
|
|
grid: template || {
|
|
type: 'void',
|
|
'x-component': 'Grid',
|
|
'x-initializer': formItemInitializers,
|
|
properties: {},
|
|
},
|
|
actions: {
|
|
type: 'void',
|
|
'x-initializer': actionInitializers,
|
|
'x-component': 'ActionBar',
|
|
'x-component-props': {
|
|
layout: 'one-column',
|
|
style: {
|
|
float: 'right',
|
|
},
|
|
},
|
|
properties: {},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
};
|
|
return schema;
|
|
};
|
|
|
|
export const createReadPrettyFormBlockSchema = (options) => {
|
|
const {
|
|
formItemInitializers = 'ReadPrettyFormItemInitializers',
|
|
actionInitializers = 'ReadPrettyFormActionInitializers',
|
|
collection,
|
|
association,
|
|
resource,
|
|
template,
|
|
...others
|
|
} = options;
|
|
const resourceName = resource || association || collection;
|
|
const schema: ISchema = {
|
|
type: 'void',
|
|
'x-acl-action': `${resourceName}:get`,
|
|
'x-decorator': 'FormBlockProvider',
|
|
'x-decorator-props': {
|
|
resource: resourceName,
|
|
collection,
|
|
association,
|
|
readPretty: true,
|
|
action: 'get',
|
|
useParams: '{{ useParamsFromRecord }}',
|
|
...others,
|
|
},
|
|
'x-designer': 'FormV2.ReadPrettyDesigner',
|
|
'x-component': 'CardItem',
|
|
properties: {
|
|
[uid()]: {
|
|
type: 'void',
|
|
'x-component': 'FormV2',
|
|
'x-read-pretty': true,
|
|
'x-component-props': {
|
|
useProps: '{{ useFormBlockProps }}',
|
|
},
|
|
properties: {
|
|
actions: {
|
|
type: 'void',
|
|
'x-initializer': actionInitializers,
|
|
'x-component': 'ActionBar',
|
|
'x-component-props': {
|
|
style: {
|
|
marginBottom: 24,
|
|
},
|
|
},
|
|
properties: {},
|
|
},
|
|
grid: template || {
|
|
type: 'void',
|
|
'x-component': 'Grid',
|
|
'x-initializer': formItemInitializers,
|
|
properties: {},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
};
|
|
// console.log(JSON.stringify(schema, null, 2));
|
|
return schema;
|
|
};
|
|
|
|
export const createTableBlockSchema = (options) => {
|
|
const {
|
|
collection,
|
|
resource,
|
|
rowKey,
|
|
tableActionInitializers,
|
|
tableColumnInitializers,
|
|
tableActionColumnInitializers,
|
|
tableBlockProvider,
|
|
disableTemplate,
|
|
TableBlockDesigner,
|
|
blockType,
|
|
pageSize = 20,
|
|
...others
|
|
} = options;
|
|
const schema: ISchema = {
|
|
type: 'void',
|
|
'x-decorator': tableBlockProvider ?? 'TableBlockProvider',
|
|
'x-acl-action': `${resource || collection}:list`,
|
|
'x-decorator-props': {
|
|
collection,
|
|
resource: resource || collection,
|
|
action: 'list',
|
|
params: {
|
|
pageSize,
|
|
},
|
|
rowKey,
|
|
showIndex: true,
|
|
dragSort: false,
|
|
disableTemplate: disableTemplate ?? false,
|
|
blockType,
|
|
...others,
|
|
},
|
|
'x-designer': TableBlockDesigner ?? 'TableBlockDesigner',
|
|
'x-component': 'CardItem',
|
|
'x-filter-targets': [],
|
|
properties: {
|
|
actions: {
|
|
type: 'void',
|
|
'x-initializer': tableActionInitializers ?? 'TableActionInitializers',
|
|
'x-component': 'ActionBar',
|
|
'x-component-props': {
|
|
style: {
|
|
marginBottom: 16,
|
|
},
|
|
},
|
|
properties: {},
|
|
},
|
|
[uid()]: {
|
|
type: 'array',
|
|
'x-initializer': tableColumnInitializers ?? 'TableColumnInitializers',
|
|
'x-component': 'TableV2',
|
|
'x-component-props': {
|
|
rowKey: 'id',
|
|
rowSelection: {
|
|
type: 'checkbox',
|
|
},
|
|
useProps: '{{ useTableBlockProps }}',
|
|
},
|
|
properties: {
|
|
actions: {
|
|
type: 'void',
|
|
title: '{{ t("Actions") }}',
|
|
'x-action-column': 'actions',
|
|
'x-decorator': 'TableV2.Column.ActionBar',
|
|
'x-component': 'TableV2.Column',
|
|
'x-designer': 'TableV2.ActionColumnDesigner',
|
|
'x-initializer': tableActionColumnInitializers ?? 'TableActionColumnInitializers',
|
|
properties: {
|
|
actions: {
|
|
type: 'void',
|
|
'x-decorator': 'DndContext',
|
|
'x-component': 'Space',
|
|
'x-component-props': {
|
|
split: '|',
|
|
},
|
|
properties: {},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
};
|
|
// console.log(JSON.stringify(schema, null, 2));
|
|
return schema;
|
|
};
|
|
|
|
export const createCollapseBlockSchema = (options) => {
|
|
const { collection, blockType } = options;
|
|
const schema: ISchema = {
|
|
type: 'void',
|
|
'x-decorator': 'AssociationFilter.Provider',
|
|
'x-decorator-props': {
|
|
collection,
|
|
blockType,
|
|
associationFilterStyle: {
|
|
width: '100%',
|
|
},
|
|
},
|
|
'x-designer': 'AssociationFilter.BlockDesigner',
|
|
'x-component': 'CardItem',
|
|
'x-filter-targets': [],
|
|
properties: {
|
|
[uid()]: {
|
|
type: 'void',
|
|
'x-action': 'associateFilter',
|
|
'x-initializer': 'AssociationFilter.FilterBlockInitializer',
|
|
'x-component': 'AssociationFilter',
|
|
properties: {},
|
|
},
|
|
},
|
|
};
|
|
|
|
return schema;
|
|
};
|
|
|
|
export const createTableSelectorSchema = (options) => {
|
|
const { collection, resource, rowKey, ...others } = options;
|
|
const schema: ISchema = {
|
|
type: 'void',
|
|
'x-acl-action': `${resource || collection}:list`,
|
|
'x-decorator': 'TableSelectorProvider',
|
|
'x-decorator-props': {
|
|
collection,
|
|
resource: resource || collection,
|
|
action: 'list',
|
|
params: {
|
|
pageSize: 20,
|
|
},
|
|
rowKey,
|
|
...others,
|
|
},
|
|
'x-designer': 'TableSelectorDesigner',
|
|
'x-component': 'BlockItem',
|
|
properties: {
|
|
actions: {
|
|
type: 'void',
|
|
'x-initializer': 'TableActionInitializers',
|
|
'x-component': 'ActionBar',
|
|
'x-component-props': {
|
|
style: {
|
|
marginBottom: 16,
|
|
},
|
|
},
|
|
properties: {},
|
|
},
|
|
value: {
|
|
type: 'array',
|
|
'x-initializer': 'TableColumnInitializers',
|
|
'x-component': 'TableV2.Selector',
|
|
'x-component-props': {
|
|
rowSelection: {
|
|
type: 'checkbox',
|
|
},
|
|
useProps: '{{ useTableSelectorProps }}',
|
|
},
|
|
properties: {},
|
|
},
|
|
},
|
|
};
|
|
console.log(JSON.stringify(schema, null, 2));
|
|
return schema;
|
|
};
|
|
|
|
export const createCalendarBlockSchema = (options) => {
|
|
const { collection, resource, fieldNames, ...others } = options;
|
|
const schema: ISchema = {
|
|
type: 'void',
|
|
'x-acl-action': `${resource || collection}:list`,
|
|
'x-decorator': 'CalendarBlockProvider',
|
|
'x-decorator-props': {
|
|
collection: collection,
|
|
resource: resource || collection,
|
|
action: 'list',
|
|
fieldNames: {
|
|
id: 'id',
|
|
...fieldNames,
|
|
},
|
|
params: {
|
|
paginate: false,
|
|
},
|
|
...others,
|
|
},
|
|
'x-designer': 'CalendarV2.Designer',
|
|
'x-component': 'CardItem',
|
|
properties: {
|
|
[uid()]: {
|
|
type: 'void',
|
|
'x-component': 'CalendarV2',
|
|
'x-component-props': {
|
|
useProps: '{{ useCalendarBlockProps }}',
|
|
},
|
|
properties: {
|
|
toolBar: {
|
|
type: 'void',
|
|
'x-component': 'CalendarV2.ActionBar',
|
|
'x-component-props': {
|
|
style: {
|
|
marginBottom: 24,
|
|
},
|
|
},
|
|
'x-initializer': 'CalendarActionInitializers',
|
|
properties: {},
|
|
},
|
|
event: {
|
|
type: 'void',
|
|
'x-component': 'CalendarV2.Event',
|
|
properties: {
|
|
drawer: {
|
|
type: 'void',
|
|
'x-component': 'Action.Drawer',
|
|
'x-component-props': {
|
|
className: 'nb-action-popup',
|
|
},
|
|
title: '{{ t("View record") }}',
|
|
properties: {
|
|
tabs: {
|
|
type: 'void',
|
|
'x-component': 'Tabs',
|
|
'x-component-props': {},
|
|
'x-initializer': 'TabPaneInitializers',
|
|
'x-initializer-props': {
|
|
gridInitializer: 'RecordBlockInitializers',
|
|
},
|
|
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-props': {
|
|
actionInitializers: 'CalendarFormActionInitializers',
|
|
},
|
|
'x-initializer': 'RecordBlockInitializers',
|
|
properties: {},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
};
|
|
console.log(JSON.stringify(schema, null, 2));
|
|
return schema;
|
|
};
|
|
|
|
export const createKanbanBlockSchema = (options) => {
|
|
const { collection, resource, groupField, ...others } = options;
|
|
const schema: ISchema = {
|
|
type: 'void',
|
|
'x-acl-action': `${resource || collection}:list`,
|
|
'x-decorator': 'KanbanBlockProvider',
|
|
'x-decorator-props': {
|
|
collection: collection,
|
|
resource: resource || collection,
|
|
action: 'list',
|
|
groupField,
|
|
params: {
|
|
paginate: false,
|
|
},
|
|
...others,
|
|
},
|
|
'x-designer': 'Kanban.Designer',
|
|
'x-component': 'CardItem',
|
|
properties: {
|
|
actions: {
|
|
type: 'void',
|
|
'x-initializer': 'KanbanActionInitializers',
|
|
'x-component': 'ActionBar',
|
|
'x-component-props': {
|
|
style: {
|
|
marginBottom: 16,
|
|
},
|
|
},
|
|
properties: {},
|
|
},
|
|
[uid()]: {
|
|
type: 'array',
|
|
'x-component': 'Kanban',
|
|
'x-component-props': {
|
|
useProps: '{{ useKanbanBlockProps }}',
|
|
},
|
|
properties: {
|
|
card: {
|
|
type: 'void',
|
|
'x-read-pretty': true,
|
|
'x-label-disabled': true,
|
|
'x-decorator': 'BlockItem',
|
|
'x-component': 'Kanban.Card',
|
|
'x-component-props': {
|
|
openMode: 'drawer',
|
|
},
|
|
'x-designer': 'Kanban.Card.Designer',
|
|
properties: {
|
|
grid: {
|
|
type: 'void',
|
|
'x-component': 'Grid',
|
|
'x-component-props': { dndContext: false },
|
|
},
|
|
},
|
|
},
|
|
cardViewer: {
|
|
type: 'void',
|
|
title: '{{ t("View") }}',
|
|
'x-designer': 'Action.Designer',
|
|
'x-component': 'Kanban.CardViewer',
|
|
'x-action': 'view',
|
|
'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': {},
|
|
'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',
|
|
properties: {},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
};
|
|
return schema;
|
|
};
|