UNPKG

@craftercms/studio-ui

Version:

Services, components, models & utils to build CrafterCMS authoring extensions.

460 lines (458 loc) 14.9 kB
/* * 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 { ofType } from 'redux-observable'; import { exhaustMap, filter, ignoreElements, map, startWith, switchMap, takeUntil, tap, withLatestFrom } from 'rxjs/operators'; import { getHostToHostBus } from '../../utils/subjects'; import { itemSuccessMessages } from '../../env/i18n-legacy'; import { emitSystemEvent, fetchGlobalMenu, fetchGlobalMenuComplete, fetchGlobalMenuFailed, messageSharedWorker, openSiteSocket, showCopyItemSuccessNotification, showCreateFolderSuccessNotification, showCreateItemSuccessNotification, showCutItemSuccessNotification, showDeleteItemSuccessNotification, showDuplicatedItemSuccessNotification, showEditItemSuccessNotification, showPasteItemSuccessNotification, showPublishItemSuccessNotification, showRejectItemSuccessNotification, showRevertItemSuccessNotification, showSystemNotification, showUnlockItemSuccessNotification, storeInitialized } from '../actions/system'; import { fetchPublishingStatus, fetchPublishingStatusComplete, fetchPublishingStatusFailed, fetchPublishingStatusProcessingComplete, startPublishingStatusFetcher, stopPublishingStatusFetcher } from '../actions/publishingStatus'; import { fetchStatus } from '../../services/publishing'; import { catchAjaxError } from '../../utils/ajax'; import { interval } from 'rxjs'; import { sessionTimeout } from '../actions/user'; import { sharedWorkerUnauthenticated } from '../actions/auth'; import { fetchGlobalMenuItems } from '../../services/configuration'; import { fetchSiteConfig } from '../actions/configuration'; import { getStoredShowToolsPanel } from '../../utils/state'; import { closeToolsPanel, openToolsPanel } from '../actions/preview'; import { getXSRFToken } from '../../utils/auth'; import { changeSite } from '../actions/sites'; const systemEpics = [ // region storeInitialized (action$, state$) => action$.pipe( ofType(storeInitialized.type), withLatestFrom(state$), switchMap(([, state]) => { var _a, _b; const hasActiveSite = Boolean(state.sites.active); const isActiveSiteAvailable = Boolean( (_a = state.sites.byId) === null || _a === void 0 ? void 0 : _a[state.sites.active] ); const showToolsPanel = hasActiveSite && isActiveSiteAvailable && getStoredShowToolsPanel( (_b = state.sites.byId) === null || _b === void 0 ? void 0 : _b[state.sites.active].uuid, state.user.username ); return [ fetchGlobalMenu(), ...(hasActiveSite ? [ startPublishingStatusFetcher(), fetchSiteConfig(), messageSharedWorker(openSiteSocket({ site: state.sites.active, xsrfToken: getXSRFToken() })), showToolsPanel === null || state.preview.showToolsPanel === showToolsPanel ? false : state.preview.showToolsPanel ? closeToolsPanel() : openToolsPanel() ].filter(Boolean) : []) ]; }) ), // endregion // region changeSite (action$) => action$.pipe( ofType(changeSite.type), switchMap(({ payload: { nextSite } }) => [ startPublishingStatusFetcher(), fetchSiteConfig(), messageSharedWorker(openSiteSocket({ site: nextSite, xsrfToken: getXSRFToken() })) ]) ), // endregion // region emitSystemEvent (action$) => action$.pipe( ofType(emitSystemEvent.type), tap(({ payload }) => { const hostToHost$ = getHostToHostBus(); hostToHost$.next(payload); }), map(({ payload: action }) => action) ), // endregion // region showDeleteItemSuccessNotification (action$, state$, { getIntl }) => action$.pipe( ofType(showDeleteItemSuccessNotification.type), tap(({ payload }) => { const hostToHost$ = getHostToHostBus(); hostToHost$.next( showSystemNotification({ message: getIntl().formatMessage(itemSuccessMessages.itemDeleted, { count: payload.items.length }) }) ); }), ignoreElements() ), // endregion // region showPublishItemSuccessNotification (action$, state$, { getIntl }) => action$.pipe( ofType(showPublishItemSuccessNotification.type), withLatestFrom(state$), tap(([{ payload }, state]) => { const hostToHost$ = getHostToHostBus(); const { type } = payload; hostToHost$.next( showSystemNotification({ message: payload.schedule === 'now' ? getIntl().formatMessage( type === 'publish' ? itemSuccessMessages.itemPublishedNow : itemSuccessMessages.itemRequestedToPublishNow, { count: payload.items.length, environment: payload.environment } ) : getIntl().formatMessage( type === 'publish' ? itemSuccessMessages.itemSchedulePublished : itemSuccessMessages.itemRequestedToSchedulePublish, { count: payload.items.length, environment: payload.environment } ) }) ); }), ignoreElements() ), // endregion // region showEditItemSuccessNotification (action$, state$, { getIntl }) => action$.pipe( ofType(showEditItemSuccessNotification.type), tap(({ payload: { action } }) => { let message; if (action === 'save') { message = getIntl().formatMessage(itemSuccessMessages.itemSavedAsDraft); } else { message = getIntl().formatMessage(itemSuccessMessages.itemEdited); } const hostToHost$ = getHostToHostBus(); hostToHost$.next( showSystemNotification({ message, options: { variant: action === 'save' ? 'warning' : 'default' } }) ); }), ignoreElements() ), // endregion // region showCreateItemSuccessNotification (action$, state$, { getIntl }) => action$.pipe( ofType(showCreateItemSuccessNotification.type), tap(({ payload: { action } }) => { const hostToHost$ = getHostToHostBus(); hostToHost$.next( showSystemNotification({ message: getIntl().formatMessage(itemSuccessMessages.itemCreated) }) ); }), ignoreElements() ), // endregion // region showCreateFolderSuccessNotification (action$, state$, { getIntl }) => action$.pipe( ofType(showCreateFolderSuccessNotification.type), tap(({ payload: { action } }) => { const hostToHost$ = getHostToHostBus(); hostToHost$.next( showSystemNotification({ message: getIntl().formatMessage(itemSuccessMessages.folderCreated) }) ); }), ignoreElements() ), // endregion // region showCopyItemSuccessNotification (action$, state$, { getIntl }) => action$.pipe( ofType(showCopyItemSuccessNotification.type), tap(({ payload }) => { var _a; const hostToHost$ = getHostToHostBus(); hostToHost$.next( showSystemNotification({ message: getIntl().formatMessage(itemSuccessMessages.itemCopied, { count: (_a = payload === null || payload === void 0 ? void 0 : payload.paths.length) !== null && _a !== void 0 ? _a : 1 }) }) ); }), ignoreElements() ), // endregion // region showCutItemSuccessNotification (action$, state$, { getIntl }) => action$.pipe( ofType(showCutItemSuccessNotification.type), tap(({ payload }) => { const hostToHost$ = getHostToHostBus(); hostToHost$.next( showSystemNotification({ message: getIntl().formatMessage(itemSuccessMessages.itemCut) }) ); }), ignoreElements() ), // endregion // region showPasteItemSuccessNotification (action$, state$, { getIntl }) => action$.pipe( ofType(showPasteItemSuccessNotification.type), tap(({ payload }) => { const hostToHost$ = getHostToHostBus(); hostToHost$.next( showSystemNotification({ message: getIntl().formatMessage(itemSuccessMessages.itemPasted) }) ); }), ignoreElements() ), // endregion // region showUnlockItemSuccessNotification (action$, state$, { getIntl }) => action$.pipe( ofType(showUnlockItemSuccessNotification.type), tap(({ payload }) => { const hostToHost$ = getHostToHostBus(); hostToHost$.next( showSystemNotification({ message: getIntl().formatMessage(itemSuccessMessages.itemUnlocked) }) ); }), ignoreElements() ), // endregion // region showDuplicatedItemSuccessNotification (action$, state$, { getIntl }) => action$.pipe( ofType(showDuplicatedItemSuccessNotification.type), tap(({ payload }) => { const hostToHost$ = getHostToHostBus(); hostToHost$.next( showSystemNotification({ message: getIntl().formatMessage(itemSuccessMessages.itemDuplicated) }) ); }), ignoreElements() ), // endregion // region showRevertItemSuccessNotification (action$, state$, { getIntl }) => action$.pipe( ofType(showRevertItemSuccessNotification.type), tap(({ payload }) => { const hostToHost$ = getHostToHostBus(); hostToHost$.next( showSystemNotification({ message: getIntl().formatMessage(itemSuccessMessages.itemReverted) }) ); }), ignoreElements() ), // endregion // region showSystemNotification (action$) => action$.pipe( ofType(showSystemNotification.type), tap(({ payload }) => { const hostToHost$ = getHostToHostBus(); hostToHost$.next(showSystemNotification(payload)); }), ignoreElements() ), // endregion // region showRejectItemSuccessNotification (action$, state$, { getIntl }) => action$.pipe( ofType(showRejectItemSuccessNotification.type), tap(({ payload }) => { var _a; const hostToHost$ = getHostToHostBus(); hostToHost$.next( showSystemNotification({ message: getIntl().formatMessage(itemSuccessMessages.itemRejected, { count: (_a = payload === null || payload === void 0 ? void 0 : payload.count) !== null && _a !== void 0 ? _a : 1 }) }) ); }), ignoreElements() ), // endregion // region messageSharedWorker (action$, state$, { worker }) => action$.pipe( ofType(messageSharedWorker.type), tap((action) => { worker.port.postMessage(action.payload); }), ignoreElements() ), // endregion // region fetchPublishingStatus (action$, state$) => action$.pipe( ofType(fetchPublishingStatus.type), withLatestFrom(state$), filter(([, state]) => Boolean(state.sites.active)), exhaustMap(([, state]) => fetchStatus(state.sites.active).pipe( switchMap((response) => { let actions = [fetchPublishingStatusComplete(response)]; if (['queued', 'ready', 'stopped', 'error'].includes(response.status)) { actions.push(fetchPublishingStatusProcessingComplete()); } return actions; }), catchAjaxError(fetchPublishingStatusFailed) ) ) ), // endregion // region startPublishingStatusFetcher (action$, state$) => action$.pipe( ofType(startPublishingStatusFetcher.type), withLatestFrom(state$), filter(([, state]) => Boolean(state.sites.active)), switchMap(() => interval(150000).pipe( startWith(0), // To fetch status immediately map(() => fetchPublishingStatus()), takeUntil( action$.pipe( ofType(stopPublishingStatusFetcher.type, sessionTimeout.type, sharedWorkerUnauthenticated.type) ) ) ) ) ), // endregion // region fetchPublishingStatusProcessing (action$, state$) => action$.pipe( ofType(fetchPublishingStatusComplete.type), withLatestFrom(state$), filter(([, state]) => ['processing', 'publishing'].includes(state.dialogs.publishingStatus.status)), switchMap(() => interval(1000).pipe( startWith(0), // To fetch status immediately map(() => fetchPublishingStatus()), takeUntil( action$.pipe( ofType( fetchPublishingStatusProcessingComplete.type, sessionTimeout.type, sharedWorkerUnauthenticated.type ) ) ) ) ) ), // endregion // region fetchGlobalMenu (action$) => action$.pipe( ofType(fetchGlobalMenu.type), exhaustMap(() => fetchGlobalMenuItems().pipe(map(fetchGlobalMenuComplete), catchAjaxError(fetchGlobalMenuFailed))) ) // endregion ]; export default systemEpics;