) => string);
- parentSchemaKey: string;
+ parentSchemaKey?: string;
defaultValue?: any;
useDefaultValue?: () => any;
schema: (defaultValue: any) => ISchema;
valueKeys?: string[];
useVisible?: () => boolean;
+ width?: number | string;
+ useSubmit?: () => (values: any) => void;
}
/**
@@ -38,9 +42,11 @@ export function createModalSettingsItem(options: CreateModalSchemaSettingsItemPr
valueKeys,
schema,
title,
+ useSubmit = useHookDefault,
useVisible,
defaultValue: propsDefaultValue,
useDefaultValue = useHookDefault,
+ width,
} = options;
return {
name,
@@ -50,15 +56,18 @@ export function createModalSettingsItem(options: CreateModalSchemaSettingsItemPr
const fieldSchema = useFieldSchema();
const { deepMerge } = useDesignable();
const defaultValue = useDefaultValue(propsDefaultValue);
- const values = _.get(fieldSchema, parentSchemaKey);
+ const values = parentSchemaKey ? _.get(fieldSchema, parentSchemaKey) : undefined;
const compile = useCompile();
const { t } = useTranslation();
+ const onSubmit = useSubmit();
return {
title: typeof title === 'function' ? title(t) : compile(title),
+ width,
schema: schema({ ...defaultValue, ...values }),
onSubmit(values) {
- deepMerge(getNewSchema({ fieldSchema, schemaKey: parentSchemaKey, value: values, valueKeys }));
+ deepMerge(getNewSchema({ fieldSchema, parentSchemaKey, value: values, valueKeys }));
+ return onSubmit?.(values);
},
};
},
diff --git a/packages/core/client/src/application/schema-settings/utils/createSelectSettingsItem.tsx b/packages/core/client/src/application/schema-settings/utils/createSelectSettingsItem.tsx
index fe392d9890..f4d1be2437 100644
--- a/packages/core/client/src/application/schema-settings/utils/createSelectSettingsItem.tsx
+++ b/packages/core/client/src/application/schema-settings/utils/createSelectSettingsItem.tsx
@@ -9,10 +9,14 @@
import _ from 'lodash';
import { useFieldSchema } from '@formily/react';
-import { SchemaSettingsItemType, SelectProps, useCompile, useDesignable } from '@nocobase/client';
-import { getNewSchema, useHookDefault } from './util';
import { TFunction, useTranslation } from 'react-i18next';
+import { SchemaSettingsItemType } from '../types';
+import { getNewSchema, useHookDefault } from './util';
+import { SelectProps } from '../../../schema-component/antd/select';
+import { useCompile } from '../../../schema-component/hooks/useCompile';
+import { useDesignable } from '../../../schema-component/hooks/useDesignable';
+
interface CreateSelectSchemaSettingsItemProps {
name: string;
title: string | ((t: TFunction<'translation', undefined>) => string);
diff --git a/packages/core/client/src/application/schema-settings/utils/createSwitchSettingsItem.tsx b/packages/core/client/src/application/schema-settings/utils/createSwitchSettingsItem.tsx
index 32177aec32..1dab8683f2 100644
--- a/packages/core/client/src/application/schema-settings/utils/createSwitchSettingsItem.tsx
+++ b/packages/core/client/src/application/schema-settings/utils/createSwitchSettingsItem.tsx
@@ -7,13 +7,15 @@
* For more information, please refer to: https://www.nocobase.com/agreement.
*/
-import { SchemaSettingsItemType, useCompile, useDesignable } from '@nocobase/client';
-import { useFieldSchema } from '@formily/react';
import _ from 'lodash';
-
-import { getNewSchema, useHookDefault } from './util';
+import { useFieldSchema } from '@formily/react';
import { TFunction, useTranslation } from 'react-i18next';
+import { SchemaSettingsItemType } from '../types';
+import { getNewSchema, useHookDefault } from './util';
+import { useCompile } from '../../../schema-component/hooks/useCompile';
+import { useDesignable } from '../../../schema-component/hooks/useDesignable';
+
export interface CreateSwitchSchemaSettingsItemProps {
name: string;
title: string | ((t: TFunction<'translation', undefined>) => string);
diff --git a/packages/core/client/src/application/schema-settings/utils/createTextSettingsItem.tsx b/packages/core/client/src/application/schema-settings/utils/createTextSettingsItem.tsx
new file mode 100644
index 0000000000..d3726c84ea
--- /dev/null
+++ b/packages/core/client/src/application/schema-settings/utils/createTextSettingsItem.tsx
@@ -0,0 +1,39 @@
+/**
+ * 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 { TFunction, useTranslation } from 'react-i18next';
+
+import { useHookDefault } from './util';
+import { SchemaSettingsItemType } from '../types';
+import { useCompile } from '../../../schema-component/hooks/useCompile';
+
+export interface CreateTextSchemaSettingsItemProps {
+ name: string;
+ useVisible?: () => boolean;
+ title: string | ((t: TFunction<'translation', undefined>) => string);
+ useTextClick: () => void;
+}
+
+export function createTextSettingsItem(options: CreateTextSchemaSettingsItemProps): SchemaSettingsItemType {
+ const { name, useVisible, title, useTextClick = useHookDefault } = options;
+ return {
+ name,
+ type: 'item',
+ useVisible,
+ useComponentProps() {
+ const compile = useCompile();
+ const { t } = useTranslation();
+ const onClick = useTextClick();
+ return {
+ title: typeof title === 'function' ? title(t) : compile(title),
+ onClick,
+ };
+ },
+ };
+}
diff --git a/packages/core/client/src/application/schema-settings/utils/index.ts b/packages/core/client/src/application/schema-settings/utils/index.ts
new file mode 100644
index 0000000000..6c220104c8
--- /dev/null
+++ b/packages/core/client/src/application/schema-settings/utils/index.ts
@@ -0,0 +1,13 @@
+/**
+ * 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.
+ */
+
+export * from './createModalSettingsItem';
+export * from './createSelectSettingsItem';
+export * from './createSwitchSettingsItem';
+export * from './createTextSettingsItem';
diff --git a/packages/core/client/src/application/schema-settings/utils/util.ts b/packages/core/client/src/application/schema-settings/utils/util.ts
index e41403e1bb..ef3538dcc1 100644
--- a/packages/core/client/src/application/schema-settings/utils/util.ts
+++ b/packages/core/client/src/application/schema-settings/utils/util.ts
@@ -12,28 +12,24 @@ import _ from 'lodash';
type IGetNewSchema = {
fieldSchema: ISchema;
- schemaKey: string;
+ schemaKey?: string;
+ parentSchemaKey?: string;
value: any;
valueKeys?: string[];
};
export function getNewSchema(options: IGetNewSchema) {
- const { fieldSchema, schemaKey, value, valueKeys } = options as any;
- const schemaKeyArr = schemaKey.split('.');
- const clonedSchema = _.cloneDeep(fieldSchema[schemaKeyArr[0]]);
+ const { fieldSchema, schemaKey, value, parentSchemaKey, valueKeys } = options;
if (value != undefined && typeof value === 'object') {
Object.keys(value).forEach((key) => {
if (valueKeys && !valueKeys.includes(key)) return;
- _.set(clonedSchema, `${schemaKeyArr.slice(1)}.${key}`, value[key]);
+ _.set(fieldSchema, `${parentSchemaKey}.${key}`, value[key]);
});
} else {
- _.set(clonedSchema, schemaKeyArr.slice(1), value);
+ _.set(fieldSchema, schemaKey, value);
}
- return {
- 'x-uid': fieldSchema['x-uid'],
- [schemaKeyArr[0]]: clonedSchema,
- };
+ return fieldSchema;
}
export const useHookDefault = (defaultValues?: any) => defaultValues;
diff --git a/packages/core/client/src/block-provider/hooks/index.ts b/packages/core/client/src/block-provider/hooks/index.ts
index 0cd84c974f..df84a3c970 100644
--- a/packages/core/client/src/block-provider/hooks/index.ts
+++ b/packages/core/client/src/block-provider/hooks/index.ts
@@ -7,6 +7,7 @@
* For more information, please refer to: https://www.nocobase.com/agreement.
*/
+import { css } from '@emotion/css';
import { Field, Form } from '@formily/core';
import { SchemaExpressionScopeContext, useField, useFieldSchema, useForm } from '@formily/react';
import { untracked } from '@formily/reactive';
@@ -21,7 +22,6 @@ import { ChangeEvent, useCallback, useContext, useEffect, useMemo } from 'react'
import { useTranslation } from 'react-i18next';
import { NavigateFunction } from 'react-router-dom';
import { useReactToPrint } from 'react-to-print';
-import { css } from '@emotion/css';
import {
AssociationFilter,
useCollection,
@@ -1582,12 +1582,13 @@ export const useParseURLAndParams = () => {
return { parseURLAndParams };
};
-export function useLinkActionProps() {
+export function useLinkActionProps(componentProps?: any) {
const navigate = useNavigateNoUpdate();
const fieldSchema = useFieldSchema();
+ const componentPropsValue = fieldSchema?.['x-component-props'] || componentProps;
const { t } = useTranslation();
- const url = fieldSchema?.['x-component-props']?.['url'];
- const searchParams = fieldSchema?.['x-component-props']?.['params'] || [];
+ const url = componentPropsValue?.['url'];
+ const searchParams = componentPropsValue?.['params'] || [];
const openInNewWindow = fieldSchema?.['x-component-props']?.['openInNewWindow'];
const { parseURLAndParams } = useParseURLAndParams();
diff --git a/packages/core/client/src/block-provider/index.tsx b/packages/core/client/src/block-provider/index.tsx
index 1547eaf172..558329067e 100644
--- a/packages/core/client/src/block-provider/index.tsx
+++ b/packages/core/client/src/block-provider/index.tsx
@@ -17,3 +17,4 @@ export * from './TableFieldProvider';
export * from './TableSelectorProvider';
export * from './DetailsBlockProvider';
export * from './hooks';
+export { useLinkActionProps } from './hooks/index';
diff --git a/packages/core/client/src/global-theme/index.tsx b/packages/core/client/src/global-theme/index.tsx
index 592f50642b..d809657a39 100644
--- a/packages/core/client/src/global-theme/index.tsx
+++ b/packages/core/client/src/global-theme/index.tsx
@@ -9,7 +9,7 @@
import { ConfigProvider, theme as antdTheme } from 'antd';
import _ from 'lodash';
-import React, { createContext, useCallback, useMemo, useRef } from 'react';
+import React, { createContext, FC, useCallback, useMemo, useRef } from 'react';
import compatOldTheme from './compatOldTheme';
import { addCustomAlgorithmToTheme } from './customAlgorithm';
import defaultTheme from './defaultTheme';
@@ -41,7 +41,11 @@ export const useGlobalTheme = () => {
return React.useContext(GlobalThemeContext) || ({ theme: {}, isDarkTheme: false } as GlobalThemeContextProps);
};
-export const GlobalThemeProvider = ({ children, theme: themeFromProps }) => {
+interface GlobalThemeProviderProps {
+ theme?: ThemeConfig;
+}
+
+export const GlobalThemeProvider: FC
= ({ children, theme: themeFromProps }) => {
const [theme, setTheme] = React.useState(themeFromProps || defaultTheme);
const currentSettingThemeRef = useRef(null);
const currentEditingThemeRef = useRef(null);
diff --git a/packages/core/client/src/index.ts b/packages/core/client/src/index.ts
index d2284473cd..f6dbc4f821 100644
--- a/packages/core/client/src/index.ts
+++ b/packages/core/client/src/index.ts
@@ -70,5 +70,6 @@ export * from './modules/blocks/data-blocks/table';
export * from './modules/blocks/data-blocks/table-selector';
export * from './modules/blocks/index';
export * from './modules/blocks/useParentRecordCommon';
+export { OpenModeProvider, useOpenModeContext } from './modules/popup/OpenModeProvider';
export { VariablePopupRecordProvider } from './modules/variable/variablesProvider/VariablePopupRecordProvider';
diff --git a/packages/core/client/src/modules/actions/add-child/CreateChildInitializer.tsx b/packages/core/client/src/modules/actions/add-child/CreateChildInitializer.tsx
index c42d3a2fc5..06b7cf539e 100644
--- a/packages/core/client/src/modules/actions/add-child/CreateChildInitializer.tsx
+++ b/packages/core/client/src/modules/actions/add-child/CreateChildInitializer.tsx
@@ -11,7 +11,9 @@ import React from 'react';
import { usePagePopup } from '../../../schema-component/antd/page/pagePopupUtils';
import { CONTEXT_SCHEMA_KEY } from '../../../schema-component/antd/page/usePopupContextInActionOrAssociationField';
import { ActionInitializerItem } from '../../../schema-initializer/items/ActionInitializerItem';
+import { useOpenModeContext } from '../../popup/OpenModeProvider';
export const CreateChildInitializer = (props) => {
+ const { defaultOpenMode } = useOpenModeContext();
const { getPopupContext } = usePagePopup();
const schema = {
type: 'void',
@@ -22,7 +24,7 @@ export const CreateChildInitializer = (props) => {
'x-component': 'Action',
'x-visible': '{{treeTable}}',
'x-component-props': {
- openMode: 'drawer',
+ openMode: defaultOpenMode,
type: 'link',
addChild: true,
style: { height: 'auto', lineHeight: 'normal' },
diff --git a/packages/core/client/src/modules/actions/add-child/addChildActionSettings.tsx b/packages/core/client/src/modules/actions/add-child/addChildActionSettings.tsx
index c69de3eb8a..bb2d13bacf 100644
--- a/packages/core/client/src/modules/actions/add-child/addChildActionSettings.tsx
+++ b/packages/core/client/src/modules/actions/add-child/addChildActionSettings.tsx
@@ -7,14 +7,14 @@
* For more information, please refer to: https://www.nocobase.com/agreement.
*/
-import { useFieldSchema } from '@formily/react';
import { useMemo } from 'react';
import { useSchemaToolbar } from '../../../application';
import { SchemaSettings } from '../../../application/schema-settings/SchemaSettings';
import { useCollection_deprecated, useCollectionManager_deprecated } from '../../../collection-manager';
import { ButtonEditor } from '../../../schema-component/antd/action/Action.Designer';
import { SchemaSettingOpenModeSchemaItems } from '../../../schema-items';
-import { SchemaSettingsLinkageRules, SchemaSettingsEnableChildCollections } from '../../../schema-settings';
+import { SchemaSettingsEnableChildCollections, SchemaSettingsLinkageRules } from '../../../schema-settings';
+import { useOpenModeContext } from '../../popup/OpenModeProvider';
export const addChildActionSettings = new SchemaSettings({
name: 'actionSettings:addChild',
@@ -42,9 +42,12 @@ export const addChildActionSettings = new SchemaSettings({
{
name: 'openMode',
Component: SchemaSettingOpenModeSchemaItems,
- componentProps: {
- openMode: true,
- openSize: true,
+ useComponentProps() {
+ const { hideOpenMode } = useOpenModeContext();
+ return {
+ openMode: !hideOpenMode,
+ openSize: !hideOpenMode,
+ };
},
},
{
diff --git a/packages/core/client/src/modules/actions/add-new/CreateActionInitializer.tsx b/packages/core/client/src/modules/actions/add-new/CreateActionInitializer.tsx
index d3b1f21099..2713434cf2 100644
--- a/packages/core/client/src/modules/actions/add-new/CreateActionInitializer.tsx
+++ b/packages/core/client/src/modules/actions/add-new/CreateActionInitializer.tsx
@@ -12,8 +12,10 @@ import { useSchemaInitializerItem } from '../../../application';
import { usePagePopup } from '../../../schema-component/antd/page/pagePopupUtils';
import { CONTEXT_SCHEMA_KEY } from '../../../schema-component/antd/page/usePopupContextInActionOrAssociationField';
import { ActionInitializerItem } from '../../../schema-initializer/items/ActionInitializerItem';
+import { useOpenModeContext } from '../../popup/OpenModeProvider';
export const CreateActionInitializer = () => {
+ const { defaultOpenMode } = useOpenModeContext();
const { getPopupContext } = usePagePopup();
const schema = {
type: 'void',
@@ -25,7 +27,7 @@ export const CreateActionInitializer = () => {
'x-component': 'Action',
'x-decorator': 'ACLActionProvider',
'x-component-props': {
- openMode: 'drawer',
+ openMode: defaultOpenMode,
type: 'primary',
component: 'CreateRecordAction',
icon: 'PlusOutlined',
diff --git a/packages/core/client/src/modules/actions/add-new/addNewActionSettings.tsx b/packages/core/client/src/modules/actions/add-new/addNewActionSettings.tsx
index e53c9dd311..f0e79b3eb7 100644
--- a/packages/core/client/src/modules/actions/add-new/addNewActionSettings.tsx
+++ b/packages/core/client/src/modules/actions/add-new/addNewActionSettings.tsx
@@ -14,6 +14,7 @@ import { useCollection_deprecated, useCollectionManager_deprecated } from '../..
import { ButtonEditor, RemoveButton } from '../../../schema-component/antd/action/Action.Designer';
import { SchemaSettingOpenModeSchemaItems } from '../../../schema-items';
import { SchemaSettingsEnableChildCollections } from '../../../schema-settings/SchemaSettings';
+import { useOpenModeContext } from '../../popup/OpenModeProvider';
export const addNewActionSettings = new SchemaSettings({
name: 'actionSettings:addNew',
@@ -29,9 +30,12 @@ export const addNewActionSettings = new SchemaSettings({
{
name: 'openMode',
Component: SchemaSettingOpenModeSchemaItems,
- componentProps: {
- openMode: true,
- openSize: true,
+ useComponentProps() {
+ const { hideOpenMode } = useOpenModeContext();
+ return {
+ openMode: !hideOpenMode,
+ openSize: !hideOpenMode,
+ };
},
},
{
diff --git a/packages/core/client/src/modules/actions/add-record/customizeAddRecordActionSettings.tsx b/packages/core/client/src/modules/actions/add-record/customizeAddRecordActionSettings.tsx
index 25476a2331..5bb83ac04c 100644
--- a/packages/core/client/src/modules/actions/add-record/customizeAddRecordActionSettings.tsx
+++ b/packages/core/client/src/modules/actions/add-record/customizeAddRecordActionSettings.tsx
@@ -11,6 +11,7 @@ import { useSchemaToolbar } from '../../../application';
import { SchemaSettings } from '../../../application/schema-settings/SchemaSettings';
import { ButtonEditor, RemoveButton } from '../../../schema-component/antd/action/Action.Designer';
import { SchemaSettingOpenModeSchemaItems } from '../../../schema-items';
+import { useOpenModeContext } from '../../popup/OpenModeProvider';
export const customizeAddRecordActionSettings = new SchemaSettings({
name: 'actionSettings:addRecord',
@@ -26,9 +27,12 @@ export const customizeAddRecordActionSettings = new SchemaSettings({
{
name: 'openMode',
Component: SchemaSettingOpenModeSchemaItems,
- componentProps: {
- openMode: true,
- openSize: true,
+ useComponentProps() {
+ const { hideOpenMode } = useOpenModeContext();
+ return {
+ openMode: !hideOpenMode,
+ openSize: !hideOpenMode,
+ };
},
},
{
diff --git a/packages/core/client/src/modules/actions/link/customizeLinkActionSettings.tsx b/packages/core/client/src/modules/actions/link/customizeLinkActionSettings.tsx
index 5d23ba1386..7bbf375e39 100644
--- a/packages/core/client/src/modules/actions/link/customizeLinkActionSettings.tsx
+++ b/packages/core/client/src/modules/actions/link/customizeLinkActionSettings.tsx
@@ -9,7 +9,7 @@
import { ArrayItems } from '@formily/antd-v5';
import { useField, useFieldSchema } from '@formily/react';
import _ from 'lodash';
-import React from 'react';
+import React, { FC } from 'react';
import { useTranslation } from 'react-i18next';
import { useCollectionRecord, useDesignable } from '../../../';
import { useSchemaToolbar } from '../../../application';
@@ -19,7 +19,11 @@ import { ButtonEditor, RemoveButton } from '../../../schema-component/antd/actio
import { SchemaSettingsLinkageRules, SchemaSettingsModalItem } from '../../../schema-settings';
import { useURLAndHTMLSchema } from './useURLAndHTMLSchema';
-export function SchemaSettingsActionLinkItem() {
+interface SchemaSettingsActionLinkItemProps {
+ afterSubmit?: () => void;
+}
+
+export const SchemaSettingsActionLinkItem: FC = ({ afterSubmit }) => {
const field = useField();
const fieldSchema = useFieldSchema();
const { dn } = useDesignable();
@@ -66,11 +70,12 @@ export function SchemaSettingsActionLinkItem() {
},
});
dn.refresh();
+ afterSubmit?.();
}}
initialValues={initialValues}
/>
);
-}
+};
export const customizeLinkActionSettings = new SchemaSettings({
name: 'actionSettings:link',
diff --git a/packages/core/client/src/modules/actions/view-edit-popup/PopupActionInitializer.tsx b/packages/core/client/src/modules/actions/view-edit-popup/PopupActionInitializer.tsx
index 2c930cf550..c908c742c8 100644
--- a/packages/core/client/src/modules/actions/view-edit-popup/PopupActionInitializer.tsx
+++ b/packages/core/client/src/modules/actions/view-edit-popup/PopupActionInitializer.tsx
@@ -12,8 +12,10 @@ import { useSchemaInitializerItem } from '../../../application';
import { usePagePopup } from '../../../schema-component/antd/page/pagePopupUtils';
import { CONTEXT_SCHEMA_KEY } from '../../../schema-component/antd/page/usePopupContextInActionOrAssociationField';
import { BlockInitializer } from '../../../schema-initializer/items';
+import { useOpenModeContext } from '../../popup/OpenModeProvider';
export const PopupActionInitializer = (props) => {
+ const { defaultOpenMode } = useOpenModeContext();
const { getPopupContext } = usePagePopup();
const schema = {
type: 'void',
@@ -23,7 +25,7 @@ export const PopupActionInitializer = (props) => {
'x-settings': 'actionSettings:popup',
'x-component': props?.['x-component'] || 'Action.Link',
'x-component-props': {
- openMode: 'drawer',
+ openMode: defaultOpenMode,
refreshDataBlockRequest: true,
},
properties: {
diff --git a/packages/core/client/src/modules/actions/view-edit-popup/UpdateActionInitializer.tsx b/packages/core/client/src/modules/actions/view-edit-popup/UpdateActionInitializer.tsx
index 094db370ba..2d395d846b 100644
--- a/packages/core/client/src/modules/actions/view-edit-popup/UpdateActionInitializer.tsx
+++ b/packages/core/client/src/modules/actions/view-edit-popup/UpdateActionInitializer.tsx
@@ -11,8 +11,10 @@ import React from 'react';
import { usePagePopup } from '../../../schema-component/antd/page/pagePopupUtils';
import { CONTEXT_SCHEMA_KEY } from '../../../schema-component/antd/page/usePopupContextInActionOrAssociationField';
import { ActionInitializerItem } from '../../../schema-initializer/items/ActionInitializerItem';
+import { useOpenModeContext } from '../../popup/OpenModeProvider';
export const UpdateActionInitializer = (props) => {
+ const { defaultOpenMode } = useOpenModeContext();
const { getPopupContext } = usePagePopup();
const schema = {
type: 'void',
@@ -22,7 +24,7 @@ export const UpdateActionInitializer = (props) => {
'x-settings': 'actionSettings:edit',
'x-component': 'Action',
'x-component-props': {
- openMode: 'drawer',
+ openMode: defaultOpenMode,
icon: 'EditOutlined',
},
properties: {
diff --git a/packages/core/client/src/modules/actions/view-edit-popup/ViewActionInitializer.tsx b/packages/core/client/src/modules/actions/view-edit-popup/ViewActionInitializer.tsx
index e24f7120fc..3324842450 100644
--- a/packages/core/client/src/modules/actions/view-edit-popup/ViewActionInitializer.tsx
+++ b/packages/core/client/src/modules/actions/view-edit-popup/ViewActionInitializer.tsx
@@ -11,8 +11,10 @@ import React from 'react';
import { usePagePopup } from '../../../schema-component/antd/page/pagePopupUtils';
import { CONTEXT_SCHEMA_KEY } from '../../../schema-component/antd/page/usePopupContextInActionOrAssociationField';
import { ActionInitializerItem } from '../../../schema-initializer/items/ActionInitializerItem';
+import { useOpenModeContext } from '../../popup/OpenModeProvider';
export const ViewActionInitializer = (props) => {
+ const { defaultOpenMode } = useOpenModeContext();
const { getPopupContext } = usePagePopup();
const schema = {
type: 'void',
@@ -22,7 +24,7 @@ export const ViewActionInitializer = (props) => {
'x-settings': 'actionSettings:view',
'x-component': 'Action',
'x-component-props': {
- openMode: 'drawer',
+ openMode: defaultOpenMode,
},
properties: {
drawer: {
diff --git a/packages/core/client/src/modules/actions/view-edit-popup/customizePopupActionSettings.tsx b/packages/core/client/src/modules/actions/view-edit-popup/customizePopupActionSettings.tsx
index d88525acd6..bb8a34a452 100644
--- a/packages/core/client/src/modules/actions/view-edit-popup/customizePopupActionSettings.tsx
+++ b/packages/core/client/src/modules/actions/view-edit-popup/customizePopupActionSettings.tsx
@@ -10,13 +10,10 @@
import { useSchemaToolbar } from '../../../application';
import { SchemaSettings } from '../../../application/schema-settings/SchemaSettings';
import { useCollection_deprecated } from '../../../collection-manager';
-import {
- ButtonEditor,
- RemoveButton,
- RefreshDataBlockRequest,
-} from '../../../schema-component/antd/action/Action.Designer';
+import { ButtonEditor, RemoveButton } from '../../../schema-component/antd/action/Action.Designer';
import { SchemaSettingOpenModeSchemaItems } from '../../../schema-items';
import { SchemaSettingsLinkageRules } from '../../../schema-settings';
+import { useOpenModeContext } from '../../popup/OpenModeProvider';
export const customizePopupActionSettings = new SchemaSettings({
name: 'actionSettings:popup',
@@ -44,9 +41,12 @@ export const customizePopupActionSettings = new SchemaSettings({
{
name: 'openMode',
Component: SchemaSettingOpenModeSchemaItems,
- componentProps: {
- openMode: true,
- openSize: true,
+ useComponentProps() {
+ const { hideOpenMode } = useOpenModeContext();
+ return {
+ openMode: !hideOpenMode,
+ openSize: !hideOpenMode,
+ };
},
},
{
diff --git a/packages/core/client/src/modules/actions/view-edit-popup/editActionSettings.tsx b/packages/core/client/src/modules/actions/view-edit-popup/editActionSettings.tsx
index 2531d1a3fd..863a0a431d 100644
--- a/packages/core/client/src/modules/actions/view-edit-popup/editActionSettings.tsx
+++ b/packages/core/client/src/modules/actions/view-edit-popup/editActionSettings.tsx
@@ -13,6 +13,7 @@ import { useCollection_deprecated } from '../../../collection-manager';
import { ButtonEditor } from '../../../schema-component/antd/action/Action.Designer';
import { SchemaSettingOpenModeSchemaItems } from '../../../schema-items';
import { SchemaSettingsLinkageRules } from '../../../schema-settings';
+import { useOpenModeContext } from '../../popup/OpenModeProvider';
export const editActionSettings = new SchemaSettings({
name: 'actionSettings:edit',
@@ -40,9 +41,12 @@ export const editActionSettings = new SchemaSettings({
{
name: 'openMode',
Component: SchemaSettingOpenModeSchemaItems,
- componentProps: {
- openMode: true,
- openSize: true,
+ useComponentProps() {
+ const { hideOpenMode } = useOpenModeContext();
+ return {
+ openMode: !hideOpenMode,
+ openSize: !hideOpenMode,
+ };
},
},
{
diff --git a/packages/core/client/src/modules/actions/view-edit-popup/viewActionSettings.tsx b/packages/core/client/src/modules/actions/view-edit-popup/viewActionSettings.tsx
index 7d705b93e1..7e67a50561 100644
--- a/packages/core/client/src/modules/actions/view-edit-popup/viewActionSettings.tsx
+++ b/packages/core/client/src/modules/actions/view-edit-popup/viewActionSettings.tsx
@@ -13,6 +13,7 @@ import { useCollection_deprecated } from '../../../collection-manager';
import { ButtonEditor, RemoveButton } from '../../../schema-component/antd/action/Action.Designer';
import { SchemaSettingOpenModeSchemaItems } from '../../../schema-items';
import { SchemaSettingsLinkageRules } from '../../../schema-settings';
+import { useOpenModeContext } from '../../popup/OpenModeProvider';
export const viewActionSettings = new SchemaSettings({
name: 'actionSettings:view',
@@ -40,9 +41,12 @@ export const viewActionSettings = new SchemaSettings({
{
name: 'openMode',
Component: SchemaSettingOpenModeSchemaItems,
- componentProps: {
- openMode: true,
- openSize: true,
+ useComponentProps() {
+ const { hideOpenMode } = useOpenModeContext();
+ return {
+ openMode: !hideOpenMode,
+ openSize: !hideOpenMode,
+ };
},
},
{
diff --git a/packages/core/client/src/modules/fields/component/Select/selectComponentFieldSettings.tsx b/packages/core/client/src/modules/fields/component/Select/selectComponentFieldSettings.tsx
index 2701d6762b..9b3f2970e3 100644
--- a/packages/core/client/src/modules/fields/component/Select/selectComponentFieldSettings.tsx
+++ b/packages/core/client/src/modules/fields/component/Select/selectComponentFieldSettings.tsx
@@ -33,6 +33,7 @@ import { SchemaSettingsDataScope } from '../../../../schema-settings/SchemaSetti
import { SchemaSettingsSortingRule } from '../../../../schema-settings/SchemaSettingsSortingRule';
import { useIsShowMultipleSwitch } from '../../../../schema-settings/hooks/useIsShowMultipleSwitch';
import { useLocalVariables, useVariables } from '../../../../variables';
+import { useOpenModeContext } from '../../../popup/OpenModeProvider';
const enableLink = {
name: 'enableLink',
@@ -162,6 +163,7 @@ const quickCreate: any = {
name: 'quickCreate',
type: 'select',
useComponentProps() {
+ const { defaultOpenMode } = useOpenModeContext();
const { t } = useTranslation();
const field = useField();
const fieldSchema = useFieldSchema();
@@ -194,7 +196,7 @@ const quickCreate: any = {
'x-component': 'Action',
'x-decorator': 'ACLActionProvider',
'x-component-props': {
- openMode: 'drawer',
+ openMode: defaultOpenMode,
type: 'default',
component: 'CreateRecordAction',
},
diff --git a/packages/core/client/src/modules/popup/OpenModeProvider.tsx b/packages/core/client/src/modules/popup/OpenModeProvider.tsx
new file mode 100644
index 0000000000..a3d102e8fe
--- /dev/null
+++ b/packages/core/client/src/modules/popup/OpenModeProvider.tsx
@@ -0,0 +1,99 @@
+/**
+ * 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 React, { FC, useCallback, useMemo } from 'react';
+import ActionDrawer from '../../schema-component/antd/action/Action.Drawer';
+import ActionModal from '../../schema-component/antd/action/Action.Modal';
+import ActionPage from '../../schema-component/antd/action/Action.Page';
+
+type OpenMode = 'drawer' | 'page' | 'modal';
+
+interface OpenModeProviderProps {
+ /**
+ * @default 'drawer'
+ * open mode 的全局默认值
+ */
+ defaultOpenMode?: OpenMode;
+ /**
+ * @default { drawer: ActionDrawer, page: ActionPage, modal: ActionModal }
+ * 根据 open mode 获取对应的组件
+ */
+ openModeToComponent?: Partial>;
+ /**
+ * @default false
+ * 隐藏 open mode 的配置选项
+ */
+ hideOpenMode?: boolean;
+}
+
+const defaultContext: OpenModeProviderProps = {
+ defaultOpenMode: 'drawer',
+ openModeToComponent: {
+ drawer: ActionDrawer,
+ page: ActionPage,
+ modal: ActionModal,
+ },
+ hideOpenMode: false,
+};
+
+const OpenModeContext = React.createContext<{
+ defaultOpenMode: OpenModeProviderProps['defaultOpenMode'];
+ hideOpenMode: boolean;
+ getComponentByOpenMode: (openMode: OpenMode) => any;
+}>(null);
+
+/**
+ * 为按钮的 Open mode 选项提供上下文
+ * @param props
+ * @returns
+ */
+export const OpenModeProvider: FC = (props) => {
+ const context = useMemo(() => {
+ const result = { ...defaultContext };
+
+ if (props.defaultOpenMode !== undefined) {
+ result.defaultOpenMode = props.defaultOpenMode;
+ }
+ if (props.openModeToComponent !== undefined) {
+ result.openModeToComponent = props.openModeToComponent;
+ }
+ if (props.hideOpenMode !== undefined) {
+ result.hideOpenMode = props.hideOpenMode;
+ }
+
+ return result;
+ }, [props.defaultOpenMode, props.openModeToComponent, props.hideOpenMode]);
+
+ const getComponentByOpenMode = useCallback(
+ (openMode: OpenMode) => {
+ const result = context.openModeToComponent[openMode];
+
+ if (!result) {
+ console.error(`OpenModeProvider: openModeToComponent[${openMode}] is not defined`);
+ }
+
+ return result;
+ },
+ [context],
+ );
+
+ const value = useMemo(() => {
+ return {
+ defaultOpenMode: context.defaultOpenMode,
+ hideOpenMode: context.hideOpenMode,
+ getComponentByOpenMode,
+ };
+ }, [context.defaultOpenMode, context.hideOpenMode, getComponentByOpenMode]);
+
+ return {props.children};
+};
+
+export const useOpenModeContext = () => {
+ return React.useContext(OpenModeContext);
+};
diff --git a/packages/core/client/src/pm/PluginManagerLink.tsx b/packages/core/client/src/pm/PluginManagerLink.tsx
index 98cefbd363..657cad7f78 100644
--- a/packages/core/client/src/pm/PluginManagerLink.tsx
+++ b/packages/core/client/src/pm/PluginManagerLink.tsx
@@ -47,7 +47,8 @@ export const SettingsCenterDropdown = () => {
return {
key: setting.name,
icon: setting.icon,
- label: {compile(setting.title)},
+ label: setting.link ? window.open(setting.link)}>{compile(setting.title)}
:
+ {compile(setting.title)}
};
});
}, [app, t]);
diff --git a/packages/core/client/src/pm/PluginSetting.tsx b/packages/core/client/src/pm/PluginSetting.tsx
index 69bab956b7..96577e8a63 100644
--- a/packages/core/client/src/pm/PluginSetting.tsx
+++ b/packages/core/client/src/pm/PluginSetting.tsx
@@ -144,6 +144,12 @@ export const AdminSettingsLayout = () => {
style={{ height: 'calc(100vh - 46px)', overflowY: 'auto', overflowX: 'hidden' }}
onClick={({ key }) => {
const plugin = settings.find((item) => item.name === key);
+
+ if (plugin.link) {
+ window.open(plugin.link, '_blank');
+ return;
+ }
+
if (plugin.children?.length) {
return navigate(getFirstDeepChildPath(plugin.children));
} else {
diff --git a/packages/core/client/src/schema-component/antd/action/Action.Container.tsx b/packages/core/client/src/schema-component/antd/action/Action.Container.tsx
index 6033ebb988..8e4f48f83a 100644
--- a/packages/core/client/src/schema-component/antd/action/Action.Container.tsx
+++ b/packages/core/client/src/schema-component/antd/action/Action.Container.tsx
@@ -10,21 +10,19 @@
import { observer, RecursionField, useField, useFieldSchema } from '@formily/react';
import React from 'react';
import { useActionContext } from '.';
-import { ActionDrawer } from './Action.Drawer';
-import { ActionModal } from './Action.Modal';
-import { ActionPage } from './Action.Page';
+import { useOpenModeContext } from '../../../modules/popup/OpenModeProvider';
+import { useCurrentPopupContext } from '../page/PagePopups';
import { ComposedActionDrawer } from './types';
export const ActionContainer: ComposedActionDrawer = observer(
(props: any) => {
const { openMode } = useActionContext();
- if (openMode === 'drawer') {
- return ;
- }
- if (openMode === 'modal') {
- return ;
- }
- return ;
+ const { getComponentByOpenMode } = useOpenModeContext();
+ const { currentLevel } = useCurrentPopupContext();
+
+ const Component = getComponentByOpenMode(openMode);
+
+ return ;
},
{ displayName: 'ActionContainer' },
);
diff --git a/packages/core/client/src/schema-component/antd/action/Action.Designer.tsx b/packages/core/client/src/schema-component/antd/action/Action.Designer.tsx
index d39603c45d..5862d10a37 100644
--- a/packages/core/client/src/schema-component/antd/action/Action.Designer.tsx
+++ b/packages/core/client/src/schema-component/antd/action/Action.Designer.tsx
@@ -28,6 +28,7 @@ import {
import { DataSourceProvider, useDataSourceKey } from '../../../data-source';
import { FlagProvider } from '../../../flag-provider';
import { SaveMode } from '../../../modules/actions/submit/createSubmitActionSettings';
+import { useOpenModeContext } from '../../../modules/popup/OpenModeProvider';
import { SchemaSettingOpenModeSchemaItems } from '../../../schema-items';
import { GeneralSchemaDesigner } from '../../../schema-settings/GeneralSchemaDesigner';
import {
@@ -656,6 +657,7 @@ export const actionSettingsItems: SchemaSettingOptions['items'] = [
name: 'openMode',
Component: SchemaSettingOpenModeSchemaItems,
useComponentProps() {
+ const { hideOpenMode } = useOpenModeContext();
const fieldSchema = useFieldSchema();
const isPopupAction = [
'create',
@@ -667,8 +669,8 @@ export const actionSettingsItems: SchemaSettingOptions['items'] = [
].includes(fieldSchema['x-action'] || '');
return {
- openMode: isPopupAction,
- openSize: isPopupAction,
+ openMode: isPopupAction && !hideOpenMode,
+ openSize: isPopupAction && !hideOpenMode,
};
},
},
diff --git a/packages/core/client/src/schema-component/antd/action/Action.Page.tsx b/packages/core/client/src/schema-component/antd/action/Action.Page.tsx
index 4565e60584..e06898c3e6 100644
--- a/packages/core/client/src/schema-component/antd/action/Action.Page.tsx
+++ b/packages/core/client/src/schema-component/antd/action/Action.Page.tsx
@@ -11,25 +11,26 @@ import { RecursionField, observer, useFieldSchema } from '@formily/react';
import React, { useMemo } from 'react';
import { createPortal } from 'react-dom';
import { useActionContext } from '.';
-import { useCurrentPopupContext } from '../page/PagePopups';
+import { BackButtonUsedInSubPage } from '../page/BackButtonUsedInSubPage';
+import { TabsContextProvider, useTabsContext } from '../tabs/context';
import { useActionPageStyle } from './Action.Page.style';
import { usePopupOrSubpagesContainerDOM } from './hooks/usePopupSlotDOM';
import { ComposedActionDrawer } from './types';
export const ActionPage: ComposedActionDrawer = observer(
- () => {
+ ({ level }) => {
const filedSchema = useFieldSchema();
const ctx = useActionContext();
const { getContainerDOM } = usePopupOrSubpagesContainerDOM();
const { styles } = useActionPageStyle();
- const { currentLevel } = useCurrentPopupContext();
+ const tabContext = useTabsContext();
const style = useMemo(() => {
return {
// 20 is the z-index value of the main page
- zIndex: 20 + currentLevel,
+ zIndex: 20 + level,
};
- }, [currentLevel]);
+ }, [level]);
if (!ctx.visible) {
return null;
@@ -37,11 +38,19 @@ export const ActionPage: ComposedActionDrawer = observer(
const actionPageNode = (
-
+ }>
+
+
);
- return createPortal(actionPageNode, getContainerDOM());
+ const container = getContainerDOM();
+
+ if (container) {
+ return createPortal(actionPageNode, container);
+ }
+
+ return actionPageNode;
},
{ displayName: 'ActionPage' },
);
diff --git a/packages/core/client/src/schema-component/antd/action/ActionBar.tsx b/packages/core/client/src/schema-component/antd/action/ActionBar.tsx
index b91552960b..9e8e8dfb92 100644
--- a/packages/core/client/src/schema-component/antd/action/ActionBar.tsx
+++ b/packages/core/client/src/schema-component/antd/action/ActionBar.tsx
@@ -79,7 +79,7 @@ export const ActionBar = withDynamicSchemaProps(
>
{props.children && (
-
+
{fieldSchema.mapProperties((schema, key) => {
return ;
})}
@@ -129,7 +129,7 @@ export const ActionBar = withDynamicSchemaProps(
return ;
})}
-
+
{fieldSchema.mapProperties((schema, key) => {
if (schema['x-align'] === 'left') {
return null;
diff --git a/packages/core/client/src/schema-component/antd/action/types.ts b/packages/core/client/src/schema-component/antd/action/types.ts
index 78484c1814..af5cbaf24b 100644
--- a/packages/core/client/src/schema-component/antd/action/types.ts
+++ b/packages/core/client/src/schema-component/antd/action/types.ts
@@ -87,7 +87,11 @@ export type ComposedAction = React.FC & {
[key: string]: any;
};
-export type ActionDrawerProps = T & { footerNodeName?: string };
+export type ActionDrawerProps = T & {
+ footerNodeName?: string;
+ /** 当前弹窗嵌套的层级 */
+ level?: number;
+};
export type ComposedActionDrawer = React.FC> & {
Footer?: React.FC;
diff --git a/packages/core/client/src/schema-component/antd/association-field/InternalViewer.tsx b/packages/core/client/src/schema-component/antd/association-field/InternalViewer.tsx
index f33f496904..153e4b8f8e 100644
--- a/packages/core/client/src/schema-component/antd/association-field/InternalViewer.tsx
+++ b/packages/core/client/src/schema-component/antd/association-field/InternalViewer.tsx
@@ -13,6 +13,7 @@ import React, { FC, Fragment, useRef, useState } from 'react';
import { useDesignable } from '../../';
import { WithoutTableFieldResource } from '../../../block-provider';
import { useCollectionManager, useCollectionRecordData } from '../../../data-source';
+import { useOpenModeContext } from '../../../modules/popup/OpenModeProvider';
import { VariablePopupRecordProvider } from '../../../modules/variable/variablesProvider/VariablePopupRecordProvider';
import { useCompile } from '../../hooks';
import { ActionContextProvider, useActionContext } from '../action';
@@ -139,6 +140,7 @@ export const ReadPrettyInternalViewer: React.FC = observer(
const ellipsisWithTooltipRef = useRef();
const { visibleWithURL, setVisibleWithURL } = usePagePopup();
const [btnHover, setBtnHover] = useState(!!visibleWithURL);
+ const { defaultOpenMode } = useOpenModeContext();
const btnElement = (
@@ -175,7 +177,7 @@ export const ReadPrettyInternalViewer: React.FC = observer(
setVisible?.(value);
setVisibleWithURL?.(value);
},
- openMode: 'drawer',
+ openMode: defaultOpenMode,
snapshot: collectionField?.interface === 'snapshot',
fieldSchema: fieldSchema,
}}
diff --git a/packages/core/client/src/schema-component/antd/block-item/BlockItem.tsx b/packages/core/client/src/schema-component/antd/block-item/BlockItem.tsx
index 1b348571d5..39facb63b8 100644
--- a/packages/core/client/src/schema-component/antd/block-item/BlockItem.tsx
+++ b/packages/core/client/src/schema-component/antd/block-item/BlockItem.tsx
@@ -73,13 +73,14 @@ const useStyles = createStyles(({ css, token }: CustomCreateStylesUtils) => {
export interface BlockItemProps {
name?: string;
className?: string;
+ style?: React.CSSProperties;
children?: React.ReactNode;
}
export const BlockItem: React.FC = withDynamicSchemaProps(
(props) => {
// 新版 UISchema(1.0 之后)中已经废弃了 useProps,这里之所以继续保留是为了兼容旧版的 UISchema
- const { className, children } = useProps(props);
+ const { className, children, style } = useProps(props);
const { styles: blockItemCss } = useStyles();
const fieldSchema = useFieldSchema();
const { render } = useSchemaToolbarRender(fieldSchema);
@@ -87,7 +88,12 @@ export const BlockItem: React.FC = withDynamicSchemaProps(
const label = useMemo(() => getAriaLabel(), [getAriaLabel]);
return (
-
+
{render()}
console.log(err)}>
{children}
diff --git a/packages/core/client/src/schema-component/antd/color-select/ColorSelect.tsx b/packages/core/client/src/schema-component/antd/color-select/ColorSelect.tsx
index 7324b4dae7..98dcba09b1 100644
--- a/packages/core/client/src/schema-component/antd/color-select/ColorSelect.tsx
+++ b/packages/core/client/src/schema-component/antd/color-select/ColorSelect.tsx
@@ -13,7 +13,7 @@ import { Select, SelectProps, Tag } from 'antd';
import React from 'react';
import { useCompile } from '../../hooks/useCompile';
-const colors = {
+const defaultColors = {
red: '{{t("Red")}}',
magenta: '{{t("Magenta")}}',
volcano: '{{t("Volcano")}}',
@@ -30,13 +30,15 @@ const colors = {
export interface ColorSelectProps extends SelectProps {
suffix?: React.ReactNode;
+ colors?: Record;
}
export const ColorSelect = connect(
(props: ColorSelectProps) => {
const compile = useCompile();
+ const { colors = defaultColors, ...selectProps } = props;
return (
-