Merge pull request 'merge_from_upstream' (#358) from merge_from_upstream into @hera/dev
Reviewed-on: daoyoucloud/tachycode#358
This commit is contained in:
commit
4bd5a1beda
29
CHANGELOG.md
29
CHANGELOG.md
@ -7,6 +7,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
||||
|
||||
## [v0.20.0-alpha.9](https://github.com/nocobase/nocobase/compare/v0.20.0-alpha.8...v0.20.0-alpha.9) - 2024-03-12
|
||||
|
||||
### Merged
|
||||
|
||||
- refactor: add child in inheritance of tree collection [`#3676`](https://github.com/nocobase/nocobase/pull/3676)
|
||||
- fix: data source add field refresh(T-3253) [`#3645`](https://github.com/nocobase/nocobase/pull/3645)
|
||||
- chore: escape underscore char in include query [`#3681`](https://github.com/nocobase/nocobase/pull/3681)
|
||||
- fix: upgrade app after restore [`#3680`](https://github.com/nocobase/nocobase/pull/3680)
|
||||
- fix: view collection association field foreignkey should be select [`#3671`](https://github.com/nocobase/nocobase/pull/3671)
|
||||
- fix: acl should return true when resource allowed [`#3675`](https://github.com/nocobase/nocobase/pull/3675)
|
||||
- fix: init scope value when all data is null value [`#3674`](https://github.com/nocobase/nocobase/pull/3674)
|
||||
- fix: inheritance cache bug [`#3669`](https://github.com/nocobase/nocobase/pull/3669)
|
||||
|
||||
### Commits
|
||||
|
||||
- chore(versions): 😊 publish v0.20.0-alpha.9 [`2e7da6e`](https://github.com/nocobase/nocobase/commit/2e7da6e29bc75def06f59d8d3bb991e7e238c64b)
|
||||
- fix: pagination error in roles collections resourcer [`023096b`](https://github.com/nocobase/nocobase/commit/023096b1a9ea6ccae364c81ba93ca32b077ccecc)
|
||||
- chore: update changelog [`56fd24e`](https://github.com/nocobase/nocobase/commit/56fd24ef4b30717e12b2c0574d4df92210bac81c)
|
||||
|
||||
## [v0.20.0-alpha.8](https://github.com/nocobase/nocobase/compare/v0.20.0-alpha.7...v0.20.0-alpha.8) - 2024-03-11
|
||||
|
||||
### Merged
|
||||
@ -597,7 +616,7 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
||||
- fix: load field when source collection not found [`95bec22`](https://github.com/nocobase/nocobase/commit/95bec2278ff2f53dfb1307e47bc8aca90d5a606a)
|
||||
- chore: update changelog [`34e026c`](https://github.com/nocobase/nocobase/commit/34e026cec5742c1a1347f2969a03446fa98c44c3)
|
||||
|
||||
## [v0.17.0-alpha.1](https://github.com/nocobase/nocobase/compare/v0.16.0-alpha.7...v0.17.0-alpha.1) - 2023-12-04
|
||||
## [v0.17.0-alpha.1](https://github.com/nocobase/nocobase/compare/v0.16.0-alpha.6...v0.17.0-alpha.1) - 2023-12-04
|
||||
|
||||
### Merged
|
||||
|
||||
@ -606,16 +625,8 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
||||
### Commits
|
||||
|
||||
- chore(versions): 😊 publish v0.17.0-alpha.1 [`1757a96`](https://github.com/nocobase/nocobase/commit/1757a96b51c7bb17f607b61467ab867e5add6567)
|
||||
- chore(versions): 😊 publish v0.16.0-alpha.6 [`9d64430`](https://github.com/nocobase/nocobase/commit/9d644304c10be0f8404f2f3370a43d2dc00e8aed)
|
||||
- chore: update changelog [`69abfc9`](https://github.com/nocobase/nocobase/commit/69abfc98327b36bbc6b7e225294835bb457518d6)
|
||||
|
||||
## [v0.16.0-alpha.7](https://github.com/nocobase/nocobase/compare/v0.16.0-alpha.6...v0.16.0-alpha.7) - 2023-12-04
|
||||
|
||||
### Commits
|
||||
|
||||
- chore(versions): 😊 publish v0.16.0-alpha.7 [`d077a17`](https://github.com/nocobase/nocobase/commit/d077a17ee8cafc901a995f1ec7271ca78e4c32c3)
|
||||
- chore(versions): 😊 publish v [`7810332`](https://github.com/nocobase/nocobase/commit/78103320eb6ee01559609784e7ba1a4493399c2c)
|
||||
|
||||
## [v0.16.0-alpha.6](https://github.com/nocobase/nocobase/compare/v0.16.0-alpha.5...v0.16.0-alpha.6) - 2023-12-04
|
||||
|
||||
### Merged
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"npmClient": "yarn",
|
||||
"useWorkspaces": true,
|
||||
"npmClientArgs": ["--ignore-engines"],
|
||||
|
@ -1,13 +1,13 @@
|
||||
{
|
||||
"name": "@nocobase/acl",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"description": "",
|
||||
"license": "Apache-2.0",
|
||||
"main": "./lib/index.js",
|
||||
"types": "./lib/index.d.ts",
|
||||
"dependencies": {
|
||||
"@nocobase/resourcer": "0.20.0-alpha.8",
|
||||
"@nocobase/utils": "0.20.0-alpha.8",
|
||||
"@nocobase/resourcer": "0.20.0-alpha.9",
|
||||
"@nocobase/utils": "0.20.0-alpha.9",
|
||||
"minimatch": "^5.1.1"
|
||||
},
|
||||
"repository": {
|
||||
|
@ -1,14 +1,14 @@
|
||||
{
|
||||
"name": "@nocobase/actions",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"description": "",
|
||||
"license": "Apache-2.0",
|
||||
"main": "./lib/index.js",
|
||||
"types": "./lib/index.d.ts",
|
||||
"dependencies": {
|
||||
"@nocobase/cache": "0.20.0-alpha.8",
|
||||
"@nocobase/database": "0.20.0-alpha.8",
|
||||
"@nocobase/resourcer": "0.20.0-alpha.8"
|
||||
"@nocobase/cache": "0.20.0-alpha.9",
|
||||
"@nocobase/database": "0.20.0-alpha.9",
|
||||
"@nocobase/resourcer": "0.20.0-alpha.9"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -1,17 +1,17 @@
|
||||
{
|
||||
"name": "@nocobase/app",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"description": "",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "./lib/index.js",
|
||||
"types": "./lib/index.d.ts",
|
||||
"dependencies": {
|
||||
"@nocobase/database": "0.20.0-alpha.8",
|
||||
"@nocobase/preset-nocobase": "0.20.0-alpha.8",
|
||||
"@nocobase/server": "0.20.0-alpha.8"
|
||||
"@nocobase/database": "0.20.0-alpha.9",
|
||||
"@nocobase/preset-nocobase": "0.20.0-alpha.9",
|
||||
"@nocobase/server": "0.20.0-alpha.9"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nocobase/client": "0.20.0-alpha.8"
|
||||
"@nocobase/client": "0.20.0-alpha.9"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -1,16 +1,16 @@
|
||||
{
|
||||
"name": "@nocobase/auth",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"description": "",
|
||||
"license": "Apache-2.0",
|
||||
"main": "./lib/index.js",
|
||||
"types": "./lib/index.d.ts",
|
||||
"dependencies": {
|
||||
"@nocobase/actions": "0.20.0-alpha.8",
|
||||
"@nocobase/cache": "0.20.0-alpha.8",
|
||||
"@nocobase/database": "0.20.0-alpha.8",
|
||||
"@nocobase/resourcer": "0.20.0-alpha.8",
|
||||
"@nocobase/utils": "0.20.0-alpha.8",
|
||||
"@nocobase/actions": "0.20.0-alpha.9",
|
||||
"@nocobase/cache": "0.20.0-alpha.9",
|
||||
"@nocobase/database": "0.20.0-alpha.9",
|
||||
"@nocobase/resourcer": "0.20.0-alpha.9",
|
||||
"@nocobase/utils": "0.20.0-alpha.9",
|
||||
"@types/jsonwebtoken": "^8.5.8",
|
||||
"jsonwebtoken": "^8.5.1"
|
||||
},
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/build",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"description": "Library build tool based on rollup.",
|
||||
"main": "lib/index.js",
|
||||
"types": "./lib/index.d.ts",
|
||||
|
@ -34,6 +34,7 @@ const external = [
|
||||
'@nocobase/cache',
|
||||
'@nocobase/client',
|
||||
'@nocobase/database',
|
||||
'@nocobase/data-source-manager',
|
||||
'@nocobase/evaluators',
|
||||
'@nocobase/logger',
|
||||
'@nocobase/resourcer',
|
||||
|
2
packages/core/cache/package.json
vendored
2
packages/core/cache/package.json
vendored
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/cache",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"description": "",
|
||||
"license": "Apache-2.0",
|
||||
"main": "./lib/index.js",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/cli",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"description": "",
|
||||
"license": "Apache-2.0",
|
||||
"main": "./src/index.js",
|
||||
@ -8,7 +8,7 @@
|
||||
"nocobase": "./bin/index.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nocobase/app": "0.20.0-alpha.8",
|
||||
"@nocobase/app": "0.20.0-alpha.9",
|
||||
"@types/fs-extra": "^11.0.1",
|
||||
"@umijs/utils": "3.5.20",
|
||||
"chalk": "^4.1.1",
|
||||
@ -25,7 +25,7 @@
|
||||
"tsx": "^4.6.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nocobase/devtools": "0.20.0-alpha.8"
|
||||
"@nocobase/devtools": "0.20.0-alpha.9"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/client",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"license": "Apache-2.0",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.mjs",
|
||||
@ -26,9 +26,9 @@
|
||||
"@formily/reactive-react": "^2.2.27",
|
||||
"@formily/shared": "^2.2.27",
|
||||
"@formily/validator": "^2.2.27",
|
||||
"@nocobase/evaluators": "0.20.0-alpha.8",
|
||||
"@nocobase/sdk": "0.20.0-alpha.8",
|
||||
"@nocobase/utils": "0.20.0-alpha.8",
|
||||
"@nocobase/evaluators": "0.20.0-alpha.9",
|
||||
"@nocobase/sdk": "0.20.0-alpha.9",
|
||||
"@nocobase/utils": "0.20.0-alpha.9",
|
||||
"ahooks": "^3.7.2",
|
||||
"antd": "^5.12.8",
|
||||
"antd-style": "3.4.5",
|
||||
|
@ -986,6 +986,11 @@ export const useBulkDestroyActionProps = () => {
|
||||
filterByTk: field.data?.selectedRowKeys,
|
||||
});
|
||||
field.data.selectedRowKeys = [];
|
||||
const currentPage = service.params[0]?.page;
|
||||
const totalPage = service.data?.meta?.totalPage;
|
||||
if (currentPage === totalPage) {
|
||||
service.params[0].page = currentPage - 1;
|
||||
}
|
||||
service?.refresh?.();
|
||||
},
|
||||
};
|
||||
|
@ -132,10 +132,10 @@ export const useSelfAndChildrenCollections = (collectionName: string) => {
|
||||
return options;
|
||||
};
|
||||
|
||||
export const useCollectionFilterOptions = (collection: any) => {
|
||||
export const useCollectionFilterOptions = (collection: any, dataSource?: string) => {
|
||||
const { getCollectionFields, getInterface } = useCollectionManager_deprecated();
|
||||
return useMemo(() => {
|
||||
const fields = getCollectionFields(collection);
|
||||
const fields = getCollectionFields(collection, dataSource);
|
||||
const field2option = (field, depth) => {
|
||||
if (!field.interface) {
|
||||
return;
|
||||
@ -165,7 +165,7 @@ export const useCollectionFilterOptions = (collection: any) => {
|
||||
option['children'] = children;
|
||||
}
|
||||
if (nested) {
|
||||
const targetFields = getCollectionFields(field.target);
|
||||
const targetFields = getCollectionFields(field.target, dataSource);
|
||||
const options = getOptions(targetFields, depth + 1).filter(Boolean);
|
||||
option['children'] = option['children'] || [];
|
||||
option['children'].push(...options);
|
||||
@ -184,7 +184,7 @@ export const useCollectionFilterOptions = (collection: any) => {
|
||||
};
|
||||
const options = getOptions(fields, 1);
|
||||
return options;
|
||||
}, [_.isString(collection) ? collection : collection?.name]);
|
||||
}, [_.isString(collection) ? collection : collection?.name, dataSource]);
|
||||
};
|
||||
|
||||
export const useCollectionFilterOptionsV2 = (collection: any) => {
|
||||
|
@ -40,6 +40,9 @@ import {
|
||||
UpdatedByFieldInterface,
|
||||
UrlFieldInterface,
|
||||
SortFieldInterface,
|
||||
UUIDFieldInterface,
|
||||
NanoidFieldInterface,
|
||||
UnixTimestampFieldInterface,
|
||||
} from './interfaces';
|
||||
import {
|
||||
GeneralCollectionTemplate,
|
||||
@ -155,6 +158,9 @@ export class CollectionPlugin extends Plugin {
|
||||
UpdatedByFieldInterface,
|
||||
UrlFieldInterface,
|
||||
SortFieldInterface,
|
||||
UUIDFieldInterface,
|
||||
NanoidFieldInterface,
|
||||
UnixTimestampFieldInterface,
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -25,3 +25,4 @@ export * from './collectionPlugin';
|
||||
export * from './mixins/InheritanceCollectionMixin';
|
||||
export * from './sub-table';
|
||||
export * from './CollectionHistoryProvider';
|
||||
export * from './utils';
|
||||
|
@ -34,3 +34,6 @@ export * from './updatedAt';
|
||||
export * from './updatedBy';
|
||||
export * from './url';
|
||||
export * from './sort';
|
||||
export * from './uuid';
|
||||
export * from './nanoid';
|
||||
export * from './unixTimestamp';
|
||||
|
@ -0,0 +1,56 @@
|
||||
import { CollectionFieldInterface } from '../../data-source/collection-field-interface/CollectionFieldInterface';
|
||||
import { operators } from './properties';
|
||||
export class NanoidFieldInterface extends CollectionFieldInterface {
|
||||
name = 'nanoid';
|
||||
type = 'object';
|
||||
group = 'advanced';
|
||||
order = 0;
|
||||
title = '{{t("Nano ID")}}';
|
||||
hidden = false;
|
||||
sortable = true;
|
||||
default = {
|
||||
type: 'nanoid',
|
||||
uiSchema: {
|
||||
type: 'string',
|
||||
'x-component': 'NanoIDInput',
|
||||
},
|
||||
};
|
||||
availableTypes = ['string', 'uid'];
|
||||
properties = {
|
||||
'uiSchema.title': {
|
||||
type: 'string',
|
||||
title: '{{t("Field display name")}}',
|
||||
required: true,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
name: {
|
||||
type: 'string',
|
||||
title: '{{t("Field name")}}',
|
||||
required: true,
|
||||
'x-disabled': true,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
description:
|
||||
"{{t('Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.')}}",
|
||||
},
|
||||
customAlphabet: {
|
||||
type: 'string',
|
||||
title: '{{t("Alphabet")}}',
|
||||
default: '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
size: {
|
||||
type: 'number',
|
||||
title: '{{t("Length")}}',
|
||||
default: 21,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'InputNumber',
|
||||
},
|
||||
};
|
||||
filterable = {
|
||||
operators: operators.string,
|
||||
};
|
||||
titleUsable = true;
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
import { CollectionFieldInterface } from '../../data-source/collection-field-interface/CollectionFieldInterface';
|
||||
import { dateTimeProps, defaultProps, operators } from './properties';
|
||||
|
||||
export class UnixTimestampFieldInterface extends CollectionFieldInterface {
|
||||
name = 'unixTimestamp';
|
||||
type = 'object';
|
||||
group = 'datetime';
|
||||
order = 1;
|
||||
title = '{{t("Unix Timestamp")}}';
|
||||
sortable = true;
|
||||
default = {
|
||||
type: 'bigInt',
|
||||
uiSchema: {
|
||||
type: 'number',
|
||||
'x-component': 'UnixTimestamp',
|
||||
'x-component-props': {
|
||||
accuracy: 'millisecond',
|
||||
showTime: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
availableTypes = ['integet', 'bigInt'];
|
||||
hasDefaultValue = true;
|
||||
properties = {
|
||||
...defaultProps,
|
||||
'uiSchema.x-component-props.accuracy': {
|
||||
type: 'string',
|
||||
title: '{{t("Accuracy")}}',
|
||||
'x-component': 'Radio.Group',
|
||||
'x-decorator': 'FormItem',
|
||||
default: 'millisecond',
|
||||
enum: [
|
||||
{ value: 'millisecond', label: '{{t("Millisecond")}}' },
|
||||
{ value: 'second', label: '{{t("Second")}}' },
|
||||
],
|
||||
},
|
||||
};
|
||||
filterable = {
|
||||
operators: operators.number,
|
||||
};
|
||||
titleUsable = true;
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
import { CollectionFieldInterface } from '../../data-source/collection-field-interface/CollectionFieldInterface';
|
||||
import { operators } from './properties';
|
||||
|
||||
export class UUIDFieldInterface extends CollectionFieldInterface {
|
||||
name = 'uuid';
|
||||
type = 'object';
|
||||
group = 'advanced';
|
||||
order = 0;
|
||||
title = '{{t("UUID")}}';
|
||||
hidden = false;
|
||||
sortable = true;
|
||||
default = {
|
||||
type: 'uuid',
|
||||
uiSchema: {
|
||||
type: 'string',
|
||||
'x-component': 'Input',
|
||||
'x-validator': 'uuid',
|
||||
},
|
||||
};
|
||||
availableTypes = ['string', 'uid'];
|
||||
properties = {
|
||||
'uiSchema.title': {
|
||||
type: 'string',
|
||||
title: '{{t("Field display name")}}',
|
||||
required: true,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
name: {
|
||||
type: 'string',
|
||||
title: '{{t("Field name")}}',
|
||||
required: true,
|
||||
'x-disabled': true,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
description:
|
||||
"{{t('Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.')}}",
|
||||
},
|
||||
};
|
||||
filterable = {
|
||||
operators: operators.string,
|
||||
};
|
||||
titleUsable = true;
|
||||
}
|
16
packages/core/client/src/collection-manager/utils.ts
Normal file
16
packages/core/client/src/collection-manager/utils.ts
Normal file
@ -0,0 +1,16 @@
|
||||
export function parseCollectionName(collection: string) {
|
||||
if (!collection) {
|
||||
return [];
|
||||
}
|
||||
const dataSourceCollection = collection.split(':');
|
||||
const collectionName = dataSourceCollection.pop();
|
||||
const dataSourceName = dataSourceCollection[0] ?? 'main';
|
||||
return [dataSourceName, collectionName];
|
||||
}
|
||||
|
||||
export function joinCollectionName(dataSourceName: string, collectionName: string) {
|
||||
if (!dataSourceName || dataSourceName === 'main') {
|
||||
return collectionName;
|
||||
}
|
||||
return `${dataSourceName}:${collectionName}`;
|
||||
}
|
@ -114,7 +114,7 @@ export const BlockRequestProvider: FC = ({ children }) => {
|
||||
<BlockRequestContext.Provider value={currentRequest}>
|
||||
{action !== 'list' ? (
|
||||
<CollectionRecordProvider
|
||||
isNew={action === undefined}
|
||||
isNew={action == null}
|
||||
record={currentRequest.data?.data}
|
||||
parentRecord={memoizedParentRecord}
|
||||
>
|
||||
|
@ -851,7 +851,7 @@
|
||||
"loading": "加载中",
|
||||
"name is required": "名称不能为空",
|
||||
"The {{type}} \"{{name}}\" may have been deleted. Please remove this {{blockType}}.": "{{type}} \"{{name}}\" 可能已被删除。请删除当前{{blockType}}.",
|
||||
"data source": "数据源",
|
||||
"Data source": "数据源",
|
||||
"DataSource": "数据源",
|
||||
"Data model": "数据模型",
|
||||
"Security": "认证与安全",
|
||||
@ -891,5 +891,12 @@
|
||||
"Owners": "负责人",
|
||||
"Plugin settings": "插件设置",
|
||||
"Menu": "菜单",
|
||||
"Drag and drop sorting field": "拖拽排序字段"
|
||||
"Drag and drop sorting field": "拖拽排序字段",
|
||||
"Alphabet": "字符",
|
||||
"Accuracy": "精确度",
|
||||
"Millisecond": "毫秒",
|
||||
"Second": "秒",
|
||||
"Unix Timestamp": "Unix 时间戳",
|
||||
"Field value do not meet the requirements": "字符不符合要求",
|
||||
"Field value size is": "字符长度要求"
|
||||
}
|
||||
|
@ -0,0 +1,21 @@
|
||||
import { test, expect } from '@nocobase/test/e2e';
|
||||
import { T3529 } from './templatesOfBug';
|
||||
|
||||
test.describe('association form block', () => {
|
||||
// https://nocobase.height.app/T-3529
|
||||
test('should be created instead of updated', async ({ page, mockPage, mockRecord }) => {
|
||||
const nocoPage = await mockPage(T3529).waitForInit();
|
||||
await mockRecord('general');
|
||||
await nocoPage.goto();
|
||||
|
||||
await page.getByLabel('action-Action.Link-View-view-general-table-0').click();
|
||||
void page.getByLabel('action-Action-Submit-submit-').click();
|
||||
|
||||
const request = await page.waitForRequest((request) => {
|
||||
return request.url().includes('m2mField0:create');
|
||||
});
|
||||
|
||||
// 应该有包含 :create 的请求
|
||||
expect(request).toBeTruthy();
|
||||
});
|
||||
});
|
@ -1,4 +1,4 @@
|
||||
import { PageConfig, generalWithM2oSingleSelect } from '@nocobase/test/e2e';
|
||||
import { PageConfig, generalWithM2oSingleSelect, generalWithMultiLevelM2mFields } from '@nocobase/test/e2e';
|
||||
|
||||
export const T2165 = {
|
||||
pageSchema: {
|
||||
@ -5701,3 +5701,374 @@ export const T3469: PageConfig = {
|
||||
'x-async': true,
|
||||
},
|
||||
};
|
||||
|
||||
// https://nocobase.height.app/T-3529
|
||||
export const T3529: PageConfig = {
|
||||
collections: generalWithMultiLevelM2mFields,
|
||||
pageSchema: {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
'x-component': 'Page',
|
||||
properties: {
|
||||
'5i47muli5of': {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
'x-component': 'Grid',
|
||||
'x-initializer': 'BlockInitializers',
|
||||
properties: {
|
||||
l62athlwjbe: {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
'x-component': 'Grid.Row',
|
||||
properties: {
|
||||
gv12rstt0n6: {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
'x-component': 'Grid.Col',
|
||||
properties: {
|
||||
'44sjepqege8': {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
'x-decorator': 'TableBlockProvider',
|
||||
'x-acl-action': 'general:list',
|
||||
'x-decorator-props': {
|
||||
collection: 'general',
|
||||
dataSource: 'main',
|
||||
resource: 'general',
|
||||
action: 'list',
|
||||
params: {
|
||||
pageSize: 20,
|
||||
},
|
||||
rowKey: 'id',
|
||||
showIndex: true,
|
||||
dragSort: false,
|
||||
disableTemplate: false,
|
||||
},
|
||||
'x-toolbar': 'BlockSchemaToolbar',
|
||||
'x-settings': 'blockSettings:table',
|
||||
'x-component': 'CardItem',
|
||||
'x-filter-targets': [],
|
||||
properties: {
|
||||
actions: {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
'x-initializer': 'TableActionInitializers',
|
||||
'x-component': 'ActionBar',
|
||||
'x-component-props': {
|
||||
style: {
|
||||
marginBottom: 'var(--nb-spacing)',
|
||||
},
|
||||
},
|
||||
'x-uid': 'gcqzwfc98cz',
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
cndkuudjlrn: {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'array',
|
||||
'x-initializer': 'TableColumnInitializers',
|
||||
'x-component': 'TableV2',
|
||||
'x-component-props': {
|
||||
rowKey: 'id',
|
||||
rowSelection: {
|
||||
type: 'checkbox',
|
||||
},
|
||||
useProps: '{{ useTableBlockProps }}',
|
||||
},
|
||||
properties: {
|
||||
actions: {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
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',
|
||||
properties: {
|
||||
'7glkmum3znh': {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
'x-decorator': 'DndContext',
|
||||
'x-component': 'Space',
|
||||
'x-component-props': {
|
||||
split: '|',
|
||||
},
|
||||
properties: {
|
||||
'34feo0sq1b1': {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
title: '{{ t("View") }}',
|
||||
'x-action': 'view',
|
||||
'x-toolbar': 'ActionSchemaToolbar',
|
||||
'x-settings': 'actionSettings:view',
|
||||
'x-component': 'Action.Link',
|
||||
'x-component-props': {
|
||||
openMode: 'drawer',
|
||||
},
|
||||
'x-decorator': 'ACLActionProvider',
|
||||
'x-designer-props': {
|
||||
linkageAction: true,
|
||||
},
|
||||
properties: {
|
||||
drawer: {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
title: '{{ t("View record") }}',
|
||||
'x-component': 'Action.Container',
|
||||
'x-component-props': {
|
||||
className: 'nb-action-popup',
|
||||
},
|
||||
properties: {
|
||||
tabs: {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
'x-component': 'Tabs',
|
||||
'x-component-props': {},
|
||||
'x-initializer': 'TabPaneInitializers',
|
||||
properties: {
|
||||
tab1: {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
title: '{{t("Details")}}',
|
||||
'x-component': 'Tabs.TabPane',
|
||||
'x-designer': 'Tabs.Designer',
|
||||
'x-component-props': {},
|
||||
properties: {
|
||||
grid: {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
'x-component': 'Grid',
|
||||
'x-initializer': 'RecordBlockInitializers',
|
||||
properties: {
|
||||
'5ubuvb82lbu': {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
'x-component': 'Grid.Row',
|
||||
properties: {
|
||||
pe6vly71p50: {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
'x-component': 'Grid.Col',
|
||||
properties: {
|
||||
ls6i68y4q5r: {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
'x-acl-action-props': {
|
||||
skipScopeCheck: true,
|
||||
},
|
||||
'x-acl-action': 'general.m2mField0:create',
|
||||
'x-decorator': 'FormBlockProvider',
|
||||
'x-decorator-props': {
|
||||
useSourceId: '{{ useSourceIdFromParentRecord }}',
|
||||
useParams: '{{ useParamsFromRecord }}',
|
||||
action: null,
|
||||
dataSource: 'main',
|
||||
resource: 'general.m2mField0',
|
||||
collection: 'm2mField1',
|
||||
association: 'general.m2mField0',
|
||||
},
|
||||
'x-toolbar': 'BlockSchemaToolbar',
|
||||
'x-settings': 'blockSettings:createForm',
|
||||
'x-component': 'CardItem',
|
||||
'x-component-props': {},
|
||||
properties: {
|
||||
'4g1wyduvzzq': {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
'x-component': 'FormV2',
|
||||
'x-component-props': {
|
||||
useProps: '{{ useFormBlockProps }}',
|
||||
},
|
||||
properties: {
|
||||
grid: {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
'x-component': 'Grid',
|
||||
'x-initializer': 'FormItemInitializers',
|
||||
'x-uid': 'aigmsbzdyeb',
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
v5tx6a8ya3q: {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
'x-initializer': 'CreateFormActionInitializers',
|
||||
'x-component': 'ActionBar',
|
||||
'x-component-props': {
|
||||
layout: 'one-column',
|
||||
style: {
|
||||
marginTop: 24,
|
||||
},
|
||||
},
|
||||
properties: {
|
||||
dhmchgjzu2d: {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
title: '{{ t("Submit") }}',
|
||||
'x-action': 'submit',
|
||||
'x-component': 'Action',
|
||||
'x-toolbar': 'ActionSchemaToolbar',
|
||||
'x-settings': 'actionSettings:createSubmit',
|
||||
'x-component-props': {
|
||||
type: 'primary',
|
||||
htmlType: 'submit',
|
||||
useProps: '{{ useCreateActionProps }}',
|
||||
},
|
||||
'x-action-settings': {
|
||||
triggerWorkflows: [],
|
||||
},
|
||||
type: 'void',
|
||||
'x-uid': 'bgi90aunfbx',
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
},
|
||||
'x-uid': '6m4zb9wz65e',
|
||||
'x-async': false,
|
||||
'x-index': 2,
|
||||
},
|
||||
},
|
||||
'x-uid': 'sbl64rh18y4',
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
},
|
||||
'x-uid': 'z76kadyn2d8',
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
},
|
||||
'x-uid': 'kb89ln0xf6j',
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
},
|
||||
'x-uid': 'zyqb93i3dfg',
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
},
|
||||
'x-uid': 'zxthz54u0wr',
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
},
|
||||
'x-uid': '4vis0296ryj',
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
},
|
||||
'x-uid': 'p23nq2w7s15',
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
},
|
||||
'x-uid': 'zaqeevlcwap',
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
},
|
||||
'x-uid': 'r1tzkph9sg3',
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
},
|
||||
'x-uid': '2k7344qkff4',
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
},
|
||||
'x-uid': 'jozmqdix3a6',
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
exdcwiv8fnb: {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
'x-decorator': 'TableV2.Column.Decorator',
|
||||
'x-toolbar': 'TableColumnSchemaToolbar',
|
||||
'x-settings': 'fieldSettings:TableColumn',
|
||||
'x-component': 'TableV2.Column',
|
||||
properties: {
|
||||
m2mField0: {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
'x-collection-field': 'general.m2mField0',
|
||||
'x-component': 'CollectionField',
|
||||
'x-component-props': {
|
||||
fieldNames: {
|
||||
value: 'id',
|
||||
label: 'id',
|
||||
},
|
||||
ellipsis: true,
|
||||
size: 'small',
|
||||
},
|
||||
'x-read-pretty': true,
|
||||
'x-decorator': null,
|
||||
'x-decorator-props': {
|
||||
labelStyle: {
|
||||
display: 'none',
|
||||
},
|
||||
},
|
||||
'x-uid': 'gzktad04dhq',
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
},
|
||||
'x-uid': 'fulrpp42vr2',
|
||||
'x-async': false,
|
||||
'x-index': 2,
|
||||
},
|
||||
},
|
||||
'x-uid': '6rucf9up8f4',
|
||||
'x-async': false,
|
||||
'x-index': 2,
|
||||
},
|
||||
},
|
||||
'x-uid': 'izfl6h66ch4',
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
},
|
||||
'x-uid': 'i8m1l6l6qg5',
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
},
|
||||
'x-uid': 'v0y71zujt89',
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
},
|
||||
'x-uid': 'vpa330z2xp5',
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
},
|
||||
'x-uid': 'l4kzvh7mdoa',
|
||||
'x-async': true,
|
||||
'x-index': 1,
|
||||
},
|
||||
};
|
||||
|
@ -0,0 +1,22 @@
|
||||
import { useFieldSchema } from '@formily/react';
|
||||
import { SchemaSettings } from '../../../../application/schema-settings/SchemaSettings';
|
||||
import { SchemaSettingsDateFormat } from '../../../../schema-settings/SchemaSettingsDateFormat';
|
||||
import { useColumnSchema } from '../../../../schema-component/antd/table-v2/Table.Column.Decorator';
|
||||
|
||||
export const unixTimestampComponentFieldSettings = new SchemaSettings({
|
||||
name: 'fieldSettings:component:UnixTimestamp',
|
||||
items: [
|
||||
{
|
||||
name: 'dateDisplayFormat',
|
||||
Component: SchemaSettingsDateFormat as any,
|
||||
useComponentProps() {
|
||||
const schema = useFieldSchema();
|
||||
const { fieldSchema: tableColumnSchema } = useColumnSchema();
|
||||
const fieldSchema = tableColumnSchema || schema;
|
||||
return {
|
||||
fieldSchema,
|
||||
};
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
@ -1,18 +1,20 @@
|
||||
import { connect, mapReadPretty, observer, useField } from '@formily/react';
|
||||
import { Select, SelectProps, Tag } from 'antd';
|
||||
import React, { useContext } from 'react';
|
||||
import { Cascader, Select, SelectProps, Tag } from 'antd';
|
||||
import React, { useCallback, useContext, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useSelfAndChildrenCollections } from '../../../collection-manager/action-hooks';
|
||||
import { useCollection_deprecated, useCollectionManager_deprecated } from '../../../collection-manager/hooks';
|
||||
import { useCompile } from '../../hooks';
|
||||
import { FilterContext } from '../filter/context';
|
||||
import { useDataSourceManager } from '../../../data-source';
|
||||
import { parseCollectionName } from '../../../collection-manager';
|
||||
|
||||
export type CollectionSelectProps = SelectProps<any, any> & {
|
||||
filter?: (item: any, index: number, array: any[]) => boolean;
|
||||
isTableOid?: boolean;
|
||||
};
|
||||
|
||||
function useOptions({ filter, isTableOid }: CollectionSelectProps) {
|
||||
function useCollectionOptions({ filter, isTableOid }: CollectionSelectProps) {
|
||||
const compile = useCompile();
|
||||
const field: any = useField();
|
||||
const ctx: any = useContext(FilterContext);
|
||||
@ -29,20 +31,30 @@ function useOptions({ filter, isTableOid }: CollectionSelectProps) {
|
||||
typeof filter === 'function'
|
||||
? ((inheritCollections || currentCollections) as any[]).filter(filter)
|
||||
: inheritCollections || currentCollections;
|
||||
return filtered
|
||||
.filter((item) => !item.hidden)
|
||||
.map((item) => ({
|
||||
label: compile(item.title || item.label),
|
||||
value: item.name || item.value,
|
||||
color: item.category?.color,
|
||||
}));
|
||||
return useMemo(
|
||||
() =>
|
||||
filtered
|
||||
.filter((item) => !item.hidden)
|
||||
.map((item) => ({
|
||||
label: compile(item.title || item.label),
|
||||
value: item.name || item.value,
|
||||
color: item.category?.color,
|
||||
})),
|
||||
[filtered],
|
||||
);
|
||||
}
|
||||
|
||||
export const CollectionSelect = connect(
|
||||
(props: CollectionSelectProps) => {
|
||||
const { filter, ...others } = props;
|
||||
const options = useOptions(props);
|
||||
const options = useCollectionOptions(props);
|
||||
const { t } = useTranslation();
|
||||
const optionFilter = useCallback(
|
||||
(input, option) =>
|
||||
(option?.label.toLowerCase() ?? '').includes(input.toLocaleLowerCase()) ||
|
||||
(option?.value.toString().toLowerCase() ?? '').includes(input.toLocaleLowerCase()),
|
||||
[],
|
||||
);
|
||||
return (
|
||||
<Select
|
||||
// @ts-ignore
|
||||
@ -52,10 +64,7 @@ export const CollectionSelect = connect(
|
||||
popupMatchSelectWidth={false}
|
||||
{...others}
|
||||
showSearch
|
||||
filterOption={(input, option) =>
|
||||
(option?.label.toLowerCase() ?? '').includes(input.toLocaleLowerCase()) ||
|
||||
(option?.value.toString().toLowerCase() ?? '').includes(input.toLocaleLowerCase())
|
||||
}
|
||||
filterOption={optionFilter}
|
||||
options={options}
|
||||
/>
|
||||
);
|
||||
@ -65,7 +74,7 @@ export const CollectionSelect = connect(
|
||||
(props: CollectionSelectProps) => {
|
||||
const { mode } = props;
|
||||
const compile = useCompile();
|
||||
const options = useOptions(props).filter((option) => {
|
||||
const options = useCollectionOptions(props).filter((option) => {
|
||||
if (mode === 'multiple') {
|
||||
return (props.value ?? []).includes(option.value);
|
||||
}
|
||||
@ -86,3 +95,88 @@ export const CollectionSelect = connect(
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
export type DataSourceSelectProps = SelectProps<any, any> & {
|
||||
filter?: (item: any, index: number, array: any[]) => boolean;
|
||||
};
|
||||
|
||||
function useDataSourceOptions({ filter }: DataSourceSelectProps) {
|
||||
const compile = useCompile();
|
||||
const dataSourceManager = useDataSourceManager();
|
||||
const dataSources = dataSourceManager.getDataSources();
|
||||
return useMemo(
|
||||
() => [
|
||||
{
|
||||
label: compile('Main'),
|
||||
value: 'main',
|
||||
},
|
||||
...(typeof filter === 'function' ? dataSources.filter(filter) : dataSources).map((item) => ({
|
||||
label: item.displayName,
|
||||
value: item.key,
|
||||
})),
|
||||
],
|
||||
[dataSources, filter],
|
||||
);
|
||||
}
|
||||
|
||||
export const DataSourceSelect = connect((props: DataSourceSelectProps) => {
|
||||
const { filter, ...others } = props;
|
||||
const options = useDataSourceOptions(props);
|
||||
const { t } = useTranslation();
|
||||
const optionFilter = useCallback(
|
||||
(input, option) =>
|
||||
(option?.label.toLowerCase() ?? '').includes(input.toLocaleLowerCase()) ||
|
||||
(option?.value.toString().toLowerCase() ?? '').includes(input.toLocaleLowerCase()),
|
||||
[],
|
||||
);
|
||||
return (
|
||||
<Select
|
||||
// @ts-ignore
|
||||
role="button"
|
||||
data-testid="select-datasource"
|
||||
placeholder={t('Select data source')}
|
||||
popupMatchSelectWidth={false}
|
||||
{...others}
|
||||
showSearch
|
||||
filterOption={optionFilter}
|
||||
options={options}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
export const DataSourceCollectionCascader = connect((props) => {
|
||||
const dataSourceManager = useDataSourceManager();
|
||||
const compile = useCompile();
|
||||
const { value, onChange, dataSourceFilter, collectionFilter, ...others } = props;
|
||||
const [dataSourceName, collectionName] = parseCollectionName(value);
|
||||
const path = [dataSourceName, collectionName].filter(Boolean);
|
||||
const dataSources = dataSourceManager.getDataSources();
|
||||
|
||||
const options = useMemo(() => {
|
||||
return (dataSourceFilter ? dataSources.filter(dataSourceFilter) : dataSources).map((dataSource) => {
|
||||
return {
|
||||
label: compile(dataSource.displayName),
|
||||
value: dataSource.key,
|
||||
children: dataSource.collectionManager.collectionInstancesArr
|
||||
.filter(collectionFilter ?? ((collection) => !collection.hidden))
|
||||
.map((collection) => {
|
||||
return {
|
||||
label: compile(collection.title),
|
||||
value: collection.name,
|
||||
};
|
||||
}),
|
||||
};
|
||||
});
|
||||
}, [dataSources, dataSourceFilter, collectionFilter]);
|
||||
|
||||
const handleChange = useCallback(
|
||||
(value) => {
|
||||
if (!value) {
|
||||
return onChange(value);
|
||||
}
|
||||
onChange(value[0] === 'main' ? value[1] : value.join(':'));
|
||||
},
|
||||
[onChange],
|
||||
);
|
||||
return <Cascader showSearch {...others} options={options} value={path} onChange={handleChange} />;
|
||||
});
|
||||
|
@ -38,6 +38,7 @@ const InternalRangePicker = connect(
|
||||
export const DatePicker = (props) => {
|
||||
const { utc = true } = useDatePickerContext();
|
||||
const value = Array.isArray(props.value) ? props.value[0] : props.value;
|
||||
console.log(value);
|
||||
props = { utc, ...props };
|
||||
return <InternalDatePicker {...props} value={value} />;
|
||||
};
|
||||
|
@ -51,5 +51,7 @@ export * from './tree-select';
|
||||
export * from './upload';
|
||||
export * from './variable';
|
||||
export * from './custom-cascader';
|
||||
export * from './unixTimestamp';
|
||||
export * from './nanoIDInput';
|
||||
|
||||
import './index.less';
|
||||
|
@ -0,0 +1,46 @@
|
||||
import { customAlphabet as Alphabet } from 'nanoid';
|
||||
import React, { useEffect } from 'react';
|
||||
import { LoadingOutlined } from '@ant-design/icons';
|
||||
import { connect, mapProps, mapReadPretty, useForm } from '@formily/react';
|
||||
import { Input as AntdInput } from 'antd';
|
||||
import { ReadPretty } from '../input';
|
||||
import { useCollectionField } from '../../../data-source/collection-field/CollectionFieldProvider';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export const NanoIDInput = Object.assign(
|
||||
connect(
|
||||
AntdInput,
|
||||
mapProps((props: any, field: any) => {
|
||||
const { size, customAlphabet } = useCollectionField();
|
||||
const { t } = useTranslation();
|
||||
const form = useForm();
|
||||
function isValidNanoid(value) {
|
||||
if (value.length !== size) {
|
||||
return t('Field value size is') + ` ${size}`;
|
||||
}
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
if (customAlphabet.indexOf(value[i]) === -1) {
|
||||
return t(`Field value do not meet the requirements`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (!field.initialValue) {
|
||||
field.setInitialValue(Alphabet(customAlphabet, size)());
|
||||
}
|
||||
form.setFieldState(field.props.name, (state) => {
|
||||
state.validator = isValidNanoid;
|
||||
});
|
||||
}, []);
|
||||
return {
|
||||
...props,
|
||||
suffix: <span>{field?.['loading'] || field?.['validating'] ? <LoadingOutlined /> : props.suffix}</span>,
|
||||
};
|
||||
}),
|
||||
mapReadPretty(ReadPretty.Input),
|
||||
),
|
||||
{
|
||||
ReadPretty: ReadPretty.Input,
|
||||
},
|
||||
);
|
@ -0,0 +1 @@
|
||||
export * from './NanoIDInput';
|
@ -21,9 +21,17 @@ Radio.__ANT_RADIO = true;
|
||||
|
||||
Radio.Group = connect(
|
||||
AntdRadio.Group,
|
||||
mapProps({
|
||||
dataSource: 'options',
|
||||
}),
|
||||
mapProps(
|
||||
{
|
||||
dataSource: 'options',
|
||||
},
|
||||
(props) => {
|
||||
return {
|
||||
...props,
|
||||
value: props.value && typeof props.value !== 'boolean' ? props.value.toString() : props.value,
|
||||
};
|
||||
},
|
||||
),
|
||||
mapReadPretty((props) => {
|
||||
if (!isValid(props.value)) {
|
||||
return <div></div>;
|
||||
|
@ -9,11 +9,11 @@ import React from 'react';
|
||||
const options = [
|
||||
{
|
||||
label: '男',
|
||||
value: 1,
|
||||
value: '1',
|
||||
},
|
||||
{
|
||||
label: '女',
|
||||
value: 2,
|
||||
value: '2',
|
||||
},
|
||||
];
|
||||
|
||||
|
@ -8,12 +8,12 @@ import React from 'react';
|
||||
const options = [
|
||||
{
|
||||
label: '男',
|
||||
value: 1,
|
||||
value: '1',
|
||||
color: 'blue',
|
||||
},
|
||||
{
|
||||
label: '女',
|
||||
value: 2,
|
||||
value: '2',
|
||||
color: 'red',
|
||||
},
|
||||
];
|
||||
|
@ -122,7 +122,7 @@ const InternalSelect = connect(
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
return v;
|
||||
return v ? v.toString() : v;
|
||||
};
|
||||
return (
|
||||
<AntdSelect
|
||||
|
@ -44,7 +44,10 @@ export function getCurrentOptions(values: string | string[], dataSource: any[],
|
||||
if (!options) return [];
|
||||
const current: Option[] = [];
|
||||
for (const value of arrValues) {
|
||||
const option = options.find((v) => v[fieldNames.value] === value) || { value, label: value };
|
||||
const option = options.find((v) => v[fieldNames.value] == value) || {
|
||||
value,
|
||||
label: value ? value.toString() : value,
|
||||
};
|
||||
current.push(option);
|
||||
}
|
||||
return current;
|
||||
|
@ -0,0 +1,49 @@
|
||||
import { connect, mapReadPretty } from '@formily/react';
|
||||
import React, { useMemo } from 'react';
|
||||
import { DatePicker } from '../date-picker';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
const toValue = (value: any, accuracy) => {
|
||||
if (value) {
|
||||
return timestampToDate(value, accuracy);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
function timestampToDate(timestamp, accuracy = 'millisecond') {
|
||||
if (accuracy === 'second') {
|
||||
timestamp *= 1000; // 如果精确度是秒级,则将时间戳乘以1000转换为毫秒级
|
||||
}
|
||||
return dayjs(timestamp);
|
||||
}
|
||||
|
||||
function getTimestamp(date, accuracy = 'millisecond') {
|
||||
if (accuracy === 'second') {
|
||||
return dayjs(date).unix();
|
||||
} else {
|
||||
return dayjs(date).valueOf(); // 默认返回毫秒级时间戳
|
||||
}
|
||||
}
|
||||
|
||||
export const UnixTimestamp = connect(
|
||||
(props) => {
|
||||
const { value, onChange, accuracy } = props;
|
||||
const v = useMemo(() => toValue(value, accuracy), [value]);
|
||||
return (
|
||||
<DatePicker
|
||||
{...props}
|
||||
value={v}
|
||||
onChange={(v: any) => {
|
||||
if (onChange) {
|
||||
onChange(getTimestamp(v, accuracy));
|
||||
}
|
||||
}}
|
||||
/>
|
||||
);
|
||||
},
|
||||
mapReadPretty((props) => {
|
||||
const { value, accuracy } = props;
|
||||
const v = useMemo(() => toValue(value, accuracy), [value]);
|
||||
return <DatePicker.ReadPretty {...props} value={v} />;
|
||||
}),
|
||||
);
|
@ -0,0 +1 @@
|
||||
export * from './UnixTimestamp';
|
@ -43,6 +43,7 @@ import { subformPopoverComponentFieldSettings } from '../modules/fields/componen
|
||||
import { selectComponentFieldSettings } from '../modules/fields/component/Select/selectComponentFieldSettings';
|
||||
import { subTablePopoverComponentFieldSettings } from '../modules/fields/component/SubTable/subTablePopoverComponentFieldSettings';
|
||||
import { tagComponentFieldSettings } from '../modules/fields/component/Tag/tagComponentFieldSettings';
|
||||
import { unixTimestampComponentFieldSettings } from '../modules/fields/component/UnixTimestamp/unixTimestampComponentFieldSettings';
|
||||
|
||||
export class SchemaSettingsPlugin extends Plugin {
|
||||
async load() {
|
||||
@ -91,6 +92,8 @@ export class SchemaSettingsPlugin extends Plugin {
|
||||
this.schemaSettingsManager.add(subformPopoverComponentFieldSettings);
|
||||
this.schemaSettingsManager.add(subTablePopoverComponentFieldSettings);
|
||||
this.schemaSettingsManager.add(datePickerComponentFieldSettings);
|
||||
this.schemaSettingsManager.add(unixTimestampComponentFieldSettings);
|
||||
|
||||
this.schemaSettingsManager.add(fileManagerComponentFieldSettings);
|
||||
this.schemaSettingsManager.add(tagComponentFieldSettings);
|
||||
this.schemaSettingsManager.add(cascadeSelectComponentFieldSettings);
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "create-nocobase-app",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"main": "src/index.js",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
|
@ -1,16 +1,16 @@
|
||||
{
|
||||
"name": "@nocobase/data-source-manager",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"description": "",
|
||||
"license": "Apache-2.0",
|
||||
"main": "./lib/index.js",
|
||||
"types": "./lib/index.d.ts",
|
||||
"dependencies": {
|
||||
"@nocobase/actions": "0.20.0-alpha.8",
|
||||
"@nocobase/cache": "0.20.0-alpha.8",
|
||||
"@nocobase/database": "0.20.0-alpha.8",
|
||||
"@nocobase/resourcer": "0.20.0-alpha.8",
|
||||
"@nocobase/utils": "0.20.0-alpha.8",
|
||||
"@nocobase/actions": "0.20.0-alpha.9",
|
||||
"@nocobase/cache": "0.20.0-alpha.9",
|
||||
"@nocobase/database": "0.20.0-alpha.9",
|
||||
"@nocobase/resourcer": "0.20.0-alpha.9",
|
||||
"@nocobase/utils": "0.20.0-alpha.9",
|
||||
"@types/jsonwebtoken": "^8.5.8",
|
||||
"jsonwebtoken": "^8.5.1"
|
||||
},
|
||||
|
@ -9,3 +9,4 @@ export * from './load-default-actions';
|
||||
export * from './types';
|
||||
|
||||
export * from './data-source-with-database';
|
||||
export * from './utils';
|
||||
|
9
packages/core/data-source-manager/src/utils.ts
Normal file
9
packages/core/data-source-manager/src/utils.ts
Normal file
@ -0,0 +1,9 @@
|
||||
export function parseCollectionName(collection: string) {
|
||||
if (!collection) {
|
||||
return [];
|
||||
}
|
||||
const dataSourceCollection = collection.split(':');
|
||||
const collectionName = dataSourceCollection.pop();
|
||||
const dataSourceName = dataSourceCollection[0] ?? 'main';
|
||||
return [dataSourceName, collectionName];
|
||||
}
|
@ -1,13 +1,13 @@
|
||||
{
|
||||
"name": "@nocobase/database",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"description": "",
|
||||
"main": "./lib/index.js",
|
||||
"types": "./lib/index.d.ts",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@nocobase/logger": "0.20.0-alpha.8",
|
||||
"@nocobase/utils": "0.20.0-alpha.8",
|
||||
"@nocobase/logger": "0.20.0-alpha.9",
|
||||
"@nocobase/utils": "0.20.0-alpha.9",
|
||||
"async-mutex": "^0.3.2",
|
||||
"chalk": "^4.1.1",
|
||||
"cron-parser": "4.4.0",
|
||||
|
@ -0,0 +1,39 @@
|
||||
import { mockDatabase } from '../';
|
||||
import { Database } from '../../database';
|
||||
|
||||
describe('nanoid field', () => {
|
||||
let db: Database;
|
||||
|
||||
beforeEach(async () => {
|
||||
db = mockDatabase();
|
||||
await db.clean({ drop: true });
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await db.close();
|
||||
});
|
||||
|
||||
it('should create nanoid field type', async () => {
|
||||
const Test = db.collection({
|
||||
name: 'tests',
|
||||
autoGenId: false,
|
||||
fields: [
|
||||
{
|
||||
type: 'nanoid',
|
||||
name: 'id',
|
||||
primaryKey: true,
|
||||
size: 21,
|
||||
customAlphabet: '1234567890abcdef',
|
||||
},
|
||||
{
|
||||
type: 'nanoid',
|
||||
name: 'id2',
|
||||
},
|
||||
],
|
||||
});
|
||||
await Test.sync();
|
||||
const test = await Test.model.create();
|
||||
expect(test.id).toHaveLength(21);
|
||||
expect(test.id2).toHaveLength(12);
|
||||
});
|
||||
});
|
@ -25,6 +25,7 @@ import { TimeFieldOptions } from './time-field';
|
||||
import { UidFieldOptions } from './uid-field';
|
||||
import { UUIDFieldOptions } from './uuid-field';
|
||||
import { VirtualFieldOptions } from './virtual-field';
|
||||
import { NanoidFieldOptions } from './nanoid-field';
|
||||
|
||||
export * from './array-field';
|
||||
export * from './belongs-to-field';
|
||||
@ -48,6 +49,7 @@ export * from './time-field';
|
||||
export * from './uid-field';
|
||||
export * from './uuid-field';
|
||||
export * from './virtual-field';
|
||||
export * from './nanoid-field';
|
||||
|
||||
export type FieldOptions =
|
||||
| BaseFieldOptions
|
||||
@ -70,6 +72,7 @@ export type FieldOptions =
|
||||
| DateFieldOptions
|
||||
| UidFieldOptions
|
||||
| UUIDFieldOptions
|
||||
| NanoidFieldOptions
|
||||
| PasswordFieldOptions
|
||||
| ContextFieldOptions
|
||||
| BelongsToFieldOptions
|
||||
|
40
packages/core/database/src/fields/nanoid-field.ts
Normal file
40
packages/core/database/src/fields/nanoid-field.ts
Normal file
@ -0,0 +1,40 @@
|
||||
import { DataTypes } from 'sequelize';
|
||||
import { BaseColumnFieldOptions, Field } from './field';
|
||||
import { customAlphabet, nanoid } from 'nanoid';
|
||||
|
||||
const DEFAULT_SIZE = 12;
|
||||
export class NanoidField extends Field {
|
||||
get dataType() {
|
||||
return DataTypes.STRING;
|
||||
}
|
||||
|
||||
init() {
|
||||
const { name, size, customAlphabet: customAlphabetOptions } = this.options;
|
||||
|
||||
this.listener = async (instance) => {
|
||||
const value = instance.get(name);
|
||||
if (!value) {
|
||||
const nanoIdFunc = customAlphabetOptions ? customAlphabet(customAlphabetOptions) : nanoid;
|
||||
instance.set(name, nanoIdFunc(size || DEFAULT_SIZE));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
bind() {
|
||||
super.bind();
|
||||
this.on('beforeCreate', this.listener);
|
||||
this.on('beforeUpdate', this.listener);
|
||||
}
|
||||
|
||||
unbind() {
|
||||
super.unbind();
|
||||
this.off('beforeCreate', this.listener);
|
||||
this.off('beforeUpdate', this.listener);
|
||||
}
|
||||
}
|
||||
|
||||
export interface NanoidFieldOptions extends BaseColumnFieldOptions {
|
||||
type: 'nanoid';
|
||||
size?: number;
|
||||
customAlphabet?: string;
|
||||
}
|
@ -1,9 +1,10 @@
|
||||
const postgres = {
|
||||
'character varying': 'string',
|
||||
varchar: 'string',
|
||||
'character varying': ['string', 'uuid', 'nanoid'],
|
||||
varchar: ['string', 'uuid', 'nanoid'],
|
||||
char: ['string', 'uuid', 'nanoid'],
|
||||
|
||||
character: 'string',
|
||||
text: 'text',
|
||||
char: 'string',
|
||||
oid: 'string',
|
||||
name: 'string',
|
||||
|
||||
@ -29,7 +30,7 @@ const postgres = {
|
||||
path: 'json',
|
||||
polygon: 'json',
|
||||
circle: 'json',
|
||||
uuid: 'string',
|
||||
uuid: 'uuid',
|
||||
};
|
||||
|
||||
const mysql = {
|
||||
@ -41,10 +42,10 @@ const mysql = {
|
||||
'tinyint unsigned': ['integer', 'boolean', 'sort'],
|
||||
'mediumint unsigned': ['integer', 'boolean', 'sort'],
|
||||
|
||||
char: 'string',
|
||||
char: ['string', 'uuid', 'nanoid'],
|
||||
varchar: ['string', 'uuid', 'nanoid'],
|
||||
date: 'date',
|
||||
time: 'time',
|
||||
varchar: 'string',
|
||||
text: 'text',
|
||||
longtext: 'text',
|
||||
int: ['integer', 'sort'],
|
||||
@ -64,7 +65,7 @@ const mysql = {
|
||||
|
||||
const sqlite = {
|
||||
text: 'text',
|
||||
varchar: 'string',
|
||||
varchar: ['string', 'uuid', 'nanoid'],
|
||||
|
||||
integer: 'integer',
|
||||
real: 'real',
|
||||
|
@ -1,13 +1,13 @@
|
||||
{
|
||||
"name": "@nocobase/devtools",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"description": "",
|
||||
"license": "Apache-2.0",
|
||||
"main": "./src/index.js",
|
||||
"dependencies": {
|
||||
"@nocobase/build": "0.20.0-alpha.8",
|
||||
"@nocobase/client": "0.20.0-alpha.8",
|
||||
"@nocobase/test": "0.20.0-alpha.8",
|
||||
"@nocobase/build": "0.20.0-alpha.9",
|
||||
"@nocobase/client": "0.20.0-alpha.9",
|
||||
"@nocobase/test": "0.20.0-alpha.9",
|
||||
"@types/koa": "^2.13.4",
|
||||
"@types/koa-bodyparser": "^4.3.4",
|
||||
"@types/lodash": "^4.14.177",
|
||||
|
@ -1,13 +1,13 @@
|
||||
{
|
||||
"name": "@nocobase/evaluators",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"description": "",
|
||||
"main": "./lib/index.js",
|
||||
"types": "./lib/index.d.ts",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@formulajs/formulajs": "4.2.0",
|
||||
"@nocobase/utils": "0.20.0-alpha.8",
|
||||
"@nocobase/utils": "0.20.0-alpha.9",
|
||||
"mathjs": "^10.6.0"
|
||||
},
|
||||
"repository": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/logger",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"description": "nocobase logging library",
|
||||
"license": "Apache-2.0",
|
||||
"main": "./lib/index.js",
|
||||
|
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@nocobase/resourcer",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"description": "",
|
||||
"main": "./lib/index.js",
|
||||
"types": "./lib/index.d.ts",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@nocobase/utils": "0.20.0-alpha.8",
|
||||
"@nocobase/utils": "0.20.0-alpha.9",
|
||||
"deepmerge": "^4.2.2",
|
||||
"koa-compose": "^4.1.0",
|
||||
"lodash": "^4.17.21",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/sdk",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"license": "Apache-2.0",
|
||||
"main": "lib/index.js",
|
||||
"types": "lib/index.d.ts",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/server",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"main": "lib/index.js",
|
||||
"types": "./lib/index.d.ts",
|
||||
"license": "Apache-2.0",
|
||||
@ -10,18 +10,18 @@
|
||||
"@koa/cors": "^3.1.0",
|
||||
"@koa/multer": "^3.0.2",
|
||||
"@koa/router": "^9.4.0",
|
||||
"@nocobase/acl": "0.20.0-alpha.8",
|
||||
"@nocobase/actions": "0.20.0-alpha.8",
|
||||
"@nocobase/auth": "0.20.0-alpha.8",
|
||||
"@nocobase/cache": "0.20.0-alpha.8",
|
||||
"@nocobase/data-source-manager": "0.20.0-alpha.8",
|
||||
"@nocobase/database": "0.20.0-alpha.8",
|
||||
"@nocobase/evaluators": "0.20.0-alpha.8",
|
||||
"@nocobase/logger": "0.20.0-alpha.8",
|
||||
"@nocobase/resourcer": "0.20.0-alpha.8",
|
||||
"@nocobase/sdk": "0.20.0-alpha.8",
|
||||
"@nocobase/telemetry": "0.20.0-alpha.8",
|
||||
"@nocobase/utils": "0.20.0-alpha.8",
|
||||
"@nocobase/acl": "0.20.0-alpha.9",
|
||||
"@nocobase/actions": "0.20.0-alpha.9",
|
||||
"@nocobase/auth": "0.20.0-alpha.9",
|
||||
"@nocobase/cache": "0.20.0-alpha.9",
|
||||
"@nocobase/data-source-manager": "0.20.0-alpha.9",
|
||||
"@nocobase/database": "0.20.0-alpha.9",
|
||||
"@nocobase/evaluators": "0.20.0-alpha.9",
|
||||
"@nocobase/logger": "0.20.0-alpha.9",
|
||||
"@nocobase/resourcer": "0.20.0-alpha.9",
|
||||
"@nocobase/sdk": "0.20.0-alpha.9",
|
||||
"@nocobase/telemetry": "0.20.0-alpha.9",
|
||||
"@nocobase/utils": "0.20.0-alpha.9",
|
||||
"@types/decompress": "4.2.4",
|
||||
"@types/ini": "^1.3.31",
|
||||
"@types/koa-send": "^4.1.3",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/telemetry",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"description": "nocobase telemetry library",
|
||||
"license": "Apache-2.0",
|
||||
"main": "./lib/index.js",
|
||||
@ -11,7 +11,7 @@
|
||||
"directory": "packages/telemetry"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nocobase/utils": "0.20.0-alpha.8",
|
||||
"@nocobase/utils": "0.20.0-alpha.9",
|
||||
"@opentelemetry/api": "^1.7.0",
|
||||
"@opentelemetry/instrumentation": "^0.46.0",
|
||||
"@opentelemetry/resources": "^1.19.0",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/test",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"main": "lib/index.js",
|
||||
"module": "./src/index.ts",
|
||||
"types": "./lib/index.d.ts",
|
||||
@ -40,7 +40,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@faker-js/faker": "8.1.0",
|
||||
"@nocobase/server": "0.20.0-alpha.8",
|
||||
"@nocobase/server": "0.20.0-alpha.9",
|
||||
"@playwright/test": "^1.42.1",
|
||||
"@testing-library/react": "^14.0.0",
|
||||
"@testing-library/user-event": "^14.4.3",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/utils",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"main": "lib/index.js",
|
||||
"types": "./lib/index.d.ts",
|
||||
"license": "Apache-2.0",
|
||||
|
@ -4,7 +4,7 @@
|
||||
"displayName.zh-CN": "权限控制",
|
||||
"description": "Based on roles, resources, and actions, access control can precisely manage interface configuration permissions, data operation permissions, menu access permissions, and plugin permissions.",
|
||||
"description.zh-CN": "基于角色、资源和操作的权限控制,可以精确控制界面配置权限、数据操作权限、菜单访问权限、插件权限。",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "./dist/server/index.js",
|
||||
"homepage": "https://docs.nocobase.com/handbook/acl",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/plugin-action-bulk-edit",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"main": "dist/server/index.js",
|
||||
"homepage": "https://docs.nocobase.com/handbook/action-bulk-edit",
|
||||
"homepage.zh-CN": "https://docs-cn.nocobase.com/handbook/action-bulk-edit",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/plugin-action-bulk-update",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"main": "dist/server/index.js",
|
||||
"homepage": "https://docs.nocobase.com/handbook/action-bulk-update",
|
||||
"homepage.zh-CN": "https://docs-cn.nocobase.com/handbook/action-bulk-update",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/plugin-action-duplicate",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"main": "dist/server/index.js",
|
||||
"homepage": "https://docs.nocobase.com/handbook/action-duplicate",
|
||||
"homepage.zh-CN": "https://docs-cn.nocobase.com/handbook/action-duplicate",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/plugin-action-print",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"main": "dist/server/index.js",
|
||||
"homepage": "https://docs.nocobase.com/handbook/action-print",
|
||||
"homepage.zh-CN": "https://docs-cn.nocobase.com/handbook/action-print",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/plugin-api-doc",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"displayName": "API documentation",
|
||||
"displayName.zh-CN": "API 文档",
|
||||
"description": "An OpenAPI documentation generator for NocoBase HTTP API.",
|
||||
|
@ -4,7 +4,7 @@
|
||||
"displayName.zh-CN": "认证:API 密钥",
|
||||
"description": "Allows users to use API key to access application's HTTP API",
|
||||
"description.zh-CN": "允许用户使用 API 密钥访问应用的 HTTP API",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "./dist/server/index.js",
|
||||
"homepage": "https://docs.nocobase.com/handbook/api-keys",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/plugin-audit-logs",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"displayName": "Audit logs (deprecated)",
|
||||
"displayName.zh-CN": "审计日志(废弃)",
|
||||
"description": "This plugin is deprecated. There will be a new audit log plugin in the future.",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/plugin-auth",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"main": "./dist/server/index.js",
|
||||
"homepage": "https://docs.nocobase.com/handbook/auth",
|
||||
"homepage.zh-CN": "https://docs-cn.nocobase.com/handbook/auth",
|
||||
|
@ -4,7 +4,7 @@
|
||||
"displayName.zh-CN": "应用的备份与还原",
|
||||
"description": "Backup and restore applications for scenarios such as application replication, migration, and upgrades.",
|
||||
"description.zh-CN": "备份和还原应用,可用于应用的复制、迁移、升级等场景。",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "./dist/server/index.js",
|
||||
"homepage": "https://docs.nocobase.com/handbook/backup-restore",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/plugin-calendar",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"displayName": "Calendar",
|
||||
"displayName.zh-CN": "日历",
|
||||
"description": "Provides callendar collection template and block for managing date data, typically for date/time related information such as events, appointments, tasks, and so on.",
|
||||
|
@ -4,7 +4,7 @@
|
||||
"displayName.zh-CN": "认证:CAS",
|
||||
"description": "CAS authentication.",
|
||||
"description.zh-CN": "通过 CAS 协议认证身份。",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "./dist/server/index.js",
|
||||
"homepage": "https://docs.nocobase.com/handbook/auth-cas",
|
||||
|
@ -4,7 +4,7 @@
|
||||
"displayName.zh-CN": "图表(废弃)",
|
||||
"description": "The plugin has been deprecated, please use the data visualization plugin instead.",
|
||||
"description.zh-CN": "已废弃插件,请使用数据可视化插件代替。",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"main": "./dist/server/index.js",
|
||||
"license": "AGPL-3.0",
|
||||
"devDependencies": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/plugin-china-region",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"displayName": "Administrative divisions of China",
|
||||
"displayName.zh-CN": "中国行政区划",
|
||||
"description": "Provides data and field type for administrative divisions of China.",
|
||||
|
@ -4,7 +4,7 @@
|
||||
"displayName.zh-CN": "WEB 客户端",
|
||||
"description": "Provides a client interface for the NocoBase server",
|
||||
"description.zh-CN": "为 NocoBase 服务端提供客户端界面",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"main": "./dist/server/index.js",
|
||||
"license": "AGPL-3.0",
|
||||
"devDependencies": {
|
||||
|
@ -4,7 +4,7 @@
|
||||
"displayName.zh-CN": "数据源:主数据库",
|
||||
"description": "NocoBase main database, supports relational databases such as MySQL, PostgreSQL, SQLite and so on.",
|
||||
"description.zh-CN": "NocoBase 主数据库,支持 MySQL、PostgreSQL、SQLite 等关系型数据库。",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"main": "./dist/server/index.js",
|
||||
"homepage": "https://docs.nocobase.com/handbook/data-source-main",
|
||||
"homepage.zh-CN": "https://docs-cn.nocobase.com/handbook/data-source-main",
|
||||
|
@ -496,23 +496,16 @@ test.describe('form item & view form', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('field component', async ({ page, mockPage, mockRecords }) => {
|
||||
await (async (mockPage, mockRecords) => {
|
||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||
const record = (await mockRecords('general', 1))[0];
|
||||
await nocoPage.goto();
|
||||
test('field component', async ({ page, mockPage, mockRecord }) => {
|
||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||
await mockRecord('general');
|
||||
await nocoPage.goto();
|
||||
|
||||
return record;
|
||||
})(mockPage, mockRecords);
|
||||
await (async (page: Page) => {
|
||||
await page.getByLabel('action-Action.Link-View record-view-general-table-0').click();
|
||||
})(page);
|
||||
await (async (page: Page, fieldName: string) => {
|
||||
await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover();
|
||||
await page
|
||||
.getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`)
|
||||
.hover();
|
||||
})(page, 'oneToMany');
|
||||
await page.getByLabel('action-Action.Link-View record-view-general-table-0').click();
|
||||
await page.getByLabel(`block-item-CollectionField-general-form-general.oneToMany-oneToMany`).hover();
|
||||
await page
|
||||
.getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.oneToMany`)
|
||||
.hover();
|
||||
await page.getByRole('menuitem', { name: 'Field component' }).click();
|
||||
|
||||
// 断言支持的选项
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/plugin-custom-request",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"main": "dist/server/index.js",
|
||||
"homepage": "https://docs.nocobase.com/handbook/action-custom-request",
|
||||
"homepage.zh-CN": "https://docs-cn.nocobase.com/handbook/action-custom-request",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/plugin-data-source-manager",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"main": "dist/server/index.js",
|
||||
"displayName": "Data source manager",
|
||||
"displayName.zh-CN": "数据源管理",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/plugin-data-visualization",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"displayName": "Data visualization",
|
||||
"displayName.zh-CN": "数据可视化",
|
||||
"description": "Provides data visualization feature, including chart block and chart filter block, support line charts, area charts, bar charts and more than a dozen kinds of charts, you can also extend more chart types.",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/plugin-disable-pm-add",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"main": "./dist/server/index.js",
|
||||
"peerDependencies": {
|
||||
"@nocobase/client": "0.x",
|
||||
|
@ -4,7 +4,7 @@
|
||||
"displayName.zh-CN": "错误处理器",
|
||||
"description": "Handling application errors and exceptions.",
|
||||
"description.zh-CN": "处理应用程序中的错误和异常。",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "./dist/server/index.js",
|
||||
"devDependencies": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/plugin-excel-formula-field",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"description": "",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "./dist/server/index.js",
|
||||
|
@ -4,7 +4,7 @@
|
||||
"displayName.zh-CN": "操作:导出记录",
|
||||
"description": "Export filtered records to excel, you can configure which fields to export.",
|
||||
"description.zh-CN": "导出筛选后的记录到 Excel 中,可以配置导出哪些字段。",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "./dist/server/index.js",
|
||||
"homepage": "https://docs.nocobase.com/handbook/action-export",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/plugin-file-manager",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"displayName": "File manager",
|
||||
"displayName.zh-CN": "文件管理器",
|
||||
"description": "Provides files storage services with files collection template and attachment field.",
|
||||
|
@ -4,7 +4,7 @@
|
||||
"displayName.zh-CN": "数据表字段:公式",
|
||||
"description": "Configure and store the results of calculations between multiple field values in the same record, supporting both Math.js and Excel formula functions.",
|
||||
"description.zh-CN": "可以配置并存储同一条记录的多字段值之间的计算结果,支持 Math.js 和 Excel formula functions 两种引擎",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "./dist/server/index.js",
|
||||
"homepage": "https://docs.nocobase.com/handbook/field-formula",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/plugin-gantt",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"displayName": "Block: Gantt",
|
||||
"displayName.zh-CN": "区块:甘特图",
|
||||
"description": "Provides Gantt block.",
|
||||
|
@ -4,7 +4,7 @@
|
||||
"displayName.zh-CN": "可视化数据表管理",
|
||||
"description": "An ER diagram-like tool. Currently only the Master database is supported.",
|
||||
"description.zh-CN": "类似 ER 图的工具,目前只支持主数据库。",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "./dist/server/index.js",
|
||||
"homepage": "https://docs.nocobase.com/handbook/graph-collection-manager",
|
||||
|
@ -4,7 +4,7 @@
|
||||
"displayName.zh-CN": "区块:iframe",
|
||||
"description": "Create an iframe block on the page to embed and display external web pages or content.",
|
||||
"description.zh-CN": "在页面上创建和管理iframe,用于嵌入和展示外部网页或内容。",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "./dist/server/index.js",
|
||||
"homepage": "https://docs.nocobase.com/handbook/block-iframe",
|
||||
|
@ -4,7 +4,7 @@
|
||||
"displayName.zh-CN": "操作:导入记录",
|
||||
"description": "Import records using excel templates. You can configure which fields to import and templates will be generated automatically.",
|
||||
"description.zh-CN": "使用 Excel 模板导入数据,可以配置导入哪些字段,自动生成模板。",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "./dist/server/index.js",
|
||||
"homepage": "https://docs.nocobase.com/handbook/action-import",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/plugin-kanban",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"main": "dist/server/index.js",
|
||||
"homepage": "https://docs.nocobase.com/handbook/block-kanban",
|
||||
"homepage.zh-CN": "https://docs-cn.nocobase.com/handbook/block-kanban",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/plugin-localization-management",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"main": "dist/server/index.js",
|
||||
"homepage": "https://docs.nocobase.com/handbook/localization-management",
|
||||
"homepage.zh-CN": "https://docs-cn.nocobase.com/handbook/localization-management",
|
||||
|
@ -4,7 +4,7 @@
|
||||
"displayName.zh-CN": "日志",
|
||||
"description": "Server-side logs, mainly including API request logs and system runtime logs, and allows to package and download log files.",
|
||||
"description.zh-CN": "服务端日志,主要包括接口请求日志和系统运行日志,并支持打包和下载日志文件。",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "dist/server/index.js",
|
||||
"homepage": "https://docs.nocobase.com/handbook/logger",
|
||||
|
@ -2,7 +2,7 @@
|
||||
"name": "@nocobase/plugin-map",
|
||||
"displayName": "Block: Map",
|
||||
"displayName.zh-CN": "区块:地图",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"description": "Map block, support Gaode map and Google map, you can also extend more map types.",
|
||||
"description.zh-CN": "地图区块,支持高德地图和 Google 地图,你也可以扩展更多地图类型。",
|
||||
"license": "AGPL-3.0",
|
||||
|
@ -4,7 +4,7 @@
|
||||
"displayName.zh-CN": "数学公式字段",
|
||||
"description": "A powerful mathematical formula field plugin designed to provide flexible mathematical and formula calculation capabilities for databases or data management systems. It seamlessly integrates with various database systems such as MySQL, PostgreSQL, and offers an intuitive user interface for defining and executing mathematical formula fields.",
|
||||
"description.zh-CN": "一个功能强大的数学公式字段插件,旨在为数据库或数据管理系统提供灵活的数学计算和公式计算功能。它可以与各种数据库系统(如MySQL、PostgreSQL)无缝集成,并提供直观的用户界面来定义和执行数学公式字段。",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "./dist/server/index.js",
|
||||
"devDependencies": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/plugin-mobile-client",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"main": "./dist/server/index.js",
|
||||
"homepage": "https://docs.nocobase.com/handbook/mobile-client",
|
||||
"homepage.zh-CN": "https://docs-cn.nocobase.com/handbook/mobile-client",
|
||||
|
@ -2,7 +2,7 @@
|
||||
"name": "@nocobase/plugin-mock-collections",
|
||||
"displayName": "mock-collections",
|
||||
"description": "mock-collections",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"main": "./dist/server/index.js",
|
||||
"license": "AGPL-3.0",
|
||||
"peerDependencies": {
|
||||
|
@ -4,7 +4,7 @@
|
||||
"displayName.zh-CN": "多应用管理器",
|
||||
"description": "Dynamically create multiple apps without separate deployments.",
|
||||
"description.zh-CN": "无需单独部署即可动态创建多个应用。",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "./dist/server/index.js",
|
||||
"homepage": "https://docs.nocobase.com/handbook/multi-app-manager",
|
||||
|
@ -4,7 +4,7 @@
|
||||
"displayName.zh-CN": "多应用数据表共享",
|
||||
"description": "",
|
||||
"description.zh-CN": "",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"main": "./dist/server/index.js",
|
||||
"devDependencies": {
|
||||
"@formily/react": "2.x",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/plugin-notifications",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"description": "",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "./dist/server/index.js",
|
||||
|
@ -4,7 +4,7 @@
|
||||
"displayName.zh-CN": "认证:OIDC",
|
||||
"description": "OIDC (OpenID Connect) authentication.",
|
||||
"description.zh-CN": "通过 OIDC (OpenID Connect) 协议认证身份。",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "./dist/server/index.js",
|
||||
"homepage": "https://docs.nocobase.com/handbook/auth-oidc",
|
||||
|
@ -4,7 +4,7 @@
|
||||
"displayName.zh-CN": "认证:SAML 2.0",
|
||||
"description": "SAML 2.0 authentication.",
|
||||
"description.zh-CN": "通过 SAML 2.0 协议认证身份。",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "./dist/server/index.js",
|
||||
"homepage": "https://docs.nocobase.com/handbook/auth-saml",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/plugin-sample-hello",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"main": "./dist/server/index.js",
|
||||
"displayName": "Hello",
|
||||
"displayName.zh-CN": "Hello",
|
||||
|
@ -4,7 +4,7 @@
|
||||
"displayName.zh-CN": "数据表字段:自动编码",
|
||||
"description": "Automatically generate codes based on configured rules, supporting combinations of dates, numbers, and text.",
|
||||
"description.zh-CN": "根据配置的规则自动生成编码,支持日期、数字、文本的组合。",
|
||||
"version": "0.20.0-alpha.8",
|
||||
"version": "0.20.0-alpha.9",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "./dist/server/index.js",
|
||||
"homepage": "https://docs.nocobase.com/handbook/field-sequence",
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user