refactor: bulk edit action set changeTo as default value (#3455)
This commit is contained in:
parent
535d14b0bb
commit
dad6072abb
@ -15,7 +15,6 @@ import { useFilterBlock } from '../../filter-provider/FilterProvider';
|
|||||||
import { transformToFilter } from '../../filter-provider/utils';
|
import { transformToFilter } from '../../filter-provider/utils';
|
||||||
import { useRecord } from '../../record-provider';
|
import { useRecord } from '../../record-provider';
|
||||||
import { removeNullCondition, useActionContext, useCompile } from '../../schema-component';
|
import { removeNullCondition, useActionContext, useCompile } from '../../schema-component';
|
||||||
import { BulkEditFormItemValueType } from '../../schema-initializer/components';
|
|
||||||
import { useCurrentUserContext } from '../../user';
|
import { useCurrentUserContext } from '../../user';
|
||||||
import { useLocalVariables, useVariables } from '../../variables';
|
import { useLocalVariables, useVariables } from '../../variables';
|
||||||
import { isVariable } from '../../variables/utils/isVariable';
|
import { isVariable } from '../../variables/utils/isVariable';
|
||||||
@ -680,94 +679,6 @@ export const useCustomizeBulkUpdateActionProps = () => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useCustomizeBulkEditActionProps = () => {
|
|
||||||
const form = useForm();
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const { field, resource, __parent } = useBlockRequestContext();
|
|
||||||
const expressionScope = useContext(SchemaExpressionScopeContext);
|
|
||||||
const actionContext = useActionContext();
|
|
||||||
const navigate = useNavigate();
|
|
||||||
const compile = useCompile();
|
|
||||||
const actionField = useField();
|
|
||||||
const tableBlockContext = useTableBlockContext();
|
|
||||||
const { modal } = App.useApp();
|
|
||||||
|
|
||||||
const { rowKey } = tableBlockContext;
|
|
||||||
const selectedRecordKeys =
|
|
||||||
tableBlockContext.field?.data?.selectedRowKeys ?? expressionScope?.selectedRecordKeys ?? {};
|
|
||||||
const { setVisible, fieldSchema: actionSchema } = actionContext;
|
|
||||||
return {
|
|
||||||
async onClick() {
|
|
||||||
const { onSuccess, skipValidator, updateMode } = actionSchema?.['x-action-settings'] ?? {};
|
|
||||||
const { filter } = __parent.service.params?.[0] ?? {};
|
|
||||||
if (!skipValidator) {
|
|
||||||
await form.submit();
|
|
||||||
}
|
|
||||||
const values = cloneDeep(form.values);
|
|
||||||
actionField.data = field.data || {};
|
|
||||||
actionField.data.loading = true;
|
|
||||||
for (const key in values) {
|
|
||||||
if (Object.prototype.hasOwnProperty.call(values, key)) {
|
|
||||||
const value = values[key];
|
|
||||||
if (BulkEditFormItemValueType.Clear in value) {
|
|
||||||
values[key] = null;
|
|
||||||
} else if (BulkEditFormItemValueType.ChangedTo in value) {
|
|
||||||
values[key] = value[BulkEditFormItemValueType.ChangedTo];
|
|
||||||
} else if (BulkEditFormItemValueType.RemainsTheSame in value) {
|
|
||||||
delete values[key];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const updateData: { filter?: any; values: any; forceUpdate: boolean } = {
|
|
||||||
values,
|
|
||||||
filter,
|
|
||||||
forceUpdate: false,
|
|
||||||
};
|
|
||||||
if (updateMode === 'selected') {
|
|
||||||
if (!selectedRecordKeys?.length) {
|
|
||||||
message.error(t('Please select the records to be updated'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
updateData.filter = { $and: [{ [rowKey || 'id']: { $in: selectedRecordKeys } }] };
|
|
||||||
}
|
|
||||||
if (!updateData.filter) {
|
|
||||||
updateData.forceUpdate = true;
|
|
||||||
}
|
|
||||||
await resource.update(updateData);
|
|
||||||
actionField.data.loading = false;
|
|
||||||
if (!(resource instanceof TableFieldResource)) {
|
|
||||||
__parent?.__parent?.service?.refresh?.();
|
|
||||||
}
|
|
||||||
__parent?.service?.refresh?.();
|
|
||||||
setVisible?.(false);
|
|
||||||
if (!onSuccess?.successMessage) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (onSuccess?.manualClose) {
|
|
||||||
modal.success({
|
|
||||||
title: compile(onSuccess?.successMessage),
|
|
||||||
onOk: async () => {
|
|
||||||
await form.reset();
|
|
||||||
if (onSuccess?.redirecting && onSuccess?.redirectTo) {
|
|
||||||
if (isURL(onSuccess.redirectTo)) {
|
|
||||||
window.location.href = onSuccess.redirectTo;
|
|
||||||
} else {
|
|
||||||
navigate(onSuccess.redirectTo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
message.success(compile(onSuccess?.successMessage));
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
actionField.data.loading = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useCustomizeRequestActionProps = () => {
|
export const useCustomizeRequestActionProps = () => {
|
||||||
const apiClient = useAPIClient();
|
const apiClient = useAPIClient();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
@ -282,119 +282,3 @@ export const updateFormActionInitializers = new SchemaInitializer({
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
export const bulkEditFormActionInitializers = new SchemaInitializer({
|
|
||||||
name: 'BulkEditFormActionInitializers',
|
|
||||||
title: '{{t("Configure actions")}}',
|
|
||||||
icon: 'SettingOutlined',
|
|
||||||
items: [
|
|
||||||
{
|
|
||||||
type: 'itemGroup',
|
|
||||||
title: '{{t("Enable actions")}}',
|
|
||||||
name: 'enableActions',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
name: 'submit',
|
|
||||||
title: '{{t("Submit")}}',
|
|
||||||
Component: 'BulkEditSubmitActionInitializer',
|
|
||||||
schema: {
|
|
||||||
'x-action-settings': {},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'divider',
|
|
||||||
type: 'divider',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'subMenu',
|
|
||||||
title: '{{t("Customize")}}',
|
|
||||||
name: 'customize',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
name: 'popup',
|
|
||||||
title: '{{t("Popup")}}',
|
|
||||||
Component: 'CustomizeActionInitializer',
|
|
||||||
schema: {
|
|
||||||
type: 'void',
|
|
||||||
title: '{{ t("Popup") }}',
|
|
||||||
'x-action': 'customize:popup',
|
|
||||||
'x-designer': 'Action.Designer',
|
|
||||||
'x-component': 'Action',
|
|
||||||
'x-component-props': {
|
|
||||||
openMode: 'drawer',
|
|
||||||
},
|
|
||||||
properties: {
|
|
||||||
drawer: {
|
|
||||||
type: 'void',
|
|
||||||
title: '{{ t("Popup") }}',
|
|
||||||
'x-component': 'Action.Container',
|
|
||||||
'x-component-props': {
|
|
||||||
className: 'nb-action-popup',
|
|
||||||
},
|
|
||||||
properties: {
|
|
||||||
tabs: {
|
|
||||||
type: 'void',
|
|
||||||
'x-component': 'Tabs',
|
|
||||||
'x-component-props': {},
|
|
||||||
'x-initializer': 'TabPaneInitializers',
|
|
||||||
properties: {
|
|
||||||
tab1: {
|
|
||||||
type: 'void',
|
|
||||||
title: '{{t("Details")}}',
|
|
||||||
'x-component': 'Tabs.TabPane',
|
|
||||||
'x-designer': 'Tabs.Designer',
|
|
||||||
'x-component-props': {},
|
|
||||||
properties: {
|
|
||||||
grid: {
|
|
||||||
type: 'void',
|
|
||||||
'x-component': 'Grid',
|
|
||||||
'x-initializer': 'RecordBlockInitializers',
|
|
||||||
properties: {},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'saveRecord',
|
|
||||||
title: '{{t("Save record")}}',
|
|
||||||
Component: 'CustomizeActionInitializer',
|
|
||||||
schema: {
|
|
||||||
title: '{{ t("Save") }}',
|
|
||||||
'x-component': 'Action',
|
|
||||||
'x-action': 'customize:save',
|
|
||||||
'x-designer': 'Action.Designer',
|
|
||||||
'x-designer-props': {
|
|
||||||
modalTip:
|
|
||||||
'{{ t("When the button is clicked, the following fields will be assigned and saved together with the fields in the form. If there are overlapping fields, the value here will overwrite the value in the form.") }}',
|
|
||||||
},
|
|
||||||
'x-action-settings': {
|
|
||||||
assignedValues: {},
|
|
||||||
skipValidator: false,
|
|
||||||
onSuccess: {
|
|
||||||
manualClose: true,
|
|
||||||
redirecting: false,
|
|
||||||
successMessage: '{{t("Submitted successfully")}}',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'x-component-props': {
|
|
||||||
useProps: '{{ useUpdateActionProps }}',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'customRequest',
|
|
||||||
title: '{{t("Custom request")}}',
|
|
||||||
Component: 'CustomRequestInitializer',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
@ -1,3 +1,2 @@
|
|||||||
export * from './assigned-field';
|
export * from './assigned-field';
|
||||||
export * from './BulkEditField';
|
|
||||||
export * from './CreateRecordAction';
|
export * from './CreateRecordAction';
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { Plugin } from '../application/Plugin';
|
import { Plugin } from '../application/Plugin';
|
||||||
import {
|
import {
|
||||||
blockInitializers,
|
blockInitializers,
|
||||||
bulkEditFormActionInitializers,
|
|
||||||
createFormActionInitializers,
|
createFormActionInitializers,
|
||||||
createFormBlockInitializers,
|
createFormBlockInitializers,
|
||||||
cusomeizeCreateFormBlockInitializers,
|
cusomeizeCreateFormBlockInitializers,
|
||||||
@ -74,7 +73,6 @@ export class SchemaInitializerPlugin extends Plugin {
|
|||||||
this.app.schemaInitializerManager.add(filterFormActionInitializers);
|
this.app.schemaInitializerManager.add(filterFormActionInitializers);
|
||||||
this.app.schemaInitializerManager.add(createFormActionInitializers);
|
this.app.schemaInitializerManager.add(createFormActionInitializers);
|
||||||
this.app.schemaInitializerManager.add(updateFormActionInitializers);
|
this.app.schemaInitializerManager.add(updateFormActionInitializers);
|
||||||
this.app.schemaInitializerManager.add(bulkEditFormActionInitializers);
|
|
||||||
this.app.schemaInitializerManager.add(filterFormItemInitializers);
|
this.app.schemaInitializerManager.add(filterFormItemInitializers);
|
||||||
this.app.schemaInitializerManager.add(gridCardActionInitializers);
|
this.app.schemaInitializerManager.add(gridCardActionInitializers);
|
||||||
this.app.schemaInitializerManager.add(gridCardItemActionInitializers);
|
this.app.schemaInitializerManager.add(gridCardItemActionInitializers);
|
||||||
|
@ -6,7 +6,6 @@ export * from '../../schema-component/antd/association-filter/AssociationFilterD
|
|||||||
export * from './ActionInitializer';
|
export * from './ActionInitializer';
|
||||||
export * from './BlockInitializer';
|
export * from './BlockInitializer';
|
||||||
export * from './BulkDestroyActionInitializer';
|
export * from './BulkDestroyActionInitializer';
|
||||||
export * from './BulkEditSubmitActionInitializer';
|
|
||||||
export * from './CollectionFieldInitializer';
|
export * from './CollectionFieldInitializer';
|
||||||
export * from './CreateActionInitializer';
|
export * from './CreateActionInitializer';
|
||||||
export * from './CreateChildInitializer';
|
export * from './CreateChildInitializer';
|
||||||
|
@ -0,0 +1,116 @@
|
|||||||
|
import { SchemaInitializer } from '@nocobase/client';
|
||||||
|
export const BulkEditFormActionInitializers = new SchemaInitializer({
|
||||||
|
name: 'BulkEditFormActionInitializers',
|
||||||
|
title: '{{t("Configure actions")}}',
|
||||||
|
icon: 'SettingOutlined',
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
type: 'itemGroup',
|
||||||
|
title: '{{t("Enable actions")}}',
|
||||||
|
name: 'enableActions',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
name: 'submit',
|
||||||
|
title: '{{t("Submit")}}',
|
||||||
|
Component: 'BulkEditSubmitActionInitializer',
|
||||||
|
schema: {
|
||||||
|
'x-action-settings': {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'divider',
|
||||||
|
type: 'divider',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'subMenu',
|
||||||
|
title: '{{t("Customize")}}',
|
||||||
|
name: 'customize',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
name: 'popup',
|
||||||
|
title: '{{t("Popup")}}',
|
||||||
|
Component: 'CustomizeActionInitializer',
|
||||||
|
schema: {
|
||||||
|
type: 'void',
|
||||||
|
title: '{{ t("Popup") }}',
|
||||||
|
'x-action': 'customize:popup',
|
||||||
|
'x-designer': 'Action.Designer',
|
||||||
|
'x-component': 'Action',
|
||||||
|
'x-component-props': {
|
||||||
|
openMode: 'drawer',
|
||||||
|
},
|
||||||
|
properties: {
|
||||||
|
drawer: {
|
||||||
|
type: 'void',
|
||||||
|
title: '{{ t("Popup") }}',
|
||||||
|
'x-component': 'Action.Container',
|
||||||
|
'x-component-props': {
|
||||||
|
className: 'nb-action-popup',
|
||||||
|
},
|
||||||
|
properties: {
|
||||||
|
tabs: {
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Tabs',
|
||||||
|
'x-component-props': {},
|
||||||
|
'x-initializer': 'TabPaneInitializers',
|
||||||
|
properties: {
|
||||||
|
tab1: {
|
||||||
|
type: 'void',
|
||||||
|
title: '{{t("Details")}}',
|
||||||
|
'x-component': 'Tabs.TabPane',
|
||||||
|
'x-designer': 'Tabs.Designer',
|
||||||
|
'x-component-props': {},
|
||||||
|
properties: {
|
||||||
|
grid: {
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Grid',
|
||||||
|
'x-initializer': 'RecordBlockInitializers',
|
||||||
|
properties: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'saveRecord',
|
||||||
|
title: '{{t("Save record")}}',
|
||||||
|
Component: 'CustomizeActionInitializer',
|
||||||
|
schema: {
|
||||||
|
title: '{{ t("Save") }}',
|
||||||
|
'x-component': 'Action',
|
||||||
|
'x-action': 'customize:save',
|
||||||
|
'x-designer': 'Action.Designer',
|
||||||
|
'x-designer-props': {
|
||||||
|
modalTip:
|
||||||
|
'{{ t("When the button is clicked, the following fields will be assigned and saved together with the fields in the form. If there are overlapping fields, the value here will overwrite the value in the form.") }}',
|
||||||
|
},
|
||||||
|
'x-action-settings': {
|
||||||
|
assignedValues: {},
|
||||||
|
skipValidator: false,
|
||||||
|
onSuccess: {
|
||||||
|
manualClose: true,
|
||||||
|
redirecting: false,
|
||||||
|
successMessage: '{{t("Submitted successfully")}}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-component-props': {
|
||||||
|
useProps: '{{ useUpdateActionProps }}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'customRequest',
|
||||||
|
title: '{{t("Custom request")}}',
|
||||||
|
Component: 'CustomRequestInitializer',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
@ -2,14 +2,19 @@ import { SchemaComponentOptions } from '@nocobase/client';
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { CustomizeBulkEditActionInitializer } from './CustomizeBulkEditActionInitializer';
|
import { CustomizeBulkEditActionInitializer } from './CustomizeBulkEditActionInitializer';
|
||||||
import { CreateFormBulkEditBlockInitializer } from './CreateFormBulkEditBlockInitializer';
|
import { CreateFormBulkEditBlockInitializer } from './CreateFormBulkEditBlockInitializer';
|
||||||
|
import { BulkEditSubmitActionInitializer } from './BulkEditSubmitActionInitializer';
|
||||||
|
import { useCustomizeBulkEditActionProps } from './utils';
|
||||||
|
import { BulkEditField } from './component/BulkEditField';
|
||||||
export const BulkEditPluginProvider = (props: any) => {
|
export const BulkEditPluginProvider = (props: any) => {
|
||||||
return (
|
return (
|
||||||
<SchemaComponentOptions
|
<SchemaComponentOptions
|
||||||
components={{
|
components={{
|
||||||
CustomizeBulkEditActionInitializer,
|
CustomizeBulkEditActionInitializer,
|
||||||
CreateFormBulkEditBlockInitializer,
|
CreateFormBulkEditBlockInitializer,
|
||||||
|
BulkEditSubmitActionInitializer,
|
||||||
|
BulkEditField,
|
||||||
}}
|
}}
|
||||||
|
scope={{ useCustomizeBulkEditActionProps }}
|
||||||
>
|
>
|
||||||
{props.children}
|
{props.children}
|
||||||
</SchemaComponentOptions>
|
</SchemaComponentOptions>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { ActionInitializer } from './ActionInitializer';
|
import { ActionInitializer } from '@nocobase/client';
|
||||||
|
|
||||||
export const BulkEditSubmitActionInitializer = (props) => {
|
export const BulkEditSubmitActionInitializer = (props) => {
|
||||||
const schema = {
|
const schema = {
|
@ -5,11 +5,19 @@ import { merge, uid } from '@formily/shared';
|
|||||||
import { Checkbox, Select, Space } from 'antd';
|
import { Checkbox, Select, Space } from 'antd';
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useFormBlockContext } from '../../block-provider';
|
import {
|
||||||
import { CollectionFieldProvider, useCollection, useCollectionField } from '../../collection-manager';
|
useFormBlockContext,
|
||||||
import { useCompile, useComponent } from '../../schema-component';
|
CollectionFieldProvider,
|
||||||
import { DeletedField } from './DeletedField';
|
useCollection,
|
||||||
|
useCollectionField,
|
||||||
|
useCompile,
|
||||||
|
useComponent,
|
||||||
|
} from '@nocobase/client';
|
||||||
|
|
||||||
|
export const DeletedField = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
return <div style={{ color: '#ccc' }}>{t('The field has bee deleted')}</div>;
|
||||||
|
};
|
||||||
const InternalField: React.FC = (props) => {
|
const InternalField: React.FC = (props) => {
|
||||||
const field = useField<Field>();
|
const field = useField<Field>();
|
||||||
const fieldSchema = useFieldSchema();
|
const fieldSchema = useFieldSchema();
|
||||||
@ -83,7 +91,7 @@ export const BulkEditField = (props: any) => {
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const fieldSchema = useFieldSchema();
|
const fieldSchema = useFieldSchema();
|
||||||
const field = useField<Field>();
|
const field = useField<Field>();
|
||||||
const [type, setType] = useState<number>(BulkEditFormItemValueType.RemainsTheSame);
|
const [type, setType] = useState<number>(BulkEditFormItemValueType.ChangedTo);
|
||||||
const [value, setValue] = useState(null);
|
const [value, setValue] = useState(null);
|
||||||
const { getField } = useCollection();
|
const { getField } = useCollection();
|
||||||
const collectionField = getField(fieldSchema.name) || {};
|
const collectionField = getField(fieldSchema.name) || {};
|
||||||
@ -135,15 +143,9 @@ export const BulkEditField = (props: any) => {
|
|||||||
<Select.Option value={BulkEditFormItemValueType.AddAttach}>{t('Add attach')}</Select.Option>
|
<Select.Option value={BulkEditFormItemValueType.AddAttach}>{t('Add attach')}</Select.Option>
|
||||||
)}
|
)}
|
||||||
</Select>
|
</Select>
|
||||||
{/* XXX: Not a best practice */}
|
|
||||||
{[BulkEditFormItemValueType.ChangedTo, BulkEditFormItemValueType.AddAttach].includes(type) &&
|
{[BulkEditFormItemValueType.ChangedTo, BulkEditFormItemValueType.AddAttach].includes(type) &&
|
||||||
collectionField?.interface !== 'checkbox' && (
|
collectionField?.interface !== 'checkbox' && (
|
||||||
<CollectionField {...props} value={value} onChange={valueChangeHandler} style={{ minWidth: 150 }} />
|
<CollectionField {...props} value={value} onChange={valueChangeHandler} style={{ minWidth: 150 }} />
|
||||||
// <SchemaComponent
|
|
||||||
// schema={collectionSchema}
|
|
||||||
// components={{ BulkEditCollectionField: CollectionField }}
|
|
||||||
// onlyRenderProperties
|
|
||||||
// />
|
|
||||||
)}
|
)}
|
||||||
{[BulkEditFormItemValueType.ChangedTo, BulkEditFormItemValueType.AddAttach].includes(type) &&
|
{[BulkEditFormItemValueType.ChangedTo, BulkEditFormItemValueType.AddAttach].includes(type) &&
|
||||||
collectionField?.interface === 'checkbox' && <Checkbox checked={value} onChange={valueChangeHandler} />}
|
collectionField?.interface === 'checkbox' && <Checkbox checked={value} onChange={valueChangeHandler} />}
|
@ -2,6 +2,7 @@ import { Plugin, useCollection } from '@nocobase/client';
|
|||||||
import { BulkEditPluginProvider } from './BulkEditPluginProvider';
|
import { BulkEditPluginProvider } from './BulkEditPluginProvider';
|
||||||
import { BulkEditFormItemInitializers } from './BulkEditFormItemInitializers';
|
import { BulkEditFormItemInitializers } from './BulkEditFormItemInitializers';
|
||||||
import { CreateFormBulkEditBlockInitializers } from './CreateFormBulkEditBlockInitializers';
|
import { CreateFormBulkEditBlockInitializers } from './CreateFormBulkEditBlockInitializers';
|
||||||
|
import { BulkEditFormActionInitializers } from './BulkEditFormActionInitializers';
|
||||||
import { bulkEditactionSettings } from './BulkEditAction.Settings';
|
import { bulkEditactionSettings } from './BulkEditAction.Settings';
|
||||||
export class BulkEditPlugin extends Plugin {
|
export class BulkEditPlugin extends Plugin {
|
||||||
async load() {
|
async load() {
|
||||||
@ -9,6 +10,7 @@ export class BulkEditPlugin extends Plugin {
|
|||||||
this.app.schemaSettingsManager.add(bulkEditactionSettings);
|
this.app.schemaSettingsManager.add(bulkEditactionSettings);
|
||||||
this.app.schemaInitializerManager.add(BulkEditFormItemInitializers);
|
this.app.schemaInitializerManager.add(BulkEditFormItemInitializers);
|
||||||
this.app.schemaInitializerManager.add(CreateFormBulkEditBlockInitializers);
|
this.app.schemaInitializerManager.add(CreateFormBulkEditBlockInitializers);
|
||||||
|
this.app.schemaInitializerManager.add(BulkEditFormActionInitializers);
|
||||||
|
|
||||||
const initializerData = {
|
const initializerData = {
|
||||||
type: 'item',
|
type: 'item',
|
||||||
|
@ -1,59 +0,0 @@
|
|||||||
import {
|
|
||||||
useCollection,
|
|
||||||
useCollectionManager,
|
|
||||||
useRemoveGridFormItem,
|
|
||||||
SchemaInitializerItemType,
|
|
||||||
} from '@nocobase/client';
|
|
||||||
import { useForm } from '@formily/react';
|
|
||||||
import { useMemo } from 'react';
|
|
||||||
|
|
||||||
export const useCustomBulkEditFormItemInitializerFields = (options?: any) => {
|
|
||||||
const { name, fields } = useCollection();
|
|
||||||
const { getInterface, getCollection } = useCollectionManager();
|
|
||||||
const form = useForm();
|
|
||||||
const { readPretty = form.readPretty, block = 'Form' } = options || {};
|
|
||||||
const remove = useRemoveGridFormItem();
|
|
||||||
const filterFields = useMemo(
|
|
||||||
() =>
|
|
||||||
fields
|
|
||||||
?.filter((field) => {
|
|
||||||
return (
|
|
||||||
field?.interface &&
|
|
||||||
!field?.uiSchema?.['x-read-pretty'] &&
|
|
||||||
field.interface !== 'snapshot' &&
|
|
||||||
field.type !== 'sequence'
|
|
||||||
);
|
|
||||||
})
|
|
||||||
.map((field) => {
|
|
||||||
const interfaceConfig = getInterface(field.interface);
|
|
||||||
const schema = {
|
|
||||||
type: 'string',
|
|
||||||
name: field.name,
|
|
||||||
title: field?.uiSchema?.title || field.name,
|
|
||||||
'x-designer': 'FormItem.Designer',
|
|
||||||
'x-component': 'BulkEditField',
|
|
||||||
'x-decorator': 'FormItem',
|
|
||||||
'x-collection-field': `${name}.${field.name}`,
|
|
||||||
};
|
|
||||||
return {
|
|
||||||
name: field?.uiSchema?.title || field.name,
|
|
||||||
type: 'item',
|
|
||||||
title: field?.uiSchema?.title || field.name,
|
|
||||||
Component: 'CollectionFieldInitializer',
|
|
||||||
remove: remove,
|
|
||||||
schemaInitialize: (s) => {
|
|
||||||
interfaceConfig?.schemaInitialize?.(s, {
|
|
||||||
field,
|
|
||||||
block,
|
|
||||||
readPretty,
|
|
||||||
targetCollection: getCollection(field.target),
|
|
||||||
});
|
|
||||||
},
|
|
||||||
schema,
|
|
||||||
} as SchemaInitializerItemType;
|
|
||||||
}),
|
|
||||||
[fields],
|
|
||||||
);
|
|
||||||
|
|
||||||
return filterFields;
|
|
||||||
};
|
|
@ -0,0 +1,159 @@
|
|||||||
|
import {
|
||||||
|
useCollection,
|
||||||
|
useCollectionManager,
|
||||||
|
useRemoveGridFormItem,
|
||||||
|
SchemaInitializerItemType,
|
||||||
|
useBlockRequestContext,
|
||||||
|
useActionContext,
|
||||||
|
useCompile,
|
||||||
|
useTableBlockContext,
|
||||||
|
TableFieldResource,
|
||||||
|
} from '@nocobase/client';
|
||||||
|
import React, { useContext } from 'react';
|
||||||
|
import { App, message } from 'antd';
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
import { SchemaExpressionScopeContext, useField, useForm } from '@formily/react';
|
||||||
|
import { cloneDeep } from 'lodash';
|
||||||
|
import { isURL } from '@nocobase/utils/client';
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { BulkEditFormItemValueType } from './component/BulkEditField';
|
||||||
|
|
||||||
|
export const useCustomBulkEditFormItemInitializerFields = (options?: any) => {
|
||||||
|
const { name, fields } = useCollection();
|
||||||
|
const { getInterface, getCollection } = useCollectionManager();
|
||||||
|
const form = useForm();
|
||||||
|
const { readPretty = form.readPretty, block = 'Form' } = options || {};
|
||||||
|
const remove = useRemoveGridFormItem();
|
||||||
|
const filterFields = useMemo(
|
||||||
|
() =>
|
||||||
|
fields
|
||||||
|
?.filter((field) => {
|
||||||
|
return (
|
||||||
|
field?.interface &&
|
||||||
|
!field?.uiSchema?.['x-read-pretty'] &&
|
||||||
|
field.interface !== 'snapshot' &&
|
||||||
|
field.type !== 'sequence'
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.map((field) => {
|
||||||
|
const interfaceConfig = getInterface(field.interface);
|
||||||
|
const schema = {
|
||||||
|
type: 'string',
|
||||||
|
name: field.name,
|
||||||
|
title: field?.uiSchema?.title || field.name,
|
||||||
|
'x-designer': 'FormItem.Designer',
|
||||||
|
'x-component': 'BulkEditField',
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
'x-collection-field': `${name}.${field.name}`,
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
name: field?.uiSchema?.title || field.name,
|
||||||
|
type: 'item',
|
||||||
|
title: field?.uiSchema?.title || field.name,
|
||||||
|
Component: 'CollectionFieldInitializer',
|
||||||
|
remove: remove,
|
||||||
|
schemaInitialize: (s) => {
|
||||||
|
interfaceConfig?.schemaInitialize?.(s, {
|
||||||
|
field,
|
||||||
|
block,
|
||||||
|
readPretty,
|
||||||
|
targetCollection: getCollection(field.target),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
schema,
|
||||||
|
} as SchemaInitializerItemType;
|
||||||
|
}),
|
||||||
|
[fields],
|
||||||
|
);
|
||||||
|
|
||||||
|
return filterFields;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useCustomizeBulkEditActionProps = () => {
|
||||||
|
const form = useForm();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const { field, resource, __parent } = useBlockRequestContext();
|
||||||
|
const expressionScope = useContext(SchemaExpressionScopeContext);
|
||||||
|
const actionContext = useActionContext();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const compile = useCompile();
|
||||||
|
const actionField = useField();
|
||||||
|
const tableBlockContext = useTableBlockContext();
|
||||||
|
const { modal } = App.useApp();
|
||||||
|
|
||||||
|
const { rowKey } = tableBlockContext;
|
||||||
|
const selectedRecordKeys =
|
||||||
|
tableBlockContext.field?.data?.selectedRowKeys ?? expressionScope?.selectedRecordKeys ?? {};
|
||||||
|
const { setVisible, fieldSchema: actionSchema } = actionContext;
|
||||||
|
return {
|
||||||
|
async onClick() {
|
||||||
|
const { onSuccess, skipValidator, updateMode } = actionSchema?.['x-action-settings'] ?? {};
|
||||||
|
const { filter } = __parent.service.params?.[0] ?? {};
|
||||||
|
if (!skipValidator) {
|
||||||
|
await form.submit();
|
||||||
|
}
|
||||||
|
const values = cloneDeep(form.values);
|
||||||
|
actionField.data = field.data || {};
|
||||||
|
actionField.data.loading = true;
|
||||||
|
for (const key in values) {
|
||||||
|
if (Object.prototype.hasOwnProperty.call(values, key)) {
|
||||||
|
const value = values[key];
|
||||||
|
if (BulkEditFormItemValueType.Clear in value) {
|
||||||
|
values[key] = null;
|
||||||
|
} else if (BulkEditFormItemValueType.ChangedTo in value) {
|
||||||
|
values[key] = value[BulkEditFormItemValueType.ChangedTo];
|
||||||
|
} else if (BulkEditFormItemValueType.RemainsTheSame in value) {
|
||||||
|
delete values[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const updateData: { filter?: any; values: any; forceUpdate: boolean } = {
|
||||||
|
values,
|
||||||
|
filter,
|
||||||
|
forceUpdate: false,
|
||||||
|
};
|
||||||
|
if (updateMode === 'selected') {
|
||||||
|
if (!selectedRecordKeys?.length) {
|
||||||
|
message.error(t('Please select the records to be updated'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
updateData.filter = { $and: [{ [rowKey || 'id']: { $in: selectedRecordKeys } }] };
|
||||||
|
}
|
||||||
|
if (!updateData.filter) {
|
||||||
|
updateData.forceUpdate = true;
|
||||||
|
}
|
||||||
|
await resource.update(updateData);
|
||||||
|
actionField.data.loading = false;
|
||||||
|
if (!(resource instanceof TableFieldResource)) {
|
||||||
|
__parent?.__parent?.service?.refresh?.();
|
||||||
|
}
|
||||||
|
__parent?.service?.refresh?.();
|
||||||
|
setVisible?.(false);
|
||||||
|
if (!onSuccess?.successMessage) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (onSuccess?.manualClose) {
|
||||||
|
modal.success({
|
||||||
|
title: compile(onSuccess?.successMessage),
|
||||||
|
onOk: async () => {
|
||||||
|
await form.reset();
|
||||||
|
if (onSuccess?.redirecting && onSuccess?.redirectTo) {
|
||||||
|
if (isURL(onSuccess.redirectTo)) {
|
||||||
|
window.location.href = onSuccess.redirectTo;
|
||||||
|
} else {
|
||||||
|
navigate(onSuccess.redirectTo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
message.success(compile(onSuccess?.successMessage));
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
actionField.data.loading = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user