diff --git a/packages/core/client/src/block-provider/hooks/index.ts b/packages/core/client/src/block-provider/hooks/index.ts index a7747989d..4380c4d19 100644 --- a/packages/core/client/src/block-provider/hooks/index.ts +++ b/packages/core/client/src/block-provider/hooks/index.ts @@ -1,4 +1,6 @@ +import { Field, Form } from '@formily/core'; import { SchemaExpressionScopeContext, useField, useFieldSchema, useForm } from '@formily/react'; +import { untracked } from '@formily/reactive'; import { isURL, parse } from '@nocobase/utils/client'; import { App, message } from 'antd'; import _ from 'lodash'; @@ -23,6 +25,7 @@ import { useFilterBlock } from '../../filter-provider/FilterProvider'; import { mergeFilter, transformToFilter } from '../../filter-provider/utils'; import { useRecord } from '../../record-provider'; import { removeNullCondition, useActionContext, useCompile } from '../../schema-component'; +import { isSubMode } from '../../schema-component/antd/association-field/util'; import { useCurrentUserContext } from '../../user'; import { useLocalVariables, useVariables } from '../../variables'; import { isVariable } from '../../variables/utils/isVariable'; @@ -30,9 +33,6 @@ import { transformVariableValue } from '../../variables/utils/transformVariableV import { useBlockRequestContext, useFilterByTk, useParamsFromRecord } from '../BlockProvider'; import { useDetailsBlockContext } from '../DetailsBlockProvider'; import { TableFieldResource } from '../TableFieldProvider'; -import { Field, Form } from '@formily/core'; -import { untracked } from '@formily/reactive'; -import { isSubMode } from '../../schema-component/antd/association-field/util'; export * from './useFormActiveFields'; export * from './useParsedFilter'; @@ -965,6 +965,34 @@ export const useRemoveActionProps = (associationName) => { }; }; +export const useDisassociateActionProps = () => { + const filterByTk = useFilterByTk(); + const { resource, service, block, __parent } = useBlockRequestContext(); + const { setVisible } = useActionContext(); + return { + async onClick() { + await resource.remove({ + values: [filterByTk], + }); + + const { count = 0, page = 0, pageSize = 0 } = service?.data?.meta || {}; + if (count % pageSize === 1 && page !== 1) { + service.run({ + ...service?.params?.[0], + page: page - 1, + }); + } else { + service?.refresh?.(); + } + + if (block && block !== 'TableField') { + __parent?.service?.refresh?.(); + setVisible?.(false); + } + }, + }; +}; + export const useDetailPrintActionProps = () => { const { formBlockRef } = useFormBlockContext(); diff --git a/packages/core/client/src/locale/en_US.json b/packages/core/client/src/locale/en_US.json index cc614f0c9..08efa19f4 100644 --- a/packages/core/client/src/locale/en_US.json +++ b/packages/core/client/src/locale/en_US.json @@ -53,6 +53,9 @@ "Insert right": "Insert right", "Insert inner": "Insert inner", "Delete": "Delete", + "Disassociate": "Disassociate", + "Disassociate record": "Disassociate record", + "Are you sure you want to disassociate it?": "Are you sure you want to disassociate it?", "UI editor": "UI editor", "Collection": "Collection", "Collection selector": "Collection selector", diff --git a/packages/core/client/src/locale/es_ES.json b/packages/core/client/src/locale/es_ES.json index d60ad1632..e2e5dfcfe 100644 --- a/packages/core/client/src/locale/es_ES.json +++ b/packages/core/client/src/locale/es_ES.json @@ -52,6 +52,9 @@ "Insert right": "Insertar a la derecha", "Insert inner": "Insertar al interior", "Delete": "Borrar", + "Disassociate": "Desasociar", + "Disassociate record": "Desasociar registro", + "Are you sure you want to disassociate it?": "¿Seguro que quieres desasociarlo?", "UI editor": "IU editor", "Collection": "Colección", "Collections & Fields": "Colección & Campos", diff --git a/packages/core/client/src/locale/fr_FR.json b/packages/core/client/src/locale/fr_FR.json index 257ae5c2d..06025ca41 100644 --- a/packages/core/client/src/locale/fr_FR.json +++ b/packages/core/client/src/locale/fr_FR.json @@ -52,6 +52,9 @@ "Insert right": "Insérer à droite", "Insert inner": "Insérer à l'intérieur", "Delete": "Supprimer", + "Disassociate": "Dissocier", + "Disassociate record": "Dissocier l'enregistrement", + "Are you sure you want to disassociate it?": "Êtes-vous sûr de vouloir le dissocier ?", "UI editor": "Éditeur d'interface utilisateur", "Collection": "Collection", "Collections & Fields": "Collections et champs", diff --git a/packages/core/client/src/locale/ja_JP.json b/packages/core/client/src/locale/ja_JP.json index b6bd69884..4b3e4cefa 100644 --- a/packages/core/client/src/locale/ja_JP.json +++ b/packages/core/client/src/locale/ja_JP.json @@ -52,6 +52,9 @@ "Insert right": "右に挿入", "Insert inner": "中に挿入", "Delete": "削除", + "Disassociate": "関連付けを解除", + "Disassociate record": "レコードの関連付けを解除", + "Are you sure you want to disassociate it?": "本当に関連付けを解除しますか?", "UI editor": "UI エディタ", "Collection": "コレクション", "Enable child collections": "启用子表", diff --git a/packages/core/client/src/locale/ko_KR.json b/packages/core/client/src/locale/ko_KR.json index f3c00c4e8..c0b8cbd38 100644 --- a/packages/core/client/src/locale/ko_KR.json +++ b/packages/core/client/src/locale/ko_KR.json @@ -60,6 +60,9 @@ "Insert right": "오른쪽에 삽입", "Insert inner": "내부에 삽입", "Delete": "삭제", + "Disassociate": "연결 해제", + "Disassociate record": "레코드 연결 해제", + "Are you sure you want to disassociate it?": "정말로 연결을 해제하시겠습니까?", "UI editor": "UI 편집기", "Collection": "컬렉션", "Collection selector": "컬렉션 선택기", diff --git a/packages/core/client/src/locale/pt_BR.json b/packages/core/client/src/locale/pt_BR.json index 642e79221..693a8250e 100644 --- a/packages/core/client/src/locale/pt_BR.json +++ b/packages/core/client/src/locale/pt_BR.json @@ -32,6 +32,9 @@ "Insert right": "Inserir à direita", "Insert inner": "Inserir interno", "Delete": "Excluir", + "Disassociate": "Desassociar", + "Disassociate record": "Desassociar registro", + "Are you sure you want to disassociate it?": "Tem certeza de que deseja desassociá-lo?", "UI editor": "Editor de UI", "Collection": "Coleção", "Collections & Fields": "Coleções e campos", diff --git a/packages/core/client/src/locale/ru_RU.json b/packages/core/client/src/locale/ru_RU.json index 3411341e1..99f45d8ad 100644 --- a/packages/core/client/src/locale/ru_RU.json +++ b/packages/core/client/src/locale/ru_RU.json @@ -52,6 +52,9 @@ "Insert right": "Вставить справа", "Insert inner": "Вставить внутрь", "Delete": "Удалить", + "Disassociate": "Разъединить", + "Disassociate record": "Разъединить запись", + "Are you sure you want to disassociate it?": "Вы уверены, что хотите разъединить это?", "UI editor": "UI редактор", "Collection": "Коллекция", "Collections & Fields": "Коллекции & Поля", diff --git a/packages/core/client/src/locale/tr_TR.json b/packages/core/client/src/locale/tr_TR.json index ec2c67ee5..0cccd69d4 100644 --- a/packages/core/client/src/locale/tr_TR.json +++ b/packages/core/client/src/locale/tr_TR.json @@ -52,6 +52,9 @@ "Insert right": "Sağa yerleştir", "Insert inner": "İçine yerleştir", "Delete": "Sil", + "Disassociate": "Bağlantıyı kes", + "Disassociate record": "Kaydı bağlantıyı kes", + "Are you sure you want to disassociate it?": "Bağlantıyı kesmek istediğinizden emin misiniz?", "UI editor": "UI editor", "Collection": "Koleksiyonlar", "Collections & Fields": "Koleksiyonlar & Alanlar", diff --git a/packages/core/client/src/locale/uk_UA.json b/packages/core/client/src/locale/uk_UA.json index da860d5da..a530f6cfb 100644 --- a/packages/core/client/src/locale/uk_UA.json +++ b/packages/core/client/src/locale/uk_UA.json @@ -52,6 +52,9 @@ "Insert right": "Вставити справа", "Insert inner": "Вставити всередину", "Delete": "Видалити", + "Disassociate": "Роз'єднати", + "Disassociate record": "Роз'єднати запис", + "Are you sure you want to disassociate it?": "Ви впевнені, що хочете роз'єднати це?", "UI editor": "Редактор UI", "Collection": "Колекція", "Collections & Fields": "Колекції та поля", diff --git a/packages/core/client/src/locale/zh-CN.json b/packages/core/client/src/locale/zh-CN.json index 2a5c4c32c..30f5d8f07 100644 --- a/packages/core/client/src/locale/zh-CN.json +++ b/packages/core/client/src/locale/zh-CN.json @@ -60,6 +60,9 @@ "Insert right": "在右边插入", "Insert inner": "在里面插入", "Delete": "删除", + "Disassociate": "解除关联", + "Disassociate record": "解除关联记录", + "Are you sure you want to disassociate it?": "你确定要解除关联吗?", "UI editor": "界面配置", "Collection": "数据表", "Collection selector": "数据表选择器", diff --git a/packages/core/client/src/locale/zh-TW.json b/packages/core/client/src/locale/zh-TW.json index 4f8c1727a..510910d3e 100644 --- a/packages/core/client/src/locale/zh-TW.json +++ b/packages/core/client/src/locale/zh-TW.json @@ -60,6 +60,9 @@ "Insert right": "從右邊插入", "Insert inner": "從裡面插入", "Delete": "刪除", + "Disassociate": "解除關聯", + "Disassociate record": "解除關聯記錄", + "Are you sure you want to disassociate it?": "你確定要解除關聯嗎?", "UI editor": "介面編輯", "Collection": "資料表", "Collection selector": "資料表選擇器", diff --git a/packages/core/client/src/modules/actions/disassociate/DisassociateActionInitializer.tsx b/packages/core/client/src/modules/actions/disassociate/DisassociateActionInitializer.tsx new file mode 100644 index 000000000..2065e4f6d --- /dev/null +++ b/packages/core/client/src/modules/actions/disassociate/DisassociateActionInitializer.tsx @@ -0,0 +1,25 @@ +import React from 'react'; + +import { ActionInitializer } from '../../../schema-initializer/items/ActionInitializer'; + +export const DisassociateActionInitializer = (props) => { + const schema = { + title: '{{ t("Disassociate") }}', + 'x-action': 'disassociate', + 'x-component': 'Action', + 'x-toolbar': 'ActionSchemaToolbar', + 'x-settings': 'actionSettings:disassociate', + 'x-component-props': { + icon: 'DeleteOutlined', + confirm: { + title: "{{t('Disassociate record')}}", + content: "{{t('Are you sure you want to disassociate it?')}}", + }, + useProps: '{{ useDisassociateActionProps }}', + }, + 'x-action-settings': { + triggerWorkflows: [], + }, + }; + return ; +}; diff --git a/packages/core/client/src/modules/actions/disassociate/disassociateActionSettings.tsx b/packages/core/client/src/modules/actions/disassociate/disassociateActionSettings.tsx new file mode 100644 index 000000000..d11d7be30 --- /dev/null +++ b/packages/core/client/src/modules/actions/disassociate/disassociateActionSettings.tsx @@ -0,0 +1,39 @@ +import { useSchemaToolbar } from '../../../application'; +import { SchemaSettings } from '../../../application/schema-settings/SchemaSettings'; +import { useCollection_deprecated } from '../../../collection-manager'; +import { ButtonEditor, SecondConFirm } from '../../../schema-component/antd/action/Action.Designer'; +import { SchemaSettingsLinkageRules } from '../../../schema-settings'; + +export const disassociateActionSettings = new SchemaSettings({ + name: 'actionSettings:disassociate', + items: [ + { + name: 'editButton', + Component: ButtonEditor, + useComponentProps() { + const { buttonEditorProps } = useSchemaToolbar(); + return buttonEditorProps; + }, + }, + { + name: 'linkageRules', + Component: SchemaSettingsLinkageRules, + useComponentProps() { + const { name } = useCollection_deprecated(); + const { linkageRulesProps } = useSchemaToolbar(); + return { + ...linkageRulesProps, + collectionName: name, + }; + }, + }, + { + name: 'secondConFirm', + Component: SecondConFirm, + }, + { + name: 'delete', + type: 'remove', + }, + ], +}); diff --git a/packages/core/client/src/modules/blocks/data-blocks/table/TableActionColumnInitializers.tsx b/packages/core/client/src/modules/blocks/data-blocks/table/TableActionColumnInitializers.tsx index 0fe2fa090..3edb4f219 100644 --- a/packages/core/client/src/modules/blocks/data-blocks/table/TableActionColumnInitializers.tsx +++ b/packages/core/client/src/modules/blocks/data-blocks/table/TableActionColumnInitializers.tsx @@ -4,13 +4,14 @@ import _ from 'lodash'; import React from 'react'; import { useTranslation } from 'react-i18next'; import { useAPIClient } from '../../../../api-client'; +import { CompatibleSchemaInitializer } from '../../../../application/schema-initializer/CompatibleSchemaInitializer'; +import { SchemaInitializerActionModal } from '../../../../application/schema-initializer/components/SchemaInitializerActionModal'; +import { SchemaInitializerItem } from '../../../../application/schema-initializer/components/SchemaInitializerItem'; +import { useSchemaInitializer } from '../../../../application/schema-initializer/context'; import { useCollection_deprecated } from '../../../../collection-manager'; +import { useDataBlockProps } from '../../../../data-source'; import { createDesignable, useDesignable } from '../../../../schema-component'; import { useGetAriaLabelOfDesigner } from '../../../../schema-settings/hooks/useGetAriaLabelOfDesigner'; -import { SchemaInitializerActionModal } from '../../../../application/schema-initializer/components/SchemaInitializerActionModal'; -import { useSchemaInitializer } from '../../../../application/schema-initializer/context'; -import { SchemaInitializerItem } from '../../../../application/schema-initializer/components/SchemaInitializerItem'; -import { CompatibleSchemaInitializer } from '../../../../application/schema-initializer/CompatibleSchemaInitializer'; export const Resizable = () => { const { t } = useTranslation(); @@ -65,11 +66,7 @@ export const Resizable = () => { ); }; -/** - * @deprecated - */ -export const tableActionColumnInitializers_deprecated = new CompatibleSchemaInitializer({ - name: 'TableActionColumnInitializers', +const commonOptions = { insertPosition: 'beforeEnd', useInsert: function useInsert() { const { refresh } = useDesignable(); @@ -156,6 +153,27 @@ export const tableActionColumnInitializers_deprecated = new CompatibleSchemaInit return (collection.template !== 'view' || collection?.writableView) && collection.template !== 'sql'; }, }, + { + type: 'item', + title: '{{t("Disassociate")}}', + name: 'disassociate', + Component: 'DisassociateActionInitializer', + schema: { + 'x-component': 'Action.Link', + 'x-action': 'disassociate', + 'x-acl-action': 'destroy', + 'x-decorator': 'ACLActionProvider', + }, + useVisible() { + const props = useDataBlockProps(); + const collection = useCollection_deprecated(); + return ( + !!props?.association && + (collection.template !== 'view' || collection?.writableView) && + collection.template !== 'sql' + ); + }, + }, { type: 'item', title: '{{t("Add child")}}', @@ -225,166 +243,20 @@ export const tableActionColumnInitializers_deprecated = new CompatibleSchemaInit Component: Resizable, }, ], +}; + +/** + * @deprecated + */ +export const tableActionColumnInitializers_deprecated = new CompatibleSchemaInitializer({ + name: 'TableActionColumnInitializers', + ...commonOptions, }); export const tableActionColumnInitializers = new CompatibleSchemaInitializer( { name: 'table:configureItemActions', - insertPosition: 'beforeEnd', - useInsert: function useInsert() { - const { refresh } = useDesignable(); - const fieldSchema = useFieldSchema(); - const api = useAPIClient(); - const { t } = useTranslation(); - - return function insert(schema) { - const spaceSchema = fieldSchema.reduceProperties((buf, schema) => { - if (schema['x-component'] === 'Space') { - return schema; - } - return buf; - }, null); - if (!spaceSchema) { - return; - } - _.set(schema, 'x-designer-props.linkageAction', true); - const dn = createDesignable({ - t, - api, - refresh, - current: spaceSchema, - }); - dn.loadAPIClientEvents(); - dn.insertBeforeEnd(schema); - }; - }, - Component: (props: any) => { - const { getAriaLabel } = useGetAriaLabelOfDesigner(); - return ( - - ); - }, - items: [ - { - type: 'itemGroup', - name: 'actions', - title: '{{t("Enable actions")}}', - children: [ - { - type: 'item', - title: '{{t("View")}}', - name: 'view', - Component: 'ViewActionInitializer', - schema: { - 'x-component': 'Action.Link', - 'x-action': 'view', - 'x-decorator': 'ACLActionProvider', - }, - }, - { - type: 'item', - name: 'edit', - title: '{{t("Edit")}}', - Component: 'UpdateActionInitializer', - schema: { - 'x-component': 'Action.Link', - 'x-action': 'update', - 'x-decorator': 'ACLActionProvider', - }, - useVisible() { - const collection = useCollection_deprecated(); - return (collection.template !== 'view' || collection?.writableView) && collection.template !== 'sql'; - }, - }, - { - type: 'item', - title: '{{t("Delete")}}', - name: 'delete', - Component: 'DestroyActionInitializer', - schema: { - 'x-component': 'Action.Link', - 'x-action': 'destroy', - 'x-decorator': 'ACLActionProvider', - }, - useVisible() { - const collection = useCollection_deprecated(); - return (collection.template !== 'view' || collection?.writableView) && collection.template !== 'sql'; - }, - }, - { - type: 'item', - title: '{{t("Add child")}}', - name: 'addChildren', - Component: 'CreateChildInitializer', - schema: { - 'x-component': 'Action.Link', - 'x-action': 'create', - 'x-decorator': 'ACLActionProvider', - }, - useVisible() { - const fieldSchema = useFieldSchema(); - const collection = useCollection_deprecated(); - const { treeTable } = fieldSchema?.parent?.parent['x-decorator-props'] || {}; - return collection.tree && treeTable !== false; - }, - }, - ], - }, - { - name: 'divider', - type: 'divider', - }, - { - type: 'subMenu', - title: '{{t("Customize")}}', - name: 'customize', - children: [ - { - type: 'item', - title: '{{t("Popup")}}', - name: 'popup', - Component: 'PopupActionInitializer', - }, - { - type: 'item', - title: '{{t("Update record")}}', - name: 'updateRecord', - Component: 'UpdateRecordActionInitializer', - useVisible() { - const collection = useCollection_deprecated(); - return (collection.template !== 'view' || collection?.writableView) && collection.template !== 'sql'; - }, - }, - { - name: 'customRequest', - title: '{{t("Custom request")}}', - Component: 'CustomRequestInitializer', - schema: { - 'x-action': 'customize:table:request', - }, - useVisible() { - const collection = useCollection_deprecated(); - return (collection.template !== 'view' || collection?.writableView) && collection.template !== 'sql'; - }, - }, - ], - }, - { - name: 'divider2', - type: 'divider', - }, - { - type: 'item', - name: 'columnWidth', - title: 't("Column width")', - Component: Resizable, - }, - ], + ...commonOptions, }, tableActionColumnInitializers_deprecated, ); diff --git a/packages/core/client/src/schema-initializer/index.ts b/packages/core/client/src/schema-initializer/index.ts index e8e9b2006..648cdb45f 100644 --- a/packages/core/client/src/schema-initializer/index.ts +++ b/packages/core/client/src/schema-initializer/index.ts @@ -12,6 +12,7 @@ import { } from '../modules/actions/add-record/customizeCreateFormBlockInitializers'; import { BulkDestroyActionInitializer } from '../modules/actions/bulk-destroy/BulkDestroyActionInitializer'; import { DestroyActionInitializer } from '../modules/actions/delete/DestroyActionInitializer'; +import { DisassociateActionInitializer } from '../modules/actions/disassociate/DisassociateActionInitializer'; import { ExpandableActionInitializer } from '../modules/actions/expand-collapse/ExpandableActionInitializer'; import { FilterActionInitializer } from '../modules/actions/filter/FilterActionInitializer'; import { RefreshActionInitializer } from '../modules/actions/refresh/RefreshActionInitializer'; @@ -121,10 +122,10 @@ import * as items from './items'; export * from './buttons'; export * from './items'; export { + createDetailsBlockSchema, createFilterFormBlockSchema, createFormBlockSchema, createReadPrettyFormBlockSchema, - createDetailsBlockSchema, createTableBlockSchema, gridRowColWrap, itemsMerge, @@ -144,6 +145,7 @@ export class SchemaInitializerPlugin extends Plugin { this.app.addComponents({ ...initializerComponents, ...items, + DestroyActionInitializer, CreateFormBlockInitializer, FormBlockInitializer, RecordFormBlockInitializer, @@ -171,7 +173,7 @@ export class SchemaInitializerPlugin extends Plugin { UpdateSubmitActionInitializer, BulkDestroyActionInitializer, ExpandableActionInitializer, - DestroyActionInitializer, + DisassociateActionInitializer, FilterActionInitializer, RefreshActionInitializer, } as any); diff --git a/packages/core/client/src/schema-settings/SchemaSettingsPlugin.ts b/packages/core/client/src/schema-settings/SchemaSettingsPlugin.ts index c6db2687b..7272480d3 100644 --- a/packages/core/client/src/schema-settings/SchemaSettingsPlugin.ts +++ b/packages/core/client/src/schema-settings/SchemaSettingsPlugin.ts @@ -4,6 +4,7 @@ import { addNewActionSettings } from '../modules/actions/add-new/addNewActionSet import { customizeAddRecordActionSettings } from '../modules/actions/add-record/customizeAddRecordActionSettings'; import { bulkDeleteActionSettings } from '../modules/actions/bulk-destroy/bulkDeleteActionSettings'; import { deleteActionSettings } from '../modules/actions/delete/deleteActionSettings'; +import { disassociateActionSettings } from '../modules/actions/disassociate/disassociateActionSettings'; import { expendableActionSettings } from '../modules/actions/expand-collapse/expendableActionSettings'; import { filterActionSettings } from '../modules/actions/filter/filterActionSettings'; import { refreshActionSettings } from '../modules/actions/refresh/refreshActionSettings'; @@ -68,6 +69,7 @@ export class SchemaSettingsPlugin extends Plugin { this.schemaSettingsManager.add(viewActionSettings); this.schemaSettingsManager.add(editActionSettings); this.schemaSettingsManager.add(deleteActionSettings); + this.schemaSettingsManager.add(disassociateActionSettings); this.schemaSettingsManager.add(bulkDeleteActionSettings); this.schemaSettingsManager.add(customizeAddRecordActionSettings); this.schemaSettingsManager.add(customizePopupActionSettings); diff --git a/packages/core/server/src/acl/available-action.ts b/packages/core/server/src/acl/available-action.ts index 0277f2fd9..c34091428 100644 --- a/packages/core/server/src/acl/available-action.ts +++ b/packages/core/server/src/acl/available-action.ts @@ -34,6 +34,7 @@ const availableActions: { }, destroy: { displayName: '{{t("Delete")}}', + aliases: ['destroy', 'remove'], type: 'old-data', }, };