diff --git a/modules/apps/document-library/document-library-web/src/main/resources/META-INF/resources/document_library/js/bulk/BulkStatus.es.js b/modules/apps/document-library/document-library-web/src/main/resources/META-INF/resources/document_library/js/bulk/BulkStatus.es.js index 155a7e66db9f7b..98c0f141315ab6 100644 --- a/modules/apps/document-library/document-library-web/src/main/resources/META-INF/resources/document_library/js/bulk/BulkStatus.es.js +++ b/modules/apps/document-library/document-library-web/src/main/resources/META-INF/resources/document_library/js/bulk/BulkStatus.es.js @@ -12,167 +12,90 @@ * details. */ -import {useResource} from '@clayui/data-provider'; import ClayLoadingIndicator from '@clayui/loading-indicator'; -import {fetch, openToast} from 'frontend-js-web'; import {useTimeout} from 'frontend-js-react-web'; +import {fetch, openToast} from 'frontend-js-web'; import PropTypes from 'prop-types'; -import React, {useEffect, useRef, useState, useCallback} from 'react'; +import React, {useCallback, useEffect, useReducer} from 'react'; -/** - * Shows a toast notification. - * - * @param {boolean} error Flag indicating if is an error or not - * @protected - */ -function _showNotification(hasError) { - let message; - - if (hasError) { - message = Liferay.Language.get('an-unexpected-error-occurred'); - } else { - message = Liferay.Language.get('changes-saved'); - } - - const openToastParams = { - message - }; - - if (hasError) { - openToastParams.title = Liferay.Language.get('error'); - openToastParams.type = 'danger'; - } - - openToast(openToastParams); -} +import reducer, {STATES} from './reducer.es'; /** * Shows the bulk actions status */ function BulkStatus({ - bulkInProgress = false, + bulkComponentId, + bulkInProgress, bulkStatusUrl = '/bulk/v1.0/status', intervalSpeed = 1000, pathModule, - portletNamespace, waitingTime = 1000 }) { const delay = useTimeout(); - const [isBulkInProgress, setIsBulkInProgress] = useState(bulkInProgress); - const [ - isBulkLoadingIndicatorVisible, - setIsBulkLoadingIndicatorVisible - ] = useState(false); - const isBulkHappened = useRef(false); + const [state, dispatch] = useReducer( + reducer, + bulkInProgress ? {current: STATES.LONG_POLLING} : {current: STATES.IDLE} + ); + + const statusCallback = useCallback(() => { + return delay(() => { + fetch( + `${Liferay.ThemeDisplay.getPortalURL()}${pathModule}${bulkStatusUrl}` + ) + .then(response => response.json()) + .then(response => { + if (response.actionInProgress) { + dispatch({type: 'check'}); + } else { + dispatch({type: 'success'}); + } + }) + .catch(() => dispatch({type: 'error'})); + }, intervalSpeed); + }, [bulkStatusUrl, delay, pathModule, intervalSpeed]); useEffect(() => { let dispose; - if (waitingTime) { - if (isBulkInProgress && !isBulkLoadingIndicatorVisible) { - dispoe = delay(() => { - setIsBulkLoadingIndicatorVisible(true); - }, waitingTime); - } - } - - return dispose; - }, [waitingTime, isBulkInProgress, isBulkLoadingIndicatorVisible]); - - const [networkState, setNetworkState] = useState({ - error: false, - loading: false, - networkStatus: 4, - unused: false - }); - - const refetchSafe = useCallback(() => refetch(), [refetch]); + if (state.current === STATES.SHORT_POLLING) { + statusCallback(); - useEffect(() => { - if (!Liferay.component(`${portletNamespace}BulkStatus`)) { - Liferay.component( - `${portletNamespace}BulkStatus`, - { - startWatch: () => { - if (!isBulkInProgress) { - setIsBulkInProgress(true); - refetchSafe(); - } - } - }, - { - destroyOnNavigate: true - } + dispose = delay( + () => dispatch({type: 'initialDelayCompleted'}), + waitingTime ); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - - const {refetch, resource} = useResource({ - link: () => { - return fetch( - Liferay.ThemeDisplay.getPortalURL() + pathModule + bulkStatusUrl - ).then(response => response.json()); - }, - onNetworkStatusChange: status => - setNetworkState({ - error: status === 5, - loading: status < 4, - networkStatus: status, - unused: status === 4 - }) - }); + } else if (state.current === STATES.LONG_POLLING) { + statusCallback(); + } else if (state.current === STATES.NOTIFY) { + openToast(state.toast); - useEffect(() => { - if (networkState.error) { - _showNotification(true); + dispatch({type: 'notificationCompleted'}); } - }, [networkState.error]); - useEffect(() => { - if ( - networkState.unused && - !isBulkInProgress && - isBulkHappened.current - ) { - _showNotification(false); - } - }, [isBulkHappened, isBulkInProgress, networkState.unused]); - - useEffect(() => { - if (resource) { - if (resource.actionInProgress && !networkState.error) { - setIsBulkInProgress(true); - setTimeout(() => { - refetchSafe(); - }, intervalSpeed); - if (isBulkHappened.current === false) { - isBulkHappened.current = true; + return dispose; + }, [delay, state, statusCallback, waitingTime]); + + if (!Liferay.component(bulkComponentId)) { + Liferay.component( + bulkComponentId, + { + startWatch: () => { + dispatch({type: 'start'}); } + }, + { + destroyOnNavigate: true } - - if (!resource.actionInProgress || networkState.error) { - setIsBulkInProgress(false); - setIsBulkLoadingIndicatorVisible(false); - } - } - }, [ - intervalSpeed, - isBulkHappened, - networkState.error, - refetchSafe, - resource - ]); + ); + } return (
-
+
+ {Liferay.Language.get('processing-actions')}
@@ -181,58 +104,10 @@ function BulkStatus({ } BulkStatus.propTypes = { - /** - * Wether to show the component or not - * @type {Boolean} - */ bulkInProgress: PropTypes.bool, - - /** - * Uri to send the bulk status fetch request. - * @instance - * @memberof BulkStatus - * @type {String} - */ bulkStatusUrl: PropTypes.string, - - /** - * The interval (in milliseconds) on how often - * we will check if there are bulk actions in progress. - * - * @instance - * @memberof BulkStatus - * @type {Number} - */ intervalSpeed: PropTypes.number, - - /** - * PathModule - * - * @instance - * @memberof EditTags - * @review - * @type {String} - */ pathModule: PropTypes.string.isRequired, - - /** - * Portlet's namespace - * - * @instance - * @memberof BulkStatus - * @review - * @type {string} - */ - portletNamespace: PropTypes.string.isRequired, - - /** - * The time (in milliseconds) we have to wait to - * show the component. - * - * @instance - * @memberof BulkStatus - * @type {Number} - */ waitingTime: PropTypes.number }; diff --git a/modules/apps/document-library/document-library-web/src/main/resources/META-INF/resources/document_library/js/bulk/reducer.es.js b/modules/apps/document-library/document-library-web/src/main/resources/META-INF/resources/document_library/js/bulk/reducer.es.js new file mode 100644 index 00000000000000..9ca1e3aa2c5925 --- /dev/null +++ b/modules/apps/document-library/document-library-web/src/main/resources/META-INF/resources/document_library/js/bulk/reducer.es.js @@ -0,0 +1,96 @@ +/** + * Copyright (c) 2000-present Liferay, Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + * + * This library 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. + */ + +const STATES = { + IDLE: {running: false, show: false}, + LONG_POLLING: {running: true, show: true}, + NOTIFY: {running: false, show: false}, + SHORT_POLLING: {running: true, show: false} +}; + +const TOASTS = { + ERROR: { + message: Liferay.Language.get('an-unexpected-error-occurred'), + title: Liferay.Language.get('error'), + type: 'danger' + }, + SUCCESS: { + message: Liferay.Language.get('changes-saved') + } +}; + +export {STATES}; + +export default function reducer(state, action) { + switch (action.type) { + case 'check': + if (state.current === STATES.LONG_POLLING) { + return { + ...state, + timestamp: Date.now() + }; + } + break; + + case 'error': + return { + ...state, + current: STATES.NOTIFY, + toast: TOASTS.ERROR + }; + + case 'initialDelayCompleted': + if (state.current === STATES.SHORT_POLLING) { + return { + ...state, + current: STATES.LONG_POLLING, + timestamp: Date.now() + }; + } + + break; + + case 'notificationCompleted': + if (state.current === STATES.NOTIFY) { + return { + ...state, + current: STATES.IDLE + }; + } + + break; + + case 'start': + if (state.current === STATES.IDLE) { + return { + ...state, + current: STATES.SHORT_POLLING + }; + } + + break; + + case 'success': + return { + ...state, + current: STATES.NOTIFY, + toast: TOASTS.SUCCESS + }; + + default: + return state; + } + + return state; +} diff --git a/modules/apps/document-library/document-library-web/src/main/resources/META-INF/resources/document_library/view.jsp b/modules/apps/document-library/document-library-web/src/main/resources/META-INF/resources/document_library/view.jsp index e9e99932d32f15..7e49e66c67d74e 100644 --- a/modules/apps/document-library/document-library-web/src/main/resources/META-INF/resources/document_library/view.jsp +++ b/modules/apps/document-library/document-library-web/src/main/resources/META-INF/resources/document_library/view.jsp @@ -70,12 +70,12 @@ String navigation = ParamUtil.getString(request, "navigation"); Map context = new HashMap<>(); + context.put("bulkComponentId", liferayPortletResponse.getNamespace() + "BulkStatus"); context.put("bulkInProgress", bulkSelectionRunner.isBusy(user)); context.put("pathModule", PortalUtil.getPathModule()); - context.put("portletNamespace", liferayPortletResponse.getNamespace()); %> -
+