mirror of
https://gitee.com/nocobase/nocobase.git
synced 2025-05-07 22:49:26 +08:00
Merge branch 'develop' of github.com:nocobase/nocobase into feat-main-datasource-mssql
This commit is contained in:
commit
b93d3bc01d
19
CHANGELOG.md
19
CHANGELOG.md
@ -5,6 +5,25 @@ All notable changes to this project will be documented in this file.
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [v1.6.10](https://github.com/nocobase/nocobase/compare/v1.6.9...v1.6.10) - 2025-03-25
|
||||
|
||||
### 🐛 Bug Fixes
|
||||
|
||||
- **[client]**
|
||||
- Unable to use 'Current User' variable when adding a link page ([#6536](https://github.com/nocobase/nocobase/pull/6536)) by @zhangzhonghe
|
||||
|
||||
- field assignment with null value is ineffective ([#6549](https://github.com/nocobase/nocobase/pull/6549)) by @katherinehhh
|
||||
|
||||
- `yarn doc` command error ([#6540](https://github.com/nocobase/nocobase/pull/6540)) by @gchust
|
||||
|
||||
- Remove the 'Allow multiple selection' option from dropdown single-select fields in filter forms ([#6515](https://github.com/nocobase/nocobase/pull/6515)) by @zhangzhonghe
|
||||
|
||||
- Relational field's data range linkage is not effective ([#6530](https://github.com/nocobase/nocobase/pull/6530)) by @zhangzhonghe
|
||||
|
||||
- **[Collection: Tree]** Migration issue for plugin-collection-tree ([#6537](https://github.com/nocobase/nocobase/pull/6537)) by @2013xile
|
||||
|
||||
- **[Action: Custom request]** Unable to download UTF-8 encoded files ([#6541](https://github.com/nocobase/nocobase/pull/6541)) by @2013xile
|
||||
|
||||
## [v1.6.9](https://github.com/nocobase/nocobase/compare/v1.6.8...v1.6.9) - 2025-03-23
|
||||
|
||||
### 🐛 Bug Fixes
|
||||
|
@ -5,6 +5,25 @@
|
||||
格式基于 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.0.0/),
|
||||
并且本项目遵循 [语义化版本](https://semver.org/spec/v2.0.0.html)。
|
||||
|
||||
## [v1.6.10](https://github.com/nocobase/nocobase/compare/v1.6.9...v1.6.10) - 2025-03-25
|
||||
|
||||
### 🐛 修复
|
||||
|
||||
- **[client]**
|
||||
- 添加链接页面时,无法使用“当前用户”变量 ([#6536](https://github.com/nocobase/nocobase/pull/6536)) by @zhangzhonghe
|
||||
|
||||
- 字段赋值对字段进行“空值”赋值无效 ([#6549](https://github.com/nocobase/nocobase/pull/6549)) by @katherinehhh
|
||||
|
||||
- `yarn doc` 命令报错 ([#6540](https://github.com/nocobase/nocobase/pull/6540)) by @gchust
|
||||
|
||||
- 筛选表单中,移除下拉单选字段的“允许多选”选项 ([#6515](https://github.com/nocobase/nocobase/pull/6515)) by @zhangzhonghe
|
||||
|
||||
- 关系字段的数据范围联动不生效 ([#6530](https://github.com/nocobase/nocobase/pull/6530)) by @zhangzhonghe
|
||||
|
||||
- **[数据表:树]** 树表插件的迁移脚本问题 ([#6537](https://github.com/nocobase/nocobase/pull/6537)) by @2013xile
|
||||
|
||||
- **[操作:自定义请求]** 无法下载utf8编码的文件 ([#6541](https://github.com/nocobase/nocobase/pull/6541)) by @2013xile
|
||||
|
||||
## [v1.6.9](https://github.com/nocobase/nocobase/compare/v1.6.8...v1.6.9) - 2025-03-23
|
||||
|
||||
### 🐛 修复
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "1.7.0-alpha.4",
|
||||
"version": "1.7.0-beta.9",
|
||||
"npmClient": "yarn",
|
||||
"useWorkspaces": true,
|
||||
"npmClientArgs": ["--ignore-engines"],
|
||||
|
@ -1,13 +1,13 @@
|
||||
{
|
||||
"name": "@nocobase/acl",
|
||||
"version": "1.7.0-alpha.4",
|
||||
"version": "1.7.0-beta.9",
|
||||
"description": "",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "./lib/index.js",
|
||||
"types": "./lib/index.d.ts",
|
||||
"dependencies": {
|
||||
"@nocobase/resourcer": "1.7.0-alpha.4",
|
||||
"@nocobase/utils": "1.7.0-alpha.4",
|
||||
"@nocobase/resourcer": "1.7.0-beta.9",
|
||||
"@nocobase/utils": "1.7.0-beta.9",
|
||||
"minimatch": "^5.1.1"
|
||||
},
|
||||
"repository": {
|
||||
|
@ -1,14 +1,14 @@
|
||||
{
|
||||
"name": "@nocobase/actions",
|
||||
"version": "1.7.0-alpha.4",
|
||||
"version": "1.7.0-beta.9",
|
||||
"description": "",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "./lib/index.js",
|
||||
"types": "./lib/index.d.ts",
|
||||
"dependencies": {
|
||||
"@nocobase/cache": "1.7.0-alpha.4",
|
||||
"@nocobase/database": "1.7.0-alpha.4",
|
||||
"@nocobase/resourcer": "1.7.0-alpha.4"
|
||||
"@nocobase/cache": "1.7.0-beta.9",
|
||||
"@nocobase/database": "1.7.0-beta.9",
|
||||
"@nocobase/resourcer": "1.7.0-beta.9"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -1,17 +1,17 @@
|
||||
{
|
||||
"name": "@nocobase/app",
|
||||
"version": "1.7.0-alpha.4",
|
||||
"version": "1.7.0-beta.9",
|
||||
"description": "",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "./lib/index.js",
|
||||
"types": "./lib/index.d.ts",
|
||||
"dependencies": {
|
||||
"@nocobase/database": "1.7.0-alpha.4",
|
||||
"@nocobase/preset-nocobase": "1.7.0-alpha.4",
|
||||
"@nocobase/server": "1.7.0-alpha.4"
|
||||
"@nocobase/database": "1.7.0-beta.9",
|
||||
"@nocobase/preset-nocobase": "1.7.0-beta.9",
|
||||
"@nocobase/server": "1.7.0-beta.9"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nocobase/client": "1.7.0-alpha.4"
|
||||
"@nocobase/client": "1.7.0-beta.9"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -1,16 +1,16 @@
|
||||
{
|
||||
"name": "@nocobase/auth",
|
||||
"version": "1.7.0-alpha.4",
|
||||
"version": "1.7.0-beta.9",
|
||||
"description": "",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "./lib/index.js",
|
||||
"types": "./lib/index.d.ts",
|
||||
"dependencies": {
|
||||
"@nocobase/actions": "1.7.0-alpha.4",
|
||||
"@nocobase/cache": "1.7.0-alpha.4",
|
||||
"@nocobase/database": "1.7.0-alpha.4",
|
||||
"@nocobase/resourcer": "1.7.0-alpha.4",
|
||||
"@nocobase/utils": "1.7.0-alpha.4",
|
||||
"@nocobase/actions": "1.7.0-beta.9",
|
||||
"@nocobase/cache": "1.7.0-beta.9",
|
||||
"@nocobase/database": "1.7.0-beta.9",
|
||||
"@nocobase/resourcer": "1.7.0-beta.9",
|
||||
"@nocobase/utils": "1.7.0-beta.9",
|
||||
"@types/jsonwebtoken": "^8.5.8",
|
||||
"jsonwebtoken": "^8.5.1"
|
||||
},
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/build",
|
||||
"version": "1.7.0-alpha.4",
|
||||
"version": "1.7.0-beta.9",
|
||||
"description": "Library build tool based on rollup.",
|
||||
"main": "lib/index.js",
|
||||
"types": "./lib/index.d.ts",
|
||||
|
4
packages/core/cache/package.json
vendored
4
packages/core/cache/package.json
vendored
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@nocobase/cache",
|
||||
"version": "1.7.0-alpha.4",
|
||||
"version": "1.7.0-beta.9",
|
||||
"description": "",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "./lib/index.js",
|
||||
"types": "./lib/index.d.ts",
|
||||
"dependencies": {
|
||||
"@nocobase/lock-manager": "1.7.0-alpha.4",
|
||||
"@nocobase/lock-manager": "1.7.0-beta.9",
|
||||
"bloom-filters": "^3.0.1",
|
||||
"cache-manager": "^5.2.4",
|
||||
"cache-manager-redis-yet": "^4.1.2"
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/cli",
|
||||
"version": "1.7.0-alpha.4",
|
||||
"version": "1.7.0-beta.9",
|
||||
"description": "",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "./src/index.js",
|
||||
@ -8,7 +8,7 @@
|
||||
"nocobase": "./bin/index.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nocobase/app": "1.7.0-alpha.4",
|
||||
"@nocobase/app": "1.7.0-beta.9",
|
||||
"@types/fs-extra": "^11.0.1",
|
||||
"@umijs/utils": "3.5.20",
|
||||
"chalk": "^4.1.1",
|
||||
@ -25,7 +25,7 @@
|
||||
"tsx": "^4.19.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nocobase/devtools": "1.7.0-alpha.4"
|
||||
"@nocobase/devtools": "1.7.0-beta.9"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/client",
|
||||
"version": "1.7.0-alpha.4",
|
||||
"version": "1.7.0-beta.9",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.mjs",
|
||||
@ -27,9 +27,9 @@
|
||||
"@formily/reactive-react": "^2.2.27",
|
||||
"@formily/shared": "^2.2.27",
|
||||
"@formily/validator": "^2.2.27",
|
||||
"@nocobase/evaluators": "1.7.0-alpha.4",
|
||||
"@nocobase/sdk": "1.7.0-alpha.4",
|
||||
"@nocobase/utils": "1.7.0-alpha.4",
|
||||
"@nocobase/evaluators": "1.7.0-beta.9",
|
||||
"@nocobase/sdk": "1.7.0-beta.9",
|
||||
"@nocobase/utils": "1.7.0-beta.9",
|
||||
"ahooks": "^3.7.2",
|
||||
"antd": "5.24.2",
|
||||
"antd-style": "3.7.1",
|
||||
|
@ -102,7 +102,8 @@ export const SettingsCenterConfigure = () => {
|
||||
expandable={{
|
||||
defaultExpandAllRows: true,
|
||||
}}
|
||||
columns={[
|
||||
columns={
|
||||
[
|
||||
{
|
||||
dataIndex: 'title',
|
||||
title: t('Plugin name'),
|
||||
@ -139,7 +140,8 @@ export const SettingsCenterConfigure = () => {
|
||||
return <Checkbox checked={checked} onChange={() => handleChange(checked, record)} />;
|
||||
},
|
||||
},
|
||||
] as TableProps['columns']}
|
||||
] as TableProps['columns']
|
||||
}
|
||||
dataSource={settings
|
||||
.filter((v) => {
|
||||
return v.isTopLevel !== false;
|
||||
|
@ -121,7 +121,8 @@ export const MenuConfigure = () => {
|
||||
expandable={{
|
||||
defaultExpandAllRows: true,
|
||||
}}
|
||||
columns={[
|
||||
columns={
|
||||
[
|
||||
{
|
||||
dataIndex: 'title',
|
||||
title: t('Menu item title'),
|
||||
@ -154,7 +155,8 @@ export const MenuConfigure = () => {
|
||||
return <Checkbox checked={checked} onChange={() => handleChange(checked, schema)} />;
|
||||
},
|
||||
},
|
||||
] as TableProps['columns']}
|
||||
] as TableProps['columns']
|
||||
}
|
||||
dataSource={translateTitle(items)}
|
||||
/>
|
||||
);
|
||||
|
@ -105,7 +105,8 @@ export const RolesResourcesActions = connect((props) => {
|
||||
className={antTableCell}
|
||||
size={'small'}
|
||||
pagination={false}
|
||||
columns={[
|
||||
columns={
|
||||
[
|
||||
{
|
||||
dataIndex: 'displayName',
|
||||
title: t('Action display name'),
|
||||
@ -146,7 +147,8 @@ export const RolesResourcesActions = connect((props) => {
|
||||
/>
|
||||
),
|
||||
},
|
||||
] as TableProps['columns']}
|
||||
] as TableProps['columns']
|
||||
}
|
||||
dataSource={availableActions?.map((item) => {
|
||||
let enabled = false;
|
||||
let scope = null;
|
||||
@ -169,7 +171,8 @@ export const RolesResourcesActions = connect((props) => {
|
||||
className={antTableCell}
|
||||
pagination={false}
|
||||
dataSource={fieldPermissions}
|
||||
columns={[
|
||||
columns={
|
||||
[
|
||||
{
|
||||
dataIndex: ['uiSchema', 'title'],
|
||||
title: t('Field display name'),
|
||||
@ -222,7 +225,8 @@ export const RolesResourcesActions = connect((props) => {
|
||||
),
|
||||
};
|
||||
}),
|
||||
] as TableProps['columns']}
|
||||
] as TableProps['columns']
|
||||
}
|
||||
/>
|
||||
</FormItem>
|
||||
</FormLayout>
|
||||
|
@ -55,7 +55,8 @@ export const StrategyActions = connect((props) => {
|
||||
size={'small'}
|
||||
pagination={false}
|
||||
rowKey={'name'}
|
||||
columns={[
|
||||
columns={
|
||||
[
|
||||
{
|
||||
dataIndex: 'displayName',
|
||||
title: t('Action display name'),
|
||||
@ -110,7 +111,8 @@ export const StrategyActions = connect((props) => {
|
||||
/>
|
||||
),
|
||||
},
|
||||
] as TableProps['columns']}
|
||||
] as TableProps['columns']
|
||||
}
|
||||
dataSource={availableActions?.map((item) => {
|
||||
let scope = 'all';
|
||||
let enabled = false;
|
||||
|
@ -167,7 +167,7 @@ export function useCollectValuesToSubmit() {
|
||||
if (parsedValue !== null && parsedValue !== undefined) {
|
||||
assignedValues[key] = transformVariableValue(parsedValue, { targetCollectionField: collectionField });
|
||||
}
|
||||
} else if (value != null && value !== '') {
|
||||
} else if (value !== '') {
|
||||
assignedValues[key] = value;
|
||||
}
|
||||
});
|
||||
@ -203,6 +203,12 @@ export function useCollectValuesToSubmit() {
|
||||
]);
|
||||
}
|
||||
|
||||
function interpolateVariables(str: string, scope: Record<string, any>): string {
|
||||
return str.replace(/\{\{\s*([a-zA-Z0-9_$-.]+?)\s*\}\}/g, (_, key) => {
|
||||
return scope[key] !== undefined ? String(scope[key]) : '';
|
||||
});
|
||||
}
|
||||
|
||||
export const useCreateActionProps = () => {
|
||||
const filterByTk = useFilterByTk();
|
||||
const record = useCollectionRecord();
|
||||
@ -219,11 +225,20 @@ export const useCreateActionProps = () => {
|
||||
const collectValues = useCollectValuesToSubmit();
|
||||
const action = record.isNew ? actionField.componentProps.saveMode || 'create' : 'update';
|
||||
const filterKeys = actionField.componentProps.filterKeys?.checked || [];
|
||||
const localVariables = useLocalVariables();
|
||||
const variables = useVariables();
|
||||
|
||||
return {
|
||||
async onClick() {
|
||||
const { onSuccess, skipValidator, triggerWorkflows } = actionSchema?.['x-action-settings'] ?? {};
|
||||
const { manualClose, redirecting, redirectTo, successMessage, actionAfterSuccess } = onSuccess || {};
|
||||
const {
|
||||
manualClose,
|
||||
redirecting,
|
||||
redirectTo: rawRedirectTo,
|
||||
successMessage,
|
||||
actionAfterSuccess,
|
||||
} = onSuccess || {};
|
||||
|
||||
if (!skipValidator) {
|
||||
await form.submit();
|
||||
}
|
||||
@ -241,6 +256,15 @@ export const useCreateActionProps = () => {
|
||||
: undefined,
|
||||
updateAssociationValues,
|
||||
});
|
||||
let redirectTo = rawRedirectTo;
|
||||
if (rawRedirectTo) {
|
||||
const { exp, scope: expScope } = await replaceVariables(rawRedirectTo, {
|
||||
variables,
|
||||
localVariables: [...localVariables, { name: '$record', ctx: new Proxy(data?.data?.data, {}) }],
|
||||
});
|
||||
redirectTo = interpolateVariables(exp, expScope);
|
||||
}
|
||||
|
||||
if (actionAfterSuccess === 'previous' || (!actionAfterSuccess && redirecting !== true)) {
|
||||
setVisible?.(false);
|
||||
}
|
||||
@ -338,7 +362,7 @@ export const useAssociationCreateActionProps = () => {
|
||||
if (parsedValue) {
|
||||
assignedValues[key] = transformVariableValue(parsedValue, { targetCollectionField: collectionField });
|
||||
}
|
||||
} else if (value != null && value !== '') {
|
||||
} else if (value !== '') {
|
||||
assignedValues[key] = value;
|
||||
}
|
||||
});
|
||||
@ -588,7 +612,13 @@ export const useCustomizeUpdateActionProps = () => {
|
||||
skipValidator,
|
||||
triggerWorkflows,
|
||||
} = actionSchema?.['x-action-settings'] ?? {};
|
||||
const { manualClose, redirecting, redirectTo, successMessage, actionAfterSuccess } = onSuccess || {};
|
||||
const {
|
||||
manualClose,
|
||||
redirecting,
|
||||
redirectTo: rawRedirectTo,
|
||||
successMessage,
|
||||
actionAfterSuccess,
|
||||
} = onSuccess || {};
|
||||
const assignedValues = {};
|
||||
const waitList = Object.keys(originalAssignedValues).map(async (key) => {
|
||||
const value = originalAssignedValues[key];
|
||||
@ -605,7 +635,7 @@ export const useCustomizeUpdateActionProps = () => {
|
||||
if (parsedValue) {
|
||||
assignedValues[key] = transformVariableValue(parsedValue, { targetCollectionField: collectionField });
|
||||
}
|
||||
} else if (value != null && value !== '') {
|
||||
} else if (value !== '') {
|
||||
assignedValues[key] = value;
|
||||
}
|
||||
});
|
||||
@ -614,7 +644,7 @@ export const useCustomizeUpdateActionProps = () => {
|
||||
if (skipValidator === false) {
|
||||
await form.submit();
|
||||
}
|
||||
await resource.update({
|
||||
const result = await resource.update({
|
||||
filterByTk,
|
||||
values: { ...assignedValues },
|
||||
// TODO(refactor): should change to inject by plugin
|
||||
@ -622,6 +652,16 @@ export const useCustomizeUpdateActionProps = () => {
|
||||
? triggerWorkflows.map((row) => [row.workflowKey, row.context].filter(Boolean).join('!')).join(',')
|
||||
: undefined,
|
||||
});
|
||||
|
||||
let redirectTo = rawRedirectTo;
|
||||
if (rawRedirectTo) {
|
||||
const { exp, scope: expScope } = await replaceVariables(rawRedirectTo, {
|
||||
variables,
|
||||
localVariables: [...localVariables, { name: '$record', ctx: new Proxy(result?.data?.data?.[0], {}) }],
|
||||
});
|
||||
redirectTo = interpolateVariables(exp, expScope);
|
||||
}
|
||||
|
||||
if (actionAfterSuccess === 'previous' || (!actionAfterSuccess && redirecting !== true)) {
|
||||
setVisible?.(false);
|
||||
}
|
||||
@ -708,7 +748,7 @@ export const useCustomizeBulkUpdateActionProps = () => {
|
||||
if (parsedValue) {
|
||||
assignedValues[key] = transformVariableValue(parsedValue, { targetCollectionField: collectionField });
|
||||
}
|
||||
} else if (value != null && value !== '') {
|
||||
} else if (value !== '') {
|
||||
assignedValues[key] = value;
|
||||
}
|
||||
});
|
||||
@ -913,7 +953,13 @@ export const useUpdateActionProps = () => {
|
||||
skipValidator,
|
||||
triggerWorkflows,
|
||||
} = actionSchema?.['x-action-settings'] ?? {};
|
||||
const { manualClose, redirecting, redirectTo, successMessage, actionAfterSuccess } = onSuccess || {};
|
||||
const {
|
||||
manualClose,
|
||||
redirecting,
|
||||
redirectTo: rawRedirectTo,
|
||||
successMessage,
|
||||
actionAfterSuccess,
|
||||
} = onSuccess || {};
|
||||
const assignedValues = {};
|
||||
const waitList = Object.keys(originalAssignedValues).map(async (key) => {
|
||||
const value = originalAssignedValues[key];
|
||||
@ -930,7 +976,7 @@ export const useUpdateActionProps = () => {
|
||||
if (parsedValue) {
|
||||
assignedValues[key] = transformVariableValue(parsedValue, { targetCollectionField: collectionField });
|
||||
}
|
||||
} else if (value != null && value !== '') {
|
||||
} else if (value !== '') {
|
||||
assignedValues[key] = value;
|
||||
}
|
||||
});
|
||||
@ -952,7 +998,7 @@ export const useUpdateActionProps = () => {
|
||||
actionField.data = field.data || {};
|
||||
actionField.data.loading = true;
|
||||
try {
|
||||
await resource.update({
|
||||
const result = await resource.update({
|
||||
filterByTk,
|
||||
values: {
|
||||
...values,
|
||||
@ -971,6 +1017,15 @@ export const useUpdateActionProps = () => {
|
||||
if (callBack) {
|
||||
callBack?.();
|
||||
}
|
||||
let redirectTo = rawRedirectTo;
|
||||
if (rawRedirectTo) {
|
||||
const { exp, scope: expScope } = await replaceVariables(rawRedirectTo, {
|
||||
variables,
|
||||
localVariables: [...localVariables, { name: '$record', ctx: new Proxy(result?.data?.data?.[0], {}) }],
|
||||
});
|
||||
redirectTo = interpolateVariables(exp, expScope);
|
||||
}
|
||||
|
||||
if (actionAfterSuccess === 'previous' || (!actionAfterSuccess && redirecting !== true)) {
|
||||
setVisible?.(false);
|
||||
}
|
||||
|
@ -157,6 +157,8 @@ export const useCollectionFilterOptions = (collection: any, dataSource?: string)
|
||||
const option = {
|
||||
name: field.name,
|
||||
title: field?.uiSchema?.title || field.name,
|
||||
label: field?.uiSchema?.title || field.name,
|
||||
value: field.name,
|
||||
schema: field?.uiSchema,
|
||||
operators:
|
||||
operators?.filter?.((operator) => {
|
||||
|
@ -843,5 +843,242 @@
|
||||
"Ellipsis overflow content": "Contenuto Ellipsis overflow",
|
||||
"Hide column": "Nascondi colonna",
|
||||
"In configuration mode, the entire column becomes transparent. In non-configuration mode, the entire column will be hidden. Even if the entire column is hidden, its configured default values and other settings will still take effect.": "In modalità di configurazione, l'intera colonna diventa trasparente. In modalità non di configurazione, l'intera colonna verrà nascosta. Anche se l'intera colonna è nascosta, i suoi valori predefiniti configurati e le altre impostazioni avranno comunque effetto.",
|
||||
"The following old template features have been deprecated and will be removed in next version.": "Le seguenti funzionalità dei modelli vecchi sono state deprecate e saranno rimosse nella prossima versione."
|
||||
"Page number": "Numero di pagina",
|
||||
"Page size": "Numero di voci per pagina",
|
||||
"Enable": "Abilita",
|
||||
"Disable": "Disabilita",
|
||||
"Tab": "Scheda",
|
||||
"Calculation engine": "Motore di calcolo",
|
||||
"Expression collection": "Raccolta espressioni",
|
||||
"Tree collection": "Raccolta struttura ad albero",
|
||||
"Parent ID": "ID record padre",
|
||||
"Parent": "Record padre",
|
||||
"Children": "Record figlio",
|
||||
"Confirm": "Conferma",
|
||||
"Block": "Blocco",
|
||||
"Unnamed": "Senza nome",
|
||||
"SQL collection": "Raccolta dati SQL",
|
||||
"Configure field": "Configura campo",
|
||||
"Username": "Nome utente",
|
||||
"Null": "Null",
|
||||
"Boolean": "Booleano",
|
||||
"String": "Stringa",
|
||||
"Syntax references": "Riferimenti sintassi",
|
||||
"Math.js comes with a large set of built-in functions and constants, and offers an integrated solution to work with different data types.": "Math.js include un ampio set di funzioni e costanti integrate e offre una soluzione integrata per lavorare con diversi tipi di dati.",
|
||||
"Formula.js supports most Microsoft Excel formula functions.": "Formula.js supporta la maggior parte delle funzioni delle formule di Microsoft Excel.",
|
||||
"String template": "Modello stringa",
|
||||
"Simple string replacement, can be used to interpolate variables in a string.": "Sostituzione semplice di stringhe, può essere utilizzata per interpolare variabili in una stringa.",
|
||||
"https://docs.nocobase.com/handbook/calculation-engines/formula": "https://docs-cn.nocobase.com/handbook/calculation-engines/formula",
|
||||
"https://docs.nocobase.com/handbook/calculation-engines/mathjs": "https://docs-cn.nocobase.com/handbook/calculation-engines/mathjs",
|
||||
"Display <icon></icon> when unchecked": "Visualizza <icon></icon> quando deselezionato",
|
||||
"Allow dissociate": "Consenti dissociazione",
|
||||
"Edit block title & description": "Modifica titolo e descrizione blocco",
|
||||
"Add Markdown": "Aggiungi Markdown",
|
||||
"Must be 1-50 characters in length (excluding @.<>\"'/)": "Deve essere lungo 1-50 caratteri (esclusi @.<>\"'/)",
|
||||
"Data source permissions": "Permessi origine dati",
|
||||
"Now": "Adesso",
|
||||
"Access control": "Controllo accessi",
|
||||
"Remove": "Rimuovi",
|
||||
"Docs": "Documenti",
|
||||
"Enable page header": "Abilita intestazione pagina",
|
||||
"Display page title": "Visualizza titolo pagina",
|
||||
"Edit page title": "Modifica titolo pagina",
|
||||
"Enable page tabs": "Abilita schede pagina",
|
||||
"Constant": "Costante",
|
||||
"Select a variable": "Seleziona una variabile",
|
||||
"Double click to choose entire object": "Doppio clic per scegliere l'intero oggetto",
|
||||
"True": "Vero",
|
||||
"False": "Falso",
|
||||
"Prettify": "Formatta",
|
||||
"Theme": "Tema",
|
||||
"Default theme": "Tema predefinito",
|
||||
"Compact theme": "Tema compatto",
|
||||
"Download": "Scarica",
|
||||
"File type is not supported for previewing, please download it to preview.": "Il tipo di file non è supportato per l'anteprima, scaricalo per visualizzarlo.",
|
||||
"Click or drag file to this area to upload": "Clicca o trascina il file in quest'area per caricarlo",
|
||||
"Support for a single or bulk upload.": "Supporta il caricamento singolo o in blocco.",
|
||||
"File size should not exceed {{size}}.": "La dimensione del file non deve superare {{size}}.",
|
||||
"File size exceeds the limit": "La dimensione del file supera il limite",
|
||||
"File type is not allowed": "Il tipo di file non è consentito",
|
||||
"Incomplete uploading files need to be resolved": "I caricamenti incompleti dei file devono essere completati",
|
||||
"Default title for each record": "Titolo predefinito per ogni record",
|
||||
"If collection inherits, choose inherited collections as templates": "Se la raccolta eredita, scegli le raccolte ereditate come modelli",
|
||||
"Select an existing piece of data as the initialization data for the form": "Seleziona un dato esistente come dati di inizializzazione per il modulo",
|
||||
"Only the selected fields will be used as the initialization data for the form": "Solo i campi selezionati verranno utilizzati come dati di inizializzazione per il modulo",
|
||||
"Template Data": "Dati modello",
|
||||
"Data fields": "Campi dati",
|
||||
"Add template": "Aggiungi modello",
|
||||
"Enable form data template": "Abilita modello dati modulo",
|
||||
"Form data templates": "Modelli dati modulo",
|
||||
"No configuration available.": "Nessuna configurazione disponibile.",
|
||||
"Reload application": "Ricarica applicazione",
|
||||
"The application is reloading, please do not close the page.": "L'applicazione si sta ricaricando, non chiudere la pagina.",
|
||||
"Application reloading": "Ricaricamento applicazione",
|
||||
"Allows to clear cache, reboot application": "Consente di cancellare la cache, riavviare l'applicazione",
|
||||
"The will interrupt service, it may take a few seconds to restart. Are you sure to continue?": "Il riavvio interromperà il servizio, potrebbero essere necessari alcuni secondi. Sei sicuro di continuare?",
|
||||
"Clear cache": "Cancella cache",
|
||||
"Quick create": "Creazione rapida",
|
||||
"Dropdown": "Menu a discesa",
|
||||
"Pop-up": "Popup",
|
||||
"Direct duplicate": "Duplicazione diretta",
|
||||
"Copy into the form and continue to fill in": "Copia nel modulo e continua a compilare",
|
||||
"Failed to load plugin": "Caricamento plugin fallito",
|
||||
"Date range limit": "Limite intervallo date",
|
||||
"MinDate": "Data minima",
|
||||
"MaxDate": "Data massima",
|
||||
"Please select time or variable": "Seleziona ora o variabile",
|
||||
"Filter out a single piece or a group of records as a template": "Filtra un singolo dato o un gruppo di record come modello",
|
||||
"The title field is used to identify the template record": "Il campo titolo è utilizzato per identificare il record modello",
|
||||
"Template fields": "Campi modello",
|
||||
"The selected fields will automatically populate the form": "I campi selezionati popoleranno automaticamente il modulo",
|
||||
"UnSelect all": "Deseleziona tutto",
|
||||
"Secondary confirmation": "Conferma secondaria",
|
||||
"Perform the {{title}}": "Esegui {{title}}",
|
||||
"Are you sure you want to perform the {{title}} action?": "Sei sicuro di voler eseguire l'azione {{title}}?",
|
||||
"Permission denied": "Permesso negato",
|
||||
"Allow add new": "Consenti aggiunta",
|
||||
"Data model": "Modello dati",
|
||||
"Security": "Sicurezza",
|
||||
"Action": "Azione",
|
||||
"System": "Sistema",
|
||||
"Other": "Altro",
|
||||
"Allow selection of existing records": "Consenti selezione di record esistenti",
|
||||
"Data Model": "Modello dati",
|
||||
"Blocks": "Blocchi",
|
||||
"Users & permissions": "Utenti e permessi",
|
||||
"System management": "Gestione sistema",
|
||||
"System & security": "Sistema e sicurezza",
|
||||
"Workflow": "Workflow",
|
||||
"Third party services": "Servizi di terze parti",
|
||||
"Data model tools": "Strumenti modello dati",
|
||||
"Data sources": "Origini dati",
|
||||
"Collections": "Raccolte",
|
||||
"Collection fields": "Campi raccolta",
|
||||
"Authentication": "Autenticazione",
|
||||
"Logging and monitoring": "Registrazione e monitoraggio",
|
||||
"Main": "Principale",
|
||||
"Index": "Indice",
|
||||
"Field values must be unique.": "I valori dei campi devono essere univoci.",
|
||||
"Alphabet": "Alfabeto",
|
||||
"Accuracy": "Precisione",
|
||||
"Millisecond": "Millisecondo",
|
||||
"Second": "Secondo",
|
||||
"Unix Timestamp": "Timestamp Unix",
|
||||
"Field value do not meet the requirements": "Il valore del campo non soddisfa i requisiti",
|
||||
"Field value size is": "La dimensione del valore del campo è",
|
||||
"Unit conversion": "Conversione unità",
|
||||
"Separator": "Separatore",
|
||||
"Prefix": "Prefisso",
|
||||
"Suffix": "Suffisso",
|
||||
"Record unique key": "Chiave univoca record",
|
||||
"Filter target key": "Chiave target filtro",
|
||||
"If a collection lacks a primary key, you must configure a unique record key to locate row records within a block, failure to configure this will prevent the creation of data blocks for the collection.": "Se una raccolta non ha una chiave primaria, devi configurare un record come chiave univoca per individuare i record di ogni riga all'interno di un blocco, la mancata configurazione impedirà la creazione di blocchi di dati per la raccolta.",
|
||||
"Filter data based on the specific field, with the requirement that the field value must be unique.": "Filtra i dati in base a un campo specifico, con il requisito che il valore del campo deve essere univoco.",
|
||||
"Multiply by": "Moltiplica per",
|
||||
"Divide by": "Dividi per",
|
||||
"Scientifix notation": "Notazione scientifica",
|
||||
"Normal": "Normale",
|
||||
"Automatically generate default values": "Genera automaticamente valori predefiniti",
|
||||
"Refresh data on close": "Refresh dei dati alla chiusura",
|
||||
"Refresh data on action": "Refresh dei dati su azione",
|
||||
"Unknown field type": "Tipo di campo sconosciuto",
|
||||
"The following field types are not compatible and do not support output and display": "I seguenti tipi di campo non sono compatibili e non supportano l'output e la visualizzazione",
|
||||
"Not fixed": "Non fissato",
|
||||
"Left fixed": "Fissato a sinistra",
|
||||
"Right fixed": "Fissato a destra",
|
||||
"Fixed": "Colonna fissa",
|
||||
"Set block height": "Imposta altezza del blocco",
|
||||
"Specify height": "Specifica altezza",
|
||||
"Full height": "Altezza completa",
|
||||
"Please configure the URL": "Configura l'URL",
|
||||
"URL": "URL",
|
||||
"Search parameters": "Parametri di ricerca URL",
|
||||
"Do not concatenate search params in the URL": "Non concatenare i parametri di ricerca nell'URL",
|
||||
"Edit link": "Modifica link",
|
||||
"Add parameter": "Aggiungi parametro",
|
||||
"Use simple pagination mode": "Usa modalità di paginazione semplice",
|
||||
"Set Template Engine": "Imposta motore template",
|
||||
"Template engine": "Motore template",
|
||||
"The current user only has the UI configuration permission, but don't have view permission for collection \"{{name}}\"": "L'utente corrente ha solo il permesso di configurazione dell'interfaccia utente, ma non ha il permesso di visualizzazione per la raccolta \"{{name}}\"",
|
||||
"Default value to current time": "Imposta il valore predefinito del campo all'ora corrente",
|
||||
"Automatically update timestamp on update": "Aggiorna automaticamente il timestamp all'aggiornamento",
|
||||
"Default value to current server time": "Imposta il valore predefinito del campo all'ora corrente del server",
|
||||
"Automatically update timestamp to the current server time on update": "Aggiorna automaticamente il timestamp all'ora corrente del server all'aggiornamento",
|
||||
"Datetime (with time zone)": "Data e ora (con fuso orario)",
|
||||
"Datetime (without time zone)": "Data e ora (senza fuso orario)",
|
||||
"DateOnly": "Solo data",
|
||||
"Content": "Contenuto",
|
||||
"Perform the Update record": "Esegui aggiornamento record",
|
||||
"Are you sure you want to perform the Update record action?": "Sei sicuro di voler eseguire l'azione di aggiornamento record?",
|
||||
"Perform the Custom request": "Esegui richiesta personalizzata",
|
||||
"Are you sure you want to perform the Custom request action": "Sei sicuro di voler eseguire l'azione di richiesta personalizzata?",
|
||||
"Perform the Refresh": "Esegui refresh",
|
||||
"Are you sure you want to perform the Refresh action?": "Sei sicuro di voler eseguire l'azione di refresh?",
|
||||
"Perform the Submit": "Esegui l'invio",
|
||||
"Are you sure you want to perform the Submit action?": "Sei sicuro di voler eseguire l'azione di invio?",
|
||||
"Perform the Trigger workflow": "Esegui il trigger del workflow",
|
||||
"Are you sure you want to perform the Trigger workflow action?": "Sei sicuro di voler eseguire l'azione di trigger del workflow?",
|
||||
"Picker": "Selettore",
|
||||
"Quarter": "Trimestre",
|
||||
"Switching the picker, the value and default value will be cleared": "Cambiando il selettore, il valore e il valore predefinito verranno cancellati",
|
||||
"Stay on the current popup or page": "Rimani nel popup o nella pagina corrente",
|
||||
"Return to the previous popup or page": "Torna al popup o alla pagina precedente",
|
||||
"Action after successful submission": "Azione dopo l'invio riuscito",
|
||||
"Allow disassociation": "Consenti la dissociazione",
|
||||
"Layout": "Layout",
|
||||
"Vertical": "Verticale",
|
||||
"Horizontal": "Orizzontale",
|
||||
"Edit group title": "Modifica titolo del gruppo",
|
||||
"Title position": "Posizione titolo",
|
||||
"Dashed": "Tratteggiato",
|
||||
"Left": "Sinistra",
|
||||
"Center": "Centro",
|
||||
"Right": "Destra",
|
||||
"Divider line color": "Colore linea di divisione",
|
||||
"Label align": "Allineamento etichetta",
|
||||
"Label width": "Larghezza etichetta",
|
||||
"When the Label exceeds the width": "Quando l'etichetta supera la larghezza",
|
||||
"Line break": "A capo",
|
||||
"Ellipsis": "Ellipsis",
|
||||
"Set block layout": "Imposta layout del blocco",
|
||||
"Add & Update": "Aggiungi e aggiorna",
|
||||
"Table size": "Dimensione della tabella",
|
||||
"Plugin": "Plugin",
|
||||
"Bulk enable": "Abilitazione in blocco",
|
||||
"Search plugin...": "Cerca plugin...",
|
||||
"Package name": "Nome pacchetto",
|
||||
"Associate": "Associa",
|
||||
"Please add or select record": "Aggiungi o seleziona record",
|
||||
"No data": "Nessun dato",
|
||||
"Fields can only be used correctly if they are defined with an interface.": "I campi possono essere utilizzati correttamente solo se sono definiti con un'interfaccia.",
|
||||
"Unauthenticated. Please sign in to continue.": "Non autenticato. Accedi per continuare.",
|
||||
"User not found. Please sign in again to continue.": "Impossibile trovare l'utente. Accedi nuovamente per continuare.",
|
||||
"Your session has expired. Please sign in again.": "La tua sessione è scaduta. Accedi nuovamente.",
|
||||
"User password changed, please signin again.": "La password dell'utente è stata modificata, accedi di nuovo.",
|
||||
"Show file name": "Mostra nome del file",
|
||||
"Outlined": "Contornato",
|
||||
"Filled": "Riempito",
|
||||
"Two tone": "Due toni",
|
||||
"Desktop routes": "Percorsi desktop",
|
||||
"Route permissions": "Permessi percorso",
|
||||
"New routes are allowed to be accessed by default": "I nuovi percorsi sono accessibili per impostazione predefinita",
|
||||
"Route name": "Nome percorso",
|
||||
"Mobile routes": "Percorsi mobile",
|
||||
"Show in menu": "Mostra nel menu",
|
||||
"Hide in menu": "Nascondi nel menu",
|
||||
"Path": "Percorso",
|
||||
"Type": "Tipo",
|
||||
"Access": "Accesso",
|
||||
"Routes": "Percorsi",
|
||||
"Add child route": "Aggiungi percorso figlio",
|
||||
"Delete routes": "Elimina percorsi",
|
||||
"Delete route": "Elimina percorso",
|
||||
"Are you sure you want to hide these routes in menu?": "Sei sicuro di voler nascondere questi percorsi nel menu?",
|
||||
"Are you sure you want to show these routes in menu?": "Sei sicuro di voler mostrare questi percorsi nel menu?",
|
||||
"Are you sure you want to hide this menu?": "Sei sicuro di voler nascondere questo menu?",
|
||||
"After hiding, this menu will no longer appear in the menu bar. To show it again, you need to go to the route management page to configure it.": "Dopo averlo nascosto, questo menu non apparirà più nella barra dei menu. Per mostrarlo di nuovo, devi andare alla pagina di gestione dei percorsi per configurarlo.",
|
||||
"If selected, the page will display Tab pages.": "Se selezionato, la pagina visualizzerà le pagine schede.",
|
||||
"If selected, the route will be displayed in the menu.": "Se selezionato, il percorso verrà visualizzato nel menu.",
|
||||
"Are you sure you want to hide this tab?": "Sei sicuro di voler nascondere questa scheda?",
|
||||
"After hiding, this tab will no longer appear in the tab bar. To show it again, you need to go to the route management page to set it.": "Dopo averla nascosta, questa scheda non apparirà più nella barra delle schede. Per mostrarla di nuovo, devi andare alla pagina di gestione dei percorsi per configurarlo."
|
||||
}
|
||||
|
@ -1094,5 +1094,6 @@
|
||||
"Font Size(px)": "字体大小(像素)",
|
||||
"Font Weight": "字体粗细",
|
||||
"Font Style": "字体样式",
|
||||
"Italic": "斜体"
|
||||
"Italic": "斜体",
|
||||
"Response record":"响应结果记录"
|
||||
}
|
||||
|
@ -126,6 +126,10 @@ export const getAllowMultiple = (params?: { title: string }) => {
|
||||
return {
|
||||
name: 'allowMultiple',
|
||||
type: 'switch',
|
||||
useVisible() {
|
||||
const isAssociationField = useIsAssociationField();
|
||||
return isAssociationField;
|
||||
},
|
||||
useComponentProps() {
|
||||
const { t } = useTranslation();
|
||||
const field = useField<Field>();
|
||||
|
@ -14,6 +14,14 @@ import React, { useCallback, useContext } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Router } from 'react-router-dom';
|
||||
import { SchemaInitializerItem } from '../../application';
|
||||
import {
|
||||
CollectionManagerProvider,
|
||||
useCollectionManager,
|
||||
} from '../../data-source/collection/CollectionManagerProvider';
|
||||
import {
|
||||
DataSourceManagerProvider,
|
||||
useDataSourceManager,
|
||||
} from '../../data-source/data-source/DataSourceManagerProvider';
|
||||
import { useGlobalTheme } from '../../global-theme';
|
||||
import { NocoBaseDesktopRouteType } from '../../route-switch/antd/admin-layout/convertRoutesToSchema';
|
||||
import {
|
||||
@ -34,6 +42,8 @@ export const LinkMenuItem = () => {
|
||||
const { urlSchema, paramsSchema } = useURLAndHTMLSchema();
|
||||
const parentRoute = useParentRoute();
|
||||
const { createRoute } = useNocoBaseRoutes();
|
||||
const dm = useDataSourceManager();
|
||||
const cm = useCollectionManager();
|
||||
|
||||
const handleClick = useCallback(async () => {
|
||||
const values = await FormDialog(
|
||||
@ -41,6 +51,8 @@ export const LinkMenuItem = () => {
|
||||
() => {
|
||||
const history = createMemoryHistory();
|
||||
return (
|
||||
<DataSourceManagerProvider dataSourceManager={dm}>
|
||||
<CollectionManagerProvider instance={cm} dataSource={cm?.dataSource?.key}>
|
||||
<Router location={history.location} navigator={history}>
|
||||
<SchemaComponentOptions scope={options.scope} components={{ ...options.components }}>
|
||||
<FormLayout layout={'vertical'}>
|
||||
@ -66,6 +78,8 @@ export const LinkMenuItem = () => {
|
||||
</FormLayout>
|
||||
</SchemaComponentOptions>
|
||||
</Router>
|
||||
</CollectionManagerProvider>
|
||||
</DataSourceManagerProvider>
|
||||
);
|
||||
},
|
||||
theme,
|
||||
|
@ -127,7 +127,8 @@ function BulkEnableButton({ plugins = [] }) {
|
||||
}}
|
||||
size={'small'}
|
||||
pagination={false}
|
||||
columns={[
|
||||
columns={
|
||||
[
|
||||
{
|
||||
title: t('Plugin'),
|
||||
dataIndex: 'displayName',
|
||||
@ -145,7 +146,8 @@ function BulkEnableButton({ plugins = [] }) {
|
||||
width: 300,
|
||||
ellipsis: true,
|
||||
},
|
||||
] as TableProps['columns']}
|
||||
] as TableProps['columns']
|
||||
}
|
||||
dataSource={items}
|
||||
/>
|
||||
</Modal>
|
||||
|
@ -52,6 +52,7 @@ import { KeepAlive } from './KeepAlive';
|
||||
import { NocoBaseDesktopRoute, NocoBaseDesktopRouteType } from './convertRoutesToSchema';
|
||||
import { MenuSchemaToolbar, ResetThemeTokenAndKeepAlgorithm } from './menuItemSettings';
|
||||
import { userCenterSettings } from './userCenterSettings';
|
||||
import { createGlobalStyle, createStyles } from 'antd-style';
|
||||
|
||||
export { KeepAlive, NocoBaseDesktopRouteType };
|
||||
|
||||
@ -268,7 +269,7 @@ const GroupItem: FC<{ item: any }> = (props) => {
|
||||
};
|
||||
|
||||
const WithTooltip: FC<{ title: string; hidden: boolean }> = (props) => {
|
||||
const { inHeader } = useContext(headerContext);
|
||||
const { inHeader } = useContext(HeaderContext);
|
||||
|
||||
return (
|
||||
<RouteContext.Consumer>
|
||||
@ -406,7 +407,7 @@ const contentStyle = {
|
||||
paddingInline: 0,
|
||||
};
|
||||
|
||||
const headerContext = React.createContext<{ inHeader: boolean }>({ inHeader: false });
|
||||
const HeaderContext = React.createContext<{ inHeader: boolean }>({ inHeader: false });
|
||||
|
||||
const popoverStyle = css`
|
||||
.ant-popover-inner {
|
||||
@ -495,9 +496,38 @@ const collapsedButtonRender = (collapsed, dom) => {
|
||||
return <CollapsedButton collapsed={collapsed}>{dom}</CollapsedButton>;
|
||||
};
|
||||
|
||||
/**
|
||||
* 这个问题源自 antd 的一个 bug,等 antd 修复了这个问题后,可以删除这个样式。
|
||||
* - issue: https://github.com/ant-design/pro-components/issues/8593
|
||||
* - issue: https://github.com/ant-design/pro-components/issues/8522
|
||||
* - issue: https://github.com/ant-design/pro-components/issues/8432
|
||||
*/
|
||||
const useHeaderStyle = createStyles(({ token }: any) => {
|
||||
return {
|
||||
headerPopup: {
|
||||
'&.ant-menu-submenu-popup>.ant-menu': {
|
||||
backgroundColor: `${token.colorBgHeader}`,
|
||||
},
|
||||
},
|
||||
headerMenuActive: {
|
||||
'& .ant-menu-submenu-selected>.ant-menu-submenu-title': {
|
||||
color: token.colorTextHeaderMenuActive,
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
const headerContextValue = { inHeader: true };
|
||||
const HeaderWrapper: FC = (props) => {
|
||||
const { styles } = useHeaderStyle();
|
||||
|
||||
return (
|
||||
<span className={styles.headerMenuActive}>
|
||||
<HeaderContext.Provider value={headerContextValue}>{props.children}</HeaderContext.Provider>
|
||||
</span>
|
||||
);
|
||||
};
|
||||
const headerRender = (props: HeaderViewProps, defaultDom: React.ReactNode) => {
|
||||
return <headerContext.Provider value={headerContextValue}>{defaultDom}</headerContext.Provider>;
|
||||
return <HeaderWrapper>{defaultDom}</HeaderWrapper>;
|
||||
};
|
||||
|
||||
const IsMobileLayoutContext = React.createContext<{
|
||||
@ -531,6 +561,7 @@ export const InternalAdminLayout = () => {
|
||||
const doNotChangeCollapsedRef = useRef(false);
|
||||
const { t } = useMenuTranslation();
|
||||
const designable = isMobileLayout ? false : _designable;
|
||||
const { styles } = useHeaderStyle();
|
||||
|
||||
const route = useMemo(() => {
|
||||
return {
|
||||
@ -544,7 +575,7 @@ export const InternalAdminLayout = () => {
|
||||
colorBgHeader: token.colorBgHeader,
|
||||
colorTextMenu: token.colorTextHeaderMenu,
|
||||
colorTextMenuSelected: token.colorTextHeaderMenuActive,
|
||||
colorTextMenuActive: token.colorTextHeaderMenuActive,
|
||||
colorTextMenuActive: token.colorTextHeaderMenuHover,
|
||||
colorBgMenuItemHover: token.colorBgHeaderMenuHover,
|
||||
colorBgMenuItemSelected: token.colorBgHeaderMenuActive,
|
||||
heightLayoutHeader: 46,
|
||||
@ -591,6 +622,12 @@ export const InternalAdminLayout = () => {
|
||||
});
|
||||
}, []);
|
||||
|
||||
const menuProps = useMemo(() => {
|
||||
return {
|
||||
overflowedIndicatorPopupClassName: styles.headerPopup,
|
||||
};
|
||||
}, [styles.headerPopup]);
|
||||
|
||||
return (
|
||||
<DndContext onDragEnd={onDragEnd}>
|
||||
<ProLayout
|
||||
@ -612,6 +649,7 @@ export const InternalAdminLayout = () => {
|
||||
onCollapse={onCollapse}
|
||||
collapsed={collapsed}
|
||||
onPageChange={onPageChange}
|
||||
menuProps={menuProps}
|
||||
>
|
||||
<RouteContext.Consumer>
|
||||
{(value: RouteContextType) => {
|
||||
|
@ -34,6 +34,8 @@ import {
|
||||
import { DefaultValueProvider } from '../../../schema-settings/hooks/useIsAllowToSetDefaultValue';
|
||||
import { useLinkageAction } from './hooks';
|
||||
import { requestSettingsSchema } from './utils';
|
||||
import { useAfterSuccessOptions } from './hooks/useGetAfterSuccessVariablesOptions';
|
||||
import { useGlobalVariable } from '../../../application/hooks/useGlobalVariable';
|
||||
|
||||
const MenuGroup = (props) => {
|
||||
return props.children;
|
||||
@ -280,11 +282,24 @@ export function SkipValidation() {
|
||||
);
|
||||
}
|
||||
|
||||
const fieldNames = {
|
||||
value: 'value',
|
||||
label: 'label',
|
||||
};
|
||||
const useVariableProps = (environmentVariables) => {
|
||||
const scope = useAfterSuccessOptions();
|
||||
return {
|
||||
scope: [environmentVariables, ...scope].filter(Boolean),
|
||||
fieldNames,
|
||||
};
|
||||
};
|
||||
|
||||
export function AfterSuccess() {
|
||||
const { dn } = useDesignable();
|
||||
const { t } = useTranslation();
|
||||
const fieldSchema = useFieldSchema();
|
||||
const { onSuccess } = fieldSchema?.['x-action-settings'] || {};
|
||||
const environmentVariables = useGlobalVariable('$env');
|
||||
return (
|
||||
<SchemaSettingsModalItem
|
||||
title={t('After successful submission')}
|
||||
@ -363,8 +378,9 @@ export function AfterSuccess() {
|
||||
redirectTo: {
|
||||
title: t('Link'),
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
'x-component-props': {},
|
||||
'x-component': 'Variable.TextArea',
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
'x-use-component-props': () => useVariableProps(environmentVariables),
|
||||
},
|
||||
},
|
||||
} as ISchema
|
||||
|
@ -16,16 +16,19 @@ import Action from './Action';
|
||||
import { ComposedAction } from './types';
|
||||
import { Icon } from '../../../icon';
|
||||
|
||||
const WrapperComponent = ({ component: Component = 'a', icon, onlyIcon, children, ...restProps }: any) => {
|
||||
const WrapperComponent = React.forwardRef(
|
||||
({ component: Component = 'a', icon, onlyIcon, children, ...restProps }: any, ref) => {
|
||||
return (
|
||||
<Component {...restProps}>
|
||||
<Component ref={ref} {...restProps}>
|
||||
<Tooltip title={restProps.title}>
|
||||
<span style={{ marginRight: 3 }}>{icon && typeof icon === 'string' ? <Icon type={icon} /> : icon}</span>
|
||||
</Tooltip>
|
||||
{onlyIcon ? children[1] : children}
|
||||
</Component>
|
||||
);
|
||||
};
|
||||
},
|
||||
);
|
||||
WrapperComponent.displayName = 'WrapperComponentLink';
|
||||
|
||||
export const ActionLink: ComposedAction = withDynamicSchemaProps(
|
||||
observer((props: any) => {
|
||||
@ -34,6 +37,7 @@ export const ActionLink: ComposedAction = withDynamicSchemaProps(
|
||||
{...props}
|
||||
component={props.component || WrapperComponent}
|
||||
className={classnames('nb-action-link', props.className)}
|
||||
isLink
|
||||
/>
|
||||
);
|
||||
}),
|
||||
|
@ -247,7 +247,6 @@ const InternalAction: React.FC<InternalActionProps> = observer(function Com(prop
|
||||
const aclCtx = useACLActionParamsContext();
|
||||
const { run, element, disabled: disableAction } = useAction?.(actionCallback) || ({} as any);
|
||||
const disabled = form.disabled || field.disabled || field.data?.disabled || propsDisabled || disableAction;
|
||||
|
||||
const buttonStyle = useMemo(() => {
|
||||
return {
|
||||
...style,
|
||||
@ -538,6 +537,7 @@ const RenderButtonInner = observer(
|
||||
Designer: React.ElementType;
|
||||
designerProps: any;
|
||||
title: string;
|
||||
isLink?: boolean;
|
||||
}) => {
|
||||
const {
|
||||
designable,
|
||||
@ -558,6 +558,7 @@ const RenderButtonInner = observer(
|
||||
Designer,
|
||||
designerProps,
|
||||
title,
|
||||
isLink,
|
||||
...others
|
||||
} = props;
|
||||
const debouncedClick = useCallback(
|
||||
@ -583,7 +584,7 @@ const RenderButtonInner = observer(
|
||||
|
||||
const actionTitle = title || field?.title;
|
||||
const { opacity, ...restButtonStyle } = buttonStyle;
|
||||
|
||||
const linkStyle = isLink && opacity ? { opacity } : undefined;
|
||||
return (
|
||||
<SortableItem
|
||||
role="button"
|
||||
@ -592,9 +593,9 @@ const RenderButtonInner = observer(
|
||||
onMouseEnter={handleMouseEnter}
|
||||
// @ts-ignore
|
||||
loading={field?.data?.loading || loading}
|
||||
icon={typeof icon === 'string' ? <Icon style={{ opacity }} type={icon} /> : icon}
|
||||
icon={typeof icon === 'string' ? <Icon type={icon} style={linkStyle} /> : icon}
|
||||
disabled={disabled}
|
||||
style={restButtonStyle}
|
||||
style={isLink ? restButtonStyle : buttonStyle}
|
||||
onClick={process.env.__E2E__ ? handleButtonClick : debouncedClick} // E2E 中的点击操作都是很快的,如果加上 debounce 会导致 E2E 测试失败
|
||||
component={tarComponent || Button}
|
||||
className={classnames(componentCls, hashId, className, 'nb-action')}
|
||||
@ -602,7 +603,7 @@ const RenderButtonInner = observer(
|
||||
title={actionTitle}
|
||||
>
|
||||
{actionTitle && (
|
||||
<span className={icon ? 'nb-action-title' : null} style={{ opacity }}>
|
||||
<span className={icon ? 'nb-action-title' : null} style={linkStyle}>
|
||||
{actionTitle}
|
||||
</span>
|
||||
)}
|
||||
|
@ -0,0 +1,66 @@
|
||||
/**
|
||||
* This file is part of the NocoBase (R) project.
|
||||
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
||||
* Authors: NocoBase Team.
|
||||
*
|
||||
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
||||
* For more information, please refer to: https://www.nocobase.com/agreement.
|
||||
*/
|
||||
|
||||
import { useMemo } from 'react';
|
||||
import { useCollection_deprecated, useCollectionFilterOptions } from '../../../../collection-manager';
|
||||
import { useCollectionRecordData } from '../../../../data-source';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useCompile } from '../../../';
|
||||
import { useBlockContext } from '../../../../block-provider/BlockProvider';
|
||||
import { usePopupVariable } from '../../../../schema-settings/VariableInput/hooks';
|
||||
import { useCurrentRoleVariable } from '../../../../schema-settings/VariableInput/hooks';
|
||||
|
||||
export const useAfterSuccessOptions = () => {
|
||||
const collection = useCollection_deprecated();
|
||||
const { t } = useTranslation();
|
||||
const fieldsOptions = useCollectionFilterOptions(collection);
|
||||
const userFieldOptions = useCollectionFilterOptions('users', 'main');
|
||||
const compile = useCompile();
|
||||
const recordData = useCollectionRecordData();
|
||||
const { name: blockType } = useBlockContext() || {};
|
||||
const [fields, userFields] = useMemo(() => {
|
||||
return [compile(fieldsOptions), compile(userFieldOptions)];
|
||||
}, [fieldsOptions, userFieldOptions]);
|
||||
const { settings: popupRecordSettings, shouldDisplayPopupRecord } = usePopupVariable();
|
||||
const { currentRoleSettings } = useCurrentRoleVariable();
|
||||
const record = useCollectionRecordData();
|
||||
return useMemo(() => {
|
||||
return [
|
||||
(record || blockType === 'form') && {
|
||||
value: '$record',
|
||||
label: t('Response record', { ns: 'client' }),
|
||||
children: [...fields],
|
||||
},
|
||||
recordData && {
|
||||
value: 'currentRecord',
|
||||
label: t('Current record', { ns: 'client' }),
|
||||
children: [...fields],
|
||||
},
|
||||
shouldDisplayPopupRecord && {
|
||||
...popupRecordSettings,
|
||||
},
|
||||
{
|
||||
value: 'currentUser',
|
||||
label: t('Current user', { ns: 'client' }),
|
||||
children: userFields,
|
||||
},
|
||||
currentRoleSettings,
|
||||
{
|
||||
value: 'currentTime',
|
||||
label: t('Current time', { ns: 'client' }),
|
||||
children: null,
|
||||
},
|
||||
{
|
||||
value: '$nToken',
|
||||
label: 'API token',
|
||||
children: null,
|
||||
},
|
||||
].filter(Boolean);
|
||||
}, [recordData, t, fields, blockType, userFields]);
|
||||
};
|
@ -16,5 +16,6 @@ export * from './hooks/useGetAriaLabelOfAction';
|
||||
export * from './hooks/useGetAriaLabelOfDrawer';
|
||||
export * from './hooks/useGetAriaLabelOfModal';
|
||||
export * from './hooks/useGetAriaLabelOfPopover';
|
||||
export * from './hooks/useGetAfterSuccessVariablesOptions';
|
||||
export * from './types';
|
||||
export * from './zIndexContext';
|
||||
|
@ -14,22 +14,22 @@ import { uid } from '@formily/shared';
|
||||
import { Space, message } from 'antd';
|
||||
import { isEqual } from 'lodash';
|
||||
import { isFunction } from 'mathjs';
|
||||
import React, { useEffect, useState, useContext } from 'react';
|
||||
import React, { useContext, useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
ClearCollectionFieldContext,
|
||||
NocoBaseRecursionField,
|
||||
RecordProvider,
|
||||
SchemaComponentContext,
|
||||
useAPIClient,
|
||||
useCollectionRecordData,
|
||||
SchemaComponentContext,
|
||||
} from '../../../';
|
||||
import { Action } from '../action';
|
||||
import { VariablePopupRecordProvider } from '../../../modules/variable/variablesProvider/VariablePopupRecordProvider';
|
||||
import { isVariable } from '../../../variables/utils/isVariable';
|
||||
import { getInnermostKeyAndValue } from '../../common/utils/uitls';
|
||||
import { Action } from '../action';
|
||||
import { RemoteSelect, RemoteSelectProps } from '../remote-select';
|
||||
import useServiceOptions, { useAssociationFieldContext } from './hooks';
|
||||
import { VariablePopupRecordProvider } from '../../../modules/variable/variablesProvider/VariablePopupRecordProvider';
|
||||
|
||||
export const AssociationFieldAddNewer = (props) => {
|
||||
const schemaComponentCtxValue = useContext(SchemaComponentContext);
|
||||
|
@ -158,7 +158,10 @@ export const InternalPicker = observer(
|
||||
}),
|
||||
[],
|
||||
);
|
||||
const newSchema = useMemo(() => isMobileLayout ? transformMultiColumnToSingleColumn(fieldSchema) : fieldSchema, [isMobileLayout, fieldSchema]);
|
||||
const newSchema = useMemo(
|
||||
() => (isMobileLayout ? transformMultiColumnToSingleColumn(fieldSchema) : fieldSchema),
|
||||
[isMobileLayout, fieldSchema],
|
||||
);
|
||||
|
||||
return (
|
||||
<PopupSettingsProvider enableURL={false}>
|
||||
|
@ -144,8 +144,14 @@ const ToManyNester = observer(
|
||||
const update = useUpdate();
|
||||
const { isMobileLayout } = useMobileLayout();
|
||||
|
||||
const newSchema = useMemo(() => isMobileLayout ? transformMultiColumnToSingleColumn(fieldSchema) : fieldSchema, [isMobileLayout, fieldSchema]);
|
||||
const newParentSchema = useMemo(() => isMobileLayout ? transformMultiColumnToSingleColumn(fieldSchema.parent) : fieldSchema.parent, [isMobileLayout, fieldSchema.parent]);
|
||||
const newSchema = useMemo(
|
||||
() => (isMobileLayout ? transformMultiColumnToSingleColumn(fieldSchema) : fieldSchema),
|
||||
[isMobileLayout, fieldSchema],
|
||||
);
|
||||
const newParentSchema = useMemo(
|
||||
() => (isMobileLayout ? transformMultiColumnToSingleColumn(fieldSchema.parent) : fieldSchema.parent),
|
||||
[isMobileLayout, fieldSchema.parent],
|
||||
);
|
||||
|
||||
const refreshComponent = useRefreshComponent();
|
||||
const refresh = useCallback(() => {
|
||||
|
@ -60,6 +60,7 @@ export function useAssociationFieldContext<F extends GeneralField>() {
|
||||
};
|
||||
}
|
||||
|
||||
// 用于获取关系字段请求数据时所需的一些参数
|
||||
export default function useServiceOptions(props) {
|
||||
const { action = 'list', service, useOriginalFilter } = props;
|
||||
const fieldSchema = useFieldSchema();
|
||||
|
@ -50,7 +50,7 @@ describe('CollectionSelect', () => {
|
||||
>
|
||||
<div
|
||||
aria-label="block-item-demo title"
|
||||
class="nb-block-item nb-form-item css-9qorhu ant-nb-block-item css-dev-only-do-not-override-11aiz3o"
|
||||
class="nb-block-item nb-form-item css-9qorhu ant-nb-block-item css-dev-only-do-not-override-1rquknz"
|
||||
role="button"
|
||||
>
|
||||
<div
|
||||
@ -191,7 +191,7 @@ describe('CollectionSelect', () => {
|
||||
>
|
||||
<div
|
||||
aria-label="block-item-demo title"
|
||||
class="nb-block-item nb-form-item css-9qorhu ant-nb-block-item css-dev-only-do-not-override-11aiz3o"
|
||||
class="nb-block-item nb-form-item css-9qorhu ant-nb-block-item css-dev-only-do-not-override-1rquknz"
|
||||
role="button"
|
||||
>
|
||||
<div
|
||||
|
@ -92,7 +92,7 @@ export const useGetFilterFieldOptions = () => {
|
||||
|
||||
const getOptions = (fields, depth, usedInVariable?: boolean) => {
|
||||
const options = [];
|
||||
fields.forEach((field) => {
|
||||
fields?.forEach((field) => {
|
||||
const option = field2option(field, depth, usedInVariable);
|
||||
if (option) {
|
||||
options.push(option);
|
||||
|
@ -52,7 +52,10 @@ const FormComponent: React.FC<FormProps> = (props) => {
|
||||
labelWrap = true,
|
||||
} = cardItemSchema?.['x-component-props'] || {};
|
||||
const { isMobileLayout } = useMobileLayout();
|
||||
const newSchema = useMemo(() => isMobileLayout ? transformMultiColumnToSingleColumn(fieldSchema) : fieldSchema, [fieldSchema, isMobileLayout]);
|
||||
const newSchema = useMemo(
|
||||
() => (isMobileLayout ? transformMultiColumnToSingleColumn(fieldSchema) : fieldSchema),
|
||||
[fieldSchema, isMobileLayout],
|
||||
);
|
||||
|
||||
return (
|
||||
<FieldContext.Provider value={undefined}>
|
||||
@ -81,12 +84,7 @@ const FormComponent: React.FC<FormProps> = (props) => {
|
||||
}
|
||||
`}
|
||||
>
|
||||
<NocoBaseRecursionField
|
||||
basePath={f.address}
|
||||
schema={newSchema}
|
||||
onlyRenderProperties
|
||||
isUseFormilyField
|
||||
/>
|
||||
<NocoBaseRecursionField basePath={f.address} schema={newSchema} onlyRenderProperties isUseFormilyField />
|
||||
</div>
|
||||
</FormLayout>
|
||||
</FormContext.Provider>
|
||||
@ -104,19 +102,17 @@ const FormDecorator: React.FC<FormProps> = (props) => {
|
||||
const f = useAttach(form.createVoidField({ ...field.props, basePath: '' }));
|
||||
const Component = useComponent(fieldSchema['x-component'], Def);
|
||||
const { isMobileLayout } = useMobileLayout();
|
||||
const newSchema = useMemo(() => isMobileLayout ? transformMultiColumnToSingleColumn(fieldSchema) : fieldSchema, [fieldSchema, isMobileLayout]);
|
||||
const newSchema = useMemo(
|
||||
() => (isMobileLayout ? transformMultiColumnToSingleColumn(fieldSchema) : fieldSchema),
|
||||
[fieldSchema, isMobileLayout],
|
||||
);
|
||||
return (
|
||||
<FieldContext.Provider value={undefined}>
|
||||
<FormContext.Provider value={form}>
|
||||
<FormLayout layout={'vertical'} {...others}>
|
||||
<FieldContext.Provider value={f}>
|
||||
<Component {...field.componentProps}>
|
||||
<NocoBaseRecursionField
|
||||
basePath={f.address}
|
||||
schema={newSchema}
|
||||
onlyRenderProperties
|
||||
isUseFormilyField
|
||||
/>
|
||||
<NocoBaseRecursionField basePath={f.address} schema={newSchema} onlyRenderProperties isUseFormilyField />
|
||||
</Component>
|
||||
</FieldContext.Provider>
|
||||
{/* <FieldContext.Provider value={f}>{children}</FieldContext.Provider> */}
|
||||
|
@ -1,5 +0,0 @@
|
||||
# Page
|
||||
|
||||
Can be used in conjunction with DocumentTitleProvider to display the page title on document.title.
|
||||
|
||||
<code src="./demos/demo1.tsx"></code>
|
@ -1,5 +0,0 @@
|
||||
# Page
|
||||
|
||||
可以与 DocumentTitleProvider 搭配使用,将 page title 显示在 document.title 上。
|
||||
|
||||
<code src="./demos/demo1.tsx"></code>
|
@ -343,14 +343,14 @@ export const TableBlockDesigner = () => {
|
||||
}}
|
||||
/>
|
||||
<SchemaSettingsConnectDataBlocks type={FilterBlockType.TABLE} emptyDescription={t('No blocks to connect')} />
|
||||
{supportTemplate && <SchemaSettingsDivider />}
|
||||
{/* {supportTemplate && <SchemaSettingsDivider />}
|
||||
{supportTemplate && (
|
||||
<SchemaSettingsTemplate
|
||||
componentName={`${componentNamePrefix}Table`}
|
||||
collectionName={name}
|
||||
resourceName={defaultResource}
|
||||
/>
|
||||
)}
|
||||
)} */}
|
||||
<SchemaSettingsDivider />
|
||||
<SchemaSettingsRemove
|
||||
removeParentsIfNoChildren
|
||||
|
@ -233,10 +233,10 @@ describe('Table.settings', () => {
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Save as template',
|
||||
type: 'modal',
|
||||
},
|
||||
// {
|
||||
// title: 'Save as template',
|
||||
// type: 'modal',
|
||||
// },
|
||||
{
|
||||
title: 'Delete',
|
||||
type: 'delete',
|
||||
@ -299,7 +299,12 @@ describe('Table.settings', () => {
|
||||
|
||||
test('menu list', async () => {
|
||||
await renderSettings(getRenderSettingsOptions());
|
||||
await checkTableSettings();
|
||||
await checkTableSettings([
|
||||
{
|
||||
title: 'Save as template',
|
||||
type: 'modal',
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
test('old schema', async () => {
|
||||
|
@ -45,9 +45,9 @@ export const Sortable = (props: any) => {
|
||||
const { draggable, droppable } = useContext(SortableContext);
|
||||
const { isOver, setNodeRef } = droppable;
|
||||
const droppableStyle = { ...style };
|
||||
|
||||
const isLinkComponent = component === 'a' || component?.displayName === 'WrapperComponentLink';
|
||||
if (isOver && draggable?.active?.id !== droppable?.over?.id) {
|
||||
droppableStyle[component === 'a' ? 'color' : 'background'] = getComputedColor(token.colorSettings);
|
||||
droppableStyle[isLinkComponent ? 'color' : 'background'] = getComputedColor(token.colorSettings);
|
||||
Object.assign(droppableStyle, overStyle);
|
||||
}
|
||||
|
||||
@ -118,7 +118,6 @@ export const SortableItem: React.FC<SortableItemProps> = React.memo((props) => {
|
||||
if (designable) {
|
||||
return <InternalSortableItem {...props} />;
|
||||
}
|
||||
|
||||
return React.createElement(
|
||||
component || 'div',
|
||||
_.omit(others, ['children', 'schema', 'overStyle', 'openMode', 'id', 'eid', 'removeParentsIfNoChildren']),
|
||||
|
@ -267,6 +267,13 @@ function FinallyButton({
|
||||
}) {
|
||||
const { getCollection } = useCollectionManager_deprecated();
|
||||
const aclCtx = useACLActionParamsContext();
|
||||
const buttonStyle = useMemo(() => {
|
||||
const shouldApplyOpacity = designable && (field?.data?.hidden || !aclCtx);
|
||||
const opacityValue = componentType !== 'link' ? (shouldApplyOpacity ? 0.1 : 1) : 1;
|
||||
return {
|
||||
opacity: opacityValue,
|
||||
};
|
||||
}, [designable, field?.data?.hidden, aclCtx, componentType]);
|
||||
|
||||
if (inheritsCollections?.length > 0) {
|
||||
if (!linkageFromForm) {
|
||||
@ -276,6 +283,7 @@ function FinallyButton({
|
||||
danger={props.danger}
|
||||
type={componentType}
|
||||
icon={<DownOutlined />}
|
||||
style={{ ...props?.style, ...buttonStyle }}
|
||||
buttonsRender={([leftButton, rightButton]) => [
|
||||
React.cloneElement(leftButton as React.ReactElement<any, string>, {
|
||||
style: props?.style,
|
||||
@ -296,7 +304,13 @@ function FinallyButton({
|
||||
) : (
|
||||
<Dropdown menu={menu}>
|
||||
{
|
||||
<Button aria-label={props['aria-label']} icon={icon} type={componentType} danger={props.danger}>
|
||||
<Button
|
||||
aria-label={props['aria-label']}
|
||||
icon={icon}
|
||||
type={componentType}
|
||||
danger={props.danger}
|
||||
style={{ ...props?.style, ...buttonStyle }}
|
||||
>
|
||||
{props.children} <DownOutlined />
|
||||
</Button>
|
||||
}
|
||||
@ -321,6 +335,7 @@ function FinallyButton({
|
||||
style={{
|
||||
display: !designable && field?.data?.hidden && 'none',
|
||||
opacity: designable && field?.data?.hidden && 0.1,
|
||||
...buttonStyle,
|
||||
}}
|
||||
>
|
||||
{props.children}
|
||||
@ -342,7 +357,7 @@ function FinallyButton({
|
||||
...props?.style,
|
||||
display: !designable && field?.data?.hidden && 'none',
|
||||
opacity: designable && field?.data?.hidden && 0.1,
|
||||
height: '100%',
|
||||
...buttonStyle,
|
||||
}}
|
||||
>
|
||||
{props.onlyIcon ? props?.children?.[1] : props?.children}
|
||||
|
@ -57,16 +57,6 @@ export const useLinkageCollectionFieldOptions = (collectionName: string, readPre
|
||||
if (nested || children || ['formula', 'richText', 'sequence'].includes(fieldInterface.name)) {
|
||||
return operator?.value !== ActionType.Value && operator?.value !== ActionType.Options;
|
||||
}
|
||||
if (!['select', 'radioGroup', 'multipleSelect', 'checkboxGroup'].includes(fieldInterface.name)) {
|
||||
return operator?.value !== ActionType.Options;
|
||||
}
|
||||
if (
|
||||
!['date', 'datetime', 'dateOnly', 'datetimeNoTz', 'unixTimestamp', 'createdAt', 'updatedAt'].includes(
|
||||
fieldInterface.name,
|
||||
)
|
||||
) {
|
||||
return operator?.value !== ActionType.DateScope;
|
||||
}
|
||||
return true;
|
||||
}) || [],
|
||||
};
|
||||
|
@ -10,6 +10,7 @@
|
||||
import { useField } from '@formily/react';
|
||||
import { useEffect, useContext } from 'react';
|
||||
import { LinkageLogicContext } from './context';
|
||||
import { ActionType } from './type';
|
||||
|
||||
const findOption = (dataIndex = [], options) => {
|
||||
let items = options;
|
||||
@ -45,9 +46,34 @@ export const useValues = (options) => {
|
||||
field.data = field.data || {};
|
||||
const operators = option?.operators;
|
||||
field.data.operators = operators?.filter((v) => {
|
||||
if (dataIndex.length > 1) {
|
||||
return !['value', 'dateScope', 'options'].includes(v.value);
|
||||
const isOptionField = ['select', 'radioGroup', 'multipleSelect', 'checkboxGroup'].includes(
|
||||
option?.interface || '',
|
||||
);
|
||||
const isDateField = [
|
||||
'date',
|
||||
'datetime',
|
||||
'dateOnly',
|
||||
'datetimeNoTz',
|
||||
'unixTimestamp',
|
||||
'createdAt',
|
||||
'updatedAt',
|
||||
].includes(option?.interface || '');
|
||||
|
||||
// 如果 多个字段,则排除 Value、DateScope、Options
|
||||
if (dataIndex.length > 1 && [ActionType.Value, ActionType.DateScope, ActionType.Options].includes(v.value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 非选项字段,去掉 Options
|
||||
if (!isOptionField && v.value === ActionType.Options) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 非时间字段,去掉 DateScope
|
||||
if (!isDateField && v.value === ActionType.DateScope) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
field.data.schema = option?.schema;
|
||||
|
@ -18,7 +18,6 @@ import { getDataSourceHeaders } from '../data-source/utils';
|
||||
import { useCompile } from '../schema-component';
|
||||
import useBuiltInVariables from './hooks/useBuiltinVariables';
|
||||
import { VariableOption, VariablesContextType } from './types';
|
||||
import { cacheLazyLoadedValues, getCachedLazyLoadedValues } from './utils/cacheLazyLoadedValues';
|
||||
import { filterEmptyValues } from './utils/filterEmptyValues';
|
||||
import { getAction } from './utils/getAction';
|
||||
import { getPath } from './utils/getPath';
|
||||
@ -144,14 +143,13 @@ const VariablesProvider = ({ children, filterVariables }: any) => {
|
||||
.then((data) => {
|
||||
clearRequested(url);
|
||||
const value = data.data.data;
|
||||
cacheLazyLoadedValues(item, currentVariablePath, value);
|
||||
return value;
|
||||
});
|
||||
stashRequested(url, result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return getCachedLazyLoadedValues(item, currentVariablePath) || item?.[key];
|
||||
return item?.[key];
|
||||
});
|
||||
current = removeThroughCollectionFields(_.flatten(await Promise.all(result)), associationField);
|
||||
} else if (
|
||||
@ -180,17 +178,9 @@ const VariablesProvider = ({ children, filterVariables }: any) => {
|
||||
}
|
||||
|
||||
const value = data.data.data;
|
||||
if (!getCachedLazyLoadedValues(current, currentVariablePath)) {
|
||||
// Cache the API response data to avoid repeated requests
|
||||
cacheLazyLoadedValues(current, currentVariablePath, value);
|
||||
}
|
||||
|
||||
current = removeThroughCollectionFields(value, associationField);
|
||||
} else {
|
||||
current = removeThroughCollectionFields(
|
||||
getCachedLazyLoadedValues(current, currentVariablePath) || getValuesByPath(current, key),
|
||||
associationField,
|
||||
);
|
||||
current = removeThroughCollectionFields(getValuesByPath(current, key), associationField);
|
||||
}
|
||||
|
||||
if (associationField?.target) {
|
||||
@ -359,13 +349,8 @@ export default VariablesProvider;
|
||||
function shouldToRequest(value, variableCtx: Record<string, any>, variablePath: string) {
|
||||
let result = false;
|
||||
|
||||
if (getCachedLazyLoadedValues(variableCtx, variablePath)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// value may be a reactive object, using untracked to avoid unexpected autorun
|
||||
untracked(() => {
|
||||
// fix https://nocobase.height.app/T-2502
|
||||
// Compatible with `xxx to many` and `xxx to one` subform fields and subtable fields
|
||||
if (JSON.stringify(value) === '[{}]' || JSON.stringify(value) === '{}') {
|
||||
result = true;
|
||||
|
@ -1,25 +0,0 @@
|
||||
/**
|
||||
* This file is part of the NocoBase (R) project.
|
||||
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
||||
* Authors: NocoBase Team.
|
||||
*
|
||||
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
||||
* For more information, please refer to: https://www.nocobase.com/agreement.
|
||||
*/
|
||||
|
||||
const cache = new Map<Record<string, any>, any>();
|
||||
|
||||
export const cacheLazyLoadedValues = (variableCtx: Record<string, any>, variablePath: string, value: any) => {
|
||||
const cachedValue = cache.get(variableCtx);
|
||||
|
||||
if (cachedValue) {
|
||||
cachedValue[variablePath] = value;
|
||||
} else {
|
||||
cache.set(variableCtx, { [variablePath]: value });
|
||||
}
|
||||
};
|
||||
|
||||
export const getCachedLazyLoadedValues = (variableCtx: Record<string, any>, variablePath: string) => {
|
||||
const cachedValue = cache.get(variableCtx);
|
||||
return cachedValue?.[variablePath];
|
||||
};
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "create-nocobase-app",
|
||||
"version": "1.7.0-alpha.4",
|
||||
"version": "1.7.0-beta.9",
|
||||
"main": "src/index.js",
|
||||
"license": "AGPL-3.0",
|
||||
"dependencies": {
|
||||
|
@ -1,16 +1,16 @@
|
||||
{
|
||||
"name": "@nocobase/data-source-manager",
|
||||
"version": "1.7.0-alpha.4",
|
||||
"version": "1.7.0-beta.9",
|
||||
"description": "",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "./lib/index.js",
|
||||
"types": "./lib/index.d.ts",
|
||||
"dependencies": {
|
||||
"@nocobase/actions": "1.7.0-alpha.4",
|
||||
"@nocobase/cache": "1.7.0-alpha.4",
|
||||
"@nocobase/database": "1.7.0-alpha.4",
|
||||
"@nocobase/resourcer": "1.7.0-alpha.4",
|
||||
"@nocobase/utils": "1.7.0-alpha.4",
|
||||
"@nocobase/actions": "1.7.0-beta.9",
|
||||
"@nocobase/cache": "1.7.0-beta.9",
|
||||
"@nocobase/database": "1.7.0-beta.9",
|
||||
"@nocobase/resourcer": "1.7.0-beta.9",
|
||||
"@nocobase/utils": "1.7.0-beta.9",
|
||||
"@types/jsonwebtoken": "^8.5.8",
|
||||
"jsonwebtoken": "^8.5.1"
|
||||
},
|
||||
|
@ -1,13 +1,13 @@
|
||||
{
|
||||
"name": "@nocobase/database",
|
||||
"version": "1.7.0-alpha.4",
|
||||
"version": "1.7.0-beta.9",
|
||||
"description": "",
|
||||
"main": "./lib/index.js",
|
||||
"types": "./lib/index.d.ts",
|
||||
"license": "AGPL-3.0",
|
||||
"dependencies": {
|
||||
"@nocobase/logger": "1.7.0-alpha.4",
|
||||
"@nocobase/utils": "1.7.0-alpha.4",
|
||||
"@nocobase/logger": "1.7.0-beta.9",
|
||||
"@nocobase/utils": "1.7.0-beta.9",
|
||||
"async-mutex": "^0.3.2",
|
||||
"chalk": "^4.1.1",
|
||||
"cron-parser": "4.4.0",
|
||||
|
@ -1,13 +1,13 @@
|
||||
{
|
||||
"name": "@nocobase/devtools",
|
||||
"version": "1.7.0-alpha.4",
|
||||
"version": "1.7.0-beta.9",
|
||||
"description": "",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "./src/index.js",
|
||||
"dependencies": {
|
||||
"@nocobase/build": "1.7.0-alpha.4",
|
||||
"@nocobase/client": "1.7.0-alpha.4",
|
||||
"@nocobase/test": "1.7.0-alpha.4",
|
||||
"@nocobase/build": "1.7.0-beta.9",
|
||||
"@nocobase/client": "1.7.0-beta.9",
|
||||
"@nocobase/test": "1.7.0-beta.9",
|
||||
"@types/koa": "^2.15.0",
|
||||
"@types/koa-bodyparser": "^4.3.4",
|
||||
"@types/lodash": "^4.14.177",
|
||||
|
@ -1,13 +1,13 @@
|
||||
{
|
||||
"name": "@nocobase/evaluators",
|
||||
"version": "1.7.0-alpha.4",
|
||||
"version": "1.7.0-beta.9",
|
||||
"description": "",
|
||||
"main": "./lib/index.js",
|
||||
"types": "./lib/index.d.ts",
|
||||
"license": "AGPL-3.0",
|
||||
"dependencies": {
|
||||
"@formulajs/formulajs": "4.4.9",
|
||||
"@nocobase/utils": "1.7.0-alpha.4",
|
||||
"@nocobase/utils": "1.7.0-beta.9",
|
||||
"mathjs": "^10.6.0"
|
||||
},
|
||||
"repository": {
|
||||
|
@ -1,10 +1,10 @@
|
||||
{
|
||||
"name": "@nocobase/lock-manager",
|
||||
"version": "1.7.0-alpha.4",
|
||||
"version": "1.7.0-beta.9",
|
||||
"main": "lib/index.js",
|
||||
"license": "AGPL-3.0",
|
||||
"devDependencies": {
|
||||
"@nocobase/utils": "1.7.0-alpha.4",
|
||||
"@nocobase/utils": "1.7.0-beta.9",
|
||||
"async-mutex": "^0.5.0"
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/logger",
|
||||
"version": "1.7.0-alpha.4",
|
||||
"version": "1.7.0-beta.9",
|
||||
"description": "nocobase logging library",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "./lib/index.js",
|
||||
|
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@nocobase/resourcer",
|
||||
"version": "1.7.0-alpha.4",
|
||||
"version": "1.7.0-beta.9",
|
||||
"description": "",
|
||||
"main": "./lib/index.js",
|
||||
"types": "./lib/index.d.ts",
|
||||
"license": "AGPL-3.0",
|
||||
"dependencies": {
|
||||
"@nocobase/utils": "1.7.0-alpha.4",
|
||||
"@nocobase/utils": "1.7.0-beta.9",
|
||||
"deepmerge": "^4.2.2",
|
||||
"koa-compose": "^4.1.0",
|
||||
"lodash": "^4.17.21",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/sdk",
|
||||
"version": "1.7.0-alpha.4",
|
||||
"version": "1.7.0-beta.9",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "lib/index.js",
|
||||
"types": "lib/index.d.ts",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/server",
|
||||
"version": "1.7.0-alpha.4",
|
||||
"version": "1.7.0-beta.9",
|
||||
"main": "lib/index.js",
|
||||
"types": "./lib/index.d.ts",
|
||||
"license": "AGPL-3.0",
|
||||
@ -10,19 +10,19 @@
|
||||
"@koa/cors": "^5.0.0",
|
||||
"@koa/multer": "^3.0.2",
|
||||
"@koa/router": "^9.4.0",
|
||||
"@nocobase/acl": "1.7.0-alpha.4",
|
||||
"@nocobase/actions": "1.7.0-alpha.4",
|
||||
"@nocobase/auth": "1.7.0-alpha.4",
|
||||
"@nocobase/cache": "1.7.0-alpha.4",
|
||||
"@nocobase/data-source-manager": "1.7.0-alpha.4",
|
||||
"@nocobase/database": "1.7.0-alpha.4",
|
||||
"@nocobase/evaluators": "1.7.0-alpha.4",
|
||||
"@nocobase/lock-manager": "1.7.0-alpha.4",
|
||||
"@nocobase/logger": "1.7.0-alpha.4",
|
||||
"@nocobase/resourcer": "1.7.0-alpha.4",
|
||||
"@nocobase/sdk": "1.7.0-alpha.4",
|
||||
"@nocobase/telemetry": "1.7.0-alpha.4",
|
||||
"@nocobase/utils": "1.7.0-alpha.4",
|
||||
"@nocobase/acl": "1.7.0-beta.9",
|
||||
"@nocobase/actions": "1.7.0-beta.9",
|
||||
"@nocobase/auth": "1.7.0-beta.9",
|
||||
"@nocobase/cache": "1.7.0-beta.9",
|
||||
"@nocobase/data-source-manager": "1.7.0-beta.9",
|
||||
"@nocobase/database": "1.7.0-beta.9",
|
||||
"@nocobase/evaluators": "1.7.0-beta.9",
|
||||
"@nocobase/lock-manager": "1.7.0-beta.9",
|
||||
"@nocobase/logger": "1.7.0-beta.9",
|
||||
"@nocobase/resourcer": "1.7.0-beta.9",
|
||||
"@nocobase/sdk": "1.7.0-beta.9",
|
||||
"@nocobase/telemetry": "1.7.0-beta.9",
|
||||
"@nocobase/utils": "1.7.0-beta.9",
|
||||
"@types/decompress": "4.2.7",
|
||||
"@types/ini": "^1.3.31",
|
||||
"@types/koa-send": "^4.1.3",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/telemetry",
|
||||
"version": "1.7.0-alpha.4",
|
||||
"version": "1.7.0-beta.9",
|
||||
"description": "nocobase telemetry library",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "./lib/index.js",
|
||||
@ -11,7 +11,7 @@
|
||||
"directory": "packages/telemetry"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nocobase/utils": "1.7.0-alpha.4",
|
||||
"@nocobase/utils": "1.7.0-beta.9",
|
||||
"@opentelemetry/api": "^1.7.0",
|
||||
"@opentelemetry/instrumentation": "^0.46.0",
|
||||
"@opentelemetry/resources": "^1.19.0",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/test",
|
||||
"version": "1.7.0-alpha.4",
|
||||
"version": "1.7.0-beta.9",
|
||||
"main": "lib/index.js",
|
||||
"module": "./src/index.ts",
|
||||
"types": "./lib/index.d.ts",
|
||||
@ -51,7 +51,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@faker-js/faker": "8.1.0",
|
||||
"@nocobase/server": "1.7.0-alpha.4",
|
||||
"@nocobase/server": "1.7.0-beta.9",
|
||||
"@playwright/test": "^1.45.3",
|
||||
"@testing-library/jest-dom": "^6.4.2",
|
||||
"@testing-library/react": "^14.0.0",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/utils",
|
||||
"version": "1.7.0-alpha.4",
|
||||
"version": "1.7.0-beta.9",
|
||||
"main": "lib/index.js",
|
||||
"types": "./lib/index.d.ts",
|
||||
"license": "AGPL-3.0",
|
||||
|
@ -37,7 +37,7 @@ vi.mock('@formily/json-schema', () => {
|
||||
const result = { ...schema, parent };
|
||||
result._isJSONSchemaObject = true;
|
||||
return result;
|
||||
})
|
||||
}),
|
||||
};
|
||||
});
|
||||
|
||||
@ -271,16 +271,16 @@ describe('transformMultiColumnToSingleColumn', () => {
|
||||
},
|
||||
parent: {
|
||||
properties: {
|
||||
grid1: {} // Will be replaced by result
|
||||
}
|
||||
grid1: {}, // Will be replaced by result
|
||||
},
|
||||
toJSON: vi.fn().mockImplementation(function() {
|
||||
},
|
||||
toJSON: vi.fn().mockImplementation(function () {
|
||||
return {
|
||||
name: this.name,
|
||||
'x-component': this['x-component'],
|
||||
properties: this.properties
|
||||
properties: this.properties,
|
||||
};
|
||||
})
|
||||
}),
|
||||
};
|
||||
|
||||
const result = transformMultiColumnToSingleColumn(mockSchema);
|
||||
|
@ -4,7 +4,7 @@
|
||||
"displayName.zh-CN": "权限控制",
|
||||
"description": "Based on roles, resources, and actions, access control can precisely manage interface configuration permissions, data operation permissions, menu access permissions, and plugin permissions.",
|
||||
"description.zh-CN": "基于角色、资源和操作的权限控制,可以精确控制界面配置权限、数据操作权限、菜单访问权限、插件权限。",
|
||||
"version": "1.7.0-alpha.4",
|
||||
"version": "1.7.0-beta.9",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "./dist/server/index.js",
|
||||
"homepage": "https://docs.nocobase.com/handbook/acl",
|
||||
|
@ -276,7 +276,8 @@ export const MenuPermissions: React.FC<{
|
||||
expandable={{
|
||||
defaultExpandAllRows: false,
|
||||
}}
|
||||
columns={[
|
||||
columns={
|
||||
[
|
||||
{
|
||||
dataIndex: 'title',
|
||||
title: t('Route name'),
|
||||
@ -310,7 +311,8 @@ export const MenuPermissions: React.FC<{
|
||||
return <Checkbox checked={checked} onChange={() => handleChange(checked, schema)} />;
|
||||
},
|
||||
},
|
||||
] as TableProps['columns']}
|
||||
] as TableProps['columns']
|
||||
}
|
||||
dataSource={translateTitle(items, t, compile)}
|
||||
/>
|
||||
</>
|
||||
|
@ -113,7 +113,8 @@ export const PluginPermissions: React.FC<{
|
||||
expandable={{
|
||||
defaultExpandAllRows: true,
|
||||
}}
|
||||
columns={[
|
||||
columns={
|
||||
[
|
||||
{
|
||||
dataIndex: 'title',
|
||||
title: t('Plugin name'),
|
||||
@ -150,7 +151,8 @@ export const PluginPermissions: React.FC<{
|
||||
return <Checkbox checked={checked} onChange={() => handleChange(checked, record)} />;
|
||||
},
|
||||
},
|
||||
] as TableProps['columns']}
|
||||
] as TableProps['columns']
|
||||
}
|
||||
dataSource={settings
|
||||
.filter((v) => {
|
||||
return v.isTopLevel !== false;
|
||||
|
@ -106,7 +106,8 @@ export const RolesResourcesActions = connect((props) => {
|
||||
className={styles}
|
||||
size={'small'}
|
||||
pagination={false}
|
||||
columns={[
|
||||
columns={
|
||||
[
|
||||
{
|
||||
dataIndex: 'displayName',
|
||||
title: t('Action display name'),
|
||||
@ -147,7 +148,8 @@ export const RolesResourcesActions = connect((props) => {
|
||||
/>
|
||||
),
|
||||
},
|
||||
] as TableProps['columns']}
|
||||
] as TableProps['columns']
|
||||
}
|
||||
dataSource={availableActions?.map((item) => {
|
||||
let enabled = false;
|
||||
let scope = null;
|
||||
@ -170,7 +172,8 @@ export const RolesResourcesActions = connect((props) => {
|
||||
className={styles}
|
||||
pagination={false}
|
||||
dataSource={fieldPermissions}
|
||||
columns={[
|
||||
columns={
|
||||
[
|
||||
{
|
||||
dataIndex: ['uiSchema', 'title'],
|
||||
title: t('Field display name'),
|
||||
@ -223,7 +226,8 @@ export const RolesResourcesActions = connect((props) => {
|
||||
),
|
||||
};
|
||||
}),
|
||||
] as TableProps['columns']}
|
||||
] as TableProps['columns']
|
||||
}
|
||||
/>
|
||||
</FormItem>
|
||||
</FormLayout>
|
||||
|
@ -55,7 +55,8 @@ export const StrategyActions = connect((props) => {
|
||||
rowKey={'name'}
|
||||
size={'small'}
|
||||
pagination={false}
|
||||
columns={[
|
||||
columns={
|
||||
[
|
||||
{
|
||||
dataIndex: 'displayName',
|
||||
title: t('Action display name'),
|
||||
@ -110,7 +111,8 @@ export const StrategyActions = connect((props) => {
|
||||
/>
|
||||
),
|
||||
},
|
||||
] as TableProps['columns']}
|
||||
] as TableProps['columns']
|
||||
}
|
||||
dataSource={availableActions?.map((item) => {
|
||||
let scope = 'all';
|
||||
let enabled = false;
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/plugin-action-bulk-edit",
|
||||
"version": "1.7.0-alpha.4",
|
||||
"version": "1.7.0-beta.9",
|
||||
"main": "dist/server/index.js",
|
||||
"homepage": "https://docs.nocobase.com/handbook/action-bulk-edit",
|
||||
"homepage.zh-CN": "https://docs-cn.nocobase.com/handbook/action-bulk-edit",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/plugin-action-bulk-update",
|
||||
"version": "1.7.0-alpha.4",
|
||||
"version": "1.7.0-beta.9",
|
||||
"main": "dist/server/index.js",
|
||||
"homepage": "https://docs.nocobase.com/handbook/action-bulk-update",
|
||||
"homepage.zh-CN": "https://docs-cn.nocobase.com/handbook/action-bulk-update",
|
||||
|
@ -8,7 +8,6 @@
|
||||
*/
|
||||
|
||||
import { ISchema, useFieldSchema } from '@formily/react';
|
||||
import { isValid } from '@formily/shared';
|
||||
import {
|
||||
ActionDesigner,
|
||||
SchemaSettings,
|
||||
@ -19,6 +18,8 @@ import {
|
||||
useDesignable,
|
||||
useSchemaToolbar,
|
||||
RefreshDataBlockRequest,
|
||||
useAfterSuccessOptions,
|
||||
useGlobalVariable,
|
||||
} from '@nocobase/client';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import React from 'react';
|
||||
@ -49,11 +50,22 @@ function UpdateMode() {
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const fieldNames = {
|
||||
value: 'value',
|
||||
label: 'label',
|
||||
};
|
||||
const useVariableProps = (environmentVariables) => {
|
||||
const scope = useAfterSuccessOptions();
|
||||
return {
|
||||
scope: [environmentVariables, ...scope].filter(Boolean),
|
||||
fieldNames,
|
||||
};
|
||||
};
|
||||
function AfterSuccess() {
|
||||
const { dn } = useDesignable();
|
||||
const { t } = useTranslation();
|
||||
const fieldSchema = useFieldSchema();
|
||||
const environmentVariables = useGlobalVariable('$env');
|
||||
return (
|
||||
<SchemaSettingsModalItem
|
||||
title={t('After successful submission')}
|
||||
@ -100,8 +112,9 @@ function AfterSuccess() {
|
||||
redirectTo: {
|
||||
title: t('Link'),
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
'x-component-props': {},
|
||||
'x-component': 'Variable.TextArea',
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
'x-use-component-props': () => useVariableProps(environmentVariables),
|
||||
},
|
||||
},
|
||||
} as ISchema
|
||||
|
@ -68,7 +68,7 @@ export const useCustomizeBulkUpdateActionProps = () => {
|
||||
if (result) {
|
||||
assignedValues[key] = transformVariableValue(result, { targetCollectionField: collectionField });
|
||||
}
|
||||
} else if (value != null && value !== '') {
|
||||
} else if (value !== '') {
|
||||
assignedValues[key] = value;
|
||||
}
|
||||
});
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/plugin-action-custom-request",
|
||||
"version": "1.7.0-alpha.4",
|
||||
"version": "1.7.0-beta.9",
|
||||
"main": "dist/server/index.js",
|
||||
"homepage": "https://docs.nocobase.com/handbook/action-custom-request",
|
||||
"homepage.zh-CN": "https://docs-cn.nocobase.com/handbook/action-custom-request",
|
||||
|
@ -68,10 +68,13 @@ export const useCustomizeRequestActionProps = () => {
|
||||
responseType: fieldSchema['x-response-type'] === 'stream' ? 'blob' : 'json',
|
||||
});
|
||||
if (res.headers['content-disposition']) {
|
||||
const regex = /attachment;\s*filename="([^"]+)"/;
|
||||
const match = res.headers['content-disposition'].match(regex);
|
||||
if (match?.[1]) {
|
||||
saveAs(res.data, match[1]);
|
||||
const contentDisposition = res.headers['content-disposition'];
|
||||
const utf8Match = contentDisposition.match(/filename\*=utf-8''([^;]+)/i);
|
||||
const asciiMatch = contentDisposition.match(/filename="([^"]+)"/i);
|
||||
if (utf8Match) {
|
||||
saveAs(res.data, decodeURIComponent(utf8Match[1]));
|
||||
} else if (asciiMatch) {
|
||||
saveAs(res.data, asciiMatch[1]);
|
||||
}
|
||||
}
|
||||
actionField.data.loading = false;
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/plugin-action-duplicate",
|
||||
"version": "1.7.0-alpha.4",
|
||||
"version": "1.7.0-beta.9",
|
||||
"main": "dist/server/index.js",
|
||||
"homepage": "https://docs.nocobase.com/handbook/action-duplicate",
|
||||
"homepage.zh-CN": "https://docs-cn.nocobase.com/handbook/action-duplicate",
|
||||
|
@ -4,7 +4,7 @@
|
||||
"displayName.zh-CN": "操作:导出记录",
|
||||
"description": "Export filtered records to excel, you can configure which fields to export.",
|
||||
"description.zh-CN": "导出筛选后的记录到 Excel 中,可以配置导出哪些字段。",
|
||||
"version": "1.7.0-alpha.4",
|
||||
"version": "1.7.0-beta.9",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "./dist/server/index.js",
|
||||
"homepage": "https://docs.nocobase.com/handbook/action-export",
|
||||
|
@ -4,7 +4,7 @@
|
||||
"displayName.zh-CN": "操作:导入记录",
|
||||
"description": "Import records using excel templates. You can configure which fields to import and templates will be generated automatically.",
|
||||
"description.zh-CN": "使用 Excel 模板导入数据,可以配置导入哪些字段,自动生成模板。",
|
||||
"version": "1.7.0-alpha.4",
|
||||
"version": "1.7.0-beta.9",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "./dist/server/index.js",
|
||||
"homepage": "https://docs.nocobase.com/handbook/action-import",
|
||||
|
@ -12,6 +12,7 @@ import { ISchema, useFieldSchema } from '@formily/react';
|
||||
import { Action, ActionContextProvider, PopupSettingsProvider, SchemaComponent, useCompile } from '@nocobase/client';
|
||||
import React, { useState } from 'react';
|
||||
import { NAMESPACE } from './constants';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { UploadOutlined } from '@ant-design/icons';
|
||||
|
||||
const importFormSchema: ISchema = {
|
||||
@ -128,7 +129,7 @@ export const ImportAction = (props) => {
|
||||
return (
|
||||
<ActionContextProvider value={{ visible, setVisible, fieldSchema }}>
|
||||
<Action
|
||||
icon={props.icon || <UploadOutlined />}
|
||||
icon={props.icon || 'uploadoutlined'}
|
||||
title={compile(fieldSchema?.title || "t('Import')")}
|
||||
{...props}
|
||||
onClick={() => setVisible(true)}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/plugin-action-print",
|
||||
"version": "1.7.0-alpha.4",
|
||||
"version": "1.7.0-beta.9",
|
||||
"main": "dist/server/index.js",
|
||||
"homepage": "https://docs.nocobase.com/handbook/action-print",
|
||||
"homepage.zh-CN": "https://docs-cn.nocobase.com/handbook/action-print",
|
||||
|
@ -4,7 +4,7 @@
|
||||
"displayName.zh-CN": "AI 集成",
|
||||
"description": "Support integration with AI services, providing AI-related workflow nodes to enhance business processing capabilities.",
|
||||
"description.zh-CN": "支持接入 AI 服务,提供 AI 相关的工作流节点,增强业务处理能力。",
|
||||
"version": "1.7.0-alpha.4",
|
||||
"version": "1.7.0-beta.9",
|
||||
"main": "dist/server/index.js",
|
||||
"peerDependencies": {
|
||||
"@nocobase/client": "1.x",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/plugin-api-doc",
|
||||
"version": "1.7.0-alpha.4",
|
||||
"version": "1.7.0-beta.9",
|
||||
"displayName": "API documentation",
|
||||
"displayName.zh-CN": "API 文档",
|
||||
"description": "An OpenAPI documentation generator for NocoBase HTTP API.",
|
||||
|
@ -4,7 +4,7 @@
|
||||
"displayName.zh-CN": "认证:API 密钥",
|
||||
"description": "Allows users to use API key to access application's HTTP API",
|
||||
"description.zh-CN": "允许用户使用 API 密钥访问应用的 HTTP API",
|
||||
"version": "1.7.0-alpha.4",
|
||||
"version": "1.7.0-beta.9",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "./dist/server/index.js",
|
||||
"homepage": "https://docs.nocobase.com/handbook/api-keys",
|
||||
|
@ -4,7 +4,7 @@
|
||||
"displayName.zh-CN": "异步任务管理器",
|
||||
"description": "Manage and monitor asynchronous tasks such as data import/export. Support task progress tracking and notification.",
|
||||
"description.zh-CN": "管理和监控数据导入导出等异步任务。支持任务进度跟踪和通知。",
|
||||
"version": "1.7.0-alpha.4",
|
||||
"version": "1.7.0-beta.9",
|
||||
"main": "dist/server/index.js",
|
||||
"peerDependencies": {
|
||||
"@nocobase/client": "1.x",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/plugin-audit-logs",
|
||||
"version": "1.7.0-alpha.4",
|
||||
"version": "1.7.0-beta.9",
|
||||
"displayName": "Audit logs (deprecated)",
|
||||
"displayName.zh-CN": "审计日志(废弃)",
|
||||
"description": "This plugin is deprecated. There will be a new audit log plugin in the future.",
|
||||
|
@ -4,7 +4,7 @@
|
||||
"displayName.zh-CN": "认证:短信",
|
||||
"description": "SMS authentication.",
|
||||
"description.zh-CN": "通过短信验证码认证身份。",
|
||||
"version": "1.7.0-alpha.4",
|
||||
"version": "1.7.0-beta.9",
|
||||
"main": "./dist/server/index.js",
|
||||
"homepage": "https://docs.nocobase.com/handbook/auth-sms",
|
||||
"homepage.zh-CN": "https://docs-cn.nocobase.com/handbook/auth-sms",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/plugin-auth",
|
||||
"version": "1.7.0-alpha.4",
|
||||
"version": "1.7.0-beta.9",
|
||||
"main": "./dist/server/index.js",
|
||||
"homepage": "https://docs.nocobase.com/handbook/auth",
|
||||
"homepage.zh-CN": "https://docs-cn.nocobase.com/handbook/auth",
|
||||
|
@ -4,7 +4,7 @@
|
||||
"displayName.zh-CN": "应用的备份与还原(废弃)",
|
||||
"description": "Backup and restore applications for scenarios such as application replication, migration, and upgrades.",
|
||||
"description.zh-CN": "备份和还原应用,可用于应用的复制、迁移、升级等场景。",
|
||||
"version": "1.7.0-alpha.4",
|
||||
"version": "1.7.0-beta.9",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "./dist/server/index.js",
|
||||
"homepage": "https://docs.nocobase.com/handbook/backup-restore",
|
||||
|
@ -111,11 +111,11 @@ const LearnMore: any = (props: { collectionsData?: any; isBackup?: boolean }) =>
|
||||
render: (_, data) => {
|
||||
const title = compile(data.title);
|
||||
const name = data.name;
|
||||
return name === title ? title : (
|
||||
return name === title ? (
|
||||
title
|
||||
) : (
|
||||
<div>
|
||||
{data.name}
|
||||
{' '}
|
||||
<span style={{ color: 'rgba(0, 0, 0, 0.3)', fontSize: '0.9em' }}>({compile(data.title)})</span>
|
||||
{data.name} <span style={{ color: 'rgba(0, 0, 0, 0.3)', fontSize: '0.9em' }}>({compile(data.title)})</span>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
@ -418,7 +418,8 @@ export const BackupAndRestoreList = () => {
|
||||
<Table
|
||||
dataSource={dataSource}
|
||||
loading={loading}
|
||||
columns={[
|
||||
columns={
|
||||
[
|
||||
{
|
||||
title: t('Backup file'),
|
||||
dataIndex: 'name',
|
||||
@ -484,7 +485,8 @@ export const BackupAndRestoreList = () => {
|
||||
</Space>
|
||||
),
|
||||
},
|
||||
] as TableProps['columns']}
|
||||
] as TableProps['columns']
|
||||
}
|
||||
/>
|
||||
</Card>
|
||||
</div>
|
||||
|
@ -4,7 +4,7 @@
|
||||
"displayName.zh-CN": "区块:iframe",
|
||||
"description": "Create an iframe block on the page to embed and display external web pages or content.",
|
||||
"description.zh-CN": "在页面上创建和管理iframe,用于嵌入和展示外部网页或内容。",
|
||||
"version": "1.7.0-alpha.4",
|
||||
"version": "1.7.0-beta.9",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "./dist/server/index.js",
|
||||
"homepage": "https://docs.nocobase.com/handbook/block-iframe",
|
||||
|
@ -4,7 +4,7 @@
|
||||
"displayName.zh-CN": "区块:模板",
|
||||
"description": "Create and manage block templates for reuse on pages.",
|
||||
"description.zh-CN": "创建和管理区块模板,用于在页面中重复使用。",
|
||||
"version": "1.7.0-alpha.4",
|
||||
"version": "1.7.0-beta.9",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "dist/server/index.js",
|
||||
"homepage": "https://docs.nocobase.com/handbook/block-template",
|
||||
|
@ -23,7 +23,7 @@ import { useLocation } from 'react-router-dom';
|
||||
|
||||
const blockDecoratorMenuMaps = {
|
||||
TableBlockProvider: ['Table', 'table'],
|
||||
FormBlockProvider: ['Form', 'form'],
|
||||
FormBlockProvider: ['FormItem', 'form'],
|
||||
DetailsBlockProvider: ['Details', 'details'],
|
||||
'List.Decorator': ['List', 'list'],
|
||||
'GridCard.Decorator': ['GridCard', 'gridCard'],
|
||||
@ -281,6 +281,7 @@ function getTemplateSchemaFromPage(schema: ISchema) {
|
||||
if (s['x-template-root-uid']) {
|
||||
return;
|
||||
}
|
||||
t = t || {};
|
||||
_.merge(t, _.omit(s, ['x-uid', 'properties']));
|
||||
t['x-uid'] = uid();
|
||||
if (s.properties) {
|
||||
@ -288,7 +289,7 @@ function getTemplateSchemaFromPage(schema: ISchema) {
|
||||
if (s.properties[key]['x-template-root-uid']) {
|
||||
continue;
|
||||
}
|
||||
_.set(t, `properties.${key}`, {});
|
||||
_.set(t, `properties.['${key}']`, {});
|
||||
traverseSchema(s.properties[key], t.properties[key]);
|
||||
}
|
||||
}
|
||||
|
@ -169,6 +169,9 @@ export class PluginBlockTemplateClient extends Plugin {
|
||||
'blockSettings:createForm',
|
||||
'blockSettings:details',
|
||||
'blockSettings:detailsWithPagination',
|
||||
'blockSettings:multiDataDetails',
|
||||
'blockSettings:singleDataDetails',
|
||||
'blockSettings:stepsForm',
|
||||
'blockSettings:filterCollapse',
|
||||
'blockSettings:filterForm',
|
||||
'blockSettings:gantt',
|
||||
@ -176,6 +179,13 @@ export class PluginBlockTemplateClient extends Plugin {
|
||||
'blockSettings:kanban',
|
||||
'blockSettings:list',
|
||||
'blockSettings:table',
|
||||
'blockSettings:tree',
|
||||
'ReadPrettyFormSettings',
|
||||
'GanttBlockSettings',
|
||||
'FormV1Settings',
|
||||
'FormSettings',
|
||||
'FormItemSettings',
|
||||
'FormDetailsSettings',
|
||||
];
|
||||
if (blockSettings.includes(key)) {
|
||||
// schemaSetting.add('template-saveAsTemplateItem', saveAsTemplateSetting);
|
||||
|
@ -43,6 +43,10 @@ export function convertTplBlock(
|
||||
if (newSchema['x-decorator'] === 'TemplateGridDecorator') {
|
||||
delete newSchema['x-decorator'];
|
||||
}
|
||||
if (newSchema['x-linkage-rules']) {
|
||||
// linkage rules 有可能保存在Grid组件中
|
||||
delete newSchema['x-linkage-rules'];
|
||||
}
|
||||
for (const key in tpl.properties) {
|
||||
const t = convertTplBlock(tpl.properties[key], virtual, isRoot, newRootId, templateKey, options);
|
||||
if (isRoot) {
|
||||
@ -154,8 +158,12 @@ export function formSchemaPatch(currentSchema: ISchema, options?: any) {
|
||||
return key !== 'grid';
|
||||
});
|
||||
if (actionKey) {
|
||||
_.set(currentSchema, `properties.${comKey}.x-use-component-props`, 'useEditFormBlockProps');
|
||||
_.set(currentSchema, `properties.${comKey}.properties.${actionKey}.x-initializer`, 'editForm:configureActions');
|
||||
_.set(currentSchema, `properties.['${comKey}'].x-use-component-props`, 'useEditFormBlockProps');
|
||||
_.set(
|
||||
currentSchema,
|
||||
`properties.['${comKey}'].properties.['${actionKey}'].x-initializer`,
|
||||
'editForm:configureActions',
|
||||
);
|
||||
|
||||
const actionBarSchema = _.get(currentSchema, `properties.${comKey}.properties.${actionKey}.properties`, {});
|
||||
for (const key in actionBarSchema) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/plugin-block-workbench",
|
||||
"version": "1.7.0-alpha.4",
|
||||
"version": "1.7.0-beta.9",
|
||||
"displayName": "Block: Action panel",
|
||||
"displayName.zh-CN": "区块:操作面板",
|
||||
"description": "Centrally manages and displays various actions, allowing users to efficiently perform tasks. It supports extensibility, with current action types including pop-ups, links, scanning, and custom requests.",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/plugin-calendar",
|
||||
"version": "1.7.0-alpha.4",
|
||||
"version": "1.7.0-beta.9",
|
||||
"displayName": "Calendar",
|
||||
"displayName.zh-CN": "日历",
|
||||
"description": "Provides callendar collection template and block for managing date data, typically for date/time related information such as events, appointments, tasks, and so on.",
|
||||
|
@ -4,7 +4,7 @@
|
||||
"displayName.zh-CN": "图表(废弃)",
|
||||
"description": "The plugin has been deprecated, please use the data visualization plugin instead.",
|
||||
"description.zh-CN": "已废弃插件,请使用数据可视化插件代替。",
|
||||
"version": "1.7.0-alpha.4",
|
||||
"version": "1.7.0-beta.9",
|
||||
"main": "./dist/server/index.js",
|
||||
"license": "AGPL-3.0",
|
||||
"devDependencies": {
|
||||
|
@ -4,7 +4,7 @@
|
||||
"displayName.zh-CN": "WEB 客户端",
|
||||
"description": "Provides a client interface for the NocoBase server",
|
||||
"description.zh-CN": "为 NocoBase 服务端提供客户端界面",
|
||||
"version": "1.7.0-alpha.4",
|
||||
"version": "1.7.0-beta.9",
|
||||
"main": "./dist/server/index.js",
|
||||
"license": "AGPL-3.0",
|
||||
"devDependencies": {
|
||||
|
@ -4,7 +4,7 @@
|
||||
"displayName.zh-CN": "数据表: SQL",
|
||||
"description": "Provides SQL collection template",
|
||||
"description.zh-CN": "提供 SQL 数据表模板",
|
||||
"version": "1.7.0-alpha.4",
|
||||
"version": "1.7.0-beta.9",
|
||||
"homepage": "https://docs-cn.nocobase.com/handbook/collection-sql",
|
||||
"homepage.zh-CN": "https://docs-cn.nocobase.com/handbook/collection-sql",
|
||||
"main": "dist/server/index.js",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/plugin-collection-tree",
|
||||
"version": "1.7.0-alpha.4",
|
||||
"version": "1.7.0-beta.9",
|
||||
"displayName": "Collection: Tree",
|
||||
"displayName.zh-CN": "数据表:树",
|
||||
"description": "Provides tree collection template",
|
||||
|
@ -31,6 +31,8 @@ export default class extends Migration {
|
||||
await this.db.sequelize.transaction(async (transaction) => {
|
||||
const treeCollections = await this.getTreeCollections({ transaction });
|
||||
for (const treeCollection of treeCollections) {
|
||||
await treeCollection.load({ transaction });
|
||||
|
||||
const name = `main_${treeCollection.name}_path`;
|
||||
const collectionOptions = {
|
||||
name,
|
||||
@ -47,35 +49,16 @@ export default class extends Migration {
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const collectionInstance = this.db.getCollection(treeCollection.name);
|
||||
const treeCollectionSchema = collectionInstance.collectionSchema();
|
||||
|
||||
if (this.app.db.inDialect('postgres') && treeCollectionSchema != this.app.db.options.schema) {
|
||||
collectionOptions['schema'] = treeCollectionSchema;
|
||||
}
|
||||
|
||||
this.app.db.collection(collectionOptions);
|
||||
|
||||
const treeExistsInDb = await this.app.db.getCollection(name).existsInDb({ transaction });
|
||||
|
||||
if (!treeExistsInDb) {
|
||||
await this.app.db.getCollection(name).sync({ transaction } as SyncOptions);
|
||||
const opts = {
|
||||
name: treeCollection.name,
|
||||
autoGenId: false,
|
||||
timestamps: false,
|
||||
fields: [
|
||||
{ type: 'integer', name: 'id' },
|
||||
{ type: 'integer', name: 'parentId' },
|
||||
],
|
||||
};
|
||||
|
||||
if (treeCollectionSchema != this.app.db.options.schema) {
|
||||
opts['schema'] = treeCollectionSchema;
|
||||
}
|
||||
|
||||
this.app.db.collection(opts);
|
||||
const chunkSize = 1000;
|
||||
await this.app.db.getRepository(treeCollection.name).chunk({
|
||||
chunkSize: chunkSize,
|
||||
|
@ -4,7 +4,7 @@
|
||||
"displayName.zh-CN": "数据源:主数据库",
|
||||
"description": "NocoBase main database, supports relational databases such as PostgreSQL, MySQL, MariaDB and so on.",
|
||||
"description.zh-CN": "NocoBase 主数据库,支持 PostgreSQL、MySQL、MariaDB 等关系型数据库。",
|
||||
"version": "1.7.0-alpha.4",
|
||||
"version": "1.7.0-beta.9",
|
||||
"main": "./dist/server/index.js",
|
||||
"homepage": "https://docs.nocobase.com/handbook/data-source-main",
|
||||
"homepage.zh-CN": "https://docs-cn.nocobase.com/handbook/data-source-main",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nocobase/plugin-data-source-manager",
|
||||
"version": "1.7.0-alpha.4",
|
||||
"version": "1.7.0-beta.9",
|
||||
"main": "dist/server/index.js",
|
||||
"displayName": "Data source manager",
|
||||
"displayName.zh-CN": "数据源管理",
|
||||
|
@ -101,7 +101,8 @@ export const RolesResourcesActions = connect((props) => {
|
||||
className={styles}
|
||||
size={'small'}
|
||||
pagination={false}
|
||||
columns={[
|
||||
columns={
|
||||
[
|
||||
{
|
||||
dataIndex: 'displayName',
|
||||
title: t('Action display name'),
|
||||
@ -142,7 +143,8 @@ export const RolesResourcesActions = connect((props) => {
|
||||
/>
|
||||
),
|
||||
},
|
||||
] as TableProps['columns']}
|
||||
] as TableProps['columns']
|
||||
}
|
||||
dataSource={availableActions?.map((item) => {
|
||||
let enabled = false;
|
||||
let scope = null;
|
||||
@ -165,7 +167,8 @@ export const RolesResourcesActions = connect((props) => {
|
||||
className={styles}
|
||||
pagination={false}
|
||||
dataSource={fieldPermissions}
|
||||
columns={[
|
||||
columns={
|
||||
[
|
||||
{
|
||||
dataIndex: ['uiSchema', 'title'],
|
||||
title: t('Field display name'),
|
||||
@ -217,7 +220,8 @@ export const RolesResourcesActions = connect((props) => {
|
||||
),
|
||||
};
|
||||
}),
|
||||
] as TableProps['columns']}
|
||||
] as TableProps['columns']
|
||||
}
|
||||
/>
|
||||
</FormItem>
|
||||
</FormLayout>
|
||||
|
@ -56,7 +56,8 @@ export const StrategyActions = connect((props) => {
|
||||
size={'small'}
|
||||
pagination={false}
|
||||
rowKey={'name'}
|
||||
columns={[
|
||||
columns={
|
||||
[
|
||||
{
|
||||
dataIndex: 'displayName',
|
||||
title: t('Action display name'),
|
||||
@ -110,7 +111,8 @@ export const StrategyActions = connect((props) => {
|
||||
/>
|
||||
),
|
||||
},
|
||||
] as TableProps['columns']}
|
||||
] as TableProps['columns']
|
||||
}
|
||||
dataSource={availableActions?.map((item) => {
|
||||
let scope = 'all';
|
||||
let enabled = false;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user