From c017d7b18dceedd1178104466c5faad886fcb155 Mon Sep 17 00:00:00 2001 From: Gianfranco Paoloni Date: Wed, 12 Jan 2022 13:47:52 -0300 Subject: [PATCH] First working implementation of custom statuses --- plugin-hrm-form/src/HrmFormPlugin.js | 3 + .../src/components/ManualPullButton/index.tsx | 31 +++++++--- .../WorkerStatusHandler.tsx | 61 +++++++++++++++++++ plugin-hrm-form/src/utils/setUpComponents.js | 14 +++++ 4 files changed, 101 insertions(+), 8 deletions(-) create mode 100644 plugin-hrm-form/src/components/WorkerStatusHandler/WorkerStatusHandler.tsx diff --git a/plugin-hrm-form/src/HrmFormPlugin.js b/plugin-hrm-form/src/HrmFormPlugin.js index 8f0b3c6021..577a8d46bf 100644 --- a/plugin-hrm-form/src/HrmFormPlugin.js +++ b/plugin-hrm-form/src/HrmFormPlugin.js @@ -198,6 +198,9 @@ const setUpComponents = setupObject => { Components.setUpStandaloneSearch(); if (featureFlags.enable_canned_responses) Components.setupCannedResponses(); + + // set feature flag here + if (true) Components.setUpWorkerStatusHandler(); }; /** diff --git a/plugin-hrm-form/src/components/ManualPullButton/index.tsx b/plugin-hrm-form/src/components/ManualPullButton/index.tsx index 6132528668..cf00028234 100644 --- a/plugin-hrm-form/src/components/ManualPullButton/index.tsx +++ b/plugin-hrm-form/src/components/ManualPullButton/index.tsx @@ -18,26 +18,44 @@ type Props = OwnProps & ReturnType; const ManualPullButton: React.FC = ({ queuesStatusState, chatChannelCapacity, worker, workerClient }) => { const [isWaitingNewTask, setWaitingNewTask] = useState(false); + const [, availableActivity] = React.useMemo(() => { + return Array.from(workerClient.activities).find(([k, v]) => v.name === 'Available'); + }, [workerClient.activities]); + + // move to utils for reusability + const setKeepAvailable = async () => { + const attributes = { ...workerClient.attributes, keepAvailable: true }; + await workerClient.setAttributes(attributes); + }; + + // move to utils for reusability + const unsetKeepAvailable = async () => { + const { keepAvailable, ...attributes } = workerClient.attributes; + await workerClient.setAttributes(attributes); + }; + // Increase chat capacity, if no reservation is created within 5 seconds, capacity is decreased and shows a notification. const increaseChatCapacity = async () => { setWaitingNewTask(true); let alertTimeout = null; - const cancelTimeout = () => { + const cancelTimeout = async () => { setWaitingNewTask(false); clearTimeout(alertTimeout); + await unsetKeepAvailable(); }; alertTimeout = setTimeout(async () => { setWaitingNewTask(false); workerClient.removeListener('reservationCreated', cancelTimeout); Notifications.showNotification('NoTaskAssignableNotification'); - await adjustChatCapacity('decrease'); + await Promise.all([unsetKeepAvailable(), adjustChatCapacity('decrease')]); }, 5000); workerClient.once('reservationCreated', cancelTimeout); - await adjustChatCapacity('increase'); + await Promise.all([setKeepAvailable(), adjustChatCapacity('increase')]); + await availableActivity.setAsCurrent(); }; const { maxMessageCapacity } = worker.attributes; @@ -46,11 +64,8 @@ const ManualPullButton: React.FC = ({ queuesStatusState, chatChannelCapac const noTasks = worker.tasks.size === 0; const disabled = - !isAvailable || - noTasks || - maxCapacityReached || - !isAnyChatPending(queuesStatusState.queuesStatus) || - isWaitingNewTask; + // !isAvailable || this should change to "not is ready" + noTasks || maxCapacityReached || !isAnyChatPending(queuesStatusState.queuesStatus) || isWaitingNewTask; return ( { + const { worker } = state.flex; + + return { worker }; +}; + +const connector = connect(mapStateToProps); +type Props = OwnProps & ConnectedProps; + +const WorkerStatusHandler: React.FC = ({ worker, workerClient }) => { + const [availableActivity, offlineActivity] = React.useMemo(() => { + const activitiesArray = Array.from(workerClient.activities); + const [, available] = activitiesArray.find(([k, v]) => v.name === 'Available'); + const [, offline] = activitiesArray.find(([k, v]) => v.name === 'Offline'); + return [available, offline]; + }, [workerClient.activities]); + + const noTasks = worker.tasks.size === 0; + const { available } = worker.activity; + const { attributes } = worker; + const isSomeTaskPending = Array.from(worker.tasks).some(([, t]) => t.status === 'pending'); + + const shouldSetAvailable = noTasks && !available; // here we want to also consider a worker attribute to indicate if should stay offline or if it's "ready to work" + const shouldSetOffline = available && !noTasks && !worker.attributes.keepAvailable && !isSomeTaskPending; + + console.log('>>>> shouldSetAvailable', shouldSetAvailable); + console.log('>>>> shouldSetOffline', shouldSetOffline); + + React.useEffect(() => { + const handleActivities = async () => { + if (shouldSetAvailable) { + console.log('>>>> setting available'); + await availableActivity.setAsCurrent(); + } else if (shouldSetOffline) { + console.log('>>>> setting offline'); + await offlineActivity.setAsCurrent(); + } + }; + + try { + handleActivities(); + } catch (err) { + console.log('>>>> err on handleActivities', err); + } + }, [availableActivity, offlineActivity, shouldSetAvailable, shouldSetOffline]); + + return null; +}; +WorkerStatusHandler.displayName = 'WorkerStatusHandler'; + +export default connector(WorkerStatusHandler); diff --git a/plugin-hrm-form/src/utils/setUpComponents.js b/plugin-hrm-form/src/utils/setUpComponents.js index 27100fdc69..f9a4fda41a 100644 --- a/plugin-hrm-form/src/utils/setUpComponents.js +++ b/plugin-hrm-form/src/utils/setUpComponents.js @@ -8,6 +8,7 @@ import * as TransferHelpers from './transfer'; import CannedResponses from '../components/CannedResponses'; import QueuesStatusWriter from '../components/queuesStatus/QueuesStatusWriter'; import QueuesStatus from '../components/queuesStatus'; +import WorkerStatusHandler from '../components/WorkerStatusHandler/WorkerStatusHandler'; import CustomCRMContainer from '../components/CustomCRMContainer'; import LocalizationContext from '../contexts/LocalizationContext'; import Translator from '../components/translator'; @@ -94,6 +95,19 @@ export const setUpQueuesStatusWriter = setupObject => { ); }; +/** + * Add an "invisible" component that tracks the state of the worker, setting the status activity accordingly + */ +export const setUpWorkerStatusHandler = () => { + Flex.MainContainer.Content.add( + , + { + sortOrder: -1, + align: 'start', + }, + ); +}; + // Re-renders UI if there is a new reservation created and no active tasks (avoid a visual bug with QueuesStatus when there are no tasks) const setUpRerenderOnReservation = () => { const manager = Flex.Manager.getInstance();