Feat/collection templates (#1124)
* feat: add collection templates * feat: collection templates * feat: collection templates * feat: collection templates * feat: collection templates * feat: collection templates * feat: calendar collection template * feat: no id does not support sorting * feat: collection template edit * feat: collectiom templates code improve * feat: collection template supports configurable field interface * feat: collection template supports configurable field interface * feat: establish relation field when there is no id * feat: collection templates * feat: collection templates locale * feat: calendar collection * feat: calendar collection default fields * feat: code optimization * feat: code optimization * feat: code optimization * feat: collectin template fix * feat: add sample-custom-collection-template * feat: code optimization * feat: code optimization * feat: code optimization * feat: code optimization * feat: import code * feat: collection template local * feat: code opimization * feat: code opimization * feat: code opimization * feat: code opimization * feat: code opimization * feat: collection template local * feat: collection template local * fix(collection-manager): exclude reverse parameters when overriding * feat: update docs * feat: disabled * feat: improve code * feat: update submodule * feat: submodules: true * fix: token * fix: with ssh-key * fix: update dockerfile * fix: ci * fix: ci * fix: ci * fix: ci * fix: --no-verify-access * fix: ci * fix: ci * fix: ci * fix: missing env * fix: env Co-authored-by: chenos <chenlinxh@gmail.com> Co-authored-by: chareice <chareice@live.com>
This commit is contained in:
parent
f7f58bfe99
commit
4085ed0db7
@ -24,6 +24,9 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
ssh-key: ${{ secrets.SUBMODULE_SSH_KEY }}
|
||||
submodules: true
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
- name: Set up Docker Buildx
|
||||
@ -51,7 +54,7 @@ jobs:
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
context: .
|
||||
file: Dockerfile
|
||||
file: Dockerfile.acr
|
||||
build-args: |
|
||||
VERDACCIO_URL=http://localhost:4873/
|
||||
COMMIT_HASH=${GITHUB_SHA}
|
||||
|
64
Dockerfile.acr
Normal file
64
Dockerfile.acr
Normal file
@ -0,0 +1,64 @@
|
||||
FROM node:16 as builder
|
||||
ARG VERDACCIO_URL=http://host.docker.internal:10104/
|
||||
ARG COMIT_HASH
|
||||
|
||||
RUN apt-get update && apt-get install -y jq
|
||||
WORKDIR /tmp
|
||||
COPY . /tmp
|
||||
RUN npx npm-cli-adduser --username test --password test -e test@nocobase.com -r $VERDACCIO_URL
|
||||
RUN cd /tmp && \
|
||||
NEWVERSION="$(cat lerna.json | jq '.version' | tr -d '"').$(date +%s)" \
|
||||
&& tmp=$(mktemp) \
|
||||
&& jq ".version = \"${NEWVERSION}\"" lerna.json > "$tmp" && mv "$tmp" lerna.json
|
||||
RUN yarn install && yarn nocobase install && yarn pm add graph-collection-manager && yarn build
|
||||
|
||||
RUN git checkout -b release \
|
||||
&& yarn version:alpha -y
|
||||
|
||||
RUN cd packages/pro-plugins && git checkout -b release \
|
||||
&& git config user.email "test@mail.com" \
|
||||
&& git config user.name "test" && git add . \
|
||||
&& git commit -m "chore(versions): test publish packages xxx"
|
||||
|
||||
RUN git config user.email "test@mail.com" \
|
||||
&& git config user.name "test" && git add . \
|
||||
&& git commit -m "chore(versions): test publish packages xxx" \
|
||||
&& git submodule update --init --recursive -- packages/pro-plugins
|
||||
|
||||
RUN yarn release:force --no-verify-access --no-git-reset --registry $VERDACCIO_URL
|
||||
|
||||
RUN yarn config set registry $VERDACCIO_URL
|
||||
WORKDIR /app
|
||||
RUN cd /app \
|
||||
&& yarn config set network-timeout 600000 -g \
|
||||
&& yarn create nocobase-app my-nocobase-app -a \
|
||||
-e APP_ENV=production \
|
||||
-e PLUGIN_PACKAGE_PREFIX=@nocobase/plugin-,@nocobase/preset-,@nocobase/plugin-pro- \
|
||||
-e PRESET_NOCOBASE_PLUGINS=error-handler,collection-manager,ui-schema-storage,ui-routes-storage,file-manager,system-settings,verification,users,acl,china-region,workflow,client,export,import,audit-logs,graph-collection-manager \
|
||||
&& cd /app/my-nocobase-app \
|
||||
&& yarn install --production \
|
||||
&& yarn add @nocobase/plugin-pro-graph-collection-manager -W
|
||||
|
||||
RUN cd /app \
|
||||
&& rm -rf my-nocobase-app/packages/app/client/src/.umi \
|
||||
&& rm -rf nocobase.tar.gz \
|
||||
&& find ./my-nocobase-app/node_modules/china-division/dist -name '*.csv' -delete \
|
||||
&& find ./my-nocobase-app/node_modules/china-division/dist -name '*.sqlite' -delete \
|
||||
&& tar -zcf ./nocobase.tar.gz -C /app/my-nocobase-app .
|
||||
|
||||
|
||||
FROM node:16-stretch-slim
|
||||
RUN apt-get update && apt-get install -y nginx
|
||||
|
||||
RUN rm -rf /etc/nginx/sites-enabled/default
|
||||
COPY ./docker/nocobase/nocobase.conf /etc/nginx/sites-enabled/nocobase.conf
|
||||
COPY --from=builder /app/nocobase.tar.gz /app/nocobase.tar.gz
|
||||
|
||||
WORKDIR /app/nocobase
|
||||
|
||||
RUN mkdir -p /app/nocobase/storage/uploads/ && echo "$COMIT_HASH" >> /app/nocobase/storage/uploads/COMIT_HASH
|
||||
|
||||
COPY ./docker/nocobase/docker-entrypoint.sh /app/
|
||||
|
||||
CMD ["/app/docker-entrypoint.sh"]
|
||||
|
@ -1,47 +0,0 @@
|
||||
FROM node:16 as builder
|
||||
ARG VERDACCIO_URL=https://pkgs.nocobase.com/
|
||||
|
||||
RUN apt-get update && apt-get install -y jq
|
||||
WORKDIR /tmp
|
||||
COPY . /tmp
|
||||
RUN npx npm-cli-adduser --username test --password test -e test@nocobase.com -r $VERDACCIO_URL
|
||||
RUN cd /tmp && \
|
||||
NEWVERSION="$(cat lerna.json | jq '.version' | tr -d '"').$(date +%s)" \
|
||||
&& tmp=$(mktemp) \
|
||||
&& jq ".version = \"${NEWVERSION}\"" lerna.json > "$tmp" && mv "$tmp" lerna.json
|
||||
RUN yarn install && yarn build
|
||||
|
||||
RUN git checkout -b release \
|
||||
&& yarn version:alpha -y \
|
||||
&& git config user.email "test@mail.com" \
|
||||
&& git config user.name "test" && git add . \
|
||||
&& git commit -m "chore(versions): test publish packages xxx" \
|
||||
&& yarn release:force --registry $VERDACCIO_URL
|
||||
|
||||
RUN yarn config set registry $VERDACCIO_URL
|
||||
WORKDIR /app
|
||||
RUN cd /app \
|
||||
&& yarn create nocobase-app my-nocobase-app -a -e APP_ENV=production \
|
||||
&& cd /app/my-nocobase-app \
|
||||
&& yarn install --production
|
||||
|
||||
RUN cd /app \
|
||||
&& rm -rf my-nocobase-app/packages/app/client/src/.umi \
|
||||
&& rm -rf nocobase.tar.gz \
|
||||
&& find ./my-nocobase-app/node_modules/china-division/dist -name '*.csv' -delete \
|
||||
&& find ./my-nocobase-app/node_modules/china-division/dist -name '*.sqlite' -delete \
|
||||
&& tar -zcf ./nocobase.tar.gz -C /app/my-nocobase-app .
|
||||
|
||||
|
||||
FROM node:16-stretch-slim
|
||||
RUN apt-get update && apt-get install -y nginx
|
||||
|
||||
RUN rm -rf /etc/nginx/sites-enabled/default
|
||||
COPY ./docker/nocobase/nocobase.conf /etc/nginx/sites-enabled/nocobase.conf
|
||||
COPY --from=builder /app/nocobase.tar.gz /app/nocobase.tar.gz
|
||||
|
||||
WORKDIR /app/nocobase
|
||||
|
||||
COPY ./docker/nocobase/docker-entrypoint.sh /app/
|
||||
|
||||
CMD ["/app/docker-entrypoint.sh"]
|
79
docs/zh-CN/welcome/release/v08-1-collection-templates.md
Normal file
79
docs/zh-CN/welcome/release/v08-1-collection-templates.md
Normal file
@ -0,0 +1,79 @@
|
||||
# v0.8.1: Collection 模板
|
||||
|
||||
<img src="./v08-1-collection-templates/v08-1-collection-templates.jpg">
|
||||
|
||||
## 为什么需要 Collection 模板?
|
||||
|
||||
待补充
|
||||
|
||||
## 配置参数说明
|
||||
|
||||
```ts
|
||||
interface ICollectionTemplate {
|
||||
name: string;
|
||||
title?: string;
|
||||
/** 排序 */
|
||||
order?: number;
|
||||
/** 默认配置 */
|
||||
default?: CollectionOptions;
|
||||
/** UI 可配置的 CollectionOptions 参数(添加或编辑的 Collection 表单的字段) */
|
||||
configurableProperties?: Record<string, ISchema>;
|
||||
/** 当前模板可用的字段类型 */
|
||||
availableFieldInterfaces?: AvailableFieldInterfacesInclude | AvailableFieldInterfacesExclude;
|
||||
}
|
||||
|
||||
interface AvailableFieldInterfacesInclude {
|
||||
include?: any[];
|
||||
}
|
||||
|
||||
interface AvailableFieldInterfacesExclude {
|
||||
exclude?: any[];
|
||||
}
|
||||
|
||||
interface CollectionOptions {
|
||||
/**
|
||||
* 自动生成 id
|
||||
* @default true
|
||||
* */
|
||||
autoGenId?: boolean;
|
||||
/** 创建人 */
|
||||
createdBy?: boolean;
|
||||
/** 最后更新人 */
|
||||
updatedBy?: boolean;
|
||||
/** 创建日期 */
|
||||
createdAt?: boolean;
|
||||
/** 更新日期 */
|
||||
updatedAt?: boolean;
|
||||
/** 可排序 */
|
||||
sortable?: boolean;
|
||||
/* 树结构 */
|
||||
tree?: string;
|
||||
/* 日志 */
|
||||
logging?: boolean;
|
||||
/** 继承 */
|
||||
inherits: string | string[];
|
||||
/* 字段列表 */
|
||||
fields?: FieldOptions[];
|
||||
}
|
||||
```
|
||||
|
||||
## 示例
|
||||
|
||||
创建时都不需要 autoGenId,并且只提供 title 和 name 配置项
|
||||
|
||||
```ts
|
||||
import { collectionConfigurableProperties } from '@nocobase/client';
|
||||
|
||||
{
|
||||
default: {
|
||||
autoGenId: false,
|
||||
fields: [],
|
||||
},
|
||||
configurableProperties: {
|
||||
...collectionConfigurableProperties('name', 'title'),
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
完整插件示例参考:[samples/custom-collection-template](https://github.com/nocobase/nocobase/tree/feat/collection-templates/packages/samples/custom-collection-template)
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 177 KiB |
@ -1,20 +1,24 @@
|
||||
import { Spin } from 'antd';
|
||||
import React, { useContext, useState } from 'react';
|
||||
import { keyBy } from 'lodash';
|
||||
import { useAPIClient, useRequest } from '../api-client';
|
||||
import { CollectionManagerSchemaComponentProvider } from './CollectionManagerSchemaComponentProvider';
|
||||
import { CollectionManagerContext } from './context';
|
||||
import * as defaultInterfaces from './interfaces';
|
||||
import { CollectionManagerOptions } from './types';
|
||||
import { templateOptions } from '../collection-manager/Configuration/templates';
|
||||
|
||||
export const CollectionManagerProvider: React.FC<CollectionManagerOptions> = (props) => {
|
||||
const { service, interfaces, collections = [], refreshCM } = props;
|
||||
const { service, interfaces, collections = [], refreshCM, templates } = props;
|
||||
const defaultTemplates = keyBy(templateOptions(), (item) => item.name);
|
||||
const ctx = useContext(CollectionManagerContext);
|
||||
return (
|
||||
<CollectionManagerContext.Provider
|
||||
value={{
|
||||
...ctx,
|
||||
service,
|
||||
interfaces: { ...defaultInterfaces, ...interfaces, ...ctx.interfaces },
|
||||
interfaces: { ...defaultInterfaces, ...interfaces },
|
||||
templates: { ...defaultTemplates, ...templates },
|
||||
collections,
|
||||
refreshCM,
|
||||
}}
|
||||
|
@ -17,6 +17,10 @@ import {
|
||||
OverridingCollectionField,
|
||||
ViewCollectionField,
|
||||
ViewFieldAction,
|
||||
AddCollection,
|
||||
AddCollectionAction,
|
||||
EditCollection,
|
||||
EditCollectionAction,
|
||||
} from './Configuration';
|
||||
|
||||
const schema: ISchema = {
|
||||
@ -53,6 +57,10 @@ export const CollectionManagerPane = () => {
|
||||
ConfigurationTable,
|
||||
AddFieldAction,
|
||||
AddCollectionField,
|
||||
AddCollection,
|
||||
AddCollectionAction,
|
||||
EditCollection,
|
||||
EditCollectionAction,
|
||||
EditFieldAction,
|
||||
EditCollectionField,
|
||||
OverridingCollectionField,
|
||||
@ -99,6 +107,8 @@ export const CollectionManagerShortcut2 = () => {
|
||||
EditFieldAction,
|
||||
OverridingFieldAction,
|
||||
ViewFieldAction,
|
||||
AddCollectionAction,
|
||||
EditCollectionAction,
|
||||
}}
|
||||
/>
|
||||
</ActionContext.Provider>
|
||||
|
@ -0,0 +1,282 @@
|
||||
import { DownOutlined, PlusOutlined } from '@ant-design/icons';
|
||||
import { ArrayTable } from '@formily/antd';
|
||||
import { ISchema, useForm } from '@formily/react';
|
||||
import { uid } from '@formily/shared';
|
||||
import { Button, Dropdown, Menu } from 'antd';
|
||||
import { cloneDeep } from 'lodash';
|
||||
import React, { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useRequest } from '../../api-client';
|
||||
import { RecordProvider, useRecord } from '../../record-provider';
|
||||
import { ActionContext, SchemaComponent, useActionContext, useCompile } from '../../schema-component';
|
||||
import { useCancelAction } from '../action-hooks';
|
||||
import { useCollectionManager } from '../hooks';
|
||||
import { useResourceActionContext, useResourceContext } from '../ResourceActionProvider';
|
||||
import * as components from './components';
|
||||
import { templateOptions } from './templates';
|
||||
|
||||
const getSchema = (schema, record: any, compile): ISchema => {
|
||||
if (!schema) {
|
||||
return;
|
||||
}
|
||||
|
||||
const properties = cloneDeep(schema.configurableProperties) as any;
|
||||
|
||||
if (schema.hasDefaultValue === true) {
|
||||
properties['defaultValue'] = cloneDeep(schema.default.uiSchema);
|
||||
properties['defaultValue']['title'] = compile('{{ t("Default value") }}');
|
||||
properties['defaultValue']['x-decorator'] = 'FormItem';
|
||||
}
|
||||
const initialValue: any = {
|
||||
name: `f_${uid()}`,
|
||||
template: schema.name,
|
||||
...cloneDeep(schema.default),
|
||||
};
|
||||
if (initialValue.reverseField) {
|
||||
initialValue.reverseField.name = `f_${uid()}`;
|
||||
}
|
||||
return {
|
||||
type: 'object',
|
||||
properties: {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
'x-component': 'Action.Drawer',
|
||||
'x-component-props': {
|
||||
getContainer: '{{ getContainer }}',
|
||||
},
|
||||
'x-decorator': 'Form',
|
||||
'x-decorator-props': {
|
||||
useValues(options) {
|
||||
return useRequest(
|
||||
() =>
|
||||
Promise.resolve({
|
||||
data: initialValue,
|
||||
}),
|
||||
options,
|
||||
);
|
||||
},
|
||||
},
|
||||
title: '{{ t("Create collection") }}',
|
||||
properties: {
|
||||
summary: {
|
||||
type: 'void',
|
||||
'x-component': 'FieldSummary',
|
||||
'x-component-props': {
|
||||
schemaKey: schema.name,
|
||||
},
|
||||
},
|
||||
// @ts-ignore
|
||||
...properties,
|
||||
footer: {
|
||||
type: 'void',
|
||||
'x-component': 'Action.Drawer.Footer',
|
||||
properties: {
|
||||
action1: {
|
||||
title: '{{ t("Cancel") }}',
|
||||
'x-component': 'Action',
|
||||
'x-component-props': {
|
||||
useAction: '{{ useCancelAction }}',
|
||||
},
|
||||
},
|
||||
action2: {
|
||||
title: '{{ t("Submit") }}',
|
||||
'x-component': 'Action',
|
||||
'x-component-props': {
|
||||
type: 'primary',
|
||||
useAction: () => useCreateCollection(),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const useDefaultCollectionFields = (values) => {
|
||||
let defaults = values.fields ? [...values.fields] : [];
|
||||
const { autoGenId = true, createdAt = true, createdBy = true, updatedAt = true, updatedBy = true } = values;
|
||||
if (autoGenId) {
|
||||
const pk = values.fields.find((f) => f.primaryKey);
|
||||
if (!pk) {
|
||||
defaults.push({
|
||||
name: 'id',
|
||||
type: 'bigInt',
|
||||
autoIncrement: true,
|
||||
primaryKey: true,
|
||||
allowNull: false,
|
||||
uiSchema: { type: 'number', title: '{{t("ID")}}', 'x-component': 'InputNumber', 'x-read-pretty': true },
|
||||
interface: 'id',
|
||||
});
|
||||
}
|
||||
}
|
||||
if (createdAt) {
|
||||
defaults.push({
|
||||
name: 'createdAt',
|
||||
interface: 'createdAt',
|
||||
type: 'date',
|
||||
field: 'createdAt',
|
||||
uiSchema: {
|
||||
type: 'datetime',
|
||||
title: '{{t("Created at")}}',
|
||||
'x-component': 'DatePicker',
|
||||
'x-component-props': {},
|
||||
'x-read-pretty': true,
|
||||
},
|
||||
});
|
||||
}
|
||||
if (createdBy) {
|
||||
defaults.push({
|
||||
name: 'createdBy',
|
||||
interface: 'createdBy',
|
||||
type: 'belongsTo',
|
||||
target: 'users',
|
||||
foreignKey: 'createdById',
|
||||
uiSchema: {
|
||||
type: 'object',
|
||||
title: '{{t("Created by")}}',
|
||||
'x-component': 'RecordPicker',
|
||||
'x-component-props': {
|
||||
fieldNames: {
|
||||
value: 'id',
|
||||
label: 'nickname',
|
||||
},
|
||||
},
|
||||
'x-read-pretty': true,
|
||||
},
|
||||
});
|
||||
}
|
||||
if (updatedAt) {
|
||||
defaults.push({
|
||||
type: 'date',
|
||||
field: 'updatedAt',
|
||||
name: 'updatedAt',
|
||||
interface: 'updatedAt',
|
||||
uiSchema: {
|
||||
type: 'string',
|
||||
title: '{{t("Last updated at")}}',
|
||||
'x-component': 'DatePicker',
|
||||
'x-component-props': {},
|
||||
'x-read-pretty': true,
|
||||
},
|
||||
});
|
||||
}
|
||||
if (updatedBy) {
|
||||
defaults.push({
|
||||
type: 'belongsTo',
|
||||
target: 'users',
|
||||
foreignKey: 'updatedById',
|
||||
name: 'updatedBy',
|
||||
interface: 'updatedBy',
|
||||
uiSchema: {
|
||||
type: 'object',
|
||||
title: '{{t("Last updated by")}}',
|
||||
'x-component': 'RecordPicker',
|
||||
'x-component-props': {
|
||||
fieldNames: {
|
||||
value: 'id',
|
||||
label: 'nickname',
|
||||
},
|
||||
},
|
||||
'x-read-pretty': true,
|
||||
},
|
||||
});
|
||||
}
|
||||
// 其他
|
||||
return defaults;
|
||||
};
|
||||
|
||||
const useCreateCollection = () => {
|
||||
const form = useForm();
|
||||
const { refreshCM } = useCollectionManager();
|
||||
const ctx = useActionContext();
|
||||
const { refresh } = useResourceActionContext();
|
||||
const { resource } = useResourceContext();
|
||||
return {
|
||||
async run() {
|
||||
await form.submit();
|
||||
const values = cloneDeep(form.values);
|
||||
const fields = useDefaultCollectionFields(values);
|
||||
console.log(fields);
|
||||
if (values.autoCreateReverseField) {
|
||||
} else {
|
||||
delete values.reverseField;
|
||||
}
|
||||
delete values.id;
|
||||
delete values.autoCreateReverseField;
|
||||
await resource.create({
|
||||
values: {
|
||||
logging: true,
|
||||
...values,
|
||||
fields,
|
||||
},
|
||||
});
|
||||
ctx.setVisible(false);
|
||||
await form.reset();
|
||||
refresh();
|
||||
await refreshCM();
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const AddCollection = (props) => {
|
||||
const record = useRecord();
|
||||
return <AddCollectionAction item={record} {...props} />;
|
||||
};
|
||||
|
||||
export const AddCollectionAction = (props) => {
|
||||
const { scope, getContainer, item: record, children, trigger, align } = props;
|
||||
const { getTemplate } = useCollectionManager();
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [schema, setSchema] = useState({});
|
||||
const compile = useCompile();
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<RecordProvider record={record}>
|
||||
<ActionContext.Provider value={{ visible, setVisible }}>
|
||||
<Dropdown
|
||||
getPopupContainer={getContainer}
|
||||
trigger={trigger}
|
||||
align={align}
|
||||
overlay={
|
||||
<Menu
|
||||
style={{
|
||||
maxHeight: '60vh',
|
||||
overflow: 'auto',
|
||||
}}
|
||||
onClick={(info) => {
|
||||
const schema = getSchema(getTemplate(info.key), record, compile);
|
||||
setSchema(schema);
|
||||
setVisible(true);
|
||||
}}
|
||||
>
|
||||
{templateOptions().map((option) => {
|
||||
return <Menu.Item key={option.name}>{compile(option.title)}</Menu.Item>;
|
||||
})}
|
||||
</Menu>
|
||||
}
|
||||
>
|
||||
{children || (
|
||||
<Button icon={<PlusOutlined />} type={'primary'}>
|
||||
{t('Create collection')} <DownOutlined />
|
||||
</Button>
|
||||
)}
|
||||
</Dropdown>
|
||||
<SchemaComponent
|
||||
schema={schema}
|
||||
components={{ ...components, ArrayTable }}
|
||||
scope={{
|
||||
getContainer,
|
||||
useCancelAction,
|
||||
createOnly: true,
|
||||
useCreateCollection,
|
||||
record,
|
||||
showReverseFieldConfig: true,
|
||||
...scope,
|
||||
}}
|
||||
/>
|
||||
</ActionContext.Provider>
|
||||
</RecordProvider>
|
||||
);
|
||||
};
|
@ -9,12 +9,12 @@ import { useTranslation } from 'react-i18next';
|
||||
import { useRequest } from '../../api-client';
|
||||
import { RecordProvider, useRecord } from '../../record-provider';
|
||||
import { ActionContext, SchemaComponent, useActionContext, useCompile } from '../../schema-component';
|
||||
import { useCancelAction, useCreateAction } from '../action-hooks';
|
||||
import { useCancelAction } from '../action-hooks';
|
||||
import { useCollectionManager } from '../hooks';
|
||||
import { IField } from '../interfaces/types';
|
||||
import { useResourceActionContext, useResourceContext } from '../ResourceActionProvider';
|
||||
import * as components from './components';
|
||||
import { getOptions } from './interfaces';
|
||||
import { options } from './interfaces';
|
||||
|
||||
const getSchema = (schema: IField, record: any, compile) => {
|
||||
if (!schema) {
|
||||
@ -114,7 +114,6 @@ export const useCollectionFieldFormValues = () => {
|
||||
|
||||
const useCreateCollectionField = () => {
|
||||
const form = useForm();
|
||||
const { run } = useCreateAction();
|
||||
const { refreshCM } = useCollectionManager();
|
||||
const ctx = useActionContext();
|
||||
const { refresh } = useResourceActionContext();
|
||||
@ -144,11 +143,44 @@ export const AddCollectionField = (props) => {
|
||||
|
||||
export const AddFieldAction = (props) => {
|
||||
const { scope, getContainer, item: record, children, trigger, align } = props;
|
||||
const { getInterface } = useCollectionManager();
|
||||
const { getInterface, getTemplate } = useCollectionManager();
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [schema, setSchema] = useState({});
|
||||
const compile = useCompile();
|
||||
const { t } = useTranslation();
|
||||
const getFieldOptions = () => {
|
||||
const { availableFieldInterfaces } = getTemplate(record.template) || {};
|
||||
const { exclude, include } = availableFieldInterfaces || {};
|
||||
const optionArr = [];
|
||||
options.forEach((v) => {
|
||||
if (v.key === 'systemInfo') {
|
||||
optionArr.push({
|
||||
...v,
|
||||
children: v.children.filter((v) => {
|
||||
if (v.value === 'id') {
|
||||
return typeof record['autoGenId'] === 'boolean' ? record['autoGenId'] : true;
|
||||
} else {
|
||||
return typeof record[v.value] === 'boolean' ? record[v.value] : true;
|
||||
}
|
||||
}),
|
||||
});
|
||||
} else {
|
||||
const children = v.children.filter((v) => {
|
||||
if (include?.length) {
|
||||
return include.includes(v.value);
|
||||
} else if (exclude?.length) {
|
||||
return !exclude.includes(v.value);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
optionArr.push({
|
||||
...v,
|
||||
children,
|
||||
});
|
||||
}
|
||||
});
|
||||
return optionArr;
|
||||
};
|
||||
return (
|
||||
<RecordProvider record={record}>
|
||||
<ActionContext.Provider value={{ visible, setVisible }}>
|
||||
@ -170,7 +202,7 @@ export const AddFieldAction = (props) => {
|
||||
}
|
||||
}}
|
||||
>
|
||||
{getOptions().map((option) => {
|
||||
{getFieldOptions().map((option) => {
|
||||
return (
|
||||
option.children.length > 0 && (
|
||||
<Menu.ItemGroup key={option.label} title={compile(option.label)}>
|
||||
|
@ -1,13 +1,12 @@
|
||||
import { useForm } from '@formily/react';
|
||||
import { action } from '@formily/reactive';
|
||||
import { uid } from '@formily/shared';
|
||||
import React, { useContext, useEffect, useRef, useState } from 'react';
|
||||
import React, { useContext, useRef, useState } from 'react';
|
||||
import { CollectionFieldsTable } from '.';
|
||||
import { useRequest } from '../../api-client';
|
||||
import { useCurrentAppInfo } from '../../appInfo';
|
||||
import { useRecord } from '../../record-provider';
|
||||
import { SchemaComponent, SchemaComponentContext, useActionContext, useCompile } from '../../schema-component';
|
||||
import { useCancelAction, useUpdateCollectionActionAndRefreshCM } from '../action-hooks';
|
||||
import { SchemaComponent, SchemaComponentContext, useCompile } from '../../schema-component';
|
||||
import { useCancelAction } from '../action-hooks';
|
||||
import { useCollectionManager } from '../hooks/useCollectionManager';
|
||||
import { DataSourceContext } from '../sub-table';
|
||||
import { AddSubFieldAction } from './AddSubFieldAction';
|
||||
@ -25,109 +24,6 @@ const useAsyncDataSource = (service: any) => (field: any) => {
|
||||
);
|
||||
};
|
||||
|
||||
const useCollectionValues = (options) => {
|
||||
const { visible } = useActionContext();
|
||||
const result = useRequest(
|
||||
() =>
|
||||
Promise.resolve({
|
||||
data: {
|
||||
name: `t_${uid()}`,
|
||||
createdBy: true,
|
||||
updatedBy: true,
|
||||
sortable: true,
|
||||
logging: true,
|
||||
fields: [
|
||||
{
|
||||
name: 'id',
|
||||
type: 'bigInt',
|
||||
autoIncrement: true,
|
||||
primaryKey: true,
|
||||
allowNull: false,
|
||||
uiSchema: { type: 'number', title: '{{t("ID")}}', 'x-component': 'InputNumber', 'x-read-pretty': true },
|
||||
interface: 'id',
|
||||
},
|
||||
{
|
||||
interface: 'createdAt',
|
||||
type: 'date',
|
||||
field: 'createdAt',
|
||||
name: 'createdAt',
|
||||
uiSchema: {
|
||||
type: 'datetime',
|
||||
title: '{{t("Created at")}}',
|
||||
'x-component': 'DatePicker',
|
||||
'x-component-props': {},
|
||||
'x-read-pretty': true,
|
||||
},
|
||||
},
|
||||
{
|
||||
interface: 'createdBy',
|
||||
type: 'belongsTo',
|
||||
target: 'users',
|
||||
foreignKey: 'createdById',
|
||||
name: 'createdBy',
|
||||
uiSchema: {
|
||||
type: 'object',
|
||||
title: '{{t("Created by")}}',
|
||||
'x-component': 'RecordPicker',
|
||||
'x-component-props': {
|
||||
fieldNames: {
|
||||
value: 'id',
|
||||
label: 'nickname',
|
||||
},
|
||||
},
|
||||
'x-read-pretty': true,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'date',
|
||||
field: 'updatedAt',
|
||||
name: 'updatedAt',
|
||||
interface: 'updatedAt',
|
||||
uiSchema: {
|
||||
type: 'string',
|
||||
title: '{{t("Last updated at")}}',
|
||||
'x-component': 'DatePicker',
|
||||
'x-component-props': {},
|
||||
'x-read-pretty': true,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'belongsTo',
|
||||
target: 'users',
|
||||
foreignKey: 'updatedById',
|
||||
name: 'updatedBy',
|
||||
interface: 'updatedBy',
|
||||
uiSchema: {
|
||||
type: 'object',
|
||||
title: '{{t("Last updated by")}}',
|
||||
'x-component': 'RecordPicker',
|
||||
'x-component-props': {
|
||||
fieldNames: {
|
||||
value: 'id',
|
||||
label: 'nickname',
|
||||
},
|
||||
},
|
||||
'x-read-pretty': true,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
{
|
||||
...options,
|
||||
manual: true,
|
||||
},
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (visible) {
|
||||
result.run();
|
||||
}
|
||||
}, [visible]);
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
const useSelectedRowKeys = () => {
|
||||
const [selectedRowKeys, setSelectedRowKeys] = useState([]);
|
||||
return [selectedRowKeys, setSelectedRowKeys];
|
||||
@ -205,13 +101,11 @@ export const ConfigurationTable = () => {
|
||||
useDestroySubField,
|
||||
useBulkDestroySubField,
|
||||
useSelectedRowKeys,
|
||||
useCollectionValues,
|
||||
useAsyncDataSource,
|
||||
loadCollections,
|
||||
useCurrentFields,
|
||||
useNewId,
|
||||
useCancelAction,
|
||||
useUpdateCollectionActionAndRefreshCM,
|
||||
enableInherits: database?.dialect === 'postgres',
|
||||
}}
|
||||
/>
|
||||
|
@ -0,0 +1,161 @@
|
||||
import { ArrayTable } from '@formily/antd';
|
||||
import { ISchema, useForm } from '@formily/react';
|
||||
import { uid } from '@formily/shared';
|
||||
import { omit } from 'lodash';
|
||||
import cloneDeep from 'lodash/cloneDeep';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useRequest } from '../../api-client';
|
||||
import { RecordProvider, useRecord } from '../../record-provider';
|
||||
import { ActionContext, SchemaComponent, useActionContext, useCompile } from '../../schema-component';
|
||||
import { useCancelAction } from '../action-hooks';
|
||||
import { useCollectionManager } from '../hooks';
|
||||
import { IField } from '../interfaces/types';
|
||||
import { useResourceActionContext, useResourceContext } from '../ResourceActionProvider';
|
||||
import * as components from './components';
|
||||
|
||||
const getSchema = (schema: IField, record: any, compile, getContainer): ISchema => {
|
||||
if (!schema) {
|
||||
return;
|
||||
}
|
||||
const properties = (cloneDeep(schema.configurableProperties) as any) || {
|
||||
title: {
|
||||
'x-component': 'CollectionField',
|
||||
'x-decorator': 'FormItem',
|
||||
},
|
||||
name: {
|
||||
'x-component': 'CollectionField',
|
||||
'x-decorator': 'FormItem',
|
||||
'x-disabled': true,
|
||||
},
|
||||
};
|
||||
properties.name['x-disabled'] = true;
|
||||
if (schema.hasDefaultValue === true) {
|
||||
properties['defaultValue'] = cloneDeep(schema.default.uiSchema);
|
||||
properties['defaultValue']['title'] = compile('{{ t("Default value") }}');
|
||||
properties['defaultValue']['x-decorator'] = 'FormItem';
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'object',
|
||||
properties: {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
'x-component': 'Action.Drawer',
|
||||
'x-decorator': 'Form',
|
||||
'x-decorator-props': {
|
||||
useValues: '{{ useValuesFromRecord }}',
|
||||
},
|
||||
title: '{{ t("Edit collection") }}',
|
||||
properties: {
|
||||
...properties,
|
||||
footer: {
|
||||
type: 'void',
|
||||
'x-component': 'Action.Drawer.Footer',
|
||||
properties: {
|
||||
action1: {
|
||||
title: '{{ t("Cancel") }}',
|
||||
'x-component': 'Action',
|
||||
'x-component-props': {
|
||||
useAction: '{{ useCancelAction }}',
|
||||
},
|
||||
},
|
||||
action2: {
|
||||
title: '{{ t("Submit") }}',
|
||||
'x-component': 'Action',
|
||||
'x-component-props': {
|
||||
type: 'primary',
|
||||
useAction: '{{ useUpdateCollectionActionAndRefreshCM }}',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const useValuesFromRecord = (options) => {
|
||||
const record = useRecord();
|
||||
const result = useRequest(() => Promise.resolve({ data: { autoGenId: true, ...record } }), {
|
||||
...options,
|
||||
manual: true,
|
||||
});
|
||||
const ctx = useActionContext();
|
||||
useEffect(() => {
|
||||
if (ctx.visible) {
|
||||
result.run();
|
||||
}
|
||||
}, [ctx.visible]);
|
||||
return result;
|
||||
};
|
||||
|
||||
export const useUpdateCollectionActionAndRefreshCM = (options) => {
|
||||
const { refreshCM } = useCollectionManager();
|
||||
const form = useForm();
|
||||
const ctx = useActionContext();
|
||||
const { refresh } = useResourceActionContext();
|
||||
const { resource, targetKey } = useResourceContext();
|
||||
const { [targetKey]: filterByTk } = useRecord();
|
||||
return {
|
||||
async run() {
|
||||
await form.submit();
|
||||
await resource.update({ filterByTk, values: omit(form.values, ['fields']) });
|
||||
ctx.setVisible(false);
|
||||
await form.reset();
|
||||
refresh();
|
||||
await refreshCM();
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const EditCollection = (props) => {
|
||||
const record = useRecord();
|
||||
return <EditCollectionAction item={record} {...props} />;
|
||||
};
|
||||
|
||||
export const EditCollectionAction = (props) => {
|
||||
const { scope, getContainer, item: record, children } = props;
|
||||
const { getTemplate } = useCollectionManager();
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [schema, setSchema] = useState({});
|
||||
const { t } = useTranslation();
|
||||
const compile = useCompile();
|
||||
|
||||
return (
|
||||
<RecordProvider record={record}>
|
||||
<ActionContext.Provider value={{ visible, setVisible }}>
|
||||
<a
|
||||
onClick={async () => {
|
||||
const templateConf = getTemplate(record.template);
|
||||
const schema = getSchema(
|
||||
{
|
||||
...templateConf,
|
||||
},
|
||||
record,
|
||||
compile,
|
||||
getContainer,
|
||||
);
|
||||
setSchema(schema);
|
||||
setVisible(true);
|
||||
}}
|
||||
>
|
||||
{children || t('Edit')}
|
||||
</a>
|
||||
<SchemaComponent
|
||||
schema={schema}
|
||||
components={{ ...components, ArrayTable }}
|
||||
scope={{
|
||||
getContainer,
|
||||
useValuesFromRecord,
|
||||
useUpdateCollectionActionAndRefreshCM,
|
||||
useCancelAction,
|
||||
createOnly: false,
|
||||
...scope,
|
||||
}}
|
||||
/>
|
||||
</ActionContext.Provider>
|
||||
</RecordProvider>
|
||||
);
|
||||
};
|
@ -0,0 +1,14 @@
|
||||
import { observer } from '@formily/react';
|
||||
import { Tag } from 'antd';
|
||||
import React from 'react';
|
||||
import { useCompile } from '../../../schema-component';
|
||||
import { useCollectionManager } from '../../hooks';
|
||||
|
||||
export const CollectionTemplate = observer((props: any) => {
|
||||
const { value } = props;
|
||||
const { getTemplate } = useCollectionManager();
|
||||
const compile = useCompile();
|
||||
const schema = getTemplate(value);
|
||||
|
||||
return <Tag>{compile(schema?.title||'{{t("General collection")}}')}</Tag>;
|
||||
});
|
@ -1,15 +1,17 @@
|
||||
import { registerValidateFormats } from '@formily/core';
|
||||
import { exp } from 'mathjs';
|
||||
|
||||
export * from './AddFieldAction';
|
||||
export * from './ConfigurationTable';
|
||||
export * from './EditFieldAction';
|
||||
export * from './interfaces';
|
||||
export * from './components';
|
||||
export * from './templates';
|
||||
export * from './CollectionFieldsTable';
|
||||
export * from './schemas/collections'
|
||||
export * from './OverridingCollectionField'
|
||||
export * from './ViewInheritedField'
|
||||
export * from './schemas/collections';
|
||||
export * from './OverridingCollectionField';
|
||||
export * from './ViewInheritedField';
|
||||
export * from './AddCollectionAction';
|
||||
export * from './EditCollectionAction';
|
||||
|
||||
registerValidateFormats({
|
||||
uid: /^[A-Za-z0-9][A-Za-z0-9_-]*$/,
|
||||
|
@ -35,6 +35,7 @@ export const getOptions = () => {
|
||||
return Object.keys(groupLabels).map((groupName) => {
|
||||
return {
|
||||
label: groupLabels[groupName],
|
||||
key: groupName,
|
||||
children: Object.keys(fields[groupName] || {})
|
||||
.map((type) => {
|
||||
const field = fields[groupName][type];
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { ISchema, Schema } from '@formily/react';
|
||||
import { i18n } from '../../../i18n';
|
||||
import { CollectionOptions } from '../../types';
|
||||
import { CollectionTemplate } from '../components/CollectionTemplate';
|
||||
import { collectionFieldSchema } from './collectionFields';
|
||||
|
||||
const compile = (source) => {
|
||||
@ -35,6 +36,16 @@ export const collection: CollectionOptions = {
|
||||
'{{t("Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.")}}',
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'string',
|
||||
name: 'template',
|
||||
interface: 'input',
|
||||
uiSchema: {
|
||||
title: '{{ t("Collection Template") }}',
|
||||
type: 'string',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'hasMany',
|
||||
name: 'fields',
|
||||
@ -60,85 +71,6 @@ export const collection: CollectionOptions = {
|
||||
],
|
||||
};
|
||||
|
||||
export const createCollectionProperties = {
|
||||
title: {
|
||||
'x-component': 'CollectionField',
|
||||
'x-decorator': 'FormItem',
|
||||
},
|
||||
name: {
|
||||
'x-component': 'CollectionField',
|
||||
'x-decorator': 'FormItem',
|
||||
'x-validator': 'uid',
|
||||
},
|
||||
inherits: {
|
||||
'x-component': 'CollectionField',
|
||||
'x-decorator': 'FormItem',
|
||||
'x-visible': '{{ enableInherits}}',
|
||||
'x-reactions': ['{{useAsyncDataSource(loadCollections)}}'],
|
||||
},
|
||||
footer: {
|
||||
type: 'void',
|
||||
'x-component': 'Action.Drawer.Footer',
|
||||
properties: {
|
||||
action1: {
|
||||
title: '{{ t("Cancel") }}',
|
||||
'x-component': 'Action',
|
||||
'x-component-props': {
|
||||
useAction: '{{ cm.useCancelAction }}',
|
||||
},
|
||||
},
|
||||
action2: {
|
||||
title: '{{ t("Submit") }}',
|
||||
'x-component': 'Action',
|
||||
'x-component-props': {
|
||||
type: 'primary',
|
||||
useAction: '{{ cm.useCreateActionAndRefreshCM }}',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const editCollectionProperties = {
|
||||
title: {
|
||||
'x-component': 'CollectionField',
|
||||
'x-decorator': 'FormItem',
|
||||
},
|
||||
name: {
|
||||
'x-component': 'CollectionField',
|
||||
'x-decorator': 'FormItem',
|
||||
'x-disabled': true,
|
||||
},
|
||||
inherits: {
|
||||
'x-component': 'CollectionField',
|
||||
'x-decorator': 'FormItem',
|
||||
'x-disabled': true,
|
||||
'x-visible': '{{ enableInherits}}',
|
||||
'x-reactions': ['{{useAsyncDataSource(loadCollections)}}'],
|
||||
},
|
||||
footer: {
|
||||
type: 'void',
|
||||
'x-component': 'Action.Drawer.Footer',
|
||||
properties: {
|
||||
action1: {
|
||||
title: '{{ t("Cancel") }}',
|
||||
'x-component': 'Action',
|
||||
'x-component-props': {
|
||||
useAction: '{{ useCancelAction }}',
|
||||
},
|
||||
},
|
||||
action2: {
|
||||
title: '{{ t("Submit") }}',
|
||||
'x-component': 'Action',
|
||||
'x-component-props': {
|
||||
type: 'primary',
|
||||
useAction: '{{ useUpdateCollectionActionAndRefreshCM }}',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const collectionSchema: ISchema = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
@ -190,6 +122,7 @@ export const collectionSchema: ISchema = {
|
||||
title: '{{ t("Delete") }}',
|
||||
'x-component': 'Action',
|
||||
'x-component-props': {
|
||||
icon: 'DeleteOutlined',
|
||||
useAction: '{{ cm.useBulkDestroyActionAndRefreshCM }}',
|
||||
confirm: {
|
||||
title: "{{t('Delete record')}}",
|
||||
@ -200,22 +133,10 @@ export const collectionSchema: ISchema = {
|
||||
create: {
|
||||
type: 'void',
|
||||
title: '{{ t("Create collection") }}',
|
||||
'x-component': 'Action',
|
||||
'x-component': 'AddCollection',
|
||||
'x-component-props': {
|
||||
type: 'primary',
|
||||
},
|
||||
properties: {
|
||||
drawer: {
|
||||
type: 'void',
|
||||
title: '{{ t("Create collection") }}',
|
||||
'x-component': 'Action.Drawer',
|
||||
'x-decorator': 'Form',
|
||||
'x-decorator-props': {
|
||||
useValues: '{{ useCollectionValues }}',
|
||||
},
|
||||
properties: createCollectionProperties,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -255,6 +176,18 @@ export const collectionSchema: ISchema = {
|
||||
},
|
||||
},
|
||||
column3: {
|
||||
type: 'void',
|
||||
'x-decorator': 'Table.Column.Decorator',
|
||||
'x-component': 'Table.Column',
|
||||
title: '{{t("Collection template")}}',
|
||||
properties: {
|
||||
template: {
|
||||
'x-component': CollectionTemplate,
|
||||
'x-read-pretty': true,
|
||||
},
|
||||
},
|
||||
},
|
||||
column4: {
|
||||
type: 'void',
|
||||
title: '{{ t("Actions") }}',
|
||||
'x-component': 'Table.Column',
|
||||
@ -294,22 +227,10 @@ export const collectionSchema: ISchema = {
|
||||
update: {
|
||||
type: 'void',
|
||||
title: '{{ t("Edit") }}',
|
||||
'x-component': 'Action.Link',
|
||||
'x-component': 'EditCollection',
|
||||
'x-component-props': {
|
||||
type: 'primary',
|
||||
},
|
||||
properties: {
|
||||
drawer: {
|
||||
type: 'void',
|
||||
'x-component': 'Action.Drawer',
|
||||
'x-decorator': 'Form',
|
||||
'x-decorator-props': {
|
||||
useValues: '{{ cm.useValuesFromRecord }}',
|
||||
},
|
||||
title: '{{ t("Edit collection") }}',
|
||||
properties: editCollectionProperties,
|
||||
},
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
type: 'void',
|
||||
|
@ -0,0 +1,23 @@
|
||||
import { ISchema } from '@formily/react';
|
||||
import * as types from '../templates';
|
||||
|
||||
export const templates = new Map<string, ISchema>();
|
||||
|
||||
const collectionTemplates: any = {};
|
||||
|
||||
export function registerTemplate(key: string, schema: any) {
|
||||
collectionTemplates[key] = schema;
|
||||
}
|
||||
|
||||
Object.keys(types).forEach((type) => {
|
||||
const schema = types[type];
|
||||
registerTemplate(schema.name || 'others', { order: 0, ...schema });
|
||||
});
|
||||
export const templateOptions = () =>
|
||||
Object.keys(collectionTemplates)
|
||||
.sort((a, b) => {
|
||||
return collectionTemplates[a].order - collectionTemplates[b].order;
|
||||
})
|
||||
.map((templace) => {
|
||||
return collectionTemplates[templace];
|
||||
});
|
@ -259,39 +259,6 @@ export const useBulkDestroyAction = () => {
|
||||
};
|
||||
};
|
||||
|
||||
export const useUpdateCollectionActionAndRefreshCM = (options) => {
|
||||
const { refreshCM } = useCollectionManager();
|
||||
const form = useForm();
|
||||
const ctx = useActionContext();
|
||||
const { refresh } = useResourceActionContext();
|
||||
const { resource, targetKey } = useResourceContext();
|
||||
const { [targetKey]: filterByTk } = useRecord();
|
||||
return {
|
||||
async run() {
|
||||
await form.submit();
|
||||
await resource.update({ filterByTk, values: omit(form.values, ['fields']) });
|
||||
ctx.setVisible(false);
|
||||
await form.reset();
|
||||
refresh();
|
||||
await refreshCM();
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const useValuesFromRecord = (options) => {
|
||||
const record = useRecord();
|
||||
const result = useRequest(() => Promise.resolve({ data: record }), {
|
||||
...options,
|
||||
manual: true,
|
||||
});
|
||||
const ctx = useActionContext();
|
||||
useEffect(() => {
|
||||
if (ctx.visible) {
|
||||
result.run();
|
||||
}
|
||||
}, [ctx.visible]);
|
||||
return result;
|
||||
};
|
||||
|
||||
export const useValuesFromRA = (options) => {
|
||||
const ctx = useResourceActionContext();
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { clone } from '@formily/shared';
|
||||
import { reduce, unionBy, uniq } from 'lodash';
|
||||
import { useContext } from 'react';
|
||||
import { reduce, unionBy,uniq } from 'lodash';
|
||||
import { CollectionManagerContext } from '../context';
|
||||
import { CollectionFieldOptions } from '../types';
|
||||
|
||||
export const useCollectionManager = () => {
|
||||
const { refreshCM, service, interfaces, collections } = useContext(CollectionManagerContext);
|
||||
const { refreshCM, service, interfaces, collections, templates } = useContext(CollectionManagerContext);
|
||||
const getInheritedFields = (name) => {
|
||||
const inheritKeys = getInheritCollections(name);
|
||||
const inheritedFields = reduce(
|
||||
@ -22,7 +22,7 @@ export const useCollectionManager = () => {
|
||||
const getCollectionFields = (name: string): CollectionFieldOptions[] => {
|
||||
const currentFields = collections?.find((collection) => collection.name === name)?.fields;
|
||||
const inheritedFields = getInheritedFields(name);
|
||||
const totalFields = unionBy(currentFields?.concat(inheritedFields) || [], 'name').filter((v:any) => {
|
||||
const totalFields = unionBy(currentFields?.concat(inheritedFields) || [], 'name').filter((v: any) => {
|
||||
return !v.isForeignKey;
|
||||
});
|
||||
return totalFields;
|
||||
@ -122,6 +122,9 @@ export const useCollectionManager = () => {
|
||||
getInterface(name: string) {
|
||||
return interfaces[name] ? clone(interfaces[name]) : null;
|
||||
},
|
||||
getTemplate(name: string = 'general') {
|
||||
return templates[name] ? clone(templates[name] || templates['general']) : null;
|
||||
},
|
||||
getParentCollectionFields: (parentCollection, currentCollection) => {
|
||||
const currentFields = collections?.find((collection) => collection.name === currentCollection)?.fields;
|
||||
const parentFields = collections?.find((collection) => collection.name === parentCollection)?.fields;
|
||||
|
@ -12,5 +12,7 @@ export * from './hooks';
|
||||
export * as interfacesProperties from './interfaces/properties';
|
||||
export * from './interfaces/types';
|
||||
export * from './ResourceActionProvider';
|
||||
export { getConfigurableProperties } from './templates/properties';
|
||||
export * from './templates/types';
|
||||
export * from './types';
|
||||
|
||||
|
@ -60,6 +60,7 @@ export const constraintsProps = {
|
||||
title: '{{t("ON DELETE")}}',
|
||||
required: true,
|
||||
default: 'SET NULL',
|
||||
'x-disabled': '{{ !createOnly }}',
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Select',
|
||||
enum: [
|
||||
|
@ -0,0 +1,37 @@
|
||||
import { getConfigurableProperties } from './properties';
|
||||
import { ICollectionTemplate } from './types';
|
||||
|
||||
export const calendar: ICollectionTemplate = {
|
||||
name: 'calendar',
|
||||
title: '{{t("Calendar collection")}}',
|
||||
order: 2,
|
||||
color: 'orange',
|
||||
default: {
|
||||
fields: [
|
||||
{
|
||||
name: 'cron',
|
||||
type: 'string',
|
||||
uiSchema: {
|
||||
type: 'string',
|
||||
title: '{{t("Cron")}}',
|
||||
'x-component': 'Select',
|
||||
enum: [
|
||||
{ value: '0 0 * * *', label: '每天' },
|
||||
{ value: '0 0 ? * 1', label: '每个星期一' },
|
||||
{ value: '0 0 12 * * ?', label: '每天中午12点' },
|
||||
{ value: '0 0 10,14,16 * * ?', label: '每天上午10点,下午2点,4点 ' },
|
||||
],
|
||||
},
|
||||
interface: 'select',
|
||||
},
|
||||
{
|
||||
name: 'exclude',
|
||||
type: 'json',
|
||||
},
|
||||
],
|
||||
},
|
||||
availableFieldInterfaces: {
|
||||
include: [],
|
||||
},
|
||||
configurableProperties: getConfigurableProperties('title', 'name', 'inherits'),
|
||||
};
|
@ -0,0 +1,23 @@
|
||||
import { getConfigurableProperties } from './properties';
|
||||
import { ICollectionTemplate } from './types';
|
||||
|
||||
export const general: ICollectionTemplate = {
|
||||
name: 'general',
|
||||
title: '{{t("General collection")}}',
|
||||
order: 1,
|
||||
color: 'blue',
|
||||
default: {
|
||||
fields: [],
|
||||
},
|
||||
configurableProperties: getConfigurableProperties(
|
||||
'title',
|
||||
'name',
|
||||
'inherits',
|
||||
'autoGenId',
|
||||
'createdAt',
|
||||
'updatedAt',
|
||||
'createdBy',
|
||||
'updatedBy',
|
||||
'sortable',
|
||||
),
|
||||
};
|
@ -0,0 +1,3 @@
|
||||
export * from './calendar';
|
||||
export * from './general';
|
||||
|
@ -0,0 +1,121 @@
|
||||
export const defaultConfigurableProperties = {
|
||||
title: {
|
||||
type: 'string',
|
||||
title: '{{ t("Collection display name") }}',
|
||||
required: true,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
name: {
|
||||
type: 'string',
|
||||
title: '{{t("Collection name")}}',
|
||||
required: true,
|
||||
'x-disabled': '{{ !createOnly }}',
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
'x-validator': 'uid',
|
||||
description:
|
||||
"{{t('Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.')}}",
|
||||
},
|
||||
inherits: {
|
||||
title: '{{t("Inherits")}}',
|
||||
type: 'hasMany',
|
||||
name: 'inherits',
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Select',
|
||||
'x-component-props': {
|
||||
mode: 'multiple',
|
||||
},
|
||||
'x-disabled': '{{ !createOnly }}',
|
||||
'x-visible': '{{ enableInherits}}',
|
||||
'x-reactions': ['{{useAsyncDataSource(loadCollections)}}'],
|
||||
},
|
||||
autoGenId: {
|
||||
type: 'boolean',
|
||||
'x-content': '{{t("AutoGenId")}}',
|
||||
default: true,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Checkbox',
|
||||
'x-disabled': '{{ !createOnly }}',
|
||||
'x-reactions': [
|
||||
{
|
||||
target: 'sortable',
|
||||
when: '{{createOnly&&!$self.value}}',
|
||||
fulfill: {
|
||||
state: {
|
||||
value: false,
|
||||
},
|
||||
schema: {
|
||||
'x-disabled': true,
|
||||
},
|
||||
},
|
||||
otherwise: {
|
||||
schema: {
|
||||
'x-disabled': '{{!createOnly}}',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
createdBy: {
|
||||
type: 'boolean',
|
||||
'x-content': '{{t("CreatedBy")}}',
|
||||
default: true,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Checkbox',
|
||||
'x-disabled': '{{ !createOnly }}',
|
||||
},
|
||||
updatedBy: {
|
||||
type: 'boolean',
|
||||
'x-content': '{{t("UpdatedBy")}}',
|
||||
default: true,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Checkbox',
|
||||
'x-disabled': '{{ !createOnly }}',
|
||||
},
|
||||
createdAt: {
|
||||
type: 'boolean',
|
||||
'x-content': '{{t("CreatedAt")}}',
|
||||
default: true,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Checkbox',
|
||||
'x-disabled': '{{ !createOnly }}',
|
||||
},
|
||||
updatedAt: {
|
||||
type: 'boolean',
|
||||
'x-content': '{{t("UpdatedAt")}}',
|
||||
default: true,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Checkbox',
|
||||
'x-disabled': '{{ !createOnly }}',
|
||||
},
|
||||
sortable: {
|
||||
type: 'boolean',
|
||||
'x-content': '{{t("Records can be sorted")}}',
|
||||
default: true,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Checkbox',
|
||||
'x-disabled': '{{ !createOnly }}',
|
||||
},
|
||||
};
|
||||
|
||||
export type DefaultConfigurableKeys =
|
||||
| 'name'
|
||||
| 'title'
|
||||
| 'inherits'
|
||||
| 'autoGenId'
|
||||
| 'createdBy'
|
||||
| 'updatedBy'
|
||||
| 'createdAt'
|
||||
| 'updatedAt'
|
||||
| 'sortable';
|
||||
|
||||
export const getConfigurableProperties = (...keys: DefaultConfigurableKeys[]) => {
|
||||
const props = {};
|
||||
for (const key of keys) {
|
||||
if (defaultConfigurableProperties[key]) {
|
||||
props[key] = defaultConfigurableProperties[key];
|
||||
}
|
||||
}
|
||||
return props;
|
||||
};
|
@ -0,0 +1,52 @@
|
||||
import { ISchema } from '@formily/react';
|
||||
import { FieldOptions } from '../../collection-manager/types';
|
||||
|
||||
|
||||
|
||||
export interface ICollectionTemplate {
|
||||
name: string;
|
||||
title?: string;
|
||||
color?:string;
|
||||
/** 排序 */
|
||||
order?: number;
|
||||
/** 默认配置 */
|
||||
default?: CollectionOptions;
|
||||
/** UI 可配置的 CollectionOptions 参数(添加或编辑的 Collection 表单的字段) */
|
||||
configurableProperties?: Record<string, ISchema>;
|
||||
/** 当前模板可用的字段类型 */
|
||||
availableFieldInterfaces?: AvailableFieldInterfacesInclude | AvailableFieldInterfacesExclude;
|
||||
}
|
||||
|
||||
interface AvailableFieldInterfacesInclude {
|
||||
include?: any[];
|
||||
}
|
||||
|
||||
interface AvailableFieldInterfacesExclude {
|
||||
exclude?: any[];
|
||||
}
|
||||
|
||||
interface CollectionOptions {
|
||||
/**
|
||||
* 自动生成 id
|
||||
* @default true
|
||||
* */
|
||||
autoGenId?: boolean;
|
||||
/** 创建人 */
|
||||
createdBy?: boolean;
|
||||
/** 最后更新人 */
|
||||
updatedBy?: boolean;
|
||||
/** 创建日期 */
|
||||
createdAt?: boolean;
|
||||
/** 更新日期 */
|
||||
updatedAt?: boolean;
|
||||
/** 可排序 */
|
||||
sortable?: boolean;
|
||||
/* 树结构 */
|
||||
tree?: string;
|
||||
/* 日志 */
|
||||
logging?: boolean;
|
||||
/** 继承 */
|
||||
inherits?: string | string[];
|
||||
/* 字段列表 */
|
||||
fields?: FieldOptions[];
|
||||
}
|
@ -4,6 +4,7 @@ export interface CollectionManagerOptions {
|
||||
service?: any;
|
||||
interfaces?: any;
|
||||
collections?: any[];
|
||||
templates?: any;
|
||||
refreshCM?: () => Promise<void>;
|
||||
}
|
||||
|
||||
|
@ -114,6 +114,15 @@ export default {
|
||||
"Collection display name": "Collection display name",
|
||||
"Collection name": "Collection name",
|
||||
"Inherits":"Inherits",
|
||||
"AutoGenId":"Auto-generated ID field",
|
||||
"CreatedBy":"Recording a row's created user",
|
||||
"UpdatedBy":"Recording a row's last updated user",
|
||||
"CreatedAt":"Recording a row's created time ",
|
||||
"UpdatedAt":"Recording a row's last updated user",
|
||||
"Records can be sorted": "Records can be sorted",
|
||||
"Collection template":"Collection template",
|
||||
"Calendar collection":"Calendar collection",
|
||||
"General collection":"General collection",
|
||||
"Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.": "Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.",
|
||||
"Storage type": "Storage type",
|
||||
"Edit": "Edit",
|
||||
|
@ -107,6 +107,16 @@ export default {
|
||||
"Create collection": "コレクションの作成",
|
||||
"Collection display name": "コレクション名",
|
||||
"Collection name": "コレクション識別子",
|
||||
"Inherits":"継承",
|
||||
"AutoGenId":"IDフィールドの自動生成",
|
||||
"CreatedBy":"レコード作成者",
|
||||
"UpdatedBy":"レコード最終更新者",
|
||||
"CreatedAt":"レコード作成時間",
|
||||
"UpdatedAt":"レコード最終更新時間",
|
||||
"Records can be sorted":"ソート可能",
|
||||
"Collection template":"データテーブルテンプレート",
|
||||
"Calendar collection":"カレンダデータテーブル",
|
||||
"General collection":"一般データテーブル",
|
||||
"Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.": "ランダムに生成され、変更可能です。 アルファベット、数字、アンダースコアをサポートし、アルファベットから始まる必要があります。",
|
||||
"Storage type": "ストレージタイプ",
|
||||
"Edit": "編集",
|
||||
@ -503,6 +513,5 @@ export default {
|
||||
"Format": "フォーマット",
|
||||
"Error message": "エラーメッセージ",
|
||||
"Record picker": "レコードピッカー",
|
||||
"Sortable": "ソート可能",
|
||||
"Search and select collection": "Search and select collection",
|
||||
}
|
||||
|
@ -118,6 +118,15 @@ export default {
|
||||
"Collection display name": "数据表名称",
|
||||
"Collection name": "数据表标识",
|
||||
"Inherits":"继承",
|
||||
"AutoGenId":"自动生成 ID 字段",
|
||||
"CreatedBy":"记录创建人",
|
||||
"UpdatedBy":"记录最后更新人",
|
||||
"CreatedAt":"记录创建时间",
|
||||
"UpdatedAt":"记录最后更新时间",
|
||||
"Records can be sorted":"可以对行记录进行排序",
|
||||
"Collection template":"数据表模板",
|
||||
"Calendar collection":"日历数据表",
|
||||
"General collection":"普通数据表",
|
||||
"Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.": "随机生成,可修改。支持英文、数字和下划线,必须以英文字母开头。",
|
||||
"Storage type": "存储类型",
|
||||
"Edit": "编辑",
|
||||
@ -228,7 +237,6 @@ export default {
|
||||
"Editable": "可编辑",
|
||||
"Readonly": "只读(禁止编辑)",
|
||||
"Easy-reading": "只读(阅读模式)",
|
||||
"Sortable": "可排序",
|
||||
"Add filter": "添加筛选条件",
|
||||
"Add filter group": "添加筛选分组",
|
||||
"Comparision": "值比较",
|
||||
|
@ -37,7 +37,7 @@ export const TableBlockDesigner = () => {
|
||||
return (
|
||||
<GeneralSchemaDesigner template={template} title={title || name}>
|
||||
<SchemaSettings.BlockTitleItem />
|
||||
<SchemaSettings.SwitchItem
|
||||
{sortable&& <SchemaSettings.SwitchItem
|
||||
title={t('Enable drag and drop sorting')}
|
||||
checked={field.decoratorProps.dragSort}
|
||||
onChange={(dragSort) => {
|
||||
@ -51,7 +51,7 @@ export const TableBlockDesigner = () => {
|
||||
},
|
||||
});
|
||||
}}
|
||||
/>
|
||||
/>}
|
||||
<SchemaSettings.ModalItem
|
||||
title={t('Set the data scope')}
|
||||
schema={
|
||||
|
@ -524,6 +524,8 @@ export const useCollectionDataSourceItems = (componentName) => {
|
||||
const b = !value || selected.includes(item.name);
|
||||
if (item.inherit) {
|
||||
return false;
|
||||
} else if (!item.fields.find((v) => v.primaryKey)) {
|
||||
return false;
|
||||
} else {
|
||||
return b && !(item?.isThrough && item?.autoCreate);
|
||||
}
|
||||
|
@ -105,6 +105,15 @@ class AppGenerator extends Generator {
|
||||
break;
|
||||
}
|
||||
|
||||
const keys = ['PLUGIN_PACKAGE_PREFIX', 'DB_HOST', 'DB_PORT', 'DB_DATABASE', 'DB_USER', 'DB_PASSWORD', 'DB_STORAGE'];
|
||||
|
||||
for (const key in env) {
|
||||
if (keys.includes(key)) {
|
||||
continue;
|
||||
}
|
||||
envs.push(`${key}=${env[key]}`);
|
||||
}
|
||||
|
||||
return {
|
||||
...this.context,
|
||||
dependencies: dependencies.join(`,\n `),
|
||||
|
@ -3,23 +3,25 @@ import path from 'path';
|
||||
|
||||
export class PresetNocoBase extends Plugin {
|
||||
async addBuiltInPlugins() {
|
||||
const plugins = [
|
||||
'error-handler',
|
||||
'collection-manager',
|
||||
'ui-schema-storage',
|
||||
'ui-routes-storage',
|
||||
'file-manager',
|
||||
'system-settings',
|
||||
'verification',
|
||||
'users',
|
||||
'acl',
|
||||
'china-region',
|
||||
'workflow',
|
||||
'client',
|
||||
'export',
|
||||
'import',
|
||||
'audit-logs',
|
||||
];
|
||||
const plugins = process.env.PRESET_NOCOBASE_PLUGINS
|
||||
? process.env.PRESET_NOCOBASE_PLUGINS.split(',')
|
||||
: [
|
||||
'error-handler',
|
||||
'collection-manager',
|
||||
'ui-schema-storage',
|
||||
'ui-routes-storage',
|
||||
'file-manager',
|
||||
'system-settings',
|
||||
'verification',
|
||||
'users',
|
||||
'acl',
|
||||
'china-region',
|
||||
'workflow',
|
||||
'client',
|
||||
'export',
|
||||
'import',
|
||||
'audit-logs',
|
||||
];
|
||||
await this.app.pm.add(plugins, {
|
||||
enabled: true,
|
||||
builtIn: true,
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 5a5fba41ae1cecaf3b073fcb610e9dc68dad0b85
|
||||
Subproject commit 67f51c7fdd132ab12821f31f737b6f0cfb70d212
|
28
packages/samples/custom-collection-template/README.md
Normal file
28
packages/samples/custom-collection-template/README.md
Normal file
@ -0,0 +1,28 @@
|
||||
# custom-collection-template
|
||||
|
||||
## Register
|
||||
|
||||
```ts
|
||||
yarn pm add sample-custom-collection-template
|
||||
```
|
||||
|
||||
## Activate
|
||||
|
||||
```bash
|
||||
yarn pm enable sample-custom-collection-template
|
||||
```
|
||||
|
||||
## Launch the app
|
||||
|
||||
```bash
|
||||
# for development
|
||||
yarn dev
|
||||
|
||||
# for production
|
||||
yarn build
|
||||
yarn start
|
||||
```
|
||||
|
||||
## Demo
|
||||
|
||||
[gif]
|
4
packages/samples/custom-collection-template/client.d.ts
vendored
Executable file
4
packages/samples/custom-collection-template/client.d.ts
vendored
Executable file
@ -0,0 +1,4 @@
|
||||
// @ts-nocheck
|
||||
export * from './lib/client';
|
||||
export { default } from './lib/client';
|
||||
|
30
packages/samples/custom-collection-template/client.js
Executable file
30
packages/samples/custom-collection-template/client.js
Executable file
@ -0,0 +1,30 @@
|
||||
"use strict";
|
||||
|
||||
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
||||
|
||||
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
||||
|
||||
var _index = _interopRequireWildcard(require("./lib/client"));
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
var _exportNames = {};
|
||||
Object.defineProperty(exports, "default", {
|
||||
enumerable: true,
|
||||
get: function get() {
|
||||
return _index.default;
|
||||
}
|
||||
});
|
||||
|
||||
Object.keys(_index).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
|
||||
if (key in exports && exports[key] === _index[key]) return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function get() {
|
||||
return _index[key];
|
||||
}
|
||||
});
|
||||
});
|
11
packages/samples/custom-collection-template/package.json
Normal file
11
packages/samples/custom-collection-template/package.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "@nocobase/plugin-sample-custom-collection-template",
|
||||
"version": "0.8.0-alpha.13",
|
||||
"main": "lib/server/index.js",
|
||||
"devDependencies": {
|
||||
"@nocobase/client": "0.8.0-alpha.13",
|
||||
"@nocobase/server": "0.8.0-alpha.13",
|
||||
"@nocobase/test": "0.8.0-alpha.13"
|
||||
},
|
||||
"gitHead": "ce588eefb0bfc50f7d5bbee575e0b5e843bf6644"
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
import { getConfigurableProperties, ICollectionTemplate, registerTemplate } from '@nocobase/client';
|
||||
import React from 'react';
|
||||
|
||||
const myCollectionTemplate: ICollectionTemplate = {
|
||||
name: 'myCollection',
|
||||
title: '{{t("Custom template")}}',
|
||||
order: 6,
|
||||
color: 'blue',
|
||||
default: {
|
||||
fields: [
|
||||
{
|
||||
name: 'uuid',
|
||||
type: 'string',
|
||||
primaryKey: true,
|
||||
allowNull: false,
|
||||
uiSchema: { type: 'number', title: '{{t("UUID")}}', 'x-component': 'Input', 'x-read-pretty': true },
|
||||
interface: 'input',
|
||||
},
|
||||
],
|
||||
},
|
||||
configurableProperties: getConfigurableProperties('name', 'title', 'inherits', 'createdAt', 'updatedAt'),
|
||||
availableFieldInterfaces: {
|
||||
exclude: ['linkTo', 'o2o'],
|
||||
},
|
||||
};
|
||||
|
||||
registerTemplate('myCollection', myCollectionTemplate);
|
||||
|
||||
export default React.memo((props) => {
|
||||
return <>{props.children}</>;
|
||||
});
|
1
packages/samples/custom-collection-template/src/index.ts
Normal file
1
packages/samples/custom-collection-template/src/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export { default } from './server';
|
@ -0,0 +1,16 @@
|
||||
import { InstallOptions, Plugin } from '@nocobase/server';
|
||||
|
||||
export class CustomCollectionTemplatePlugin extends Plugin {
|
||||
|
||||
afterAdd() {}
|
||||
|
||||
beforeLoad() {}
|
||||
|
||||
async load() {}
|
||||
|
||||
async install(options: InstallOptions) {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
export default CustomCollectionTemplatePlugin;
|
337
yarn.lock
337
yarn.lock
@ -329,23 +329,6 @@
|
||||
csstype "^3.0.8"
|
||||
tslib "^2.0.3"
|
||||
|
||||
"@antv/x6-react-shape@^1.6.2":
|
||||
version "1.6.3"
|
||||
resolved "https://registry.yarnpkg.com/@antv/x6-react-shape/-/x6-react-shape-1.6.3.tgz#053660bd555c4356e9719134e3e2a857b51301e2"
|
||||
integrity sha512-iCsRVkvKCVs7HUUblF/ALg5XxeeEPXDLHuYzRvbvNlCKKLbXLbaz6vJQSgTTrk2i4lrD+7xl4riA76FyWA3k/g==
|
||||
|
||||
"@antv/x6@^1.34.2":
|
||||
version "1.34.6"
|
||||
resolved "https://registry.yarnpkg.com/@antv/x6/-/x6-1.34.6.tgz#b802b09b52c8620acf01734397714ea5e3f715b6"
|
||||
integrity sha512-cl8ywN7CTNVT94/ZEbq2mnZQTQe6FUgIlGOAjNOPL8sljZTBrpE6OsuGw4BDA2/XllwELfUfvVpgBvbdwRKrxw==
|
||||
dependencies:
|
||||
csstype "^3.0.3"
|
||||
jquery "^3.5.1"
|
||||
jquery-mousewheel "^3.1.13"
|
||||
lodash-es "^4.17.15"
|
||||
mousetrap "^1.6.5"
|
||||
utility-types "^3.10.0"
|
||||
|
||||
"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.16.0":
|
||||
version "7.16.0"
|
||||
resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.0.tgz#0dfc80309beec8411e65e706461c408b0bb9b431"
|
||||
@ -2969,15 +2952,6 @@
|
||||
resolved "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.4.0.tgz#c3c5ae543c897caa9c2a68630bed355be5f9990f"
|
||||
integrity sha512-JZButFdZ1+/xAfpguQHoabIXkcqRRKpMrWKBkpEZZyxfY9C1DpADFB8PEqGSTeFr135SaTRfKqGKx5xSCLI7ZQ==
|
||||
|
||||
"@dabh/diagnostics@^2.0.2":
|
||||
version "2.0.3"
|
||||
resolved "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz#7f7e97ee9a725dffc7808d93668cc984e1dc477a"
|
||||
integrity sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==
|
||||
dependencies:
|
||||
colorspace "1.1.x"
|
||||
enabled "2.0.x"
|
||||
kuler "^2.0.0"
|
||||
|
||||
"@dnd-kit/accessibility@^3.0.0":
|
||||
version "3.0.0"
|
||||
resolved "https://registry.npmjs.org/@dnd-kit/accessibility/-/accessibility-3.0.0.tgz#b56e3750414fd907b7d6972b3116aa8f96d07fde"
|
||||
@ -4383,153 +4357,6 @@
|
||||
call-me-maybe "^1.0.1"
|
||||
glob-to-regexp "^0.3.0"
|
||||
|
||||
"@nocobase/acl@0.8.0-alpha.9":
|
||||
version "0.8.0-alpha.9"
|
||||
resolved "https://registry.yarnpkg.com/@nocobase/acl/-/acl-0.8.0-alpha.9.tgz#7ffab4a367befc74daa681b1d5c2c907126cb280"
|
||||
integrity sha512-jEgpjO6gGi4GwSyWxlmcwd368/AQgmrdsODDTLhhrJJI9+ovj2mxO664lQgh3FkDGtmduKlBiZ+qcgK+/RWa1w==
|
||||
dependencies:
|
||||
"@nocobase/resourcer" "0.8.0-alpha.9"
|
||||
json-templates "^4.2.0"
|
||||
|
||||
"@nocobase/actions@0.8.0-alpha.9":
|
||||
version "0.8.0-alpha.9"
|
||||
resolved "https://registry.yarnpkg.com/@nocobase/actions/-/actions-0.8.0-alpha.9.tgz#3804bbf30f7c4e8aa205b9802ec4f56a58c18c72"
|
||||
integrity sha512-EvdNjXa+TTMU2Xn+MnA7tSa5rooGFtzsvJsSYbkpODtsVQsmTDRIZYZsOYFk/XcezxjzTTsxxXMSA7sLq6wifQ==
|
||||
dependencies:
|
||||
"@nocobase/cache" "0.8.0-alpha.9"
|
||||
"@nocobase/database" "0.8.0-alpha.9"
|
||||
"@nocobase/resourcer" "0.8.0-alpha.9"
|
||||
|
||||
"@nocobase/cache@0.8.0-alpha.9":
|
||||
version "0.8.0-alpha.9"
|
||||
resolved "https://registry.yarnpkg.com/@nocobase/cache/-/cache-0.8.0-alpha.9.tgz#99f7ca196dacd41b69ed7b7f179fcc1c4c5baa27"
|
||||
integrity sha512-GCi7OE9nLrXKq/Og6SPtPcjtreUxxAL9x7CwmD2x3Zb7gNTc2GvQ9NWoAlO8KTLlWuzuNcJXegBhxaxV8Lt5ew==
|
||||
dependencies:
|
||||
cache-manager "^4.1.0"
|
||||
|
||||
"@nocobase/client@0.8.0-alpha.9":
|
||||
version "0.8.0-alpha.9"
|
||||
resolved "https://registry.yarnpkg.com/@nocobase/client/-/client-0.8.0-alpha.9.tgz#03446b4c4160a7ebda9dfd8aa80e2203541eb72c"
|
||||
integrity sha512-cvh01k8Ujhc9D7kDYQ7QKP5tnLF+wBOqixtisivti9aeklMBaOKj1oLmxKHZlB2IJzKpT+rUntpsxGxUS6co9A==
|
||||
dependencies:
|
||||
"@antv/g2plot" "^2.4.18"
|
||||
"@dnd-kit/core" "^5.0.1"
|
||||
"@dnd-kit/sortable" "^6.0.0"
|
||||
"@emotion/css" "^11.7.1"
|
||||
"@formily/antd" "2.0.20"
|
||||
"@formily/core" "2.0.20"
|
||||
"@formily/react" "2.0.20"
|
||||
"@nocobase/sdk" "0.8.0-alpha.9"
|
||||
"@nocobase/utils" "0.8.0-alpha.9"
|
||||
ahooks "^3.0.5"
|
||||
antd "~4.19.5"
|
||||
axios "^0.26.1"
|
||||
classnames "^2.3.1"
|
||||
cron-parser "^4.6.0"
|
||||
cronstrue "^2.11.0"
|
||||
file-saver "^2.0.5"
|
||||
i18next "^21.6.0"
|
||||
json-templates "^4.2.0"
|
||||
marked "^4.0.12"
|
||||
mathjs "^10.6.0"
|
||||
react-beautiful-dnd "^13.1.0"
|
||||
react-big-calendar "^0.38.7"
|
||||
react-contenteditable "^3.3.6"
|
||||
react-drag-listview "^0.1.9"
|
||||
react-helmet "^6.1.0"
|
||||
react-hotkeys-hook "^3.4.7"
|
||||
react-i18next "^11.15.1"
|
||||
react-image-lightbox "^5.1.4"
|
||||
react-js-cron "^1.4.0"
|
||||
react-quill "^1.3.5"
|
||||
react-router-dom "^5.2.0"
|
||||
react-to-print "^2.14.7"
|
||||
solarlunar-es "^1.0.9"
|
||||
use-deep-compare-effect "^1.8.1"
|
||||
|
||||
"@nocobase/database@0.8.0-alpha.9":
|
||||
version "0.8.0-alpha.9"
|
||||
resolved "https://registry.yarnpkg.com/@nocobase/database/-/database-0.8.0-alpha.9.tgz#9684b4ddcfc5396df2ef3d4ae9cd2ce59142df81"
|
||||
integrity sha512-zkLTW2iFg1tlbSTlW40oEmM7O2GxHXmIzErnDR4it0GWoLqjDgzNHP5QjODOxiiB/+/unNFudfGTNCoXxu2ZvA==
|
||||
dependencies:
|
||||
"@nocobase/utils" "0.8.0-alpha.9"
|
||||
async-mutex "^0.3.2"
|
||||
cron-parser "4.4.0"
|
||||
deepmerge "^4.2.2"
|
||||
flat "^5.0.2"
|
||||
glob "^7.1.6"
|
||||
mathjs "^10.6.1"
|
||||
moment "2.x"
|
||||
semver "^7.3.7"
|
||||
sequelize "^6.9.0"
|
||||
umzug "^3.1.1"
|
||||
|
||||
"@nocobase/resourcer@0.8.0-alpha.9":
|
||||
version "0.8.0-alpha.9"
|
||||
resolved "https://registry.yarnpkg.com/@nocobase/resourcer/-/resourcer-0.8.0-alpha.9.tgz#5415af5944b31293e5e2da73bf5c999866a90fab"
|
||||
integrity sha512-6v9bfUex2RfT8C3xX+SUhj8/zECCY6pQA3ce8GV3xd9cu6ku8c7hIiNM3KwgPOD189aND3FxNwxqpECNaoWQ1A==
|
||||
dependencies:
|
||||
"@nocobase/utils" "0.8.0-alpha.9"
|
||||
deepmerge "^4.2.2"
|
||||
koa-compose "^4.1.0"
|
||||
lodash "^4.17.21"
|
||||
path-to-regexp "^6.1.0"
|
||||
qs "^6.9.4"
|
||||
|
||||
"@nocobase/sdk@0.8.0-alpha.9":
|
||||
version "0.8.0-alpha.9"
|
||||
resolved "https://registry.yarnpkg.com/@nocobase/sdk/-/sdk-0.8.0-alpha.9.tgz#5306e7bf4aabf00894a65036c584508d93bda379"
|
||||
integrity sha512-v+GF4N5ldYwmoqQIukGWzz/eOm2TgxcUZq3uE+YeP/aiDa4XAfkLrpBNsvCS24k3s/U+84FYrvTWRRStJGSzBA==
|
||||
dependencies:
|
||||
axios "^0.26.1"
|
||||
qs "^6.10.1"
|
||||
|
||||
"@nocobase/server@0.8.0-alpha.9":
|
||||
version "0.8.0-alpha.9"
|
||||
resolved "https://registry.yarnpkg.com/@nocobase/server/-/server-0.8.0-alpha.9.tgz#bc1955e41b2ac9f6640fdf109516376604d4092c"
|
||||
integrity sha512-/mHk2Uc8RS/3GcGvnMnFKlbf2aCufGuc+GOr5gEKuyWa50ibD4nZ7LKJx023uEO07rxWkFkhR6+ExuZ+BGRDGQ==
|
||||
dependencies:
|
||||
"@hapi/topo" "^6.0.0"
|
||||
"@koa/cors" "^3.1.0"
|
||||
"@koa/router" "^9.4.0"
|
||||
"@nocobase/acl" "0.8.0-alpha.9"
|
||||
"@nocobase/actions" "0.8.0-alpha.9"
|
||||
"@nocobase/database" "0.8.0-alpha.9"
|
||||
"@nocobase/resourcer" "0.8.0-alpha.9"
|
||||
chalk "^4.1.1"
|
||||
commander "^9.2.0"
|
||||
find-package-json "^1.2.0"
|
||||
i18next "^21.6.0"
|
||||
koa "^2.13.4"
|
||||
koa-bodyparser "^4.3.0"
|
||||
koa-static "^5.0.0"
|
||||
lodash "^4.17.21"
|
||||
semver "^7.3.7"
|
||||
xpipe "^1.0.5"
|
||||
|
||||
"@nocobase/test@0.8.0-alpha.9":
|
||||
version "0.8.0-alpha.9"
|
||||
resolved "https://registry.yarnpkg.com/@nocobase/test/-/test-0.8.0-alpha.9.tgz#40aaed50af9b8fd23c0666156c806273c75b0a3f"
|
||||
integrity sha512-bpzcogPKzfq8mjIsLDy0xlsd0dNAUgmju9kk+RPV5wNZfhvofaA7YduexawbL+dLJQC+iyjmhAhARxl8rVhKuA==
|
||||
dependencies:
|
||||
"@nocobase/server" "0.8.0-alpha.9"
|
||||
"@types/supertest" "^2.0.11"
|
||||
mockjs "^1.1.0"
|
||||
mysql2 "^2.3.3"
|
||||
pg "^8.7.3"
|
||||
pg-hstore "^2.3.4"
|
||||
sqlite3 "^5.0.8"
|
||||
supertest "^6.1.6"
|
||||
|
||||
"@nocobase/utils@0.8.0-alpha.9":
|
||||
version "0.8.0-alpha.9"
|
||||
resolved "https://registry.yarnpkg.com/@nocobase/utils/-/utils-0.8.0-alpha.9.tgz#fa7e203412e91ab7a6ebb12a6d53d83e09465591"
|
||||
integrity sha512-oEqKs4+0sO4x0TFEtf+Tf1nIkb9q+9y9YmrqOn6MyMo/ejTSh6nlNt1rAYgs02gTP4uHkSOb2/4K4oDm0JXLdg==
|
||||
dependencies:
|
||||
"@hapi/topo" "^6.0.0"
|
||||
deepmerge "^4.2.2"
|
||||
flat-to-nested "^1.1.1"
|
||||
|
||||
"@nodelib/fs.scandir@2.1.5":
|
||||
version "2.1.5"
|
||||
resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"
|
||||
@ -6949,11 +6776,6 @@ async@^2.6.3, async@~2.6.1:
|
||||
dependencies:
|
||||
lodash "^4.17.14"
|
||||
|
||||
async@^3.2.3:
|
||||
version "3.2.4"
|
||||
resolved "https://registry.npmjs.org/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c"
|
||||
integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==
|
||||
|
||||
asynckit@^0.4.0:
|
||||
version "0.4.0"
|
||||
resolved "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
|
||||
@ -8334,7 +8156,7 @@ color-support@^1.1.2, color-support@^1.1.3:
|
||||
resolved "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2"
|
||||
integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==
|
||||
|
||||
color@^3.0.0, color@^3.1.3:
|
||||
color@^3.0.0:
|
||||
version "3.2.1"
|
||||
resolved "https://registry.npmjs.org/color/-/color-3.2.1.tgz#3544dc198caf4490c3ecc9a790b54fe9ff45e164"
|
||||
integrity sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==
|
||||
@ -8357,14 +8179,6 @@ colors@~1.2.1:
|
||||
resolved "https://registry.npmjs.org/colors/-/colors-1.2.5.tgz#89c7ad9a374bc030df8013241f68136ed8835afc"
|
||||
integrity sha512-erNRLao/Y3Fv54qUa0LBB+//Uf3YwMUmdJinN20yMXm9zdKKqH9wt7R9IIVZ+K7ShzfpLV/Zg8+VyrBJYB4lpg==
|
||||
|
||||
colorspace@1.1.x:
|
||||
version "1.1.4"
|
||||
resolved "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz#8d442d1186152f60453bf8070cd66eb364e59243"
|
||||
integrity sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==
|
||||
dependencies:
|
||||
color "^3.1.3"
|
||||
text-hex "1.0.x"
|
||||
|
||||
columnify@^1.5.4:
|
||||
version "1.5.4"
|
||||
resolved "https://registry.npmjs.org/columnify/-/columnify-1.5.4.tgz#4737ddf1c7b69a8a7c340570782e947eec8e78bb"
|
||||
@ -9268,11 +9082,6 @@ csstype@^3.0.2:
|
||||
resolved "https://registry.npmjs.org/csstype/-/csstype-3.0.9.tgz#6410af31b26bd0520933d02cbc64fce9ce3fbf0b"
|
||||
integrity sha512-rpw6JPxK6Rfg1zLOYCSwle2GFOOsnjmDYDaBwEcwoOg4qlsIVCN789VkBZDJAGi4T07gI4YSutR43t9Zz4Lzuw==
|
||||
|
||||
csstype@^3.0.3:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.1.tgz#841b532c45c758ee546a11d5bd7b7b473c8c30b9"
|
||||
integrity sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==
|
||||
|
||||
csstype@^3.0.8:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz#4ddcac3718d787cf9df0d1b7d15033925c8f29f2"
|
||||
@ -9322,14 +9131,6 @@ d3-timer@^1.0.9:
|
||||
resolved "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.10.tgz#dfe76b8a91748831b13b6d9c793ffbd508dd9de5"
|
||||
integrity sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw==
|
||||
|
||||
dagre@^0.8.5:
|
||||
version "0.8.5"
|
||||
resolved "https://registry.yarnpkg.com/dagre/-/dagre-0.8.5.tgz#ba30b0055dac12b6c1fcc247817442777d06afee"
|
||||
integrity sha512-/aTqmnRta7x7MCCpExk7HQL2O4owCT2h8NT//9I1OQ9vt29Pa0BzSAkR5lwFUcQ7491yVi/3CXU9jQ5o0Mn2Sw==
|
||||
dependencies:
|
||||
graphlib "^2.1.8"
|
||||
lodash "^4.17.15"
|
||||
|
||||
dargs@^7.0.0:
|
||||
version "7.0.0"
|
||||
resolved "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz#04015c41de0bcb69ec84050f3d9be0caf8d6d5cc"
|
||||
@ -10049,11 +9850,6 @@ emojis-list@^3.0.0:
|
||||
resolved "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78"
|
||||
integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==
|
||||
|
||||
enabled@2.0.x:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz#f9dd92ec2d6f4bbc0d5d1e64e21d61cd4665e7c2"
|
||||
integrity sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==
|
||||
|
||||
encodeurl@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
|
||||
@ -10942,7 +10738,7 @@ fclone@1.0.11, fclone@~1.0.11:
|
||||
resolved "https://registry.npmjs.org/fclone/-/fclone-1.0.11.tgz#10e85da38bfea7fc599341c296ee1d77266ee640"
|
||||
integrity sha1-EOhdo4v+p/xZk0HClu4ddyZu5kA=
|
||||
|
||||
fecha@^4.2.0, fecha@~4.2.0:
|
||||
fecha@~4.2.0:
|
||||
version "4.2.3"
|
||||
resolved "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz#4d9ccdbc61e8629b259fdca67e65891448d569fd"
|
||||
integrity sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==
|
||||
@ -10973,13 +10769,6 @@ file-saver@^2.0.5:
|
||||
resolved "https://registry.npmmirror.com/file-saver/download/file-saver-2.0.5.tgz#d61cfe2ce059f414d899e9dd6d4107ee25670c38"
|
||||
integrity sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==
|
||||
|
||||
file-stream-rotator@^0.6.1:
|
||||
version "0.6.1"
|
||||
resolved "https://registry.npmjs.org/file-stream-rotator/-/file-stream-rotator-0.6.1.tgz#007019e735b262bb6c6f0197e58e5c87cb96cec3"
|
||||
integrity sha512-u+dBid4PvZw17PmDeRcNOtCP9CCK/9lRN2w+r1xIS7yOL9JFrIBKTvrYsxT4P0pGtThYTn++QS5ChHaUov3+zQ==
|
||||
dependencies:
|
||||
moment "^2.29.1"
|
||||
|
||||
file-type@^3.3.0:
|
||||
version "3.9.0"
|
||||
resolved "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz#257a078384d1db8087bc449d107d52a52672b9e9"
|
||||
@ -11158,11 +10947,6 @@ fmin@^0.0.2:
|
||||
tape "^4.5.1"
|
||||
uglify-js "^2.6.2"
|
||||
|
||||
fn.name@1.x.x:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc"
|
||||
integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==
|
||||
|
||||
follow-redirects@^1.14.0, follow-redirects@^1.14.8:
|
||||
version "1.14.9"
|
||||
resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz#dd4ea157de7bfaf9ea9b3fbd85aa16951f78d8d7"
|
||||
@ -11794,13 +11578,6 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6
|
||||
resolved "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725"
|
||||
integrity sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=
|
||||
|
||||
graphlib@^2.1.8:
|
||||
version "2.1.8"
|
||||
resolved "https://registry.yarnpkg.com/graphlib/-/graphlib-2.1.8.tgz#5761d414737870084c92ec7b5dbcb0592c9d35da"
|
||||
integrity sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==
|
||||
dependencies:
|
||||
lodash "^4.17.15"
|
||||
|
||||
growly@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081"
|
||||
@ -14197,16 +13974,6 @@ jmespath@0.15.0:
|
||||
resolved "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz#a3f222a9aae9f966f5d27c796510e28091764217"
|
||||
integrity sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=
|
||||
|
||||
jquery-mousewheel@^3.1.13:
|
||||
version "3.1.13"
|
||||
resolved "https://registry.yarnpkg.com/jquery-mousewheel/-/jquery-mousewheel-3.1.13.tgz#06f0335f16e353a695e7206bf50503cb523a6ee5"
|
||||
integrity sha512-GXhSjfOPyDemM005YCEHvzrEALhKDIswtxSHSR2e4K/suHVJKJxxRCGz3skPjNxjJjQa9AVSGGlYjv1M3VLIPg==
|
||||
|
||||
jquery@^3.5.1:
|
||||
version "3.6.1"
|
||||
resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.6.1.tgz#fab0408f8b45fc19f956205773b62b292c147a16"
|
||||
integrity sha512-opJeO4nCucVnsjiXOE+/PcCgYw9Gwpvs/a6B1LL/lQhwWwpbVEVYDZ1FokFr8PRc7ghYlrFPuyHuiiDNTQxmcw==
|
||||
|
||||
js-base64@^2.5.2:
|
||||
version "2.6.4"
|
||||
resolved "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz#f4e686c5de1ea1f867dbcad3d46d969428df98c4"
|
||||
@ -14674,11 +14441,6 @@ koa@^2.13.4:
|
||||
type-is "^1.6.16"
|
||||
vary "^1.1.2"
|
||||
|
||||
kuler@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz#e2c570a3800388fb44407e851531c1d670b061b3"
|
||||
integrity sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==
|
||||
|
||||
latest-version@^3.0.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz#a205383fea322b33b5ae3b18abee0dc2f356ee15"
|
||||
@ -14919,7 +14681,7 @@ lockfile@^1.0.4:
|
||||
dependencies:
|
||||
signal-exit "^3.0.2"
|
||||
|
||||
lodash-es@^4.17.11, lodash-es@^4.17.15:
|
||||
lodash-es@^4.17.11:
|
||||
version "4.17.21"
|
||||
resolved "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee"
|
||||
integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==
|
||||
@ -15086,17 +14848,6 @@ log-driver@^1.2.7:
|
||||
resolved "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz#63b95021f0702fedfa2c9bb0a24e7797d71871d8"
|
||||
integrity sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==
|
||||
|
||||
logform@^2.3.2, logform@^2.4.0:
|
||||
version "2.4.2"
|
||||
resolved "https://registry.npmjs.org/logform/-/logform-2.4.2.tgz#a617983ac0334d0c3b942c34945380062795b47c"
|
||||
integrity sha512-W4c9himeAwXEdZ05dQNerhFz2XG80P9Oj0loPUMV23VC2it0orMHQhJm4hdnnor3rd1HsGf6a2lPwBM1zeXHGw==
|
||||
dependencies:
|
||||
"@colors/colors" "1.5.0"
|
||||
fecha "^4.2.0"
|
||||
ms "^2.1.1"
|
||||
safe-stable-stringify "^2.3.1"
|
||||
triple-beam "^1.3.0"
|
||||
|
||||
long@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.npmjs.org/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28"
|
||||
@ -15989,7 +15740,7 @@ moment-timezone@^0.5.31:
|
||||
dependencies:
|
||||
moment ">= 2.9.0"
|
||||
|
||||
moment@2.x, moment@^2.29.1:
|
||||
moment@2.x:
|
||||
version "2.29.4"
|
||||
resolved "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108"
|
||||
integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==
|
||||
@ -16004,11 +15755,6 @@ moo@^0.5.0:
|
||||
resolved "https://registry.npmjs.org/moo/-/moo-0.5.1.tgz#7aae7f384b9b09f620b6abf6f74ebbcd1b65dbc4"
|
||||
integrity sha512-I1mnb5xn4fO80BH9BLcF0yLypy2UKl+Cb01Fu0hJRkJjlCRtxZMWkTdAtDd5ZqCOxtCkhmRwyI57vWT+1iZ67w==
|
||||
|
||||
mousetrap@^1.6.5:
|
||||
version "1.6.5"
|
||||
resolved "https://registry.yarnpkg.com/mousetrap/-/mousetrap-1.6.5.tgz#8a766d8c272b08393d5f56074e0b5ec183485bf9"
|
||||
integrity sha512-QNo4kEepaIBwiT8CDhP98umTetp+JNfQYBWvC1pc6/OAibuXtRcxZ58Qz8skvEHYvURne/7R8T5VoOI7rDsEUA==
|
||||
|
||||
mri@^1.1.5:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b"
|
||||
@ -16689,11 +16435,6 @@ object-copy@^0.1.0:
|
||||
define-property "^0.2.5"
|
||||
kind-of "^3.0.3"
|
||||
|
||||
object-hash@^2.0.1:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz#5ad518581eefc443bd763472b8ff2e9c2c0d54a5"
|
||||
integrity sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==
|
||||
|
||||
object-inspect@^1.11.0, object-inspect@^1.9.0:
|
||||
version "1.11.0"
|
||||
resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.0.tgz#9dceb146cedd4148a0d9e51ab88d34cf509922b1"
|
||||
@ -16814,13 +16555,6 @@ once@^1.3.0, once@^1.3.1, once@^1.3.2, once@^1.4.0:
|
||||
dependencies:
|
||||
wrappy "1"
|
||||
|
||||
one-time@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz#e06bc174aed214ed58edede573b433bbf827cb45"
|
||||
integrity sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==
|
||||
dependencies:
|
||||
fn.name "1.x.x"
|
||||
|
||||
onetime@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4"
|
||||
@ -19763,7 +19497,7 @@ readable-stream@1.1.x:
|
||||
isarray "0.0.1"
|
||||
string_decoder "~0.10.x"
|
||||
|
||||
"readable-stream@2 || 3", readable-stream@3, readable-stream@^3.0.0, readable-stream@^3.0.2, readable-stream@^3.4.0, readable-stream@^3.6.0:
|
||||
"readable-stream@2 || 3", readable-stream@3, readable-stream@^3.0.0, readable-stream@^3.0.2, readable-stream@^3.6.0:
|
||||
version "3.6.0"
|
||||
resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
|
||||
integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
|
||||
@ -20644,11 +20378,6 @@ safe-regex@^1.1.0:
|
||||
dependencies:
|
||||
ret "~0.1.10"
|
||||
|
||||
safe-stable-stringify@^2.3.1:
|
||||
version "2.4.1"
|
||||
resolved "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.1.tgz#34694bd8a30575b7f94792aa51527551bd733d61"
|
||||
integrity sha512-dVHE6bMtS/bnL2mwualjc6IxEv1F+OCUpA46pKUj6F8uDbUM0jCCulPqRNPSnWwGNKx5etqMjZYdXtrm5KJZGA==
|
||||
|
||||
"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
|
||||
@ -21337,11 +21066,6 @@ stable@^0.1.8:
|
||||
resolved "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf"
|
||||
integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==
|
||||
|
||||
stack-trace@0.0.x:
|
||||
version "0.0.10"
|
||||
resolved "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0"
|
||||
integrity sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==
|
||||
|
||||
stack-utils@^1.0.1:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.5.tgz#a19b0b01947e0029c8e451d5d61a498f5bb1471b"
|
||||
@ -21981,11 +21705,6 @@ text-extensions@^1.0.0:
|
||||
resolved "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz#1853e45fee39c945ce6f6c36b2d659b5aabc2a26"
|
||||
integrity sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==
|
||||
|
||||
text-hex@1.0.x:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz#69dc9c1b17446ee79a92bf5b884bb4b9127506f5"
|
||||
integrity sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==
|
||||
|
||||
text-table@^0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
|
||||
@ -22243,11 +21962,6 @@ trim-newlines@^3.0.0:
|
||||
resolved "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz#260a5d962d8b752425b32f3a7db0dcacd176c144"
|
||||
integrity sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==
|
||||
|
||||
triple-beam@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz#a595214c7298db8339eeeee083e4d10bd8cb8dd9"
|
||||
integrity sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==
|
||||
|
||||
trough@^1.0.0:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz#b8b639cefad7d0bb2abd37d433ff8293efa5f406"
|
||||
@ -23072,11 +22786,6 @@ util@^0.11.0:
|
||||
dependencies:
|
||||
inherits "2.0.3"
|
||||
|
||||
utility-types@^3.10.0:
|
||||
version "3.10.0"
|
||||
resolved "https://registry.yarnpkg.com/utility-types/-/utility-types-3.10.0.tgz#ea4148f9a741015f05ed74fd615e1d20e6bed82b"
|
||||
integrity sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg==
|
||||
|
||||
utility@0.1.11:
|
||||
version "0.1.11"
|
||||
resolved "https://registry.npmjs.org/utility/-/utility-0.1.11.tgz#fde60cf9b4e4751947a0cf5d104ce29367226715"
|
||||
@ -23469,42 +23178,6 @@ window-size@0.1.0:
|
||||
resolved "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d"
|
||||
integrity sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=
|
||||
|
||||
winston-daily-rotate-file@^4.7.1:
|
||||
version "4.7.1"
|
||||
resolved "https://registry.npmjs.org/winston-daily-rotate-file/-/winston-daily-rotate-file-4.7.1.tgz#f60a643af87f8867f23170d8cd87dbe3603a625f"
|
||||
integrity sha512-7LGPiYGBPNyGHLn9z33i96zx/bd71pjBn9tqQzO3I4Tayv94WPmBNwKC7CO1wPHdP9uvu+Md/1nr6VSH9h0iaA==
|
||||
dependencies:
|
||||
file-stream-rotator "^0.6.1"
|
||||
object-hash "^2.0.1"
|
||||
triple-beam "^1.3.0"
|
||||
winston-transport "^4.4.0"
|
||||
|
||||
winston-transport@^4.4.0, winston-transport@^4.5.0:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.npmjs.org/winston-transport/-/winston-transport-4.5.0.tgz#6e7b0dd04d393171ed5e4e4905db265f7ab384fa"
|
||||
integrity sha512-YpZzcUzBedhlTAfJg6vJDlyEai/IFMIVcaEZZyl3UXIl4gmqRpU7AE89AHLkbzLUsv0NVmw7ts+iztqKxxPW1Q==
|
||||
dependencies:
|
||||
logform "^2.3.2"
|
||||
readable-stream "^3.6.0"
|
||||
triple-beam "^1.3.0"
|
||||
|
||||
winston@^3.8.2:
|
||||
version "3.8.2"
|
||||
resolved "https://registry.npmjs.org/winston/-/winston-3.8.2.tgz#56e16b34022eb4cff2638196d9646d7430fdad50"
|
||||
integrity sha512-MsE1gRx1m5jdTTO9Ld/vND4krP2To+lgDoMEHGGa4HIlAUyXJtfc7CxQcGXVyz2IBpw5hbFkj2b/AtUdQwyRew==
|
||||
dependencies:
|
||||
"@colors/colors" "1.5.0"
|
||||
"@dabh/diagnostics" "^2.0.2"
|
||||
async "^3.2.3"
|
||||
is-stream "^2.0.0"
|
||||
logform "^2.4.0"
|
||||
one-time "^1.0.0"
|
||||
readable-stream "^3.4.0"
|
||||
safe-stable-stringify "^2.3.1"
|
||||
stack-trace "0.0.x"
|
||||
triple-beam "^1.3.0"
|
||||
winston-transport "^4.5.0"
|
||||
|
||||
wkx@^0.5.0:
|
||||
version "0.5.0"
|
||||
resolved "https://registry.npmjs.org/wkx/-/wkx-0.5.0.tgz#c6c37019acf40e517cc6b94657a25a3d4aa33e8c"
|
||||
|
Loading…
Reference in New Issue
Block a user