@craftercms/studio-ui
Version:
Services, components, models & utils to build CrafterCMS authoring extensions.
420 lines (418 loc) • 19.4 kB
JavaScript
/*
* Copyright (C) 2007-2022 Crafter Software Corporation. All Rights Reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Copyright (C) 2007-2022 Crafter Software Corporation. All Rights Reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import React, { lazy, Suspense, useEffect } from 'react';
import { useDispatch } from 'react-redux';
import { isPlainObject } from '../../utils/object';
import { useSnackbar } from 'notistack';
import { getHostToHostBus } from '../../utils/subjects';
import { filter } from 'rxjs/operators';
import { showSystemNotification } from '../../state/actions/system';
import Launcher from '../Launcher/Launcher';
import useSelection from '../../hooks/useSelection';
import { useWithPendingChangesCloseRequest } from '../../hooks/useWithPendingChangesCloseRequest';
import MinimizedBar from '../MinimizedBar';
import { RenameAssetDialog } from '../RenameAssetDialog';
const ViewVersionDialog = lazy(() => import('../ViewVersionDialog'));
const CompareVersionsDialog = lazy(() => import('../CompareVersionsDialog'));
const RejectDialog = lazy(() => import('../RejectDialog'));
const EditSiteDialog = lazy(() => import('../EditSiteDialog'));
const ConfirmDialog = lazy(() => import('../ConfirmDialog'));
const ErrorDialog = lazy(() => import('../ErrorDialog'));
const NewContentDialog = lazy(() => import('../NewContentDialog'));
const ChangeContentTypeDialog = lazy(() => import('../ChangeContentTypeDialog'));
const HistoryDialog = lazy(() => import('../HistoryDialog'));
const PublishDialog = lazy(() => import('../PublishDialog'));
const DependenciesDialog = lazy(() => import('../DependenciesDialog/DependenciesDialog'));
const DeleteDialog = lazy(() => import('../DeleteDialog'));
const WorkflowCancellationDialog = lazy(() => import('../WorkflowCancellationDialog'));
const LegacyFormDialog = lazy(() => import('../LegacyFormDialog'));
const CreateFolderDialog = lazy(() => import('../CreateFolderDialog'));
const CopyItemsDialog = lazy(() => import('../CopyDialog'));
const CreateFileDialog = lazy(() => import('../CreateFileDialog'));
const BulkUploadDialog = lazy(() => import('../UploadDialog'));
const SingleFileUploadDialog = lazy(() => import('../SingleFileUploadDialog'));
const PreviewDialog = lazy(() => import('../PreviewDialog'));
const ItemMenu = lazy(() => import('../ItemActionsMenu'));
const ItemMegaMenu = lazy(() => import('../ItemMegaMenu'));
const AuthMonitor = lazy(() => import('../AuthMonitor'));
const PublishingStatusDialog = lazy(() => import('../PublishingStatusDialog'));
const UIBlocker = lazy(() => import('../UIBlocker'));
const PathSelectionDialog = lazy(() => import('../PathSelectionDialog'));
const UnlockPublisherDialog = lazy(() => import('../UnlockPublisherDialog'));
const WidgetDialog = lazy(() => import('../WidgetDialog'));
const CodeEditorDialog = lazy(() => import('../CodeEditorDialog'));
// @formatter:off
function createCallback(action, dispatch) {
// prettier-ignore
return action ? (output) => {
const hasPayload = Boolean(action.payload);
const hasOutput = Boolean(output) && isPlainObject(output);
const payload = (hasPayload && !hasOutput)
// If there's a payload in the original action and there
// is no output from the resulting callback, simply use the
// original payload
? action.payload
// Otherwise, if there's no payload but there is an output sent
// to the resulting callback, use the output as the payload
: (!hasPayload && hasOutput)
? output
: ((hasPayload && hasOutput)
// If there's an output and a payload, merge them both into a single object.
// We're supposed to be using objects for all our payloads, otherwise this
// could fail with literal native values such as strings or numbers.
? Array.isArray(action.payload)
// If it's an array, assume is a BATCH_ACTIONS action payload; each item
// of the array should be an action, so merge each item with output.
? action.payload.map((a) => (Object.assign(Object.assign({}, a), { payload: Object.assign(Object.assign({}, a.payload), output) })))
// If it's not an array, it's a single action. Merge with output.
: Object.assign(Object.assign({}, action.payload), output)
// Later, we check if there's a payload to add it
: false);
dispatch(Object.assign({ type: action.type }, (payload ? { payload } : {})));
} : null;
}
// @formatter:on
function GlobalDialogManager() {
var _a, _b, _c;
const state = useSelection((state) => state.dialogs);
const contentTypesBranch = useSelection((state) => state.contentTypes);
const versionsBranch = useSelection((state) => state.versions);
const { enqueueSnackbar } = useSnackbar();
const dispatch = useDispatch();
useEffect(() => {
const hostToHost$ = getHostToHostBus();
const subscription = hostToHost$
.pipe(filter((e) => e.type === showSystemNotification.type))
.subscribe(({ payload }) => {
enqueueSnackbar(payload.message, payload.options);
});
return () => {
subscription.unsubscribe();
};
}, [enqueueSnackbar]);
return React.createElement(
Suspense,
{ fallback: '' },
React.createElement(
ConfirmDialog,
Object.assign({}, state.confirm, {
onOk: createCallback(state.confirm.onOk, dispatch),
onCancel: createCallback(state.confirm.onCancel, dispatch),
onClose: createCallback(state.confirm.onClose, dispatch),
onClosed: createCallback(state.confirm.onClosed, dispatch)
})
),
React.createElement(
ErrorDialog,
Object.assign({}, state.error, {
onClose: createCallback(state.error.onClose, dispatch),
onClosed: createCallback(state.error.onClosed, dispatch),
onDismiss: createCallback(state.error.onDismiss, dispatch)
})
),
React.createElement(
LegacyFormDialog,
Object.assign({}, state.edit, {
onClose: createCallback(state.edit.onClose, dispatch),
onMinimize: createCallback(state.edit.onMinimize, dispatch),
onMaximize: createCallback(state.edit.onMaximize, dispatch),
onClosed: createCallback(state.edit.onClosed, dispatch),
onSaveSuccess: createCallback(state.edit.onSaveSuccess, dispatch)
})
),
React.createElement(
CodeEditorDialog,
Object.assign({}, state.codeEditor, {
onClose: createCallback(state.codeEditor.onClose, dispatch),
onMinimize: createCallback(state.codeEditor.onMinimize, dispatch),
onMaximize: createCallback(state.codeEditor.onMaximize, dispatch),
onClosed: createCallback(state.codeEditor.onClosed, dispatch),
onSuccess: createCallback(state.codeEditor.onSuccess, dispatch),
onFullScreen: createCallback(state.codeEditor.onFullScreen, dispatch),
onCancelFullScreen: createCallback(state.codeEditor.onCancelFullScreen, dispatch),
onWithPendingChangesCloseRequest: useWithPendingChangesCloseRequest(
createCallback(state.codeEditor.onClose, dispatch)
)
})
),
React.createElement(
PublishDialog,
Object.assign({}, state.publish, {
onClose: createCallback(state.publish.onClose, dispatch),
onClosed: createCallback(state.publish.onClosed, dispatch),
onSuccess: createCallback(state.publish.onSuccess, dispatch),
onWithPendingChangesCloseRequest: useWithPendingChangesCloseRequest(
createCallback(state.publish.onClose, dispatch)
)
})
),
React.createElement(
NewContentDialog,
Object.assign({}, state.newContent, {
onContentTypeSelected: createCallback(state.newContent.onContentTypeSelected, dispatch),
onClose: createCallback(state.newContent.onClose, dispatch),
onClosed: createCallback(state.newContent.onClosed, dispatch)
})
),
React.createElement(
ChangeContentTypeDialog,
Object.assign({}, state.changeContentType, {
onContentTypeSelected: createCallback(state.changeContentType.onContentTypeSelected, dispatch),
onClose: createCallback(state.changeContentType.onClose, dispatch),
onClosed: createCallback(state.changeContentType.onClosed, dispatch)
})
),
React.createElement(
DependenciesDialog,
Object.assign({}, state.dependencies, {
onClose: createCallback(state.dependencies.onClose, dispatch),
onClosed: createCallback(state.dependencies.onClosed, dispatch)
})
),
React.createElement(
DeleteDialog,
Object.assign({}, state.delete, {
onClose: createCallback(state.delete.onClose, dispatch),
onClosed: createCallback(state.delete.onClosed, dispatch),
onSuccess: createCallback(state.delete.onSuccess, dispatch),
onWithPendingChangesCloseRequest: useWithPendingChangesCloseRequest(
createCallback(state.delete.onClose, dispatch)
)
})
),
React.createElement(
HistoryDialog,
Object.assign({}, state.history, {
versionsBranch: versionsBranch,
onClose: createCallback(state.history.onClose, dispatch),
onClosed: createCallback(state.history.onClosed, dispatch)
})
),
React.createElement(
ViewVersionDialog,
Object.assign({}, state.viewVersion, {
rightActions:
(_a = state.viewVersion.rightActions) === null || _a === void 0
? void 0
: _a.map((action) =>
Object.assign(Object.assign({}, action), { onClick: createCallback(action.onClick, dispatch) })
),
leftActions:
(_b = state.viewVersion.leftActions) === null || _b === void 0
? void 0
: _b.map((action) =>
Object.assign(Object.assign({}, action), { onClick: createCallback(action.onClick, dispatch) })
),
contentTypesBranch: contentTypesBranch,
onClose: createCallback(state.viewVersion.onClose, dispatch),
onClosed: createCallback(state.viewVersion.onClosed, dispatch)
})
),
React.createElement(
CompareVersionsDialog,
Object.assign({}, state.compareVersions, {
rightActions:
(_c = state.compareVersions.rightActions) === null || _c === void 0
? void 0
: _c.map((action) =>
Object.assign(Object.assign({}, action), { onClick: createCallback(action.onClick, dispatch) })
),
contentTypesBranch: contentTypesBranch,
selectedA: (versionsBranch === null || versionsBranch === void 0 ? void 0 : versionsBranch.selected[0])
? versionsBranch.byId[versionsBranch.selected[0]]
: null,
selectedB: (versionsBranch === null || versionsBranch === void 0 ? void 0 : versionsBranch.selected[1])
? versionsBranch.byId[versionsBranch.selected[1]]
: null,
versionsBranch: versionsBranch,
onClose: createCallback(state.compareVersions.onClose, dispatch),
onClosed: createCallback(state.compareVersions.onClosed, dispatch)
})
),
React.createElement(AuthMonitor, null),
React.createElement(
WorkflowCancellationDialog,
Object.assign({}, state.workflowCancellation, {
onClose: createCallback(state.workflowCancellation.onClose, dispatch),
onClosed: createCallback(state.workflowCancellation.onClosed, dispatch),
onContinue: createCallback(state.workflowCancellation.onContinue, dispatch)
})
),
React.createElement(
RejectDialog,
Object.assign({}, state.reject, {
onClose: createCallback(state.reject.onClose, dispatch),
onClosed: createCallback(state.reject.onClosed, dispatch),
onRejectSuccess: createCallback(state.reject.onRejectSuccess, dispatch),
onWithPendingChangesCloseRequest: useWithPendingChangesCloseRequest(
createCallback(state.reject.onClose, dispatch)
)
})
),
React.createElement(
CreateFolderDialog,
Object.assign({}, state.createFolder, {
onClose: createCallback(state.createFolder.onClose, dispatch),
onClosed: createCallback(state.createFolder.onClosed, dispatch),
onCreated: createCallback(state.createFolder.onCreated, dispatch),
onRenamed: createCallback(state.createFolder.onRenamed, dispatch),
onWithPendingChangesCloseRequest: useWithPendingChangesCloseRequest(
createCallback(state.createFolder.onClose, dispatch)
)
})
),
React.createElement(
CreateFileDialog,
Object.assign({}, state.createFile, {
onClose: createCallback(state.createFile.onClose, dispatch),
onClosed: createCallback(state.createFile.onClosed, dispatch),
onCreated: createCallback(state.createFile.onCreated, dispatch),
onWithPendingChangesCloseRequest: useWithPendingChangesCloseRequest(
createCallback(state.createFile.onClose, dispatch)
)
})
),
React.createElement(
RenameAssetDialog,
Object.assign({}, state.renameAsset, {
onClose: createCallback(state.renameAsset.onClose, dispatch),
onClosed: createCallback(state.renameAsset.onClosed, dispatch),
onRenamed: createCallback(state.renameAsset.onRenamed, dispatch),
onWithPendingChangesCloseRequest: useWithPendingChangesCloseRequest(
createCallback(state.renameAsset.onClose, dispatch)
)
})
),
React.createElement(
CopyItemsDialog,
Object.assign({}, state.copy, {
onClose: createCallback(state.copy.onClose, dispatch),
onClosed: createCallback(state.copy.onClosed, dispatch),
onOk: createCallback(state.copy.onOk, dispatch)
})
),
React.createElement(
BulkUploadDialog,
Object.assign({}, state.upload, {
onClose: createCallback(state.upload.onClose, dispatch),
onClosed: createCallback(state.upload.onClosed, dispatch)
})
),
React.createElement(
SingleFileUploadDialog,
Object.assign({}, state.singleFileUpload, {
onClose: createCallback(state.singleFileUpload.onClose, dispatch),
onClosed: createCallback(state.singleFileUpload.onClosed, dispatch),
onUploadStart: createCallback(state.singleFileUpload.onUploadStart, dispatch),
onUploadComplete: createCallback(state.singleFileUpload.onUploadComplete, dispatch),
onUploadError: createCallback(state.singleFileUpload.onUploadError, dispatch)
})
),
React.createElement(
PreviewDialog,
Object.assign({}, state.preview, {
onMinimize: createCallback(state.preview.onMinimize, dispatch),
onMaximize: createCallback(state.preview.onMaximize, dispatch),
onClose: createCallback(state.preview.onClose, dispatch),
onClosed: createCallback(state.preview.onClosed, dispatch),
onFullScreen: createCallback(state.preview.onFullScreen, dispatch),
onCancelFullScreen: createCallback(state.preview.onCancelFullScreen, dispatch)
})
),
React.createElement(
EditSiteDialog,
Object.assign({}, state.editSite, {
onClose: createCallback(state.editSite.onClose, dispatch),
onClosed: createCallback(state.editSite.onClosed, dispatch),
onSaveSuccess: createCallback(state.editSite.onSaveSuccess, dispatch),
onSiteImageChange: createCallback(state.editSite.onSiteImageChange, dispatch),
onWithPendingChangesCloseRequest: useWithPendingChangesCloseRequest(
createCallback(state.editSite.onClose, dispatch)
)
})
),
React.createElement(
PathSelectionDialog,
Object.assign({}, state.pathSelection, {
onClose: createCallback(state.pathSelection.onClose, dispatch),
onClosed: createCallback(state.pathSelection.onClosed, dispatch),
onOk: createCallback(state.pathSelection.onOk, dispatch)
})
),
React.createElement(
ItemMenu,
Object.assign({}, state.itemMenu, { onClose: createCallback(state.itemMenu.onClose, dispatch) })
),
React.createElement(
ItemMegaMenu,
Object.assign({}, state.itemMegaMenu, { onClose: createCallback(state.itemMegaMenu.onClose, dispatch) })
),
React.createElement(Launcher, Object.assign({}, state.launcher)),
React.createElement(
PublishingStatusDialog,
Object.assign({}, state.publishingStatus, {
onClose: createCallback(state.publishingStatus.onClose, dispatch),
onRefresh: createCallback(state.publishingStatus.onRefresh, dispatch),
onUnlock: createCallback(state.publishingStatus.onUnlock, dispatch)
})
),
React.createElement(UnlockPublisherDialog, {
open: state.unlockPublisher.open,
onError: createCallback(state.unlockPublisher.onError, dispatch),
onCancel: createCallback(state.unlockPublisher.onCancel, dispatch),
onComplete: createCallback(state.unlockPublisher.onComplete, dispatch)
}),
React.createElement(
WidgetDialog,
Object.assign({}, state.widget, {
onClose: createCallback(state.widget.onClose, dispatch),
onMinimize: createCallback(state.widget.onMinimize, dispatch),
onMaximize: createCallback(state.widget.onMaximize, dispatch),
onClosed: createCallback(state.widget.onClosed, dispatch),
onWithPendingChangesCloseRequest: useWithPendingChangesCloseRequest(
createCallback(state.widget.onClose, dispatch)
)
})
),
Object.values(state.minimizedTabs).map((tab) =>
React.createElement(MinimizedBar, {
key: tab.id,
open: tab.minimized,
title: tab.title,
subtitle: tab.subtitle,
status: tab.status,
onMaximize: createCallback(tab.onMaximized, dispatch)
})
),
React.createElement(UIBlocker, Object.assign({}, state.uiBlocker))
);
}
export default React.memo(GlobalDialogManager);