From eea2b271c44c6f9a04f537cff8e6190872a69c9b Mon Sep 17 00:00:00 2001 From: Rafael Ferreira Date: Tue, 29 Dec 2020 18:34:40 -0300 Subject: [PATCH 1/5] business hour - error showing on "single" configuration and not able to edit and create with "multiple" --- .../omnichannel/businessHours/BusinessHoursFormContainer.js | 2 +- client/views/omnichannel/businessHours/BusinessHoursPage.js | 4 ++-- client/views/omnichannel/businessHours/BusinessHoursRouter.js | 2 +- .../omnichannel/additionalForms/BusinessHoursMultiple.js | 2 +- packages/rocketchat-i18n/i18n/pt-BR.i18n.json | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/client/views/omnichannel/businessHours/BusinessHoursFormContainer.js b/client/views/omnichannel/businessHours/BusinessHoursFormContainer.js index 7501928aa38dc..a5c2ea2706fb1 100644 --- a/client/views/omnichannel/businessHours/BusinessHoursFormContainer.js +++ b/client/views/omnichannel/businessHours/BusinessHoursFormContainer.js @@ -23,7 +23,7 @@ const getInitalData = ({ workHours }) => ({ const cleanFunc = () => {}; -const BusinessHoursFormContainer = ({ data, saveRef, onChange }) => { +const BusinessHoursFormContainer = ({ data, saveRef, onChange = () => {} }) => { const forms = useSubscription(formsSubscription); const { diff --git a/client/views/omnichannel/businessHours/BusinessHoursPage.js b/client/views/omnichannel/businessHours/BusinessHoursPage.js index 55c2c9198248c..9484e3ade59e0 100644 --- a/client/views/omnichannel/businessHours/BusinessHoursPage.js +++ b/client/views/omnichannel/businessHours/BusinessHoursPage.js @@ -22,8 +22,8 @@ const BusinessHoursPage = () => { return - diff --git a/client/views/omnichannel/businessHours/BusinessHoursRouter.js b/client/views/omnichannel/businessHours/BusinessHoursRouter.js index 55f9b937039c9..24b989d14cc2b 100644 --- a/client/views/omnichannel/businessHours/BusinessHoursRouter.js +++ b/client/views/omnichannel/businessHours/BusinessHoursRouter.js @@ -28,7 +28,7 @@ const BusinessHoursRouter = () => { }, [context, isSingleBH, router, type]); if ((context === 'edit' && type) || (isSingleBH && (context !== 'edit' || type !== 'default'))) { - return ; + return type ? : null; } if (context === 'new') { diff --git a/ee/client/omnichannel/additionalForms/BusinessHoursMultiple.js b/ee/client/omnichannel/additionalForms/BusinessHoursMultiple.js index 98efc572e9db0..6991d58d5e29f 100644 --- a/ee/client/omnichannel/additionalForms/BusinessHoursMultiple.js +++ b/ee/client/omnichannel/additionalForms/BusinessHoursMultiple.js @@ -59,7 +59,7 @@ export const BusinessHoursMultiple = ({ values = {}, handlers = {}, className, d - {t('Name')} + {t('Name')}* diff --git a/packages/rocketchat-i18n/i18n/pt-BR.i18n.json b/packages/rocketchat-i18n/i18n/pt-BR.i18n.json index 19686a3b8d335..482c5572e593e 100644 --- a/packages/rocketchat-i18n/i18n/pt-BR.i18n.json +++ b/packages/rocketchat-i18n/i18n/pt-BR.i18n.json @@ -1574,7 +1574,7 @@ "Forward_to_user": "Encaminhar ao usuário", "Free": "Grátis", "Frequently_Used": "Usados frequentemente", - "Friday": "Sexta-Feira", + "Friday": "Sexta-feira", "From": "De", "From_Email": "Email De", "From_email_warning": "Aviso: O campo De está sujeito às configurações do seu servidor de emails.", @@ -3229,7 +3229,7 @@ "Triggers": "Gatilhos", "Troubleshoot_Disable_Notifications": "Desativar as notificações", "True": "Sim", - "Tuesday": "terça", + "Tuesday": "Terça-feira", "Turn_OFF": "Desligar", "Turn_ON": "Ligar", "Two Factor Authentication": "Autenticação de dois fatores", From d5e2ef4316bcfbf36ee08aab2aa7622746168fa7 Mon Sep 17 00:00:00 2001 From: Rafael Ferreira Date: Tue, 29 Dec 2020 21:36:28 -0300 Subject: [PATCH 2/5] Implement validation for new values and valid form for business hours (edit/create) --- .../BusinessHoursFormContainer.js | 11 +++++---- .../businessHours/EditBusinessHoursPage.js | 6 ++--- .../businessHours/NewBusinessHoursPage.js | 8 ++++--- .../additionalForms/BusinessHoursMultiple.js | 7 ++++-- .../additionalForms/BusinessHoursTimeZone.js | 24 +++++++++++-------- 5 files changed, 34 insertions(+), 22 deletions(-) diff --git a/client/views/omnichannel/businessHours/BusinessHoursFormContainer.js b/client/views/omnichannel/businessHours/BusinessHoursFormContainer.js index a5c2ea2706fb1..5a8aa37d80cc7 100644 --- a/client/views/omnichannel/businessHours/BusinessHoursFormContainer.js +++ b/client/views/omnichannel/businessHours/BusinessHoursFormContainer.js @@ -1,4 +1,4 @@ -import React, { useEffect } from 'react'; +import React, { useEffect, useState } from 'react'; import { FieldGroup, Box } from '@rocket.chat/fuselage'; import { useMutableCallback } from '@rocket.chat/fuselage-hooks'; import { useSubscription } from 'use-subscription'; @@ -26,6 +26,9 @@ const cleanFunc = () => {}; const BusinessHoursFormContainer = ({ data, saveRef, onChange = () => {} }) => { const forms = useSubscription(formsSubscription); + const [hasChangesMultiple, setHasChangesMultiple] = useState(false); + const [hasChangesTimeZone, setHasChangesTimeZone] = useState(false); + const { useBusinessHoursTimeZone = cleanFunc, useBusinessHoursMultiple = cleanFunc, @@ -45,13 +48,13 @@ const BusinessHoursFormContainer = ({ data, saveRef, onChange = () => {} }) => { saveRef.current.form = values; useEffect(() => { - onChange(hasUnsavedChanges); + onChange(hasUnsavedChanges || (showMultipleBHForm && hasChangesMultiple) || (showTimezone && hasChangesTimeZone)); }); return - {showMultipleBHForm && MultipleBHForm && } - {showTimezone && TimezoneForm && } + {showMultipleBHForm && MultipleBHForm && } + {showTimezone && TimezoneForm && } ; diff --git a/client/views/omnichannel/businessHours/EditBusinessHoursPage.js b/client/views/omnichannel/businessHours/EditBusinessHoursPage.js index 260a0a0f6f4c4..535d601c01838 100644 --- a/client/views/omnichannel/businessHours/EditBusinessHoursPage.js +++ b/client/views/omnichannel/businessHours/EditBusinessHoursPage.js @@ -23,7 +23,7 @@ const EditBusinessHoursPage = ({ id, type }) => { const saveData = useRef({ form: {} }); - const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false); + const [hasChanges, setHasChanges] = useState(false); const save = useMethod('livechat:saveBusinessHour'); const deleteBH = useMethod('livechat:removeBusinessHour'); @@ -112,7 +112,7 @@ const EditBusinessHoursPage = ({ id, type }) => { {type === 'custom' && } - @@ -121,7 +121,7 @@ const EditBusinessHoursPage = ({ id, type }) => { setHasUnsavedChanges(hasChanges)} /> + onChange={setHasChanges} /> ; }; diff --git a/client/views/omnichannel/businessHours/NewBusinessHoursPage.js b/client/views/omnichannel/businessHours/NewBusinessHoursPage.js index 74199b6e007ad..f23b596916944 100644 --- a/client/views/omnichannel/businessHours/NewBusinessHoursPage.js +++ b/client/views/omnichannel/businessHours/NewBusinessHoursPage.js @@ -1,4 +1,4 @@ -import React, { useRef } from 'react'; +import React, { useRef, useState } from 'react'; import { Button, ButtonGroup } from '@rocket.chat/fuselage'; import { useMutableCallback } from '@rocket.chat/fuselage-hooks'; @@ -35,6 +35,8 @@ const NewBusinessHoursPage = () => { const t = useTranslation(); const dispatchToastMessage = useToastMessageDispatch(); + const [hasChanges, setHasChanges] = useState(false); + const saveData = useRef({ form: {} }); const save = useMethod('livechat:saveBusinessHour'); @@ -83,13 +85,13 @@ const NewBusinessHoursPage = () => { - - + ; }; diff --git a/ee/client/omnichannel/additionalForms/BusinessHoursMultiple.js b/ee/client/omnichannel/additionalForms/BusinessHoursMultiple.js index 6991d58d5e29f..9280866237a81 100644 --- a/ee/client/omnichannel/additionalForms/BusinessHoursMultiple.js +++ b/ee/client/omnichannel/additionalForms/BusinessHoursMultiple.js @@ -14,12 +14,15 @@ const getInitialData = (data = {}) => ({ departments: mapDepartments(data.departments), }); -const BusinessHoursMultipleContainer = ({ onChange, data: initialData, className }) => { +const BusinessHoursMultipleContainer = ({ onChange, data: initialData, className, hasChangesAndIsValid = () => {} }) => { const { value: data, phase: state } = useEndpointData('livechat/department'); - const { values, handlers } = useForm(getInitialData(initialData)); + const { values, handlers, hasUnsavedChanges } = useForm(getInitialData(initialData)); + + const { name } = values; onChange(values); + hasChangesAndIsValid(hasUnsavedChanges && !!name); const departmentList = useMemo(() => data && data.departments?.map(({ _id, name }) => [_id, name]), [data]); diff --git a/ee/client/omnichannel/additionalForms/BusinessHoursTimeZone.js b/ee/client/omnichannel/additionalForms/BusinessHoursTimeZone.js index 19ab8046c31cc..874cc0a1c4205 100644 --- a/ee/client/omnichannel/additionalForms/BusinessHoursTimeZone.js +++ b/ee/client/omnichannel/additionalForms/BusinessHoursTimeZone.js @@ -1,14 +1,21 @@ -import React, { useMemo, useState } from 'react'; +import React, { useMemo } from 'react'; import { SelectFiltered, Field } from '@rocket.chat/fuselage'; -import { useMutableCallback } from '@rocket.chat/fuselage-hooks'; import { useTranslation } from '../../../../client/contexts/TranslationContext'; import { useTimezoneNameList } from '../../../../client/hooks/useTimezoneNameList'; +import { useForm } from '../../../../client/hooks/useForm'; -const BusinessHoursTimeZone = ({ onChange, data, className }) => { +const getInitialData = (data = {}) => ({ + name: data ?? '', +}); + +const BusinessHoursTimeZone = ({ onChange, data, className, hasChanges = () => {} }) => { const t = useTranslation(); - const [timezone, setTimezone] = useState(data); + const { values, handlers, hasUnsavedChanges } = useForm(getInitialData(data)); + + const { name } = values; + const { handleName } = handlers; const timeZones = useTimezoneNameList(); @@ -17,18 +24,15 @@ const BusinessHoursTimeZone = ({ onChange, data, className }) => { t(name), ]), [t, timeZones]); - const handleChange = useMutableCallback((value) => { - setTimezone(value); - }); - - onChange({ name: timezone }); + onChange({ name }); + hasChanges(hasUnsavedChanges); return {t('Timezone')} - + ; }; From e7af467cbded31febd2111ba0a7e3fe0678fde4e Mon Sep 17 00:00:00 2001 From: Rafael Ferreira Date: Wed, 30 Dec 2020 11:04:46 -0300 Subject: [PATCH 3/5] Missing translations PT-BR for Business Hour pages. --- packages/rocketchat-i18n/i18n/en.i18n.json | 1 + packages/rocketchat-i18n/i18n/pt-BR.i18n.json | 2 ++ 2 files changed, 3 insertions(+) diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index cd9fee79c2c86..a47ce922cb57b 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -2737,6 +2737,7 @@ "Newer_than_may_not_exceed_Older_than": "\"Newer than\" may not exceed \"Older than\"", "Nickname": "Nickname", "Nickname_Placeholder": "Enter your nickname...", + "No": "No", "No_available_agents_to_transfer": "No available agents to transfer", "No_Canned_Responses": "No Canned Responses", "No_channel_with_name_%s_was_found": "No channel with name \"%s\" was found!", diff --git a/packages/rocketchat-i18n/i18n/pt-BR.i18n.json b/packages/rocketchat-i18n/i18n/pt-BR.i18n.json index 482c5572e593e..757a9e620119a 100644 --- a/packages/rocketchat-i18n/i18n/pt-BR.i18n.json +++ b/packages/rocketchat-i18n/i18n/pt-BR.i18n.json @@ -2370,6 +2370,7 @@ "Newer_than_may_not_exceed_Older_than": "\"Mais recente que\" não pode exceder \"Mais antigo que\"", "Nickname": "Apelido", "Nickname_Placeholder": "Digite seu apelido...", + "No": "Não", "No_available_agents_to_transfer": "Nenhum agente disponível para transferir", "No_channel_with_name_%s_was_found": "Nenhum canal com nome \"%s\" foi encontrado!", "No_channels_yet": "Você não faz parte de nenhum canal ainda.", @@ -3180,6 +3181,7 @@ "Thursday": "Quinta-feira", "Time_in_seconds": "Tempo em segundos", "Timeouts": "Tempos limite", + "Timezone": "Fuso horário", "Title": "Título", "Title_bar_color": "Cor da barra de título", "Title_bar_color_offline": "Cor da barra de título quando offline", From 7e401a8b77270a8eeabfce91dd450e20040dc6b7 Mon Sep 17 00:00:00 2001 From: Rafael Ferreira Date: Wed, 30 Dec 2020 15:40:16 -0300 Subject: [PATCH 4/5] Fill full height screen of table on Business Hours list. --- client/views/omnichannel/businessHours/BusinessHoursPage.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/views/omnichannel/businessHours/BusinessHoursPage.js b/client/views/omnichannel/businessHours/BusinessHoursPage.js index 9484e3ade59e0..f3a6dacaff9f5 100644 --- a/client/views/omnichannel/businessHours/BusinessHoursPage.js +++ b/client/views/omnichannel/businessHours/BusinessHoursPage.js @@ -27,9 +27,9 @@ const BusinessHoursPage = () => { - + - + ; }; From 95439b36f983882c5242b6ecbecbf6b16438d335 Mon Sep 17 00:00:00 2001 From: Renato Becker Date: Wed, 30 Dec 2020 17:35:16 -0300 Subject: [PATCH 5/5] Fix method not found on LivechatDepartmentAgentsRaw(EE) --- client/sidebar/sections/Omnichannel.js | 15 +++++++++++++-- .../server/business-hour/Multiple.ts | 6 +++--- ee/app/models/server/index.js | 2 ++ .../models/server/raw/LivechatDepartmentAgents.ts | 3 +++ 4 files changed, 21 insertions(+), 5 deletions(-) diff --git a/client/sidebar/sections/Omnichannel.js b/client/sidebar/sections/Omnichannel.js index e17db6bbea9b1..0b76c661d8768 100644 --- a/client/sidebar/sections/Omnichannel.js +++ b/client/sidebar/sections/Omnichannel.js @@ -1,17 +1,20 @@ import React from 'react'; import { Sidebar } from '@rocket.chat/fuselage'; +import { useMutableCallback } from '@rocket.chat/fuselage-hooks'; +import { useToastMessageDispatch } from '../../contexts/ToastMessagesContext'; import { useTranslation } from '../../contexts/TranslationContext'; import { useMethod } from '../../contexts/ServerContext'; import { useOmnichannelShowQueueLink, useOmnichannelAgentAvailable, useOmnichannelQueueLink, useOmnichannelDirectoryLink } from '../../contexts/OmnichannelContext'; const OmnichannelSection = React.memo((props) => { - const method = useMethod('livechat:changeLivechatStatus'); + const changeAgentStatus = useMethod('livechat:changeLivechatStatus'); const t = useTranslation(); const agentAvailable = useOmnichannelAgentAvailable(); const showOmnichannelQueueLink = useOmnichannelShowQueueLink(); const queueLink = useOmnichannelQueueLink(); const directoryLink = useOmnichannelDirectoryLink(); + const dispatchToastMessage = useToastMessageDispatch(); const icon = { title: agentAvailable ? t('Available') : t('Not_Available'), @@ -23,12 +26,20 @@ const OmnichannelSection = React.memo((props) => { title: t('Contact_Center'), icon: 'contact', }; + const handleStatusChange = useMutableCallback(async () => { + try { + await changeAgentStatus(); + } catch (error) { + dispatchToastMessage({ type: 'error', message: error }); + console.log(error); + } + }); return {t('Omnichannel')} {showOmnichannelQueueLink && } - { method(); }}/> + ; diff --git a/ee/app/livechat-enterprise/server/business-hour/Multiple.ts b/ee/app/livechat-enterprise/server/business-hour/Multiple.ts index 35b1177712498..22f2e67e3d519 100644 --- a/ee/app/livechat-enterprise/server/business-hour/Multiple.ts +++ b/ee/app/livechat-enterprise/server/business-hour/Multiple.ts @@ -6,8 +6,8 @@ import { } from '../../../../../app/livechat/server/business-hour/AbstractBusinessHour'; import { ILivechatBusinessHour } from '../../../../../definition/ILivechatBusinessHour'; import { LivechatDepartmentRaw } from '../../../../../app/models/server/raw/LivechatDepartment'; -import { LivechatDepartmentAgentsRaw } from '../../../models/server/raw/LivechatDepartmentAgents'; -import { LivechatDepartment, LivechatDepartmentAgents } from '../../../../../app/models/server/raw'; +import LivechatDepartmentAgentsRaw from '../../../models/server/raw/LivechatDepartmentAgents'; +import { LivechatDepartment } from '../../../../../app/models/server/raw'; import { filterBusinessHoursThatMustBeOpened } from '../../../../../app/livechat/server/business-hour/Helper'; import { closeBusinessHour, openBusinessHour, removeBusinessHourByAgentIds } from './Helper'; @@ -19,7 +19,7 @@ interface IBusinessHoursExtraProperties extends ILivechatBusinessHour { export class MultipleBusinessHoursBehavior extends AbstractBusinessHourBehavior implements IBusinessHourBehavior { private DepartmentsRepository: LivechatDepartmentRaw = LivechatDepartment; - private DepartmentsAgentsRepository = LivechatDepartmentAgents as LivechatDepartmentAgentsRaw; + private DepartmentsAgentsRepository = LivechatDepartmentAgentsRaw; constructor() { super(); diff --git a/ee/app/models/server/index.js b/ee/app/models/server/index.js index 30d5dd386edc0..c44afe4be4bb1 100644 --- a/ee/app/models/server/index.js +++ b/ee/app/models/server/index.js @@ -7,6 +7,7 @@ import CannedResponseRaw from './raw/CannedResponse'; import LivechatPriorityRaw from './raw/LivechatPriority'; import LivechatTagRaw from './raw/LivechatTag'; import LivechatUnitMonitorsRaw from './raw/LivechatUnitMonitors'; +import LivechatDepartmentAgentsRaw from './raw/LivechatDepartmentAgents'; import './models/LivechatDepartment'; import './models/LivechatRooms'; import './models/LivechatInquiry'; @@ -24,4 +25,5 @@ export { LivechatUnitMonitorsRaw, LivechatPriority, LivechatPriorityRaw, + LivechatDepartmentAgentsRaw, }; diff --git a/ee/app/models/server/raw/LivechatDepartmentAgents.ts b/ee/app/models/server/raw/LivechatDepartmentAgents.ts index c64046c4f4b6e..51f4c343056b6 100644 --- a/ee/app/models/server/raw/LivechatDepartmentAgents.ts +++ b/ee/app/models/server/raw/LivechatDepartmentAgents.ts @@ -1,4 +1,5 @@ import { LivechatDepartmentAgentsRaw as Raw } from '../../../../../app/models/server/raw/LivechatDepartmentAgents'; +import { LivechatDepartmentAgents } from '../../../../../app/models/server'; export class LivechatDepartmentAgentsRaw extends Raw { findAgentsByAgentIdAndBusinessHourId(agentId: string, businessHourId: string): Promise> { @@ -24,3 +25,5 @@ export class LivechatDepartmentAgentsRaw extends Raw { return this.col.aggregate([match, lookup, unwind, withBusinessHourId, project]).toArray(); } } + +export default new LivechatDepartmentAgentsRaw(LivechatDepartmentAgents.model.rawCollection());