@atlaskit/editor-plugin-synced-block
Version:
SyncedBlock plugin for @atlaskit/editor-core
233 lines (232 loc) • 11 kB
JavaScript
/* DeleteConfirmationModal.tsx generated by @compiled/babel-plugin v0.39.1 */
import "./DeleteConfirmationModal.compiled.css";
import { ax, ix } from "@compiled/react/runtime";
import React, { useCallback, useEffect, useState } from 'react';
import { useIntl } from 'react-intl-next';
import Button from '@atlaskit/button/new';
import { useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks';
import { syncBlockMessages as messages } from '@atlaskit/editor-common/messages';
import { isOfflineMode } from '@atlaskit/editor-plugin-connectivity';
import ModalDialog, { ModalBody, ModalFooter, ModalHeader, ModalTitle, ModalTransition } from '@atlaskit/modal-dialog';
import { fg } from '@atlaskit/platform-feature-flags';
import { Text, Box } from '@atlaskit/primitives/compiled';
import Spinner from '@atlaskit/spinner';
import { syncedBlockPluginKey } from '../pm-plugins/main';
const modalContentMapOld = {
'source-block-deleted': {
titleMultiple: messages.deleteConfirmationModalTitleMultiple,
titleSingle: messages.deletionConfirmationModalTitleSingle,
descriptionSingle: messages.deletionConfirmationModalDescriptionNoRef,
descriptionMultiple: messages.deletionConfirmationModalDescription,
confirmButtonLabel: messages.deleteConfirmationModalDeleteButton
},
'source-block-unpublished': {
titleMultiple: messages.deleteConfirmationModalTitleMultiple,
titleSingle: messages.deletionConfirmationModalTitleSingle,
descriptionSingle: messages.deletionConfirmationModalDescriptionNoRef,
descriptionMultiple: messages.deletionConfirmationModalDescription,
confirmButtonLabel: messages.deleteConfirmationModalDeleteButton
},
'source-block-unsynced': {
titleMultiple: messages.unsyncConfirmationModalTitle,
titleSingle: messages.unsyncConfirmationModalTitle,
descriptionSingle: messages.unsyncConfirmModalDescriptionSingle,
descriptionMultiple: messages.unsyncConfirmModalDescriptionMultiple,
confirmButtonLabel: messages.deleteConfirmationModalUnsyncButton
}
};
const modalContentMap = {
'source-block-deleted': {
titleMultiple: messages.deleteConfirmationModalTitleMultiple,
titleSingle: messages.deletionConfirmationModalTitleSingle,
descriptionSingle: messages.deletionConfirmationModalDescriptionNoRef,
descriptionMultiple: messages.deletionConfirmationModalDescriptionNew,
confirmButtonLabel: messages.deleteConfirmationModalDeleteButton
},
'source-block-unpublished': {
titleMultiple: messages.deleteConfirmationModalTitleMultiple,
titleSingle: messages.deletionConfirmationModalTitleSingle,
descriptionSingle: messages.deletionConfirmationModalDescriptionNoRef,
descriptionMultiple: messages.deletionConfirmationModalDescriptionNew,
confirmButtonLabel: messages.deleteConfirmationModalDeleteButton
},
'source-block-unsynced': {
titleMultiple: messages.unsyncConfirmationModalTitle,
titleSingle: messages.unsyncConfirmationModalTitle,
descriptionSingle: messages.unsyncConfirmModalDescriptionSingle,
descriptionMultiple: messages.unsyncConfirmModalDescriptionMultipleNew,
confirmButtonLabel: messages.deleteConfirmationModalUnsyncButton
}
};
const styles = {
spinner: "_1mou1wug _195g1wug"
};
export const DeleteConfirmationModal = ({
syncBlockStoreManager,
api
}) => {
var _api$core2, _api$core4, _api$core6;
const [isOpen, setIsOpen] = useState(false);
const [syncBlockIds, setSyncBlockIds] = useState(undefined);
const [referenceCount, setReferenceCount] = useState(undefined);
const [deleteReason, setDeleteReason] = useState('source-block-deleted');
const {
mode,
bodiedSyncBlockDeletionStatus,
activeFlag
} = useSharedPluginStateWithSelector(api, ['connectivity', 'syncedBlock'], states => {
var _states$connectivityS, _states$syncedBlockSt, _states$syncedBlockSt2;
return {
mode: (_states$connectivityS = states.connectivityState) === null || _states$connectivityS === void 0 ? void 0 : _states$connectivityS.mode,
bodiedSyncBlockDeletionStatus: (_states$syncedBlockSt = states.syncedBlockState) === null || _states$syncedBlockSt === void 0 ? void 0 : _states$syncedBlockSt.bodiedSyncBlockDeletionStatus,
activeFlag: (_states$syncedBlockSt2 = states.syncedBlockState) === null || _states$syncedBlockSt2 === void 0 ? void 0 : _states$syncedBlockSt2.activeFlag
};
});
const {
formatMessage
} = useIntl();
const resolverRef = React.useRef(undefined);
const handleClick = useCallback(confirm => () => {
var _api$core;
if (resolverRef.current) {
resolverRef.current(confirm);
resolverRef.current = undefined;
}
if (!confirm) {
setIsOpen(false);
setReferenceCount(undefined);
}
api === null || api === void 0 ? void 0 : (_api$core = api.core) === null || _api$core === void 0 ? void 0 : _api$core.actions.execute(({
tr
}) => {
return tr.setMeta(syncedBlockPluginKey, {
bodiedSyncBlockDeletionStatus: confirm ? 'processing' : 'none',
activeFlag: false
});
});
}, [api === null || api === void 0 ? void 0 : (_api$core2 = api.core) === null || _api$core2 === void 0 ? void 0 : _api$core2.actions]);
const confirmationCallback = useCallback((syncBlockIds, deleteReason) => {
setIsOpen(true);
setSyncBlockIds(syncBlockIds);
if (deleteReason) {
setDeleteReason(deleteReason);
}
const confirmedPromise = new Promise(resolve => {
resolverRef.current = resolve;
});
if (activeFlag) {
var _api$core3;
api === null || api === void 0 ? void 0 : (_api$core3 = api.core) === null || _api$core3 === void 0 ? void 0 : _api$core3.actions.execute(({
tr
}) => {
return tr.setMeta(syncedBlockPluginKey, {
// Clear flag to avoid potential retry deletion of different blocks
activeFlag: false
});
});
}
return confirmedPromise;
}, [activeFlag, api === null || api === void 0 ? void 0 : (_api$core4 = api.core) === null || _api$core4 === void 0 ? void 0 : _api$core4.actions]);
useEffect(() => {
const unregister = syncBlockStoreManager.sourceManager.registerConfirmationCallback(confirmationCallback);
return () => {
unregister();
};
}, [syncBlockStoreManager, confirmationCallback]);
useEffect(() => {
if (bodiedSyncBlockDeletionStatus === 'completed' && isOpen) {
var _api$core5;
// auto close modal once deletion is successful
// eslint-disable-next-line @atlassian/perf-linting/no-chain-state-updates -- Ignored via go/ees017 (to be fixed)
setIsOpen(false);
api === null || api === void 0 ? void 0 : (_api$core5 = api.core) === null || _api$core5 === void 0 ? void 0 : _api$core5.actions.execute(({
tr
}) => {
return tr.setMeta(syncedBlockPluginKey, {
// Reset deletion status to have a clean state for next deletion
bodiedSyncBlockDeletionStatus: 'none'
});
});
}
}, [api === null || api === void 0 ? void 0 : (_api$core6 = api.core) === null || _api$core6 === void 0 ? void 0 : _api$core6.actions, bodiedSyncBlockDeletionStatus, isOpen]);
useEffect(() => {
if (isOpen && syncBlockIds !== undefined) {
const fetchReferences = async () => {
try {
const references = await Promise.all(syncBlockIds.map(async syncBlockId => {
var _references$reference, _references$reference2;
const references = await syncBlockStoreManager.sourceManager.fetchReferences(syncBlockId.resourceId);
if (references !== null && references !== void 0 && references.error) {
// Consider fetch fails as soon as one of the fetches fails
throw new Error();
}
return (_references$reference = (_references$reference2 = references.references) === null || _references$reference2 === void 0 ? void 0 : _references$reference2.length) !== null && _references$reference !== void 0 ? _references$reference : 0;
}));
const totalCount = references.reduce((sum, count) => sum + count, 0);
setReferenceCount(totalCount);
} catch {
setReferenceCount(0);
}
};
// eslint-disable-next-line @atlassian/perf-linting/no-chain-state-updates -- Ignored via go/ees017 (to be fixed)
fetchReferences();
}
}, [isOpen, syncBlockIds, syncBlockStoreManager.sourceManager]);
return /*#__PURE__*/React.createElement(ModalTransition, null, isOpen && /*#__PURE__*/React.createElement(ModalDialog, {
onClose: handleClick(false),
testId: "sync-block-delete-confirmation",
height: 184
}, /*#__PURE__*/React.createElement(React.Fragment, null, referenceCount === undefined ? /*#__PURE__*/React.createElement(Box, {
xcss: styles.spinner
}, /*#__PURE__*/React.createElement(Spinner, {
size: "large"
})) : /*#__PURE__*/React.createElement(ModalContent, {
content: fg('platform_synced_block_patch_8') ? modalContentMap[deleteReason] : modalContentMapOld[deleteReason],
referenceCount: referenceCount,
handleClick: handleClick,
formatMessage: formatMessage,
isDeleting: bodiedSyncBlockDeletionStatus === 'processing',
isDisabled: isOfflineMode(mode),
deleteReason: deleteReason,
sourceCount: (syncBlockIds === null || syncBlockIds === void 0 ? void 0 : syncBlockIds.length) || 0
}))));
};
const ModalContent = ({
content,
referenceCount,
handleClick,
formatMessage,
isDeleting,
isDisabled,
deleteReason,
sourceCount
}) => {
const {
titleMultiple,
titleSingle,
descriptionSingle,
descriptionMultiple,
confirmButtonLabel
} = content;
const hasNoReferenceOrFailToFetch = referenceCount === 0;
const syncBlockCount = deleteReason === 'source-block-deleted' ? referenceCount + sourceCount : referenceCount;
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(ModalHeader, {
hasCloseButton: true
}, /*#__PURE__*/React.createElement(ModalTitle, {
appearance: "warning"
}, hasNoReferenceOrFailToFetch ? formatMessage(titleSingle) : formatMessage(titleMultiple, {
count: syncBlockCount
}))), /*#__PURE__*/React.createElement(ModalBody, null, /*#__PURE__*/React.createElement(Text, null, hasNoReferenceOrFailToFetch ? formatMessage(descriptionSingle) : formatMessage(descriptionMultiple, {
syncBlockCount
}))), /*#__PURE__*/React.createElement(ModalFooter, null, /*#__PURE__*/React.createElement(Button, {
appearance: "subtle",
onClick: handleClick(false)
}, formatMessage(messages.deleteConfirmationModalCancelButton)), /*#__PURE__*/React.createElement(Button, {
appearance: "warning",
onClick: handleClick(true),
autoFocus: true,
isDisabled: isDisabled,
isLoading: isDeleting,
testId: `synced-block-delete-confirmation-modal-${deleteReason}-button`
}, formatMessage(confirmButtonLabel))));
};