Files
pole-book/server/node_modules/@strapi/content-manager/dist/admin/hooks/useDocumentActions.mjs

587 lines
20 KiB
JavaScript

import * as React from 'react';
import { useNotification, useTracking, useAPIErrorHandler, useGuidedTour } from '@strapi/admin/strapi-admin';
import { useIntl } from 'react-intl';
import { useNavigate } from 'react-router-dom';
import { useRelationModal } from '../pages/EditView/components/FormInputs/Relations/RelationModal.mjs';
import { usePreviewContext } from '../preview/pages/Preview.mjs';
import { useDeleteDocumentMutation, useDeleteManyDocumentsMutation, useDiscardDocumentMutation, usePublishDocumentMutation, usePublishManyDocumentsMutation, useUpdateDocumentMutation, useUnpublishDocumentMutation, useUnpublishManyDocumentsMutation, useCreateDocumentMutation, useAutoCloneDocumentMutation, useCloneDocumentMutation, useLazyGetDocumentQuery } from '../services/documents.mjs';
import { getTranslation } from '../utils/translations.mjs';
const DEFAULT_UNEXPECTED_ERROR_MSG = {
id: 'notification.error',
defaultMessage: 'An error occurred, please try again'
};
/**
* @alpha
* @public
* @description Contains all the operations that can be performed on a single document.
* Designed to be able to be used anywhere within a Strapi app. The hooks will handle
* notifications should the operation fail, however the response is always returned incase
* the user needs to handle side-effects.
* @example
* ```tsx
* import { Form } from '@strapi/admin/admin';
*
* const { id, model, collectionType } = useParams<{ id: string; model: string; collectionType: string }>();
* const { update } = useDocumentActions();
*
* const handleSubmit = async (data) => {
* await update({ collectionType, model, documentId: id }, data);
* }
*
* return <Form method="PUT" onSubmit={handleSubmit} />
* ```
*
* @see {@link https://contributor.strapi.io/docs/core/content-manager/hooks/use-document-operations} for more information
*/ const useDocumentActions = ()=>{
const { toggleNotification } = useNotification();
const { formatMessage } = useIntl();
const { trackUsage } = useTracking();
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
const navigate = useNavigate();
const setCurrentStep = useGuidedTour('useDocumentActions', (state)=>state.setCurrentStep);
// Get metadata from context providers for tracking purposes
const previewContext = usePreviewContext('useDocumentActions', ()=>true, false);
const relationContext = useRelationModal('useDocumentActions', ()=>true, false);
const fromPreview = previewContext != undefined;
const fromRelationModal = relationContext != undefined;
const [deleteDocument, { isLoading: isDeleting }] = useDeleteDocumentMutation();
const _delete = React.useCallback(async ({ collectionType, model, documentId, params }, trackerProperty)=>{
try {
trackUsage('willDeleteEntry', trackerProperty);
const res = await deleteDocument({
collectionType,
model,
documentId,
params
});
if ('error' in res) {
toggleNotification({
type: 'danger',
message: formatAPIError(res.error)
});
return {
error: res.error
};
}
toggleNotification({
type: 'success',
message: formatMessage({
id: getTranslation('success.record.delete'),
defaultMessage: 'Deleted document'
})
});
trackUsage('didDeleteEntry', trackerProperty);
return res.data;
} catch (err) {
toggleNotification({
type: 'danger',
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
});
trackUsage('didNotDeleteEntry', {
error: err,
...trackerProperty
});
throw err;
}
}, [
trackUsage,
deleteDocument,
toggleNotification,
formatMessage,
formatAPIError
]);
const [deleteManyDocuments, { isLoading: isDeletingMany }] = useDeleteManyDocumentsMutation();
const deleteMany = React.useCallback(async ({ model, documentIds, params })=>{
try {
trackUsage('willBulkDeleteEntries');
const res = await deleteManyDocuments({
model,
documentIds,
params
});
if ('error' in res) {
toggleNotification({
type: 'danger',
message: formatAPIError(res.error)
});
return {
error: res.error
};
}
toggleNotification({
type: 'success',
title: formatMessage({
id: getTranslation('success.records.delete'),
defaultMessage: 'Successfully deleted.'
}),
message: ''
});
trackUsage('didBulkDeleteEntries');
return res.data;
} catch (err) {
toggleNotification({
type: 'danger',
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
});
trackUsage('didNotBulkDeleteEntries');
throw err;
}
}, [
trackUsage,
deleteManyDocuments,
toggleNotification,
formatMessage,
formatAPIError
]);
const [discardDocument, { isLoading: isDiscardingDocument }] = useDiscardDocumentMutation();
const discard = React.useCallback(async ({ collectionType, model, documentId, params })=>{
try {
const res = await discardDocument({
collectionType,
model,
documentId,
params
});
if ('error' in res) {
toggleNotification({
type: 'danger',
message: formatAPIError(res.error)
});
return {
error: res.error
};
}
toggleNotification({
type: 'success',
message: formatMessage({
id: 'content-manager.success.record.discard',
defaultMessage: 'Changes discarded'
})
});
return res.data;
} catch (err) {
toggleNotification({
type: 'danger',
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
});
throw err;
}
}, [
discardDocument,
formatAPIError,
formatMessage,
toggleNotification
]);
const [publishDocument, { isLoading: isPublishing }] = usePublishDocumentMutation();
const publish = React.useCallback(async ({ collectionType, model, documentId, params }, data)=>{
try {
trackUsage('willPublishEntry', {
documentId
});
const res = await publishDocument({
collectionType,
model,
documentId,
data,
params
});
if ('error' in res) {
toggleNotification({
type: 'danger',
message: formatAPIError(res.error)
});
return {
error: res.error
};
}
trackUsage('didPublishEntry', {
documentId,
fromPreview,
fromRelationModal
});
toggleNotification({
type: 'success',
message: formatMessage({
id: getTranslation('success.record.publish'),
defaultMessage: 'Published document'
})
});
return res.data;
} catch (err) {
toggleNotification({
type: 'danger',
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
});
throw err;
}
}, [
trackUsage,
publishDocument,
fromPreview,
fromRelationModal,
toggleNotification,
formatMessage,
formatAPIError
]);
const [publishManyDocuments, { isLoading: isPublishingMany }] = usePublishManyDocumentsMutation();
const publishMany = React.useCallback(async ({ model, documentIds, params })=>{
try {
// TODO Confirm tracking events for bulk publish?
const res = await publishManyDocuments({
model,
documentIds,
params
});
if ('error' in res) {
toggleNotification({
type: 'danger',
message: formatAPIError(res.error)
});
return {
error: res.error
};
}
toggleNotification({
type: 'success',
message: formatMessage({
id: getTranslation('success.record.publish'),
defaultMessage: 'Published document'
})
});
return res.data;
} catch (err) {
toggleNotification({
type: 'danger',
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
});
throw err;
}
}, [
// trackUsage,
publishManyDocuments,
toggleNotification,
formatMessage,
formatAPIError
]);
const [updateDocument, { isLoading: isUpdating }] = useUpdateDocumentMutation();
const update = React.useCallback(async ({ collectionType, model, documentId, params }, data, trackerProperty)=>{
try {
trackUsage('willEditEntry', trackerProperty);
const res = await updateDocument({
collectionType,
model,
documentId,
data,
params
});
if ('error' in res) {
toggleNotification({
type: 'danger',
message: formatAPIError(res.error)
});
trackUsage('didNotEditEntry', {
error: res.error,
...trackerProperty
});
return {
error: res.error
};
}
trackUsage('didEditEntry', {
...trackerProperty,
documentId: res.data.data.documentId,
fromPreview,
fromRelationModal
});
toggleNotification({
type: 'success',
message: formatMessage({
id: getTranslation('success.record.save'),
defaultMessage: 'Saved document'
})
});
return res.data;
} catch (err) {
trackUsage('didNotEditEntry', {
error: err,
...trackerProperty
});
toggleNotification({
type: 'danger',
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
});
throw err;
}
}, [
trackUsage,
updateDocument,
fromPreview,
fromRelationModal,
toggleNotification,
formatMessage,
formatAPIError
]);
const [unpublishDocument] = useUnpublishDocumentMutation();
const unpublish = React.useCallback(async ({ collectionType, model, documentId, params }, discardDraft = false)=>{
try {
trackUsage('willUnpublishEntry');
const res = await unpublishDocument({
collectionType,
model,
documentId,
params,
data: {
discardDraft
}
});
if ('error' in res) {
toggleNotification({
type: 'danger',
message: formatAPIError(res.error)
});
return {
error: res.error
};
}
trackUsage('didUnpublishEntry');
toggleNotification({
type: 'success',
message: formatMessage({
id: getTranslation('success.record.unpublish'),
defaultMessage: 'Unpublished document'
})
});
return res.data;
} catch (err) {
toggleNotification({
type: 'danger',
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
});
throw err;
}
}, [
trackUsage,
unpublishDocument,
toggleNotification,
formatMessage,
formatAPIError
]);
const [unpublishManyDocuments, { isLoading: isUnpublishingMany }] = useUnpublishManyDocumentsMutation();
const unpublishMany = React.useCallback(async ({ model, documentIds, params })=>{
try {
trackUsage('willBulkUnpublishEntries');
const res = await unpublishManyDocuments({
model,
documentIds,
params
});
if ('error' in res) {
toggleNotification({
type: 'danger',
message: formatAPIError(res.error)
});
return {
error: res.error
};
}
trackUsage('didBulkUnpublishEntries');
toggleNotification({
type: 'success',
title: formatMessage({
id: getTranslation('success.records.unpublish'),
defaultMessage: 'Successfully unpublished.'
}),
message: ''
});
return res.data;
} catch (err) {
toggleNotification({
type: 'danger',
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
});
trackUsage('didNotBulkUnpublishEntries');
throw err;
}
}, [
trackUsage,
unpublishManyDocuments,
toggleNotification,
formatMessage,
formatAPIError
]);
const [createDocument] = useCreateDocumentMutation();
const create = React.useCallback(async ({ model, params }, data, trackerProperty)=>{
try {
const res = await createDocument({
model,
data,
params
});
if ('error' in res) {
toggleNotification({
type: 'danger',
message: formatAPIError(res.error)
});
trackUsage('didNotCreateEntry', {
error: res.error,
...trackerProperty
});
return {
error: res.error
};
}
trackUsage('didCreateEntry', {
...trackerProperty,
documentId: res.data.data.documentId,
fromPreview,
fromRelationModal
});
toggleNotification({
type: 'success',
message: formatMessage({
id: getTranslation('success.record.save'),
defaultMessage: 'Saved document'
})
});
setCurrentStep('contentManager.success');
return res.data;
} catch (err) {
toggleNotification({
type: 'danger',
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
});
trackUsage('didNotCreateEntry', {
error: err,
...trackerProperty
});
throw err;
}
}, [
createDocument,
formatAPIError,
formatMessage,
fromPreview,
fromRelationModal,
setCurrentStep,
toggleNotification,
trackUsage
]);
const [autoCloneDocument] = useAutoCloneDocumentMutation();
const autoClone = React.useCallback(async ({ model, sourceId })=>{
try {
const res = await autoCloneDocument({
model,
sourceId
});
if ('error' in res) {
return {
error: res.error
};
}
toggleNotification({
type: 'success',
message: formatMessage({
id: getTranslation('success.record.clone'),
defaultMessage: 'Cloned document'
})
});
return res.data;
} catch (err) {
toggleNotification({
type: 'danger',
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
});
throw err;
}
}, [
autoCloneDocument,
formatMessage,
toggleNotification
]);
const [cloneDocument] = useCloneDocumentMutation();
const clone = React.useCallback(async ({ model, documentId, params }, body, trackerProperty)=>{
try {
const { id: _id, ...restBody } = body;
/**
* If we're cloning we want to post directly to this endpoint
* so that the relations even if they're not listed in the EditView
* are correctly attached to the entry.
*/ const res = await cloneDocument({
model,
sourceId: documentId,
data: restBody,
params
});
if ('error' in res) {
toggleNotification({
type: 'danger',
message: formatAPIError(res.error)
});
trackUsage('didNotCreateEntry', {
error: res.error,
...trackerProperty
});
return {
error: res.error
};
}
trackUsage('didCreateEntry', trackerProperty);
toggleNotification({
type: 'success',
message: formatMessage({
id: getTranslation('success.record.clone'),
defaultMessage: 'Cloned document'
})
});
// Redirect to normal edit view
navigate(`../../${res.data.data.documentId}`, {
relative: 'path'
});
return res.data;
} catch (err) {
toggleNotification({
type: 'danger',
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
});
trackUsage('didNotCreateEntry', {
error: err,
...trackerProperty
});
throw err;
}
}, [
cloneDocument,
trackUsage,
toggleNotification,
formatMessage,
formatAPIError,
navigate
]);
const [getDoc] = useLazyGetDocumentQuery();
const getDocument = React.useCallback(async (args)=>{
const { data } = await getDoc(args);
return data;
}, [
getDoc
]);
return {
isLoading: isPublishing || isUpdating || isDiscardingDocument || isDeleting || isDeletingMany || isUnpublishingMany || isPublishingMany,
autoClone,
clone,
create,
delete: _delete,
deleteMany,
discard,
getDocument,
publish,
publishMany,
unpublish,
unpublishMany,
update
};
};
export { useDocumentActions };
//# sourceMappingURL=useDocumentActions.mjs.map