Merge remote-tracking branch 'origin/main' into merge_from_upstream
This commit is contained in:
commit
de89814eba
19
.github/workflows/manual-e2e.yml
vendored
19
.github/workflows/manual-e2e.yml
vendored
@ -43,18 +43,11 @@ jobs:
|
|||||||
ref: ${{ inputs.branch }}
|
ref: ${{ inputs.branch }}
|
||||||
path: packages/pro-plugins
|
path: packages/pro-plugins
|
||||||
ssh-key: ${{ secrets.SUBMODULE_SSH_KEY }}
|
ssh-key: ${{ secrets.SUBMODULE_SSH_KEY }}
|
||||||
# - name: Set variables
|
- name: Set variables
|
||||||
# run: |
|
run: |
|
||||||
# target_directory="./packages/pro-plugins/@nocobase"
|
APPEND_PRESET_LOCAL_PLUGINS=$(find ./packages/pro-plugins/@nocobase -mindepth 1 -maxdepth 1 -type d -exec basename {} \; | sed 's/^plugin-//' | tr '\n' ',' | sed 's/,$//')
|
||||||
# subdirectories=$(find "$target_directory" -mindepth 1 -maxdepth 1 -type d -exec basename {} \; | tr '\n' ' ')
|
echo "var2=$APPEND_PRESET_LOCAL_PLUGINS" >> $GITHUB_OUTPUT
|
||||||
# trimmed_variable=$(echo "$subdirectories" | xargs)
|
id: vars
|
||||||
# packageNames="@nocobase/${trimmed_variable// / @nocobase/}"
|
|
||||||
# pluginNames="${trimmed_variable//plugin-/}"
|
|
||||||
# BEFORE_PACK_NOCOBASE="yarn add @nocobase/plugin-notifications @nocobase/plugin-disable-pm-add $packageNames -W"
|
|
||||||
# APPEND_PRESET_LOCAL_PLUGINS="notifications,disable-pm-add,${pluginNames// /,}"
|
|
||||||
# echo "var1=$BEFORE_PACK_NOCOBASE" >> $GITHUB_OUTPUT
|
|
||||||
# echo "var2=$APPEND_PRESET_LOCAL_PLUGINS" >> $GITHUB_OUTPUT
|
|
||||||
# id: vars
|
|
||||||
- name: Use Node.js ${{ matrix.node_version }}
|
- name: Use Node.js ${{ matrix.node_version }}
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
@ -89,5 +82,5 @@ jobs:
|
|||||||
DB_USER: nocobase
|
DB_USER: nocobase
|
||||||
DB_PASSWORD: password
|
DB_PASSWORD: password
|
||||||
DB_DATABASE: nocobase
|
DB_DATABASE: nocobase
|
||||||
APPEND_PRESET_BUILT_IN_PLUGINS: mock-collections,workflow-response-message,workflow-request-interceptor,workflow-json-query,workflow-approval,telemetry-prometheus,data-source-external-postgres,embed,data-source-external-mysql,workflow-variable,collection-fdw,demo-platform,departments,data-source-external-mariadb
|
APPEND_PRESET_LOCAL_PLUGINS: ${{ steps.vars.outputs.var2 }}
|
||||||
timeout-minutes: 120
|
timeout-minutes: 120
|
||||||
|
22
CHANGELOG.md
22
CHANGELOG.md
@ -7,6 +7,28 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
||||||
|
|
||||||
|
## [v0.20.0-alpha.15](https://github.com/nocobase/nocobase/compare/v0.20.0-alpha.14...v0.20.0-alpha.15) - 2024-03-20
|
||||||
|
|
||||||
|
### Merged
|
||||||
|
|
||||||
|
- fix(auth): sso auth bug when deploying with subpath [`#3764`](https://github.com/nocobase/nocobase/pull/3764)
|
||||||
|
- chore: load roles after start [`#3763`](https://github.com/nocobase/nocobase/pull/3763)
|
||||||
|
- fix: uuid & nanoid should be disabled when editing [`#3762`](https://github.com/nocobase/nocobase/pull/3762)
|
||||||
|
- fix(logger): output error cause info [`#3760`](https://github.com/nocobase/nocobase/pull/3760)
|
||||||
|
- fix: uuid field [`#3736`](https://github.com/nocobase/nocobase/pull/3736)
|
||||||
|
- feat: disassociate action [`#3759`](https://github.com/nocobase/nocobase/pull/3759)
|
||||||
|
- chore: merge sub app database options [`#3640`](https://github.com/nocobase/nocobase/pull/3640)
|
||||||
|
- fix(acl): bug of user filtering when adding them to roles [`#3754`](https://github.com/nocobase/nocobase/pull/3754)
|
||||||
|
- fix: app stopped status [`#3723`](https://github.com/nocobase/nocobase/pull/3723)
|
||||||
|
- fix: fix the disappearing collections when searching [`#3750`](https://github.com/nocobase/nocobase/pull/3750)
|
||||||
|
- fix: configure openSize for table action is only immediately valid for one row [`#3752`](https://github.com/nocobase/nocobase/pull/3752)
|
||||||
|
|
||||||
|
### Commits
|
||||||
|
|
||||||
|
- test: add e2e for Disassociate [`8e322ae`](https://github.com/nocobase/nocobase/commit/8e322ae1517e0cea5eac289bb5641b85d4997002)
|
||||||
|
- chore(versions): 😊 publish v0.20.0-alpha.15 [`bef9c8a`](https://github.com/nocobase/nocobase/commit/bef9c8ab7b54b0400dfd25c9ec85a141448125a2)
|
||||||
|
- chore: update yarn.lock [`3da340c`](https://github.com/nocobase/nocobase/commit/3da340c88d3a689e22e20dae798a1b51ed0405f7)
|
||||||
|
|
||||||
## [v0.20.0-alpha.14](https://github.com/nocobase/nocobase/compare/v0.20.0-alpha.13...v0.20.0-alpha.14) - 2024-03-18
|
## [v0.20.0-alpha.14](https://github.com/nocobase/nocobase/compare/v0.20.0-alpha.13...v0.20.0-alpha.14) - 2024-03-18
|
||||||
|
|
||||||
### Merged
|
### Merged
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"npmClient": "yarn",
|
"npmClient": "yarn",
|
||||||
"useWorkspaces": true,
|
"useWorkspaces": true,
|
||||||
"npmClientArgs": ["--ignore-engines"],
|
"npmClientArgs": ["--ignore-engines"],
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
{
|
{
|
||||||
"name": "@nocobase/acl",
|
"name": "@nocobase/acl",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"description": "",
|
"description": "",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"main": "./lib/index.js",
|
"main": "./lib/index.js",
|
||||||
"types": "./lib/index.d.ts",
|
"types": "./lib/index.d.ts",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nocobase/resourcer": "0.20.0-alpha.14",
|
"@nocobase/resourcer": "0.20.0-alpha.15",
|
||||||
"@nocobase/utils": "0.20.0-alpha.14",
|
"@nocobase/utils": "0.20.0-alpha.15",
|
||||||
"minimatch": "^5.1.1"
|
"minimatch": "^5.1.1"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
{
|
{
|
||||||
"name": "@nocobase/actions",
|
"name": "@nocobase/actions",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"description": "",
|
"description": "",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"main": "./lib/index.js",
|
"main": "./lib/index.js",
|
||||||
"types": "./lib/index.d.ts",
|
"types": "./lib/index.d.ts",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nocobase/cache": "0.20.0-alpha.14",
|
"@nocobase/cache": "0.20.0-alpha.15",
|
||||||
"@nocobase/database": "0.20.0-alpha.14",
|
"@nocobase/database": "0.20.0-alpha.15",
|
||||||
"@nocobase/resourcer": "0.20.0-alpha.14"
|
"@nocobase/resourcer": "0.20.0-alpha.15"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
{
|
{
|
||||||
"name": "@nocobase/app",
|
"name": "@nocobase/app",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"description": "",
|
"description": "",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"main": "./lib/index.js",
|
"main": "./lib/index.js",
|
||||||
"types": "./lib/index.d.ts",
|
"types": "./lib/index.d.ts",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nocobase/database": "0.20.0-alpha.14",
|
"@nocobase/database": "0.20.0-alpha.15",
|
||||||
"@nocobase/preset-nocobase": "0.20.0-alpha.14",
|
"@nocobase/preset-nocobase": "0.20.0-alpha.15",
|
||||||
"@nocobase/server": "0.20.0-alpha.14"
|
"@nocobase/server": "0.20.0-alpha.15"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@nocobase/client": "0.20.0-alpha.14"
|
"@nocobase/client": "0.20.0-alpha.15"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
{
|
{
|
||||||
"name": "@nocobase/auth",
|
"name": "@nocobase/auth",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"description": "",
|
"description": "",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"main": "./lib/index.js",
|
"main": "./lib/index.js",
|
||||||
"types": "./lib/index.d.ts",
|
"types": "./lib/index.d.ts",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nocobase/actions": "0.20.0-alpha.14",
|
"@nocobase/actions": "0.20.0-alpha.15",
|
||||||
"@nocobase/cache": "0.20.0-alpha.14",
|
"@nocobase/cache": "0.20.0-alpha.15",
|
||||||
"@nocobase/database": "0.20.0-alpha.14",
|
"@nocobase/database": "0.20.0-alpha.15",
|
||||||
"@nocobase/resourcer": "0.20.0-alpha.14",
|
"@nocobase/resourcer": "0.20.0-alpha.15",
|
||||||
"@nocobase/utils": "0.20.0-alpha.14",
|
"@nocobase/utils": "0.20.0-alpha.15",
|
||||||
"@types/jsonwebtoken": "^8.5.8",
|
"@types/jsonwebtoken": "^8.5.8",
|
||||||
"jsonwebtoken": "^8.5.1"
|
"jsonwebtoken": "^8.5.1"
|
||||||
},
|
},
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nocobase/build",
|
"name": "@nocobase/build",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"description": "Library build tool based on rollup.",
|
"description": "Library build tool based on rollup.",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"types": "./lib/index.d.ts",
|
"types": "./lib/index.d.ts",
|
||||||
|
2
packages/core/cache/package.json
vendored
2
packages/core/cache/package.json
vendored
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nocobase/cache",
|
"name": "@nocobase/cache",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"description": "",
|
"description": "",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"main": "./lib/index.js",
|
"main": "./lib/index.js",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nocobase/cli",
|
"name": "@nocobase/cli",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"description": "",
|
"description": "",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"main": "./src/index.js",
|
"main": "./src/index.js",
|
||||||
@ -8,7 +8,7 @@
|
|||||||
"nocobase": "./bin/index.js"
|
"nocobase": "./bin/index.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nocobase/app": "0.20.0-alpha.14",
|
"@nocobase/app": "0.20.0-alpha.15",
|
||||||
"@types/fs-extra": "^11.0.1",
|
"@types/fs-extra": "^11.0.1",
|
||||||
"@umijs/utils": "3.5.20",
|
"@umijs/utils": "3.5.20",
|
||||||
"chalk": "^4.1.1",
|
"chalk": "^4.1.1",
|
||||||
@ -25,7 +25,7 @@
|
|||||||
"tsx": "^4.6.2"
|
"tsx": "^4.6.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@nocobase/devtools": "0.20.0-alpha.14"
|
"@nocobase/devtools": "0.20.0-alpha.15"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nocobase/client",
|
"name": "@nocobase/client",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"module": "es/index.mjs",
|
"module": "es/index.mjs",
|
||||||
@ -26,9 +26,9 @@
|
|||||||
"@formily/reactive-react": "^2.2.27",
|
"@formily/reactive-react": "^2.2.27",
|
||||||
"@formily/shared": "^2.2.27",
|
"@formily/shared": "^2.2.27",
|
||||||
"@formily/validator": "^2.2.27",
|
"@formily/validator": "^2.2.27",
|
||||||
"@nocobase/evaluators": "0.20.0-alpha.14",
|
"@nocobase/evaluators": "0.20.0-alpha.15",
|
||||||
"@nocobase/sdk": "0.20.0-alpha.14",
|
"@nocobase/sdk": "0.20.0-alpha.15",
|
||||||
"@nocobase/utils": "0.20.0-alpha.14",
|
"@nocobase/utils": "0.20.0-alpha.15",
|
||||||
"ahooks": "^3.7.2",
|
"ahooks": "^3.7.2",
|
||||||
"antd": "^5.12.8",
|
"antd": "^5.12.8",
|
||||||
"antd-style": "3.4.5",
|
"antd-style": "3.4.5",
|
||||||
|
@ -349,7 +349,7 @@ export const useParamsFromRecord = () => {
|
|||||||
if (record.__collection && collectionField && !['oho', 'm2o', 'obo'].includes(collectionField.interface)) {
|
if (record.__collection && collectionField && !['oho', 'm2o', 'obo'].includes(collectionField.interface)) {
|
||||||
obj['targetCollection'] = record.__collection;
|
obj['targetCollection'] = record.__collection;
|
||||||
}
|
}
|
||||||
if (!filterByTk) {
|
if (!filterByTk && Object.keys(filter).length > 0) {
|
||||||
obj['filter'] = filter;
|
obj['filter'] = filter;
|
||||||
}
|
}
|
||||||
return obj;
|
return obj;
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
|
import { Field, Form } from '@formily/core';
|
||||||
import { SchemaExpressionScopeContext, useField, useFieldSchema, useForm } from '@formily/react';
|
import { SchemaExpressionScopeContext, useField, useFieldSchema, useForm } from '@formily/react';
|
||||||
|
import { untracked } from '@formily/reactive';
|
||||||
import { isURL, parse } from '@nocobase/utils/client';
|
import { isURL, parse } from '@nocobase/utils/client';
|
||||||
import { App, message } from 'antd';
|
import { App, message } from 'antd';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
@ -23,6 +25,7 @@ import { useFilterBlock } from '../../filter-provider/FilterProvider';
|
|||||||
import { mergeFilter, transformToFilter } from '../../filter-provider/utils';
|
import { mergeFilter, transformToFilter } from '../../filter-provider/utils';
|
||||||
import { useRecord } from '../../record-provider';
|
import { useRecord } from '../../record-provider';
|
||||||
import { removeNullCondition, useActionContext, useCompile } from '../../schema-component';
|
import { removeNullCondition, useActionContext, useCompile } from '../../schema-component';
|
||||||
|
import { isSubMode } from '../../schema-component/antd/association-field/util';
|
||||||
import { useCurrentUserContext } from '../../user';
|
import { useCurrentUserContext } from '../../user';
|
||||||
import { useLocalVariables, useVariables } from '../../variables';
|
import { useLocalVariables, useVariables } from '../../variables';
|
||||||
import { isVariable } from '../../variables/utils/isVariable';
|
import { isVariable } from '../../variables/utils/isVariable';
|
||||||
@ -30,9 +33,6 @@ import { transformVariableValue } from '../../variables/utils/transformVariableV
|
|||||||
import { useBlockRequestContext, useFilterByTk, useParamsFromRecord } from '../BlockProvider';
|
import { useBlockRequestContext, useFilterByTk, useParamsFromRecord } from '../BlockProvider';
|
||||||
import { useDetailsBlockContext } from '../DetailsBlockProvider';
|
import { useDetailsBlockContext } from '../DetailsBlockProvider';
|
||||||
import { TableFieldResource } from '../TableFieldProvider';
|
import { TableFieldResource } from '../TableFieldProvider';
|
||||||
import { Field, Form } from '@formily/core';
|
|
||||||
import { untracked } from '@formily/reactive';
|
|
||||||
import { isSubMode } from '../../schema-component/antd/association-field/util';
|
|
||||||
|
|
||||||
export * from './useFormActiveFields';
|
export * from './useFormActiveFields';
|
||||||
export * from './useParsedFilter';
|
export * from './useParsedFilter';
|
||||||
@ -965,6 +965,34 @@ export const useRemoveActionProps = (associationName) => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const useDisassociateActionProps = () => {
|
||||||
|
const filterByTk = useFilterByTk();
|
||||||
|
const { resource, service, block, __parent } = useBlockRequestContext();
|
||||||
|
const { setVisible } = useActionContext();
|
||||||
|
return {
|
||||||
|
async onClick() {
|
||||||
|
await resource.remove({
|
||||||
|
values: [filterByTk],
|
||||||
|
});
|
||||||
|
|
||||||
|
const { count = 0, page = 0, pageSize = 0 } = service?.data?.meta || {};
|
||||||
|
if (count % pageSize === 1 && page !== 1) {
|
||||||
|
service.run({
|
||||||
|
...service?.params?.[0],
|
||||||
|
page: page - 1,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
service?.refresh?.();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (block && block !== 'TableField') {
|
||||||
|
__parent?.service?.refresh?.();
|
||||||
|
setVisible?.(false);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export const useDetailPrintActionProps = () => {
|
export const useDetailPrintActionProps = () => {
|
||||||
const { formBlockRef } = useFormBlockContext();
|
const { formBlockRef } = useFormBlockContext();
|
||||||
|
|
||||||
|
@ -284,7 +284,7 @@ export const ForeignKey = observer(
|
|||||||
}}
|
}}
|
||||||
onChange={(value, option) => {
|
onChange={(value, option) => {
|
||||||
props?.onChange?.(value);
|
props?.onChange?.(value);
|
||||||
setInitialValue(option.label);
|
setInitialValue(option.label || value);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -28,9 +28,9 @@ export class NanoidFieldInterface extends CollectionFieldInterface {
|
|||||||
type: 'string',
|
type: 'string',
|
||||||
title: '{{t("Field name")}}',
|
title: '{{t("Field name")}}',
|
||||||
required: true,
|
required: true,
|
||||||
'x-disabled': true,
|
|
||||||
'x-decorator': 'FormItem',
|
'x-decorator': 'FormItem',
|
||||||
'x-component': 'Input',
|
'x-component': 'Input',
|
||||||
|
'x-disabled': '{{ !createOnly }}',
|
||||||
description:
|
description:
|
||||||
"{{t('Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.')}}",
|
"{{t('Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.')}}",
|
||||||
},
|
},
|
||||||
|
@ -30,9 +30,9 @@ export class UUIDFieldInterface extends CollectionFieldInterface {
|
|||||||
type: 'string',
|
type: 'string',
|
||||||
title: '{{t("Field name")}}',
|
title: '{{t("Field name")}}',
|
||||||
required: true,
|
required: true,
|
||||||
'x-disabled': true,
|
|
||||||
'x-decorator': 'FormItem',
|
'x-decorator': 'FormItem',
|
||||||
'x-component': 'Input',
|
'x-component': 'Input',
|
||||||
|
'x-disabled': '{{ !createOnly }}',
|
||||||
description:
|
description:
|
||||||
"{{t('Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.')}}",
|
"{{t('Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.')}}",
|
||||||
},
|
},
|
||||||
|
@ -53,6 +53,9 @@
|
|||||||
"Insert right": "Insert right",
|
"Insert right": "Insert right",
|
||||||
"Insert inner": "Insert inner",
|
"Insert inner": "Insert inner",
|
||||||
"Delete": "Delete",
|
"Delete": "Delete",
|
||||||
|
"Disassociate": "Disassociate",
|
||||||
|
"Disassociate record": "Disassociate record",
|
||||||
|
"Are you sure you want to disassociate it?": "Are you sure you want to disassociate it?",
|
||||||
"UI editor": "UI editor",
|
"UI editor": "UI editor",
|
||||||
"Collection": "Collection",
|
"Collection": "Collection",
|
||||||
"Collection selector": "Collection selector",
|
"Collection selector": "Collection selector",
|
||||||
|
@ -52,6 +52,9 @@
|
|||||||
"Insert right": "Insertar a la derecha",
|
"Insert right": "Insertar a la derecha",
|
||||||
"Insert inner": "Insertar al interior",
|
"Insert inner": "Insertar al interior",
|
||||||
"Delete": "Borrar",
|
"Delete": "Borrar",
|
||||||
|
"Disassociate": "Desasociar",
|
||||||
|
"Disassociate record": "Desasociar registro",
|
||||||
|
"Are you sure you want to disassociate it?": "¿Seguro que quieres desasociarlo?",
|
||||||
"UI editor": "IU editor",
|
"UI editor": "IU editor",
|
||||||
"Collection": "Colección",
|
"Collection": "Colección",
|
||||||
"Collections & Fields": "Colección & Campos",
|
"Collections & Fields": "Colección & Campos",
|
||||||
|
@ -52,6 +52,9 @@
|
|||||||
"Insert right": "Insérer à droite",
|
"Insert right": "Insérer à droite",
|
||||||
"Insert inner": "Insérer à l'intérieur",
|
"Insert inner": "Insérer à l'intérieur",
|
||||||
"Delete": "Supprimer",
|
"Delete": "Supprimer",
|
||||||
|
"Disassociate": "Dissocier",
|
||||||
|
"Disassociate record": "Dissocier l'enregistrement",
|
||||||
|
"Are you sure you want to disassociate it?": "Êtes-vous sûr de vouloir le dissocier ?",
|
||||||
"UI editor": "Éditeur d'interface utilisateur",
|
"UI editor": "Éditeur d'interface utilisateur",
|
||||||
"Collection": "Collection",
|
"Collection": "Collection",
|
||||||
"Collections & Fields": "Collections et champs",
|
"Collections & Fields": "Collections et champs",
|
||||||
|
@ -52,6 +52,9 @@
|
|||||||
"Insert right": "右に挿入",
|
"Insert right": "右に挿入",
|
||||||
"Insert inner": "中に挿入",
|
"Insert inner": "中に挿入",
|
||||||
"Delete": "削除",
|
"Delete": "削除",
|
||||||
|
"Disassociate": "関連付けを解除",
|
||||||
|
"Disassociate record": "レコードの関連付けを解除",
|
||||||
|
"Are you sure you want to disassociate it?": "本当に関連付けを解除しますか?",
|
||||||
"UI editor": "UI エディタ",
|
"UI editor": "UI エディタ",
|
||||||
"Collection": "コレクション",
|
"Collection": "コレクション",
|
||||||
"Enable child collections": "启用子表",
|
"Enable child collections": "启用子表",
|
||||||
|
@ -60,6 +60,9 @@
|
|||||||
"Insert right": "오른쪽에 삽입",
|
"Insert right": "오른쪽에 삽입",
|
||||||
"Insert inner": "내부에 삽입",
|
"Insert inner": "내부에 삽입",
|
||||||
"Delete": "삭제",
|
"Delete": "삭제",
|
||||||
|
"Disassociate": "연결 해제",
|
||||||
|
"Disassociate record": "레코드 연결 해제",
|
||||||
|
"Are you sure you want to disassociate it?": "정말로 연결을 해제하시겠습니까?",
|
||||||
"UI editor": "UI 편집기",
|
"UI editor": "UI 편집기",
|
||||||
"Collection": "컬렉션",
|
"Collection": "컬렉션",
|
||||||
"Collection selector": "컬렉션 선택기",
|
"Collection selector": "컬렉션 선택기",
|
||||||
|
@ -32,6 +32,9 @@
|
|||||||
"Insert right": "Inserir à direita",
|
"Insert right": "Inserir à direita",
|
||||||
"Insert inner": "Inserir interno",
|
"Insert inner": "Inserir interno",
|
||||||
"Delete": "Excluir",
|
"Delete": "Excluir",
|
||||||
|
"Disassociate": "Desassociar",
|
||||||
|
"Disassociate record": "Desassociar registro",
|
||||||
|
"Are you sure you want to disassociate it?": "Tem certeza de que deseja desassociá-lo?",
|
||||||
"UI editor": "Editor de UI",
|
"UI editor": "Editor de UI",
|
||||||
"Collection": "Coleção",
|
"Collection": "Coleção",
|
||||||
"Collections & Fields": "Coleções e campos",
|
"Collections & Fields": "Coleções e campos",
|
||||||
|
@ -52,6 +52,9 @@
|
|||||||
"Insert right": "Вставить справа",
|
"Insert right": "Вставить справа",
|
||||||
"Insert inner": "Вставить внутрь",
|
"Insert inner": "Вставить внутрь",
|
||||||
"Delete": "Удалить",
|
"Delete": "Удалить",
|
||||||
|
"Disassociate": "Разъединить",
|
||||||
|
"Disassociate record": "Разъединить запись",
|
||||||
|
"Are you sure you want to disassociate it?": "Вы уверены, что хотите разъединить это?",
|
||||||
"UI editor": "UI редактор",
|
"UI editor": "UI редактор",
|
||||||
"Collection": "Коллекция",
|
"Collection": "Коллекция",
|
||||||
"Collections & Fields": "Коллекции & Поля",
|
"Collections & Fields": "Коллекции & Поля",
|
||||||
|
@ -52,6 +52,9 @@
|
|||||||
"Insert right": "Sağa yerleştir",
|
"Insert right": "Sağa yerleştir",
|
||||||
"Insert inner": "İçine yerleştir",
|
"Insert inner": "İçine yerleştir",
|
||||||
"Delete": "Sil",
|
"Delete": "Sil",
|
||||||
|
"Disassociate": "Bağlantıyı kes",
|
||||||
|
"Disassociate record": "Kaydı bağlantıyı kes",
|
||||||
|
"Are you sure you want to disassociate it?": "Bağlantıyı kesmek istediğinizden emin misiniz?",
|
||||||
"UI editor": "UI editor",
|
"UI editor": "UI editor",
|
||||||
"Collection": "Koleksiyonlar",
|
"Collection": "Koleksiyonlar",
|
||||||
"Collections & Fields": "Koleksiyonlar & Alanlar",
|
"Collections & Fields": "Koleksiyonlar & Alanlar",
|
||||||
|
@ -52,6 +52,9 @@
|
|||||||
"Insert right": "Вставити справа",
|
"Insert right": "Вставити справа",
|
||||||
"Insert inner": "Вставити всередину",
|
"Insert inner": "Вставити всередину",
|
||||||
"Delete": "Видалити",
|
"Delete": "Видалити",
|
||||||
|
"Disassociate": "Роз'єднати",
|
||||||
|
"Disassociate record": "Роз'єднати запис",
|
||||||
|
"Are you sure you want to disassociate it?": "Ви впевнені, що хочете роз'єднати це?",
|
||||||
"UI editor": "Редактор UI",
|
"UI editor": "Редактор UI",
|
||||||
"Collection": "Колекція",
|
"Collection": "Колекція",
|
||||||
"Collections & Fields": "Колекції та поля",
|
"Collections & Fields": "Колекції та поля",
|
||||||
|
@ -60,6 +60,9 @@
|
|||||||
"Insert right": "在右边插入",
|
"Insert right": "在右边插入",
|
||||||
"Insert inner": "在里面插入",
|
"Insert inner": "在里面插入",
|
||||||
"Delete": "删除",
|
"Delete": "删除",
|
||||||
|
"Disassociate": "解除关联",
|
||||||
|
"Disassociate record": "解除关联记录",
|
||||||
|
"Are you sure you want to disassociate it?": "你确定要解除关联吗?",
|
||||||
"UI editor": "界面配置",
|
"UI editor": "界面配置",
|
||||||
"Collection": "数据表",
|
"Collection": "数据表",
|
||||||
"Collection selector": "数据表选择器",
|
"Collection selector": "数据表选择器",
|
||||||
|
@ -60,6 +60,9 @@
|
|||||||
"Insert right": "從右邊插入",
|
"Insert right": "從右邊插入",
|
||||||
"Insert inner": "從裡面插入",
|
"Insert inner": "從裡面插入",
|
||||||
"Delete": "刪除",
|
"Delete": "刪除",
|
||||||
|
"Disassociate": "解除關聯",
|
||||||
|
"Disassociate record": "解除關聯記錄",
|
||||||
|
"Are you sure you want to disassociate it?": "你確定要解除關聯嗎?",
|
||||||
"UI editor": "介面編輯",
|
"UI editor": "介面編輯",
|
||||||
"Collection": "資料表",
|
"Collection": "資料表",
|
||||||
"Collection selector": "資料表選擇器",
|
"Collection selector": "資料表選擇器",
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { ActionInitializer } from '../../../schema-initializer/items/ActionInitializer';
|
||||||
|
|
||||||
|
export const DisassociateActionInitializer = (props) => {
|
||||||
|
const schema = {
|
||||||
|
title: '{{ t("Disassociate") }}',
|
||||||
|
'x-action': 'disassociate',
|
||||||
|
'x-component': 'Action',
|
||||||
|
'x-toolbar': 'ActionSchemaToolbar',
|
||||||
|
'x-settings': 'actionSettings:disassociate',
|
||||||
|
'x-component-props': {
|
||||||
|
icon: 'DeleteOutlined',
|
||||||
|
confirm: {
|
||||||
|
title: "{{t('Disassociate record')}}",
|
||||||
|
content: "{{t('Are you sure you want to disassociate it?')}}",
|
||||||
|
},
|
||||||
|
useProps: '{{ useDisassociateActionProps }}',
|
||||||
|
},
|
||||||
|
'x-action-settings': {
|
||||||
|
triggerWorkflows: [],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return <ActionInitializer {...props} schema={schema} />;
|
||||||
|
};
|
@ -0,0 +1,53 @@
|
|||||||
|
import { test, expect } from '@nocobase/test/e2e';
|
||||||
|
import { disassociatePage } from './templatesOfPage';
|
||||||
|
|
||||||
|
test('basic', async ({ page, mockPage, mockRecord }) => {
|
||||||
|
await mockPage(disassociatePage).goto();
|
||||||
|
const record = await mockRecord('collection1');
|
||||||
|
|
||||||
|
// 1. 打开弹窗,并创建一个 Table 关系区块
|
||||||
|
await page.getByLabel('action-Action.Link-Edit record-update-collection1-table-0').click();
|
||||||
|
await page.getByLabel('schema-initializer-Grid-popup').hover();
|
||||||
|
await page.getByRole('menuitem', { name: 'table Table right' }).hover();
|
||||||
|
await page.getByRole('menuitem', { name: 'manyToMany -> collection2' }).click();
|
||||||
|
|
||||||
|
// 2. Table 中显示 Role UID 字段
|
||||||
|
await page
|
||||||
|
.getByTestId('drawer-Action.Container-collection1-Edit record')
|
||||||
|
.getByLabel('schema-initializer-TableV2-')
|
||||||
|
.hover();
|
||||||
|
await page.getByRole('menuitem', { name: 'singleLineText' }).click();
|
||||||
|
|
||||||
|
// 3. 显示 Disassociate 按钮
|
||||||
|
await page
|
||||||
|
.getByTestId('drawer-Action.Container-collection1-Edit record')
|
||||||
|
.getByRole('button', { name: 'Actions', exact: true })
|
||||||
|
.hover();
|
||||||
|
await page
|
||||||
|
.getByTestId('drawer-Action.Container-collection1-Edit record')
|
||||||
|
.getByLabel('designer-schema-settings-TableV2.Column-TableV2.ActionColumnDesigner-collection2')
|
||||||
|
.hover();
|
||||||
|
await page.getByRole('menuitem', { name: 'Disassociate' }).click();
|
||||||
|
|
||||||
|
// 4. 点击 Disassociate 按钮,解除关联
|
||||||
|
await expect(
|
||||||
|
page
|
||||||
|
.getByTestId('drawer-Action.Container-collection1-Edit record')
|
||||||
|
.getByLabel('block-item-CardItem-')
|
||||||
|
.getByText(record.manyToMany[0].singleLineText),
|
||||||
|
).toBeVisible();
|
||||||
|
await page.getByLabel('action-Action.Link-Disassociate-disassociate-collection2-table-0').click();
|
||||||
|
await page.getByRole('button', { name: 'OK', exact: true }).click();
|
||||||
|
await expect(
|
||||||
|
page
|
||||||
|
.getByTestId('drawer-Action.Container-collection1-Edit record')
|
||||||
|
.getByLabel('block-item-CardItem-')
|
||||||
|
.getByText(record.manyToMany[0].singleLineText),
|
||||||
|
).toBeHidden();
|
||||||
|
|
||||||
|
// 5. 刷新页面后,页面中 collection2 的表格中的 singleLineText 字段不应该被删除
|
||||||
|
await page.reload();
|
||||||
|
await expect(
|
||||||
|
page.getByLabel('block-item-CardItem-collection2-table').getByText(record.manyToMany[0].singleLineText),
|
||||||
|
).toBeVisible();
|
||||||
|
});
|
@ -0,0 +1,384 @@
|
|||||||
|
import { PageConfig } from '@nocobase/test/e2e';
|
||||||
|
|
||||||
|
export const disassociatePage: PageConfig = {
|
||||||
|
collections: [
|
||||||
|
{
|
||||||
|
name: 'collection1',
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'manyToMany',
|
||||||
|
interface: 'm2m',
|
||||||
|
target: 'collection2',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'collection2',
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'singleLineText',
|
||||||
|
interface: 'input',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
pageSchema: {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Page',
|
||||||
|
'x-index': 1,
|
||||||
|
properties: {
|
||||||
|
wpr26fau9xr: {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Grid',
|
||||||
|
'x-initializer': 'page:addBlock',
|
||||||
|
'x-index': 1,
|
||||||
|
properties: {
|
||||||
|
en9rmxzezha: {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Grid.Row',
|
||||||
|
properties: {
|
||||||
|
yxbglvb5hog: {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Grid.Col',
|
||||||
|
properties: {
|
||||||
|
'8j54tok1ami': {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'void',
|
||||||
|
'x-decorator': 'TableBlockProvider',
|
||||||
|
'x-acl-action': 'collection1:list',
|
||||||
|
'x-decorator-props': {
|
||||||
|
collection: 'collection1',
|
||||||
|
dataSource: 'main',
|
||||||
|
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': 'table:configureActions',
|
||||||
|
'x-component': 'ActionBar',
|
||||||
|
'x-component-props': {
|
||||||
|
style: {
|
||||||
|
marginBottom: 'var(--nb-spacing)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 'b678n93qa6y',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
qikcey9adni: {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'array',
|
||||||
|
'x-initializer': 'table:configureColumns',
|
||||||
|
'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': 'table:configureItemActions',
|
||||||
|
properties: {
|
||||||
|
m7jxx6ybqin: {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'void',
|
||||||
|
'x-decorator': 'DndContext',
|
||||||
|
'x-component': 'Space',
|
||||||
|
'x-component-props': {
|
||||||
|
split: '|',
|
||||||
|
},
|
||||||
|
properties: {
|
||||||
|
xm4xv98j8rq: {
|
||||||
|
'x-uid': 'zzpqq51vya7',
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'void',
|
||||||
|
title: 'Edit record',
|
||||||
|
'x-action': 'update',
|
||||||
|
'x-toolbar': 'ActionSchemaToolbar',
|
||||||
|
'x-settings': 'actionSettings:edit',
|
||||||
|
'x-component': 'Action.Link',
|
||||||
|
'x-component-props': {
|
||||||
|
openMode: 'drawer',
|
||||||
|
danger: false,
|
||||||
|
},
|
||||||
|
'x-decorator': 'ACLActionProvider',
|
||||||
|
'x-designer-props': {
|
||||||
|
linkageAction: true,
|
||||||
|
},
|
||||||
|
properties: {
|
||||||
|
drawer: {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'void',
|
||||||
|
title: '{{ t("Edit 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("Edit")}}',
|
||||||
|
'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': 'popup:common:addBlock',
|
||||||
|
'x-uid': '4ywsuzafbcb',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 'i9vjup0exgk',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 'v193kvjot2a',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 'cm1v9u7tfsu',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': '1wxlbm4mmvg',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': '5sqdt97tixj',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 'kplsu47q2a6',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 'pq9i71986i8',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 'oce2w1t8coi',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 'i7ti4qryd4o',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
gq928ipecvy: {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Grid.Row',
|
||||||
|
properties: {
|
||||||
|
zue50ioabjl: {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Grid.Col',
|
||||||
|
properties: {
|
||||||
|
dv7csive187: {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'void',
|
||||||
|
'x-decorator': 'TableBlockProvider',
|
||||||
|
'x-acl-action': 'collection2:list',
|
||||||
|
'x-decorator-props': {
|
||||||
|
collection: 'collection2',
|
||||||
|
dataSource: 'main',
|
||||||
|
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': 'table:configureActions',
|
||||||
|
'x-component': 'ActionBar',
|
||||||
|
'x-component-props': {
|
||||||
|
style: {
|
||||||
|
marginBottom: 'var(--nb-spacing)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 'oe1qrytmueq',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
gjd57a4bks3: {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'array',
|
||||||
|
'x-initializer': 'table:configureColumns',
|
||||||
|
'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': 'table:configureItemActions',
|
||||||
|
properties: {
|
||||||
|
'3ysynbg1lv6': {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'void',
|
||||||
|
'x-decorator': 'DndContext',
|
||||||
|
'x-component': 'Space',
|
||||||
|
'x-component-props': {
|
||||||
|
split: '|',
|
||||||
|
},
|
||||||
|
'x-uid': 'aelf0u0qx6q',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': '5iadqvuebvd',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
'10a10qkpiz7': {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'void',
|
||||||
|
'x-decorator': 'TableV2.Column.Decorator',
|
||||||
|
'x-toolbar': 'TableColumnSchemaToolbar',
|
||||||
|
'x-settings': 'fieldSettings:TableColumn',
|
||||||
|
'x-component': 'TableV2.Column',
|
||||||
|
properties: {
|
||||||
|
singleLineText: {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
'x-collection-field': 'collection2.singleLineText',
|
||||||
|
'x-component': 'CollectionField',
|
||||||
|
'x-component-props': {
|
||||||
|
ellipsis: true,
|
||||||
|
},
|
||||||
|
'x-read-pretty': true,
|
||||||
|
'x-decorator': null,
|
||||||
|
'x-decorator-props': {
|
||||||
|
labelStyle: {
|
||||||
|
display: 'none',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 'fixqxflxl3p',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': '8huj8o6hk58',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 'zyewv4tfzsm',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 'c5o951ypirb',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 'i50ffbtryxp',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 'w6dx01br9dy',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 'aro2fcypx34',
|
||||||
|
'x-async': false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': '8ykc66k5p12',
|
||||||
|
'x-async': true,
|
||||||
|
},
|
||||||
|
};
|
@ -0,0 +1,39 @@
|
|||||||
|
import { useSchemaToolbar } from '../../../application';
|
||||||
|
import { SchemaSettings } from '../../../application/schema-settings/SchemaSettings';
|
||||||
|
import { useCollection_deprecated } from '../../../collection-manager';
|
||||||
|
import { ButtonEditor, SecondConFirm } from '../../../schema-component/antd/action/Action.Designer';
|
||||||
|
import { SchemaSettingsLinkageRules } from '../../../schema-settings';
|
||||||
|
|
||||||
|
export const disassociateActionSettings = new SchemaSettings({
|
||||||
|
name: 'actionSettings:disassociate',
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
name: 'editButton',
|
||||||
|
Component: ButtonEditor,
|
||||||
|
useComponentProps() {
|
||||||
|
const { buttonEditorProps } = useSchemaToolbar();
|
||||||
|
return buttonEditorProps;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'linkageRules',
|
||||||
|
Component: SchemaSettingsLinkageRules,
|
||||||
|
useComponentProps() {
|
||||||
|
const { name } = useCollection_deprecated();
|
||||||
|
const { linkageRulesProps } = useSchemaToolbar();
|
||||||
|
return {
|
||||||
|
...linkageRulesProps,
|
||||||
|
collectionName: name,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'secondConFirm',
|
||||||
|
Component: SecondConFirm,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'delete',
|
||||||
|
type: 'remove',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
@ -4,13 +4,14 @@ import _ from 'lodash';
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useAPIClient } from '../../../../api-client';
|
import { useAPIClient } from '../../../../api-client';
|
||||||
|
import { CompatibleSchemaInitializer } from '../../../../application/schema-initializer/CompatibleSchemaInitializer';
|
||||||
|
import { SchemaInitializerActionModal } from '../../../../application/schema-initializer/components/SchemaInitializerActionModal';
|
||||||
|
import { SchemaInitializerItem } from '../../../../application/schema-initializer/components/SchemaInitializerItem';
|
||||||
|
import { useSchemaInitializer } from '../../../../application/schema-initializer/context';
|
||||||
import { useCollection_deprecated } from '../../../../collection-manager';
|
import { useCollection_deprecated } from '../../../../collection-manager';
|
||||||
|
import { useDataBlockProps } from '../../../../data-source';
|
||||||
import { createDesignable, useDesignable } from '../../../../schema-component';
|
import { createDesignable, useDesignable } from '../../../../schema-component';
|
||||||
import { useGetAriaLabelOfDesigner } from '../../../../schema-settings/hooks/useGetAriaLabelOfDesigner';
|
import { useGetAriaLabelOfDesigner } from '../../../../schema-settings/hooks/useGetAriaLabelOfDesigner';
|
||||||
import { SchemaInitializerActionModal } from '../../../../application/schema-initializer/components/SchemaInitializerActionModal';
|
|
||||||
import { useSchemaInitializer } from '../../../../application/schema-initializer/context';
|
|
||||||
import { SchemaInitializerItem } from '../../../../application/schema-initializer/components/SchemaInitializerItem';
|
|
||||||
import { CompatibleSchemaInitializer } from '../../../../application/schema-initializer/CompatibleSchemaInitializer';
|
|
||||||
|
|
||||||
export const Resizable = () => {
|
export const Resizable = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@ -65,11 +66,7 @@ export const Resizable = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
const commonOptions = {
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
export const tableActionColumnInitializers_deprecated = new CompatibleSchemaInitializer({
|
|
||||||
name: 'TableActionColumnInitializers',
|
|
||||||
insertPosition: 'beforeEnd',
|
insertPosition: 'beforeEnd',
|
||||||
useInsert: function useInsert() {
|
useInsert: function useInsert() {
|
||||||
const { refresh } = useDesignable();
|
const { refresh } = useDesignable();
|
||||||
@ -156,6 +153,27 @@ export const tableActionColumnInitializers_deprecated = new CompatibleSchemaInit
|
|||||||
return (collection.template !== 'view' || collection?.writableView) && collection.template !== 'sql';
|
return (collection.template !== 'view' || collection?.writableView) && collection.template !== 'sql';
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
type: 'item',
|
||||||
|
title: '{{t("Disassociate")}}',
|
||||||
|
name: 'disassociate',
|
||||||
|
Component: 'DisassociateActionInitializer',
|
||||||
|
schema: {
|
||||||
|
'x-component': 'Action.Link',
|
||||||
|
'x-action': 'disassociate',
|
||||||
|
'x-acl-action': 'destroy',
|
||||||
|
'x-decorator': 'ACLActionProvider',
|
||||||
|
},
|
||||||
|
useVisible() {
|
||||||
|
const props = useDataBlockProps();
|
||||||
|
const collection = useCollection_deprecated();
|
||||||
|
return (
|
||||||
|
!!props?.association &&
|
||||||
|
(collection.template !== 'view' || collection?.writableView) &&
|
||||||
|
collection.template !== 'sql'
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
type: 'item',
|
type: 'item',
|
||||||
title: '{{t("Add child")}}',
|
title: '{{t("Add child")}}',
|
||||||
@ -225,166 +243,20 @@ export const tableActionColumnInitializers_deprecated = new CompatibleSchemaInit
|
|||||||
Component: Resizable,
|
Component: Resizable,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
|
export const tableActionColumnInitializers_deprecated = new CompatibleSchemaInitializer({
|
||||||
|
name: 'TableActionColumnInitializers',
|
||||||
|
...commonOptions,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const tableActionColumnInitializers = new CompatibleSchemaInitializer(
|
export const tableActionColumnInitializers = new CompatibleSchemaInitializer(
|
||||||
{
|
{
|
||||||
name: 'table:configureItemActions',
|
name: 'table:configureItemActions',
|
||||||
insertPosition: 'beforeEnd',
|
...commonOptions,
|
||||||
useInsert: function useInsert() {
|
|
||||||
const { refresh } = useDesignable();
|
|
||||||
const fieldSchema = useFieldSchema();
|
|
||||||
const api = useAPIClient();
|
|
||||||
const { t } = useTranslation();
|
|
||||||
|
|
||||||
return function insert(schema) {
|
|
||||||
const spaceSchema = fieldSchema.reduceProperties((buf, schema) => {
|
|
||||||
if (schema['x-component'] === 'Space') {
|
|
||||||
return schema;
|
|
||||||
}
|
|
||||||
return buf;
|
|
||||||
}, null);
|
|
||||||
if (!spaceSchema) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_.set(schema, 'x-designer-props.linkageAction', true);
|
|
||||||
const dn = createDesignable({
|
|
||||||
t,
|
|
||||||
api,
|
|
||||||
refresh,
|
|
||||||
current: spaceSchema,
|
|
||||||
});
|
|
||||||
dn.loadAPIClientEvents();
|
|
||||||
dn.insertBeforeEnd(schema);
|
|
||||||
};
|
|
||||||
},
|
|
||||||
Component: (props: any) => {
|
|
||||||
const { getAriaLabel } = useGetAriaLabelOfDesigner();
|
|
||||||
return (
|
|
||||||
<MenuOutlined
|
|
||||||
{...props}
|
|
||||||
role="button"
|
|
||||||
aria-label={getAriaLabel('schema-settings')}
|
|
||||||
style={{ cursor: 'pointer' }}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
items: [
|
|
||||||
{
|
|
||||||
type: 'itemGroup',
|
|
||||||
name: 'actions',
|
|
||||||
title: '{{t("Enable actions")}}',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
type: 'item',
|
|
||||||
title: '{{t("View")}}',
|
|
||||||
name: 'view',
|
|
||||||
Component: 'ViewActionInitializer',
|
|
||||||
schema: {
|
|
||||||
'x-component': 'Action.Link',
|
|
||||||
'x-action': 'view',
|
|
||||||
'x-decorator': 'ACLActionProvider',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'item',
|
|
||||||
name: 'edit',
|
|
||||||
title: '{{t("Edit")}}',
|
|
||||||
Component: 'UpdateActionInitializer',
|
|
||||||
schema: {
|
|
||||||
'x-component': 'Action.Link',
|
|
||||||
'x-action': 'update',
|
|
||||||
'x-decorator': 'ACLActionProvider',
|
|
||||||
},
|
|
||||||
useVisible() {
|
|
||||||
const collection = useCollection_deprecated();
|
|
||||||
return (collection.template !== 'view' || collection?.writableView) && collection.template !== 'sql';
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'item',
|
|
||||||
title: '{{t("Delete")}}',
|
|
||||||
name: 'delete',
|
|
||||||
Component: 'DestroyActionInitializer',
|
|
||||||
schema: {
|
|
||||||
'x-component': 'Action.Link',
|
|
||||||
'x-action': 'destroy',
|
|
||||||
'x-decorator': 'ACLActionProvider',
|
|
||||||
},
|
|
||||||
useVisible() {
|
|
||||||
const collection = useCollection_deprecated();
|
|
||||||
return (collection.template !== 'view' || collection?.writableView) && collection.template !== 'sql';
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'item',
|
|
||||||
title: '{{t("Add child")}}',
|
|
||||||
name: 'addChildren',
|
|
||||||
Component: 'CreateChildInitializer',
|
|
||||||
schema: {
|
|
||||||
'x-component': 'Action.Link',
|
|
||||||
'x-action': 'create',
|
|
||||||
'x-decorator': 'ACLActionProvider',
|
|
||||||
},
|
|
||||||
useVisible() {
|
|
||||||
const fieldSchema = useFieldSchema();
|
|
||||||
const collection = useCollection_deprecated();
|
|
||||||
const { treeTable } = fieldSchema?.parent?.parent['x-decorator-props'] || {};
|
|
||||||
return collection.tree && treeTable !== false;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'divider',
|
|
||||||
type: 'divider',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'subMenu',
|
|
||||||
title: '{{t("Customize")}}',
|
|
||||||
name: 'customize',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
type: 'item',
|
|
||||||
title: '{{t("Popup")}}',
|
|
||||||
name: 'popup',
|
|
||||||
Component: 'PopupActionInitializer',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'item',
|
|
||||||
title: '{{t("Update record")}}',
|
|
||||||
name: 'updateRecord',
|
|
||||||
Component: 'UpdateRecordActionInitializer',
|
|
||||||
useVisible() {
|
|
||||||
const collection = useCollection_deprecated();
|
|
||||||
return (collection.template !== 'view' || collection?.writableView) && collection.template !== 'sql';
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'customRequest',
|
|
||||||
title: '{{t("Custom request")}}',
|
|
||||||
Component: 'CustomRequestInitializer',
|
|
||||||
schema: {
|
|
||||||
'x-action': 'customize:table:request',
|
|
||||||
},
|
|
||||||
useVisible() {
|
|
||||||
const collection = useCollection_deprecated();
|
|
||||||
return (collection.template !== 'view' || collection?.writableView) && collection.template !== 'sql';
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'divider2',
|
|
||||||
type: 'divider',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'item',
|
|
||||||
name: 'columnWidth',
|
|
||||||
title: 't("Column width")',
|
|
||||||
Component: Resizable,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
tableActionColumnInitializers_deprecated,
|
tableActionColumnInitializers_deprecated,
|
||||||
);
|
);
|
||||||
|
@ -12,6 +12,7 @@ import {
|
|||||||
} from '../modules/actions/add-record/customizeCreateFormBlockInitializers';
|
} from '../modules/actions/add-record/customizeCreateFormBlockInitializers';
|
||||||
import { BulkDestroyActionInitializer } from '../modules/actions/bulk-destroy/BulkDestroyActionInitializer';
|
import { BulkDestroyActionInitializer } from '../modules/actions/bulk-destroy/BulkDestroyActionInitializer';
|
||||||
import { DestroyActionInitializer } from '../modules/actions/delete/DestroyActionInitializer';
|
import { DestroyActionInitializer } from '../modules/actions/delete/DestroyActionInitializer';
|
||||||
|
import { DisassociateActionInitializer } from '../modules/actions/disassociate/DisassociateActionInitializer';
|
||||||
import { ExpandableActionInitializer } from '../modules/actions/expand-collapse/ExpandableActionInitializer';
|
import { ExpandableActionInitializer } from '../modules/actions/expand-collapse/ExpandableActionInitializer';
|
||||||
import { FilterActionInitializer } from '../modules/actions/filter/FilterActionInitializer';
|
import { FilterActionInitializer } from '../modules/actions/filter/FilterActionInitializer';
|
||||||
import { RefreshActionInitializer } from '../modules/actions/refresh/RefreshActionInitializer';
|
import { RefreshActionInitializer } from '../modules/actions/refresh/RefreshActionInitializer';
|
||||||
@ -121,10 +122,10 @@ import * as items from './items';
|
|||||||
export * from './buttons';
|
export * from './buttons';
|
||||||
export * from './items';
|
export * from './items';
|
||||||
export {
|
export {
|
||||||
|
createDetailsBlockSchema,
|
||||||
createFilterFormBlockSchema,
|
createFilterFormBlockSchema,
|
||||||
createFormBlockSchema,
|
createFormBlockSchema,
|
||||||
createReadPrettyFormBlockSchema,
|
createReadPrettyFormBlockSchema,
|
||||||
createDetailsBlockSchema,
|
|
||||||
createTableBlockSchema,
|
createTableBlockSchema,
|
||||||
gridRowColWrap,
|
gridRowColWrap,
|
||||||
itemsMerge,
|
itemsMerge,
|
||||||
@ -144,6 +145,7 @@ export class SchemaInitializerPlugin extends Plugin {
|
|||||||
this.app.addComponents({
|
this.app.addComponents({
|
||||||
...initializerComponents,
|
...initializerComponents,
|
||||||
...items,
|
...items,
|
||||||
|
DestroyActionInitializer,
|
||||||
CreateFormBlockInitializer,
|
CreateFormBlockInitializer,
|
||||||
FormBlockInitializer,
|
FormBlockInitializer,
|
||||||
RecordFormBlockInitializer,
|
RecordFormBlockInitializer,
|
||||||
@ -171,7 +173,7 @@ export class SchemaInitializerPlugin extends Plugin {
|
|||||||
UpdateSubmitActionInitializer,
|
UpdateSubmitActionInitializer,
|
||||||
BulkDestroyActionInitializer,
|
BulkDestroyActionInitializer,
|
||||||
ExpandableActionInitializer,
|
ExpandableActionInitializer,
|
||||||
DestroyActionInitializer,
|
DisassociateActionInitializer,
|
||||||
FilterActionInitializer,
|
FilterActionInitializer,
|
||||||
RefreshActionInitializer,
|
RefreshActionInitializer,
|
||||||
} as any);
|
} as any);
|
||||||
|
@ -4,6 +4,7 @@ import { addNewActionSettings } from '../modules/actions/add-new/addNewActionSet
|
|||||||
import { customizeAddRecordActionSettings } from '../modules/actions/add-record/customizeAddRecordActionSettings';
|
import { customizeAddRecordActionSettings } from '../modules/actions/add-record/customizeAddRecordActionSettings';
|
||||||
import { bulkDeleteActionSettings } from '../modules/actions/bulk-destroy/bulkDeleteActionSettings';
|
import { bulkDeleteActionSettings } from '../modules/actions/bulk-destroy/bulkDeleteActionSettings';
|
||||||
import { deleteActionSettings } from '../modules/actions/delete/deleteActionSettings';
|
import { deleteActionSettings } from '../modules/actions/delete/deleteActionSettings';
|
||||||
|
import { disassociateActionSettings } from '../modules/actions/disassociate/disassociateActionSettings';
|
||||||
import { expendableActionSettings } from '../modules/actions/expand-collapse/expendableActionSettings';
|
import { expendableActionSettings } from '../modules/actions/expand-collapse/expendableActionSettings';
|
||||||
import { filterActionSettings } from '../modules/actions/filter/filterActionSettings';
|
import { filterActionSettings } from '../modules/actions/filter/filterActionSettings';
|
||||||
import { refreshActionSettings } from '../modules/actions/refresh/refreshActionSettings';
|
import { refreshActionSettings } from '../modules/actions/refresh/refreshActionSettings';
|
||||||
@ -69,6 +70,7 @@ export class SchemaSettingsPlugin extends Plugin {
|
|||||||
this.schemaSettingsManager.add(viewActionSettings);
|
this.schemaSettingsManager.add(viewActionSettings);
|
||||||
this.schemaSettingsManager.add(editActionSettings);
|
this.schemaSettingsManager.add(editActionSettings);
|
||||||
this.schemaSettingsManager.add(deleteActionSettings);
|
this.schemaSettingsManager.add(deleteActionSettings);
|
||||||
|
this.schemaSettingsManager.add(disassociateActionSettings);
|
||||||
this.schemaSettingsManager.add(bulkDeleteActionSettings);
|
this.schemaSettingsManager.add(bulkDeleteActionSettings);
|
||||||
this.schemaSettingsManager.add(customizeAddRecordActionSettings);
|
this.schemaSettingsManager.add(customizeAddRecordActionSettings);
|
||||||
this.schemaSettingsManager.add(customizePopupActionSettings);
|
this.schemaSettingsManager.add(customizePopupActionSettings);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "create-nocobase-app",
|
"name": "create-nocobase-app",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
{
|
{
|
||||||
"name": "@nocobase/data-source-manager",
|
"name": "@nocobase/data-source-manager",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"description": "",
|
"description": "",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"main": "./lib/index.js",
|
"main": "./lib/index.js",
|
||||||
"types": "./lib/index.d.ts",
|
"types": "./lib/index.d.ts",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nocobase/actions": "0.20.0-alpha.14",
|
"@nocobase/actions": "0.20.0-alpha.15",
|
||||||
"@nocobase/cache": "0.20.0-alpha.14",
|
"@nocobase/cache": "0.20.0-alpha.15",
|
||||||
"@nocobase/database": "0.20.0-alpha.14",
|
"@nocobase/database": "0.20.0-alpha.15",
|
||||||
"@nocobase/resourcer": "0.20.0-alpha.14",
|
"@nocobase/resourcer": "0.20.0-alpha.15",
|
||||||
"@nocobase/utils": "0.20.0-alpha.14",
|
"@nocobase/utils": "0.20.0-alpha.15",
|
||||||
"@types/jsonwebtoken": "^8.5.8",
|
"@types/jsonwebtoken": "^8.5.8",
|
||||||
"jsonwebtoken": "^8.5.1"
|
"jsonwebtoken": "^8.5.1"
|
||||||
},
|
},
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
{
|
{
|
||||||
"name": "@nocobase/database",
|
"name": "@nocobase/database",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "./lib/index.js",
|
"main": "./lib/index.js",
|
||||||
"types": "./lib/index.d.ts",
|
"types": "./lib/index.d.ts",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nocobase/logger": "0.20.0-alpha.14",
|
"@nocobase/logger": "0.20.0-alpha.15",
|
||||||
"@nocobase/utils": "0.20.0-alpha.14",
|
"@nocobase/utils": "0.20.0-alpha.15",
|
||||||
"async-mutex": "^0.3.2",
|
"async-mutex": "^0.3.2",
|
||||||
"chalk": "^4.1.1",
|
"chalk": "^4.1.1",
|
||||||
"cron-parser": "4.4.0",
|
"cron-parser": "4.4.0",
|
||||||
|
@ -13,19 +13,20 @@ describe('string field', () => {
|
|||||||
await db.close();
|
await db.close();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('define', async () => {
|
it('should create uuid field', async () => {
|
||||||
const Test = db.collection({
|
const Test = db.collection({
|
||||||
name: 'tests',
|
name: 'tests',
|
||||||
autoGenId: false,
|
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
|
name: 'uuid',
|
||||||
type: 'uuid',
|
type: 'uuid',
|
||||||
name: 'id',
|
|
||||||
primaryKey: true,
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
await Test.sync();
|
await Test.sync();
|
||||||
await Test.model.create();
|
const item = await Test.model.create();
|
||||||
|
|
||||||
|
expect(item['uuid']).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -5,7 +5,7 @@ export class UuidField extends Field {
|
|||||||
constructor(options?: any, context?: FieldContext) {
|
constructor(options?: any, context?: FieldContext) {
|
||||||
super(
|
super(
|
||||||
{
|
{
|
||||||
defaultValue: DataTypes.UUIDV4,
|
defaultValue: new DataTypes.UUIDV4(),
|
||||||
...options,
|
...options,
|
||||||
},
|
},
|
||||||
context,
|
context,
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
{
|
{
|
||||||
"name": "@nocobase/devtools",
|
"name": "@nocobase/devtools",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"description": "",
|
"description": "",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"main": "./src/index.js",
|
"main": "./src/index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nocobase/build": "0.20.0-alpha.14",
|
"@nocobase/build": "0.20.0-alpha.15",
|
||||||
"@nocobase/client": "0.20.0-alpha.14",
|
"@nocobase/client": "0.20.0-alpha.15",
|
||||||
"@nocobase/test": "0.20.0-alpha.14",
|
"@nocobase/test": "0.20.0-alpha.15",
|
||||||
"@types/koa": "^2.13.4",
|
"@types/koa": "^2.13.4",
|
||||||
"@types/koa-bodyparser": "^4.3.4",
|
"@types/koa-bodyparser": "^4.3.4",
|
||||||
"@types/lodash": "^4.14.177",
|
"@types/lodash": "^4.14.177",
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
{
|
{
|
||||||
"name": "@nocobase/evaluators",
|
"name": "@nocobase/evaluators",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "./lib/index.js",
|
"main": "./lib/index.js",
|
||||||
"types": "./lib/index.d.ts",
|
"types": "./lib/index.d.ts",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@formulajs/formulajs": "4.2.0",
|
"@formulajs/formulajs": "4.2.0",
|
||||||
"@nocobase/utils": "0.20.0-alpha.14",
|
"@nocobase/utils": "0.20.0-alpha.15",
|
||||||
"mathjs": "^10.6.0"
|
"mathjs": "^10.6.0"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nocobase/logger",
|
"name": "@nocobase/logger",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"description": "nocobase logging library",
|
"description": "nocobase logging library",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"main": "./lib/index.js",
|
"main": "./lib/index.js",
|
||||||
|
@ -49,13 +49,13 @@ class SystemLoggerTransport extends Transport {
|
|||||||
}
|
}
|
||||||
|
|
||||||
log(info: any, callback: any) {
|
log(info: any, callback: any) {
|
||||||
const { level, message, reqId, app, stack, [SPLAT]: args } = info;
|
const { level, message, reqId, app, stack, cause, [SPLAT]: args } = info;
|
||||||
const logger = level === 'error' && this.errorLogger ? this.errorLogger : this.logger;
|
const logger = level === 'error' && this.errorLogger ? this.errorLogger : this.logger;
|
||||||
const { module, submodule, method, ...meta } = args?.[0] || {};
|
const { module, submodule, method, ...meta } = args?.[0] || {};
|
||||||
logger.log({
|
logger.log({
|
||||||
level,
|
level,
|
||||||
stack,
|
|
||||||
message,
|
message,
|
||||||
|
stack,
|
||||||
meta,
|
meta,
|
||||||
module: module || info['module'] || '',
|
module: module || info['module'] || '',
|
||||||
submodule: submodule || info['submodule'] || '',
|
submodule: submodule || info['submodule'] || '',
|
||||||
@ -63,11 +63,51 @@ class SystemLoggerTransport extends Transport {
|
|||||||
app,
|
app,
|
||||||
reqId,
|
reqId,
|
||||||
});
|
});
|
||||||
|
if (cause) {
|
||||||
|
logger.log({
|
||||||
|
level,
|
||||||
|
message: cause.message,
|
||||||
|
stack: cause.stack,
|
||||||
|
app,
|
||||||
|
reqId,
|
||||||
|
});
|
||||||
|
}
|
||||||
callback(null, true);
|
callback(null, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const createSystemLogger = (options: SystemLoggerOptions): SystemLogger =>
|
function child(defaultRequestMetadata: any) {
|
||||||
winston.createLogger({
|
const logger = this;
|
||||||
|
return Object.create(logger, {
|
||||||
|
write: {
|
||||||
|
value: function (info: any) {
|
||||||
|
const infoClone = Object.assign({}, defaultRequestMetadata, info);
|
||||||
|
|
||||||
|
if (info instanceof Error) {
|
||||||
|
infoClone.stack = info.stack;
|
||||||
|
infoClone.message = info.message;
|
||||||
|
infoClone.cause = info.cause;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.write(infoClone);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export const createSystemLogger = (options: SystemLoggerOptions): SystemLogger => {
|
||||||
|
const logger = winston.createLogger({
|
||||||
transports: [new SystemLoggerTransport(options)],
|
transports: [new SystemLoggerTransport(options)],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Since error.cause is not supported by child logger of winston
|
||||||
|
// we have to use a proxy to rewrite child method
|
||||||
|
return new Proxy(logger, {
|
||||||
|
get(target, prop) {
|
||||||
|
if (prop === 'child') {
|
||||||
|
return child.bind(target);
|
||||||
|
}
|
||||||
|
return Reflect.get(target, prop);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "@nocobase/resourcer",
|
"name": "@nocobase/resourcer",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "./lib/index.js",
|
"main": "./lib/index.js",
|
||||||
"types": "./lib/index.d.ts",
|
"types": "./lib/index.d.ts",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nocobase/utils": "0.20.0-alpha.14",
|
"@nocobase/utils": "0.20.0-alpha.15",
|
||||||
"deepmerge": "^4.2.2",
|
"deepmerge": "^4.2.2",
|
||||||
"koa-compose": "^4.1.0",
|
"koa-compose": "^4.1.0",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nocobase/sdk",
|
"name": "@nocobase/sdk",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"types": "lib/index.d.ts",
|
"types": "lib/index.d.ts",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nocobase/server",
|
"name": "@nocobase/server",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"types": "./lib/index.d.ts",
|
"types": "./lib/index.d.ts",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
@ -10,18 +10,18 @@
|
|||||||
"@koa/cors": "^3.1.0",
|
"@koa/cors": "^3.1.0",
|
||||||
"@koa/multer": "^3.0.2",
|
"@koa/multer": "^3.0.2",
|
||||||
"@koa/router": "^9.4.0",
|
"@koa/router": "^9.4.0",
|
||||||
"@nocobase/acl": "0.20.0-alpha.14",
|
"@nocobase/acl": "0.20.0-alpha.15",
|
||||||
"@nocobase/actions": "0.20.0-alpha.14",
|
"@nocobase/actions": "0.20.0-alpha.15",
|
||||||
"@nocobase/auth": "0.20.0-alpha.14",
|
"@nocobase/auth": "0.20.0-alpha.15",
|
||||||
"@nocobase/cache": "0.20.0-alpha.14",
|
"@nocobase/cache": "0.20.0-alpha.15",
|
||||||
"@nocobase/data-source-manager": "0.20.0-alpha.14",
|
"@nocobase/data-source-manager": "0.20.0-alpha.15",
|
||||||
"@nocobase/database": "0.20.0-alpha.14",
|
"@nocobase/database": "0.20.0-alpha.15",
|
||||||
"@nocobase/evaluators": "0.20.0-alpha.14",
|
"@nocobase/evaluators": "0.20.0-alpha.15",
|
||||||
"@nocobase/logger": "0.20.0-alpha.14",
|
"@nocobase/logger": "0.20.0-alpha.15",
|
||||||
"@nocobase/resourcer": "0.20.0-alpha.14",
|
"@nocobase/resourcer": "0.20.0-alpha.15",
|
||||||
"@nocobase/sdk": "0.20.0-alpha.14",
|
"@nocobase/sdk": "0.20.0-alpha.15",
|
||||||
"@nocobase/telemetry": "0.20.0-alpha.14",
|
"@nocobase/telemetry": "0.20.0-alpha.15",
|
||||||
"@nocobase/utils": "0.20.0-alpha.14",
|
"@nocobase/utils": "0.20.0-alpha.15",
|
||||||
"@types/decompress": "4.2.4",
|
"@types/decompress": "4.2.4",
|
||||||
"@types/ini": "^1.3.31",
|
"@types/ini": "^1.3.31",
|
||||||
"@types/koa-send": "^4.1.3",
|
"@types/koa-send": "^4.1.3",
|
||||||
|
@ -34,6 +34,7 @@ const availableActions: {
|
|||||||
},
|
},
|
||||||
destroy: {
|
destroy: {
|
||||||
displayName: '{{t("Delete")}}',
|
displayName: '{{t("Delete")}}',
|
||||||
|
aliases: ['destroy', 'remove'],
|
||||||
type: 'old-data',
|
type: 'old-data',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nocobase/telemetry",
|
"name": "@nocobase/telemetry",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"description": "nocobase telemetry library",
|
"description": "nocobase telemetry library",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"main": "./lib/index.js",
|
"main": "./lib/index.js",
|
||||||
@ -11,7 +11,7 @@
|
|||||||
"directory": "packages/telemetry"
|
"directory": "packages/telemetry"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nocobase/utils": "0.20.0-alpha.14",
|
"@nocobase/utils": "0.20.0-alpha.15",
|
||||||
"@opentelemetry/api": "^1.7.0",
|
"@opentelemetry/api": "^1.7.0",
|
||||||
"@opentelemetry/instrumentation": "^0.46.0",
|
"@opentelemetry/instrumentation": "^0.46.0",
|
||||||
"@opentelemetry/resources": "^1.19.0",
|
"@opentelemetry/resources": "^1.19.0",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nocobase/test",
|
"name": "@nocobase/test",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"module": "./src/index.ts",
|
"module": "./src/index.ts",
|
||||||
"types": "./lib/index.d.ts",
|
"types": "./lib/index.d.ts",
|
||||||
@ -40,7 +40,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@faker-js/faker": "8.1.0",
|
"@faker-js/faker": "8.1.0",
|
||||||
"@nocobase/server": "0.20.0-alpha.14",
|
"@nocobase/server": "0.20.0-alpha.15",
|
||||||
"@playwright/test": "^1.42.1",
|
"@playwright/test": "^1.42.1",
|
||||||
"@testing-library/react": "^14.0.0",
|
"@testing-library/react": "^14.0.0",
|
||||||
"@testing-library/user-event": "^14.4.3",
|
"@testing-library/user-event": "^14.4.3",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nocobase/utils",
|
"name": "@nocobase/utils",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"types": "./lib/index.d.ts",
|
"types": "./lib/index.d.ts",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
"displayName.zh-CN": "权限控制",
|
"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": "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": "基于角色、资源和操作的权限控制,可以精确控制界面配置权限、数据操作权限、菜单访问权限、插件权限。",
|
"description.zh-CN": "基于角色、资源和操作的权限控制,可以精确控制界面配置权限、数据操作权限、菜单访问权限、插件权限。",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"main": "./dist/server/index.js",
|
"main": "./dist/server/index.js",
|
||||||
"homepage": "https://docs.nocobase.com/handbook/acl",
|
"homepage": "https://docs.nocobase.com/handbook/acl",
|
||||||
|
@ -1,6 +1,13 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { Card, Row, Col, Tabs, Divider } from 'antd';
|
import { Card, Row, Col, Tabs, Divider } from 'antd';
|
||||||
import { CollectionProvider, CollectionProvider_deprecated, ResourceActionProvider, usePlugin } from '@nocobase/client';
|
import {
|
||||||
|
CollectionProvider,
|
||||||
|
CollectionProvider_deprecated,
|
||||||
|
ResourceActionProvider,
|
||||||
|
SchemaComponentContext,
|
||||||
|
usePlugin,
|
||||||
|
useSchemaComponentContext,
|
||||||
|
} from '@nocobase/client';
|
||||||
import { ISchema, Schema } from '@formily/react';
|
import { ISchema, Schema } from '@formily/react';
|
||||||
import { RolesMenu } from './RolesMenu';
|
import { RolesMenu } from './RolesMenu';
|
||||||
import { useACLTranslation } from './locale';
|
import { useACLTranslation } from './locale';
|
||||||
@ -58,53 +65,55 @@ export const RolesManagement: React.FC = () => {
|
|||||||
children: item.Component ? React.createElement(item.Component, { active: activeKey === name }) : null,
|
children: item.Component ? React.createElement(item.Component, { active: activeKey === name }) : null,
|
||||||
}));
|
}));
|
||||||
const [role, setRole] = useState(null);
|
const [role, setRole] = useState(null);
|
||||||
|
const scCtx = useSchemaComponentContext();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RolesManagerContext.Provider value={{ role, setRole }}>
|
<SchemaComponentContext.Provider value={{ ...scCtx, designable: false }}>
|
||||||
<Card>
|
<RolesManagerContext.Provider value={{ role, setRole }}>
|
||||||
<Row gutter={24} style={{ flexWrap: 'nowrap' }}>
|
<Card>
|
||||||
<Col flex="280px" style={{ borderRight: '1px solid #eee', minWidth: '250px' }}>
|
<Row gutter={24} style={{ flexWrap: 'nowrap' }}>
|
||||||
<ResourceActionProvider
|
<Col flex="280px" style={{ borderRight: '1px solid #eee', minWidth: '250px' }}>
|
||||||
collection={collection}
|
<ResourceActionProvider
|
||||||
request={{
|
collection={collection}
|
||||||
resource: 'roles',
|
request={{
|
||||||
action: 'list',
|
resource: 'roles',
|
||||||
params: {
|
action: 'list',
|
||||||
pagination: false,
|
params: {
|
||||||
filter: {
|
filter: {
|
||||||
'name.$ne': 'root',
|
'name.$ne': 'root',
|
||||||
|
},
|
||||||
|
showAnonymous: true,
|
||||||
|
sort: ['createdAt'],
|
||||||
|
appends: [],
|
||||||
},
|
},
|
||||||
showAnonymous: true,
|
}}
|
||||||
sort: ['createdAt'],
|
>
|
||||||
appends: [],
|
<CollectionProvider_deprecated collection={collection}>
|
||||||
},
|
<Row>
|
||||||
}}
|
<NewRole />
|
||||||
>
|
</Row>
|
||||||
<CollectionProvider_deprecated collection={collection}>
|
<Divider style={{ margin: '12px 0' }} />
|
||||||
<Row>
|
<RolesMenu />
|
||||||
<NewRole />
|
</CollectionProvider_deprecated>
|
||||||
</Row>
|
</ResourceActionProvider>
|
||||||
<Divider style={{ margin: '12px 0' }} />
|
</Col>
|
||||||
<RolesMenu />
|
<Col flex="auto" style={{ overflow: 'hidden' }}>
|
||||||
</CollectionProvider_deprecated>
|
<Tabs
|
||||||
</ResourceActionProvider>
|
activeKey={activeKey}
|
||||||
</Col>
|
onChange={(key) => setActiveKey(key)}
|
||||||
<Col flex="auto" style={{ overflow: 'hidden' }}>
|
items={[
|
||||||
<Tabs
|
{
|
||||||
activeKey={activeKey}
|
key: 'permissions',
|
||||||
onChange={(key) => setActiveKey(key)}
|
label: t('Permissions'),
|
||||||
items={[
|
children: <Permissions active={activeKey === 'permissions'} />,
|
||||||
{
|
},
|
||||||
key: 'permissions',
|
...tabs,
|
||||||
label: t('Permissions'),
|
]}
|
||||||
children: <Permissions active={activeKey === 'permissions'} />,
|
/>
|
||||||
},
|
</Col>
|
||||||
...tabs,
|
</Row>
|
||||||
]}
|
</Card>
|
||||||
/>
|
</RolesManagerContext.Provider>
|
||||||
</Col>
|
</SchemaComponentContext.Provider>
|
||||||
</Row>
|
|
||||||
</Card>
|
|
||||||
</RolesManagerContext.Provider>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -5,55 +5,98 @@ import {
|
|||||||
useAPIClient,
|
useAPIClient,
|
||||||
useResourceActionContext,
|
useResourceActionContext,
|
||||||
} from '@nocobase/client';
|
} from '@nocobase/client';
|
||||||
import { Menu, Empty, Dropdown, App, Tag, Row, Col } from 'antd';
|
import { Menu, Empty, Dropdown, App, Tag, Row, Col, Spin } from 'antd';
|
||||||
import { TagOutlined, MoreOutlined } from '@ant-design/icons';
|
import { TagOutlined, MoreOutlined } from '@ant-design/icons';
|
||||||
import React, { useContext, useEffect } from 'react';
|
import React, { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';
|
||||||
import { useACLTranslation } from './locale';
|
import { useACLTranslation } from './locale';
|
||||||
import { Schema } from '@formily/react';
|
import { Schema } from '@formily/react';
|
||||||
import { RolesManagerContext } from './RolesManagerProvider';
|
import { RolesManagerContext } from './RolesManagerProvider';
|
||||||
import { roleEditSchema } from './schemas/roles';
|
import { roleEditSchema } from './schemas/roles';
|
||||||
|
import { useLoadMoreObserver } from './hooks/load-more-observer';
|
||||||
|
|
||||||
export const RolesMenu: React.FC & {
|
export const RolesMenu: React.FC & {
|
||||||
Item: React.FC<{ item: any; onEdit: () => void }>;
|
Item: React.FC<{ item: any; onEdit: () => void }>;
|
||||||
} = () => {
|
} = () => {
|
||||||
const { t } = useACLTranslation();
|
const { t } = useACLTranslation();
|
||||||
const { data } = useResourceActionContext();
|
const { data, run, loading } = useResourceActionContext();
|
||||||
const [visible, setVisible] = React.useState(false);
|
const [visible, setVisible] = useState(false);
|
||||||
const [record, setRecord] = React.useState(null);
|
const [record, setRecord] = useState(null);
|
||||||
const { role, setRole } = useContext(RolesManagerContext);
|
const { role, setRole } = useContext(RolesManagerContext);
|
||||||
const items = (data?.data || []).map((item: any) => ({
|
const [roles, setRoles] = useState([]);
|
||||||
key: item.name,
|
|
||||||
label: (
|
const loadMore = useCallback(() => {
|
||||||
<RolesMenu.Item
|
const meta = data?.meta;
|
||||||
item={item}
|
if (!meta || meta.page >= meta.totalPage) {
|
||||||
onEdit={() => {
|
return;
|
||||||
setVisible(true);
|
}
|
||||||
setRecord(item);
|
run({
|
||||||
}}
|
page: meta.page + 1,
|
||||||
/>
|
});
|
||||||
),
|
}, [data]);
|
||||||
}));
|
const { lastItem, setLastItem } = useLoadMoreObserver({ loadMore });
|
||||||
|
|
||||||
const handleSelect = ({ key }) => {
|
const handleSelect = ({ key }) => {
|
||||||
setRole((data?.data || []).find((item: any) => item.name === key));
|
setRole(roles.find((item: any) => item.name === key));
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!data?.data.length) {
|
if (!roles[0]) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setRole(data?.data[0]);
|
setRole(roles[0]);
|
||||||
}, [data, setRole]);
|
}, [roles, setRole]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!data?.data?.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ref = React.createRef<any>();
|
||||||
|
setLastItem(ref);
|
||||||
|
|
||||||
|
setRoles((prev) => prev.concat(data.data));
|
||||||
|
}, [data, setLastItem]);
|
||||||
|
|
||||||
|
const items = useMemo(
|
||||||
|
() =>
|
||||||
|
roles.map((item: any, index: number) => ({
|
||||||
|
key: item.name,
|
||||||
|
label:
|
||||||
|
index === roles.length - 1 ? (
|
||||||
|
<div ref={lastItem}>
|
||||||
|
<RolesMenu.Item
|
||||||
|
item={item}
|
||||||
|
onEdit={() => {
|
||||||
|
setVisible(true);
|
||||||
|
setRecord(item);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<RolesMenu.Item
|
||||||
|
item={item}
|
||||||
|
onEdit={() => {
|
||||||
|
setVisible(true);
|
||||||
|
setRecord(item);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
})),
|
||||||
|
[roles, lastItem],
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{items.length ? (
|
{roles.length ? (
|
||||||
<Menu
|
<>
|
||||||
style={{ border: 'none', maxHeight: '65vh', overflowY: 'auto' }}
|
<Menu
|
||||||
items={items}
|
style={{ border: 'none', maxHeight: '65vh', overflowY: 'auto' }}
|
||||||
selectedKeys={[role?.name]}
|
items={items}
|
||||||
onSelect={handleSelect}
|
selectedKeys={[role?.name]}
|
||||||
/>
|
onSelect={handleSelect}
|
||||||
|
/>
|
||||||
|
{loading && <Spin />}
|
||||||
|
</>
|
||||||
) : (
|
) : (
|
||||||
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
|
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
|
||||||
)}
|
)}
|
||||||
@ -92,12 +135,15 @@ RolesMenu.Item = function DepartmentTreeItem({ item, onEdit }) {
|
|||||||
deleteDepartment();
|
deleteDepartment();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const title = Schema.compile(item.title, { t });
|
||||||
return (
|
return (
|
||||||
<Row>
|
<Row>
|
||||||
<Col flex={3} style={{ display: 'inline-flex', alignItems: 'center' }}>
|
<Col flex={3} style={{ display: 'inline-flex', alignItems: 'center' }}>
|
||||||
<span style={{ whiteSpace: 'nowrap', width: '120px', overflow: 'hidden', textOverflow: 'ellipsis' }}>
|
<span style={{ whiteSpace: 'nowrap', width: '120px', overflow: 'hidden', textOverflow: 'ellipsis' }}>
|
||||||
<TagOutlined />
|
<TagOutlined />
|
||||||
<span style={{ marginLeft: '10px' }}>{Schema.compile(item.title, { t })}</span>
|
<span style={{ marginLeft: '10px' }} title={title}>
|
||||||
|
{title}
|
||||||
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</Col>
|
</Col>
|
||||||
<Col>
|
<Col>
|
||||||
|
@ -0,0 +1,45 @@
|
|||||||
|
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
||||||
|
|
||||||
|
export const useLoadMoreObserver = ({
|
||||||
|
loadMore,
|
||||||
|
}: {
|
||||||
|
loadMore: () => void; // callback
|
||||||
|
}) => {
|
||||||
|
const [lastItem, setLastItem] = useState<React.RefObject<any>>(null);
|
||||||
|
const observer = useRef<IntersectionObserver | null>(null);
|
||||||
|
const observeExposure = useCallback(
|
||||||
|
(lastItem: React.RefObject<any>) => {
|
||||||
|
if (!lastItem) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
observer.current && observer.current.disconnect();
|
||||||
|
observer.current = new IntersectionObserver((entries) => {
|
||||||
|
entries.forEach((entry) => {
|
||||||
|
if (entry.target !== lastItem.current) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (entry.isIntersecting) {
|
||||||
|
observer.current && observer.current.unobserve(lastItem.current);
|
||||||
|
loadMore();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
lastItem.current && observer.current && observer.current.observe(lastItem.current);
|
||||||
|
},
|
||||||
|
[loadMore],
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
observeExposure(lastItem);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
observer.current && observer.current.disconnect();
|
||||||
|
};
|
||||||
|
}, [lastItem, observeExposure]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
lastItem,
|
||||||
|
setLastItem,
|
||||||
|
};
|
||||||
|
};
|
@ -398,11 +398,12 @@ export class PluginACL extends Plugin {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// sync database role data to acl
|
// sync database role data to acl
|
||||||
this.app.on('afterLoad', async () => {
|
this.app.on('afterStart', async () => {
|
||||||
await writeRolesToACL(this.app, {
|
await writeRolesToACL(this.app, {
|
||||||
withOutResources: true,
|
withOutResources: true,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// this.app.on('afterInstall', writeRolesToACL);
|
// this.app.on('afterInstall', writeRolesToACL);
|
||||||
|
|
||||||
this.app.on('afterInstallPlugin', async (plugin) => {
|
this.app.on('afterInstallPlugin', async (plugin) => {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nocobase/plugin-action-bulk-edit",
|
"name": "@nocobase/plugin-action-bulk-edit",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"main": "dist/server/index.js",
|
"main": "dist/server/index.js",
|
||||||
"homepage": "https://docs.nocobase.com/handbook/action-bulk-edit",
|
"homepage": "https://docs.nocobase.com/handbook/action-bulk-edit",
|
||||||
"homepage.zh-CN": "https://docs-cn.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",
|
"name": "@nocobase/plugin-action-bulk-update",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"main": "dist/server/index.js",
|
"main": "dist/server/index.js",
|
||||||
"homepage": "https://docs.nocobase.com/handbook/action-bulk-update",
|
"homepage": "https://docs.nocobase.com/handbook/action-bulk-update",
|
||||||
"homepage.zh-CN": "https://docs-cn.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",
|
"name": "@nocobase/plugin-action-duplicate",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"main": "dist/server/index.js",
|
"main": "dist/server/index.js",
|
||||||
"homepage": "https://docs.nocobase.com/handbook/action-duplicate",
|
"homepage": "https://docs.nocobase.com/handbook/action-duplicate",
|
||||||
"homepage.zh-CN": "https://docs-cn.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",
|
"name": "@nocobase/plugin-action-print",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"main": "dist/server/index.js",
|
"main": "dist/server/index.js",
|
||||||
"homepage": "https://docs.nocobase.com/handbook/action-print",
|
"homepage": "https://docs.nocobase.com/handbook/action-print",
|
||||||
"homepage.zh-CN": "https://docs-cn.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",
|
"name": "@nocobase/plugin-api-doc",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"displayName": "API documentation",
|
"displayName": "API documentation",
|
||||||
"displayName.zh-CN": "API 文档",
|
"displayName.zh-CN": "API 文档",
|
||||||
"description": "An OpenAPI documentation generator for NocoBase HTTP API.",
|
"description": "An OpenAPI documentation generator for NocoBase HTTP API.",
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
"displayName.zh-CN": "认证:API 密钥",
|
"displayName.zh-CN": "认证:API 密钥",
|
||||||
"description": "Allows users to use API key to access application's HTTP API",
|
"description": "Allows users to use API key to access application's HTTP API",
|
||||||
"description.zh-CN": "允许用户使用 API 密钥访问应用的 HTTP API",
|
"description.zh-CN": "允许用户使用 API 密钥访问应用的 HTTP API",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"main": "./dist/server/index.js",
|
"main": "./dist/server/index.js",
|
||||||
"homepage": "https://docs.nocobase.com/handbook/api-keys",
|
"homepage": "https://docs.nocobase.com/handbook/api-keys",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nocobase/plugin-audit-logs",
|
"name": "@nocobase/plugin-audit-logs",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"displayName": "Audit logs (deprecated)",
|
"displayName": "Audit logs (deprecated)",
|
||||||
"displayName.zh-CN": "审计日志(废弃)",
|
"displayName.zh-CN": "审计日志(废弃)",
|
||||||
"description": "This plugin is deprecated. There will be a new audit log plugin in the future.",
|
"description": "This plugin is deprecated. There will be a new audit log plugin in the future.",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nocobase/plugin-auth",
|
"name": "@nocobase/plugin-auth",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"main": "./dist/server/index.js",
|
"main": "./dist/server/index.js",
|
||||||
"homepage": "https://docs.nocobase.com/handbook/auth",
|
"homepage": "https://docs.nocobase.com/handbook/auth",
|
||||||
"homepage.zh-CN": "https://docs-cn.nocobase.com/handbook/auth",
|
"homepage.zh-CN": "https://docs-cn.nocobase.com/handbook/auth",
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
"displayName.zh-CN": "应用的备份与还原",
|
"displayName.zh-CN": "应用的备份与还原",
|
||||||
"description": "Backup and restore applications for scenarios such as application replication, migration, and upgrades.",
|
"description": "Backup and restore applications for scenarios such as application replication, migration, and upgrades.",
|
||||||
"description.zh-CN": "备份和还原应用,可用于应用的复制、迁移、升级等场景。",
|
"description.zh-CN": "备份和还原应用,可用于应用的复制、迁移、升级等场景。",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"main": "./dist/server/index.js",
|
"main": "./dist/server/index.js",
|
||||||
"homepage": "https://docs.nocobase.com/handbook/backup-restore",
|
"homepage": "https://docs.nocobase.com/handbook/backup-restore",
|
||||||
|
@ -85,6 +85,43 @@ describe('dumper', () => {
|
|||||||
expect(items.length).toBe(1);
|
expect(items.length).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should dump and restore uuid field', async () => {
|
||||||
|
await db.getRepository('collections').create({
|
||||||
|
values: {
|
||||||
|
name: 'tests',
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
type: 'uuid',
|
||||||
|
name: 'uuid_test',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
context: {},
|
||||||
|
});
|
||||||
|
|
||||||
|
await db.getRepository('tests').create({
|
||||||
|
values: {},
|
||||||
|
});
|
||||||
|
|
||||||
|
const dumper = new Dumper(app);
|
||||||
|
|
||||||
|
const result = await dumper.dump({
|
||||||
|
groups: new Set(['required', 'custom']),
|
||||||
|
});
|
||||||
|
|
||||||
|
const restorer = new Restorer(app, {
|
||||||
|
backUpFilePath: result.filePath,
|
||||||
|
});
|
||||||
|
|
||||||
|
await restorer.restore({
|
||||||
|
groups: new Set(['required', 'custom']),
|
||||||
|
});
|
||||||
|
|
||||||
|
const testCollection = app.db.getCollection('tests');
|
||||||
|
const items = await testCollection.repository.find();
|
||||||
|
expect(items.length).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
describe('id seq', () => {
|
describe('id seq', () => {
|
||||||
let allGroups;
|
let allGroups;
|
||||||
|
|
||||||
|
@ -412,12 +412,18 @@ export class Dumper extends AppMigrator {
|
|||||||
|
|
||||||
if (collectionField) {
|
if (collectionField) {
|
||||||
// is a field
|
// is a field
|
||||||
return {
|
const fieldAttributes: any = {
|
||||||
field: attr.field,
|
field: attr.field,
|
||||||
isCollectionField: true,
|
isCollectionField: true,
|
||||||
type: collectionField.type,
|
type: collectionField.type,
|
||||||
typeOptions: collectionField.options,
|
typeOptions: collectionField.options,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (fieldAttributes.typeOptions?.defaultValue?.constructor?.name === 'UUIDV4') {
|
||||||
|
delete fieldAttributes.typeOptions.defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fieldAttributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nocobase/plugin-calendar",
|
"name": "@nocobase/plugin-calendar",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"displayName": "Calendar",
|
"displayName": "Calendar",
|
||||||
"displayName.zh-CN": "日历",
|
"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.",
|
"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",
|
"displayName.zh-CN": "认证:CAS",
|
||||||
"description": "CAS authentication.",
|
"description": "CAS authentication.",
|
||||||
"description.zh-CN": "通过 CAS 协议认证身份。",
|
"description.zh-CN": "通过 CAS 协议认证身份。",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"main": "./dist/server/index.js",
|
"main": "./dist/server/index.js",
|
||||||
"homepage": "https://docs.nocobase.com/handbook/auth-cas",
|
"homepage": "https://docs.nocobase.com/handbook/auth-cas",
|
||||||
|
@ -3,20 +3,25 @@ import { AppSupervisor } from '@nocobase/server';
|
|||||||
import { CASAuth } from '../auth';
|
import { CASAuth } from '../auth';
|
||||||
|
|
||||||
export const service = async (ctx: Context, next: Next) => {
|
export const service = async (ctx: Context, next: Next) => {
|
||||||
const { authenticator, __appName: appName, redirect = '/admin' } = ctx.action.params;
|
const { authenticator, __appName: appName, redirect } = ctx.action.params;
|
||||||
|
|
||||||
let prefix = '';
|
let prefix = process.env.APP_PUBLIC_PATH || '';
|
||||||
if (appName && appName !== 'main') {
|
if (appName && appName !== 'main') {
|
||||||
const appSupervisor = AppSupervisor.getInstance();
|
const appSupervisor = AppSupervisor.getInstance();
|
||||||
if (appSupervisor?.runningMode !== 'single') {
|
if (appSupervisor?.runningMode !== 'single') {
|
||||||
prefix = process.env.APP_PUBLIC_PATH + `apps/${appName}`;
|
prefix += `apps/${appName}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const auth = (await ctx.app.authManager.get(authenticator, ctx)) as CASAuth;
|
const auth = (await ctx.app.authManager.get(authenticator, ctx)) as CASAuth;
|
||||||
|
|
||||||
|
if (prefix.endsWith('/')) {
|
||||||
|
prefix = prefix.slice(0, -1);
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { token } = await auth.signIn();
|
const { token } = await auth.signIn();
|
||||||
ctx.redirect(`${prefix}${redirect}?authenticator=${authenticator}&token=${token}`);
|
ctx.redirect(`${prefix}${redirect || '/admin'}?authenticator=${authenticator}&token=${token}`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
ctx.redirect(`${prefix}/signin?authenticator=${authenticator}&error=${error.message}&redirect=${redirect}`);
|
ctx.redirect(`${prefix}/signin?authenticator=${authenticator}&error=${error.message}&redirect=${redirect}`);
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
"displayName.zh-CN": "图表(废弃)",
|
"displayName.zh-CN": "图表(废弃)",
|
||||||
"description": "The plugin has been deprecated, please use the data visualization plugin instead.",
|
"description": "The plugin has been deprecated, please use the data visualization plugin instead.",
|
||||||
"description.zh-CN": "已废弃插件,请使用数据可视化插件代替。",
|
"description.zh-CN": "已废弃插件,请使用数据可视化插件代替。",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"main": "./dist/server/index.js",
|
"main": "./dist/server/index.js",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nocobase/plugin-china-region",
|
"name": "@nocobase/plugin-china-region",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"displayName": "Administrative divisions of China",
|
"displayName": "Administrative divisions of China",
|
||||||
"displayName.zh-CN": "中国行政区划",
|
"displayName.zh-CN": "中国行政区划",
|
||||||
"description": "Provides data and field type for administrative divisions of China.",
|
"description": "Provides data and field type for administrative divisions of China.",
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
"displayName.zh-CN": "WEB 客户端",
|
"displayName.zh-CN": "WEB 客户端",
|
||||||
"description": "Provides a client interface for the NocoBase server",
|
"description": "Provides a client interface for the NocoBase server",
|
||||||
"description.zh-CN": "为 NocoBase 服务端提供客户端界面",
|
"description.zh-CN": "为 NocoBase 服务端提供客户端界面",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"main": "./dist/server/index.js",
|
"main": "./dist/server/index.js",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
"displayName.zh-CN": "数据源:主数据库",
|
"displayName.zh-CN": "数据源:主数据库",
|
||||||
"description": "NocoBase main database, supports relational databases such as MySQL, PostgreSQL, SQLite and so on.",
|
"description": "NocoBase main database, supports relational databases such as MySQL, PostgreSQL, SQLite and so on.",
|
||||||
"description.zh-CN": "NocoBase 主数据库,支持 MySQL、PostgreSQL、SQLite 等关系型数据库。",
|
"description.zh-CN": "NocoBase 主数据库,支持 MySQL、PostgreSQL、SQLite 等关系型数据库。",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"main": "./dist/server/index.js",
|
"main": "./dist/server/index.js",
|
||||||
"homepage": "https://docs.nocobase.com/handbook/data-source-main",
|
"homepage": "https://docs.nocobase.com/handbook/data-source-main",
|
||||||
"homepage.zh-CN": "https://docs-cn.nocobase.com/handbook/data-source-main",
|
"homepage.zh-CN": "https://docs-cn.nocobase.com/handbook/data-source-main",
|
||||||
|
@ -0,0 +1,46 @@
|
|||||||
|
import Database, { Collection as DBCollection } from '@nocobase/database';
|
||||||
|
import Application from '@nocobase/server';
|
||||||
|
import { createApp } from '..';
|
||||||
|
|
||||||
|
describe('uuid', () => {
|
||||||
|
let db: Database;
|
||||||
|
let app: Application;
|
||||||
|
let Collection: DBCollection;
|
||||||
|
let Field: DBCollection;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
app = await createApp();
|
||||||
|
db = app.db;
|
||||||
|
Collection = db.getCollection('collections');
|
||||||
|
Field = db.getCollection('fields');
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
await app.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create uuid field', async () => {
|
||||||
|
await Collection.repository.create({
|
||||||
|
values: {
|
||||||
|
name: 'tests',
|
||||||
|
},
|
||||||
|
context: {},
|
||||||
|
});
|
||||||
|
|
||||||
|
await Field.repository.create({
|
||||||
|
values: {
|
||||||
|
collectionName: 'tests',
|
||||||
|
type: 'uuid',
|
||||||
|
name: 'uuid',
|
||||||
|
},
|
||||||
|
context: {},
|
||||||
|
});
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
const resp = await app.agent().resource('tests').create({});
|
||||||
|
expect(resp.status).toBe(200);
|
||||||
|
|
||||||
|
const data = resp.body.data;
|
||||||
|
expect(data['uuid']).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/);
|
||||||
|
});
|
||||||
|
});
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nocobase/plugin-custom-request",
|
"name": "@nocobase/plugin-custom-request",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"main": "dist/server/index.js",
|
"main": "dist/server/index.js",
|
||||||
"homepage": "https://docs.nocobase.com/handbook/action-custom-request",
|
"homepage": "https://docs.nocobase.com/handbook/action-custom-request",
|
||||||
"homepage.zh-CN": "https://docs-cn.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",
|
"name": "@nocobase/plugin-data-source-manager",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"main": "dist/server/index.js",
|
"main": "dist/server/index.js",
|
||||||
"displayName": "Data source manager",
|
"displayName": "Data source manager",
|
||||||
"displayName.zh-CN": "数据源管理",
|
"displayName.zh-CN": "数据源管理",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nocobase/plugin-data-visualization",
|
"name": "@nocobase/plugin-data-visualization",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"displayName": "Data visualization",
|
"displayName": "Data visualization",
|
||||||
"displayName.zh-CN": "数据可视化",
|
"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.",
|
"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",
|
"name": "@nocobase/plugin-disable-pm-add",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"main": "./dist/server/index.js",
|
"main": "./dist/server/index.js",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@nocobase/client": "0.x",
|
"@nocobase/client": "0.x",
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
"displayName.zh-CN": "错误处理器",
|
"displayName.zh-CN": "错误处理器",
|
||||||
"description": "Handling application errors and exceptions.",
|
"description": "Handling application errors and exceptions.",
|
||||||
"description.zh-CN": "处理应用程序中的错误和异常。",
|
"description.zh-CN": "处理应用程序中的错误和异常。",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"main": "./dist/server/index.js",
|
"main": "./dist/server/index.js",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nocobase/plugin-excel-formula-field",
|
"name": "@nocobase/plugin-excel-formula-field",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"description": "",
|
"description": "",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"main": "./dist/server/index.js",
|
"main": "./dist/server/index.js",
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
"displayName.zh-CN": "操作:导出记录",
|
"displayName.zh-CN": "操作:导出记录",
|
||||||
"description": "Export filtered records to excel, you can configure which fields to export.",
|
"description": "Export filtered records to excel, you can configure which fields to export.",
|
||||||
"description.zh-CN": "导出筛选后的记录到 Excel 中,可以配置导出哪些字段。",
|
"description.zh-CN": "导出筛选后的记录到 Excel 中,可以配置导出哪些字段。",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"main": "./dist/server/index.js",
|
"main": "./dist/server/index.js",
|
||||||
"homepage": "https://docs.nocobase.com/handbook/action-export",
|
"homepage": "https://docs.nocobase.com/handbook/action-export",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nocobase/plugin-file-manager",
|
"name": "@nocobase/plugin-file-manager",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"displayName": "File manager",
|
"displayName": "File manager",
|
||||||
"displayName.zh-CN": "文件管理器",
|
"displayName.zh-CN": "文件管理器",
|
||||||
"description": "Provides files storage services with files collection template and attachment field.",
|
"description": "Provides files storage services with files collection template and attachment field.",
|
||||||
|
@ -1,158 +1,6 @@
|
|||||||
import { CollectionTemplate, getConfigurableProperties } from '@nocobase/client';
|
import { CollectionTemplate, getConfigurableProperties } from '@nocobase/client';
|
||||||
// import { CollectionOptions } from '@nocobase/database';
|
|
||||||
import { NAMESPACE } from '../locale';
|
import { NAMESPACE } from '../locale';
|
||||||
|
|
||||||
// export const fileCollectionTemplate = {
|
|
||||||
// name: 'file',
|
|
||||||
// title: `{{t("File collection", { ns: "${NAMESPACE}" })}}`,
|
|
||||||
// order: 3,
|
|
||||||
// color: 'blue',
|
|
||||||
// default: {
|
|
||||||
// createdBy: true,
|
|
||||||
// updatedBy: true,
|
|
||||||
// fields: [
|
|
||||||
// {
|
|
||||||
// interface: 'input',
|
|
||||||
// type: 'string',
|
|
||||||
// name: 'title',
|
|
||||||
// deletable: false,
|
|
||||||
// uiSchema: {
|
|
||||||
// type: 'string',
|
|
||||||
// title: `{{t("Title")}}`,
|
|
||||||
// 'x-component': 'Input',
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// // '系统文件名(含扩展名)',
|
|
||||||
// {
|
|
||||||
// interface: 'input',
|
|
||||||
// type: 'string',
|
|
||||||
// name: 'filename',
|
|
||||||
// deletable: false,
|
|
||||||
// uiSchema: {
|
|
||||||
// type: 'string',
|
|
||||||
// title: `{{t("File name", { ns: "${NAMESPACE}" })}}`,
|
|
||||||
// 'x-component': 'Input',
|
|
||||||
// 'x-read-pretty': true,
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// // '扩展名(含“.”)',
|
|
||||||
// {
|
|
||||||
// interface: 'input',
|
|
||||||
// type: 'string',
|
|
||||||
// name: 'extname',
|
|
||||||
// deletable: false,
|
|
||||||
// uiSchema: {
|
|
||||||
// type: 'string',
|
|
||||||
// title: `{{t("Extension name", { ns: "${NAMESPACE}" })}}`,
|
|
||||||
// 'x-component': 'Input',
|
|
||||||
// 'x-read-pretty': true,
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// // '文件体积(字节)',
|
|
||||||
// {
|
|
||||||
// interface: 'integer',
|
|
||||||
// type: 'integer',
|
|
||||||
// name: 'size',
|
|
||||||
// deletable: false,
|
|
||||||
// uiSchema: {
|
|
||||||
// type: 'number',
|
|
||||||
// title: `{{t("Size", { ns: "${NAMESPACE}" })}}`,
|
|
||||||
// 'x-component': 'InputNumber',
|
|
||||||
// 'x-read-pretty': true,
|
|
||||||
// 'x-component-props': {
|
|
||||||
// stringMode: true,
|
|
||||||
// step: '0',
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// interface: 'input',
|
|
||||||
// type: 'string',
|
|
||||||
// name: 'mimetype',
|
|
||||||
// deletable: false,
|
|
||||||
// uiSchema: {
|
|
||||||
// type: 'string',
|
|
||||||
// title: `{{t("MIME type", { ns: "${NAMESPACE}" })}}`,
|
|
||||||
// 'x-component': 'Input',
|
|
||||||
// 'x-read-pretty': true,
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// // '相对路径(含“/”前缀)',
|
|
||||||
// {
|
|
||||||
// interface: 'input',
|
|
||||||
// type: 'string',
|
|
||||||
// name: 'path',
|
|
||||||
// deletable: false,
|
|
||||||
// uiSchema: {
|
|
||||||
// type: 'string',
|
|
||||||
// title: `{{t("Path")}}`,
|
|
||||||
// 'x-component': 'Input',
|
|
||||||
// 'x-read-pretty': true,
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// // 文件的可访问地址
|
|
||||||
// {
|
|
||||||
// interface: 'input',
|
|
||||||
// type: 'string',
|
|
||||||
// name: 'url',
|
|
||||||
// deletable: false,
|
|
||||||
// uiSchema: {
|
|
||||||
// type: 'string',
|
|
||||||
// title: `{{t("URL")}}`,
|
|
||||||
// 'x-component': 'Input.URL',
|
|
||||||
// 'x-read-pretty': true,
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// // 用于预览
|
|
||||||
// {
|
|
||||||
// interface: 'url',
|
|
||||||
// type: 'string',
|
|
||||||
// name: 'preview',
|
|
||||||
// field: 'url', // 直接引用 url 字段
|
|
||||||
// deletable: false,
|
|
||||||
// uiSchema: {
|
|
||||||
// type: 'string',
|
|
||||||
// title: `{{t("Preview")}}`,
|
|
||||||
// 'x-component': 'Preview',
|
|
||||||
// 'x-read-pretty': true,
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// comment: '存储引擎',
|
|
||||||
// type: 'belongsTo',
|
|
||||||
// name: 'storage',
|
|
||||||
// target: 'storages',
|
|
||||||
// foreignKey: 'storageId',
|
|
||||||
// deletable: false,
|
|
||||||
// },
|
|
||||||
// // '其他文件信息(如图片的宽高)',
|
|
||||||
// {
|
|
||||||
// type: 'jsonb',
|
|
||||||
// name: 'meta',
|
|
||||||
// deletable: false,
|
|
||||||
// defaultValue: {},
|
|
||||||
// },
|
|
||||||
// ],
|
|
||||||
// },
|
|
||||||
// configurableProperties: {
|
|
||||||
// ...getConfigurableProperties('title', 'name'),
|
|
||||||
// inherits: {
|
|
||||||
// ...getConfigurableProperties('inherits').inherits,
|
|
||||||
// 'x-reactions': ['{{useAsyncDataSource(loadCollections)}}'],
|
|
||||||
// },
|
|
||||||
// ...getConfigurableProperties('category', 'description'),
|
|
||||||
// storage: {
|
|
||||||
// title: `{{t("File storage", { ns: "${NAMESPACE}" })}}`,
|
|
||||||
// type: 'hasOne',
|
|
||||||
// name: 'storage',
|
|
||||||
// required: true,
|
|
||||||
// 'x-decorator': 'FormItem',
|
|
||||||
// 'x-component': 'Select',
|
|
||||||
// 'x-reactions': ['{{useAsyncDataSource(loadStorages)}}'],
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// } as CollectionOptions;
|
|
||||||
|
|
||||||
export class FileCollectionTemplate extends CollectionTemplate {
|
export class FileCollectionTemplate extends CollectionTemplate {
|
||||||
name = 'file';
|
name = 'file';
|
||||||
title = `{{t("File collection", { ns: "${NAMESPACE}" })}}`;
|
title = `{{t("File collection", { ns: "${NAMESPACE}" })}}`;
|
||||||
@ -236,7 +84,7 @@ export class FileCollectionTemplate extends CollectionTemplate {
|
|||||||
deletable: false,
|
deletable: false,
|
||||||
uiSchema: {
|
uiSchema: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
title: `{{t("Path")}}`,
|
title: `{{t("Path", { ns: "${NAMESPACE}" })}}`,
|
||||||
'x-component': 'Input',
|
'x-component': 'Input',
|
||||||
'x-read-pretty': true,
|
'x-read-pretty': true,
|
||||||
},
|
},
|
||||||
@ -263,7 +111,7 @@ export class FileCollectionTemplate extends CollectionTemplate {
|
|||||||
deletable: false,
|
deletable: false,
|
||||||
uiSchema: {
|
uiSchema: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
title: `{{t("Preview")}}`,
|
title: `{{t("Preview", { ns: "${NAMESPACE}" })}}`,
|
||||||
'x-component': 'Preview',
|
'x-component': 'Preview',
|
||||||
'x-read-pretty': true,
|
'x-read-pretty': true,
|
||||||
},
|
},
|
||||||
@ -275,6 +123,12 @@ export class FileCollectionTemplate extends CollectionTemplate {
|
|||||||
target: 'storages',
|
target: 'storages',
|
||||||
foreignKey: 'storageId',
|
foreignKey: 'storageId',
|
||||||
deletable: false,
|
deletable: false,
|
||||||
|
uiSchema: {
|
||||||
|
type: 'string',
|
||||||
|
title: `{{t("Storage", { ns: "${NAMESPACE}" })}}`,
|
||||||
|
'x-component': 'Input',
|
||||||
|
'x-read-pretty': true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
// '其他文件信息(如图片的宽高)',
|
// '其他文件信息(如图片的宽高)',
|
||||||
{
|
{
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
"displayName.zh-CN": "数据表字段:公式",
|
"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": "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 两种引擎",
|
"description.zh-CN": "可以配置并存储同一条记录的多字段值之间的计算结果,支持 Math.js 和 Excel formula functions 两种引擎",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"main": "./dist/server/index.js",
|
"main": "./dist/server/index.js",
|
||||||
"homepage": "https://docs.nocobase.com/handbook/field-formula",
|
"homepage": "https://docs.nocobase.com/handbook/field-formula",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nocobase/plugin-gantt",
|
"name": "@nocobase/plugin-gantt",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"displayName": "Block: Gantt",
|
"displayName": "Block: Gantt",
|
||||||
"displayName.zh-CN": "区块:甘特图",
|
"displayName.zh-CN": "区块:甘特图",
|
||||||
"description": "Provides Gantt block.",
|
"description": "Provides Gantt block.",
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
"displayName.zh-CN": "可视化数据表管理",
|
"displayName.zh-CN": "可视化数据表管理",
|
||||||
"description": "An ER diagram-like tool. Currently only the Master database is supported.",
|
"description": "An ER diagram-like tool. Currently only the Master database is supported.",
|
||||||
"description.zh-CN": "类似 ER 图的工具,目前只支持主数据库。",
|
"description.zh-CN": "类似 ER 图的工具,目前只支持主数据库。",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"main": "./dist/server/index.js",
|
"main": "./dist/server/index.js",
|
||||||
"homepage": "https://docs.nocobase.com/handbook/graph-collection-manager",
|
"homepage": "https://docs.nocobase.com/handbook/graph-collection-manager",
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
"displayName.zh-CN": "区块:iframe",
|
"displayName.zh-CN": "区块:iframe",
|
||||||
"description": "Create an iframe block on the page to embed and display external web pages or content.",
|
"description": "Create an iframe block on the page to embed and display external web pages or content.",
|
||||||
"description.zh-CN": "在页面上创建和管理iframe,用于嵌入和展示外部网页或内容。",
|
"description.zh-CN": "在页面上创建和管理iframe,用于嵌入和展示外部网页或内容。",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"main": "./dist/server/index.js",
|
"main": "./dist/server/index.js",
|
||||||
"homepage": "https://docs.nocobase.com/handbook/block-iframe",
|
"homepage": "https://docs.nocobase.com/handbook/block-iframe",
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
"displayName.zh-CN": "操作:导入记录",
|
"displayName.zh-CN": "操作:导入记录",
|
||||||
"description": "Import records using excel templates. You can configure which fields to import and templates will be generated automatically.",
|
"description": "Import records using excel templates. You can configure which fields to import and templates will be generated automatically.",
|
||||||
"description.zh-CN": "使用 Excel 模板导入数据,可以配置导入哪些字段,自动生成模板。",
|
"description.zh-CN": "使用 Excel 模板导入数据,可以配置导入哪些字段,自动生成模板。",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"main": "./dist/server/index.js",
|
"main": "./dist/server/index.js",
|
||||||
"homepage": "https://docs.nocobase.com/handbook/action-import",
|
"homepage": "https://docs.nocobase.com/handbook/action-import",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nocobase/plugin-kanban",
|
"name": "@nocobase/plugin-kanban",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"main": "dist/server/index.js",
|
"main": "dist/server/index.js",
|
||||||
"homepage": "https://docs.nocobase.com/handbook/block-kanban",
|
"homepage": "https://docs.nocobase.com/handbook/block-kanban",
|
||||||
"homepage.zh-CN": "https://docs-cn.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",
|
"name": "@nocobase/plugin-localization-management",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"main": "dist/server/index.js",
|
"main": "dist/server/index.js",
|
||||||
"homepage": "https://docs.nocobase.com/handbook/localization-management",
|
"homepage": "https://docs.nocobase.com/handbook/localization-management",
|
||||||
"homepage.zh-CN": "https://docs-cn.nocobase.com/handbook/localization-management",
|
"homepage.zh-CN": "https://docs-cn.nocobase.com/handbook/localization-management",
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
"displayName.zh-CN": "日志",
|
"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": "Server-side logs, mainly including API request logs and system runtime logs, and allows to package and download log files.",
|
||||||
"description.zh-CN": "服务端日志,主要包括接口请求日志和系统运行日志,并支持打包和下载日志文件。",
|
"description.zh-CN": "服务端日志,主要包括接口请求日志和系统运行日志,并支持打包和下载日志文件。",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"main": "dist/server/index.js",
|
"main": "dist/server/index.js",
|
||||||
"homepage": "https://docs.nocobase.com/handbook/logger",
|
"homepage": "https://docs.nocobase.com/handbook/logger",
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
"name": "@nocobase/plugin-map",
|
"name": "@nocobase/plugin-map",
|
||||||
"displayName": "Block: Map",
|
"displayName": "Block: Map",
|
||||||
"displayName.zh-CN": "区块:地图",
|
"displayName.zh-CN": "区块:地图",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"description": "Map block, support Gaode map and Google map, you can also extend more map types.",
|
"description": "Map block, support Gaode map and Google map, you can also extend more map types.",
|
||||||
"description.zh-CN": "地图区块,支持高德地图和 Google 地图,你也可以扩展更多地图类型。",
|
"description.zh-CN": "地图区块,支持高德地图和 Google 地图,你也可以扩展更多地图类型。",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
"displayName.zh-CN": "数学公式字段",
|
"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": "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)无缝集成,并提供直观的用户界面来定义和执行数学公式字段。",
|
"description.zh-CN": "一个功能强大的数学公式字段插件,旨在为数据库或数据管理系统提供灵活的数学计算和公式计算功能。它可以与各种数据库系统(如MySQL、PostgreSQL)无缝集成,并提供直观的用户界面来定义和执行数学公式字段。",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"main": "./dist/server/index.js",
|
"main": "./dist/server/index.js",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nocobase/plugin-mobile-client",
|
"name": "@nocobase/plugin-mobile-client",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"main": "./dist/server/index.js",
|
"main": "./dist/server/index.js",
|
||||||
"homepage": "https://docs.nocobase.com/handbook/mobile-client",
|
"homepage": "https://docs.nocobase.com/handbook/mobile-client",
|
||||||
"homepage.zh-CN": "https://docs-cn.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",
|
"name": "@nocobase/plugin-mock-collections",
|
||||||
"displayName": "mock-collections",
|
"displayName": "mock-collections",
|
||||||
"description": "mock-collections",
|
"description": "mock-collections",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"main": "./dist/server/index.js",
|
"main": "./dist/server/index.js",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
"displayName.zh-CN": "多应用管理器",
|
"displayName.zh-CN": "多应用管理器",
|
||||||
"description": "Dynamically create multiple apps without separate deployments.",
|
"description": "Dynamically create multiple apps without separate deployments.",
|
||||||
"description.zh-CN": "无需单独部署即可动态创建多个应用。",
|
"description.zh-CN": "无需单独部署即可动态创建多个应用。",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"main": "./dist/server/index.js",
|
"main": "./dist/server/index.js",
|
||||||
"homepage": "https://docs.nocobase.com/handbook/multi-app-manager",
|
"homepage": "https://docs.nocobase.com/handbook/multi-app-manager",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { Database } from '@nocobase/database';
|
import { Database } from '@nocobase/database';
|
||||||
import { AppSupervisor, Gateway } from '@nocobase/server';
|
import { AppSupervisor, Gateway } from '@nocobase/server';
|
||||||
import { MockServer, createMockServer } from '@nocobase/test';
|
import { createMockServer, MockServer } from '@nocobase/test';
|
||||||
import { uid } from '@nocobase/utils';
|
import { uid } from '@nocobase/utils';
|
||||||
import { vi } from 'vitest';
|
import { vi } from 'vitest';
|
||||||
import { PluginMultiAppManager } from '../server';
|
import { PluginMultiAppManager } from '../server';
|
||||||
@ -22,6 +22,29 @@ describe('multiple apps', () => {
|
|||||||
await app.destroy();
|
await app.destroy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should merge database options', async () => {
|
||||||
|
const name = `td_${uid()}`;
|
||||||
|
|
||||||
|
await db.getRepository('applications').create({
|
||||||
|
values: {
|
||||||
|
name,
|
||||||
|
options: {
|
||||||
|
plugins: [],
|
||||||
|
database: {
|
||||||
|
underscored: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
context: {
|
||||||
|
waitSubAppInstall: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const subApp = await AppSupervisor.getInstance().getApp(name);
|
||||||
|
|
||||||
|
expect(subApp.db.options.underscored).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
it('should register db creator', async () => {
|
it('should register db creator', async () => {
|
||||||
const fn = vi.fn();
|
const fn = vi.fn();
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { Model, Transactionable } from '@nocobase/database';
|
import { Model, Transactionable } from '@nocobase/database';
|
||||||
import { Application } from '@nocobase/server';
|
import { Application } from '@nocobase/server';
|
||||||
import { AppOptionsFactory } from '../server';
|
import { AppOptionsFactory } from '../server';
|
||||||
|
import { merge } from '@nocobase/utils';
|
||||||
|
|
||||||
export interface registerAppOptions extends Transactionable {
|
export interface registerAppOptions extends Transactionable {
|
||||||
skipInstall?: boolean;
|
skipInstall?: boolean;
|
||||||
@ -10,11 +11,12 @@ export interface registerAppOptions extends Transactionable {
|
|||||||
export class ApplicationModel extends Model {
|
export class ApplicationModel extends Model {
|
||||||
registerToSupervisor(mainApp: Application, options: registerAppOptions) {
|
registerToSupervisor(mainApp: Application, options: registerAppOptions) {
|
||||||
const appName = this.get('name') as string;
|
const appName = this.get('name') as string;
|
||||||
const appOptions = (this.get('options') as any) || {};
|
const appModelOptions = (this.get('options') as any) || {};
|
||||||
|
|
||||||
|
const appOptions = options.appOptionsFactory(appName, mainApp);
|
||||||
|
|
||||||
const subAppOptions = {
|
const subAppOptions = {
|
||||||
...options.appOptionsFactory(appName, mainApp),
|
...(merge(appOptions, appModelOptions) as object),
|
||||||
...appOptions,
|
|
||||||
name: appName,
|
name: appName,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { Database, IDatabaseOptions, Transactionable } from '@nocobase/database';
|
import { Database, IDatabaseOptions, Transactionable } from '@nocobase/database';
|
||||||
import Application, { AppSupervisor, Gateway, Plugin } from '@nocobase/server';
|
import Application, { AppSupervisor, Gateway, Plugin } from '@nocobase/server';
|
||||||
import { Mutex } from 'async-mutex';
|
|
||||||
import lodash from 'lodash';
|
import lodash from 'lodash';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { ApplicationModel } from '../server';
|
import { ApplicationModel } from '../server';
|
||||||
@ -125,8 +124,6 @@ export class PluginMultiAppManager extends Plugin {
|
|||||||
appOptionsFactory: AppOptionsFactory = defaultAppOptionsFactory;
|
appOptionsFactory: AppOptionsFactory = defaultAppOptionsFactory;
|
||||||
subAppUpgradeHandler: SubAppUpgradeHandler = defaultSubAppUpgradeHandle;
|
subAppUpgradeHandler: SubAppUpgradeHandler = defaultSubAppUpgradeHandle;
|
||||||
|
|
||||||
private beforeGetApplicationMutex = new Mutex();
|
|
||||||
|
|
||||||
static getDatabaseConfig(app: Application): IDatabaseOptions {
|
static getDatabaseConfig(app: Application): IDatabaseOptions {
|
||||||
let oldConfig =
|
let oldConfig =
|
||||||
app.options.database instanceof Database
|
app.options.database instanceof Database
|
||||||
@ -136,6 +133,7 @@ export class PluginMultiAppManager extends Plugin {
|
|||||||
if (!oldConfig && app.db) {
|
if (!oldConfig && app.db) {
|
||||||
oldConfig = app.db.options;
|
oldConfig = app.db.options;
|
||||||
}
|
}
|
||||||
|
|
||||||
return lodash.cloneDeep(lodash.omit(oldConfig, ['migrator']));
|
return lodash.cloneDeep(lodash.omit(oldConfig, ['migrator']));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
"displayName.zh-CN": "多应用数据表共享",
|
"displayName.zh-CN": "多应用数据表共享",
|
||||||
"description": "",
|
"description": "",
|
||||||
"description.zh-CN": "",
|
"description.zh-CN": "",
|
||||||
"version": "0.20.0-alpha.14",
|
"version": "0.20.0-alpha.15",
|
||||||
"main": "./dist/server/index.js",
|
"main": "./dist/server/index.js",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@formily/react": "2.x",
|
"@formily/react": "2.x",
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user