import { useBlockRequestContext, useTableBlockContext, useCompile, useRecord, useVariables, useCollection, useLocalVariables, isVariable, transformVariableValue, TableFieldResource, } from '@nocobase/client'; import { isURL } from '@nocobase/utils/client'; import { SchemaExpressionScopeContext, useFieldSchema, useField } from '@formily/react'; import { useNavigate } from 'react-router-dom'; import { App, message } from 'antd'; import { useContext } from 'react'; import { useBulkUpdateTranslation } from './locale'; export const useCustomizeBulkUpdateActionProps = () => { const { field, resource, __parent, service } = useBlockRequestContext(); const expressionScope = useContext(SchemaExpressionScopeContext); const actionSchema = useFieldSchema(); const tableBlockContext = useTableBlockContext(); const { rowKey } = tableBlockContext; const selectedRecordKeys = tableBlockContext.field?.data?.selectedRowKeys ?? expressionScope?.selectedRecordKeys ?? {}; const navigate = useNavigate(); const compile = useCompile(); const { t } = useBulkUpdateTranslation(); const actionField: any = useField(); const { modal } = App.useApp(); const variables = useVariables(); const record = useRecord(); const { name, getField } = useCollection(); const localVariables = useLocalVariables({ currentRecord: { __parent: record, __collectionName: name } }); return { async onClick() { const { assignedValues: originalAssignedValues = {}, onSuccess, updateMode, } = actionSchema?.['x-action-settings'] ?? {}; actionField.data = field.data || {}; actionField.data.loading = true; const assignedValues = {}; const waitList = Object.keys(originalAssignedValues).map(async (key) => { const value = originalAssignedValues[key]; const collectionField = getField(key); if (process.env.NODE_ENV !== 'production') { if (!collectionField) { throw new Error(`useCustomizeBulkUpdateActionProps: field "${key}" not found in collection "${name}"`); } } if (isVariable(value)) { const result = await variables?.parseVariable(value, localVariables); if (result) { assignedValues[key] = transformVariableValue(result, { targetCollectionField: collectionField }); } } else if (value != null && value !== '') { assignedValues[key] = value; } }); await Promise.all(waitList); modal.confirm({ title: t('Bulk update', { ns: 'client' }), content: updateMode === 'selected' ? t('Update selected data?', { ns: 'client' }) : t('Update all data?', { ns: 'client' }), async onOk() { const { filter } = service.params?.[0] ?? {}; const updateData: { filter?: any; values: any; forceUpdate: boolean } = { values: { ...assignedValues }, filter, forceUpdate: false, }; if (updateMode === 'selected') { if (!selectedRecordKeys?.length) { message.error(t('Please select the records to be updated')); actionField.data.loading = false; return; } updateData.filter = { $and: [{ [rowKey || 'id']: { $in: selectedRecordKeys } }] }; } if (!updateData.filter) { updateData.forceUpdate = true; } try { await resource.update(updateData); } catch (error) { /* empty */ } finally { actionField.data.loading = false; } service?.refresh?.(); if (!(resource instanceof TableFieldResource)) { __parent?.service?.refresh?.(); } if (!onSuccess?.successMessage) { return; } if (onSuccess?.manualClose) { modal.success({ title: compile(onSuccess?.successMessage), onOk: async () => { if (onSuccess?.redirecting && onSuccess?.redirectTo) { if (isURL(onSuccess.redirectTo)) { window.location.href = onSuccess.redirectTo; } else { navigate(onSuccess.redirectTo); } } }, }); } else { message.success(compile(onSuccess?.successMessage)); if (onSuccess?.redirecting && onSuccess?.redirectTo) { if (isURL(onSuccess.redirectTo)) { window.location.href = onSuccess.redirectTo; } else { navigate(onSuccess.redirectTo); } } } }, async onCancel() { actionField.data.loading = false; }, }); }, }; };