Regression: Create livechat-monitor permissions for Canned Responses (#22781)

* contextual-bar monitor permissions

* Add monitor to livechat-canned-responses permission

* omnichannel canned-responses monitor permissions

* remove button

* fix

Co-authored-by: Kevin Aleman <kevin.aleman@rocket.chat>
pull/22782/head^2
Tiago Evangelista Pinto 4 years ago committed by GitHub
parent 66c51f1a29
commit 1937aae726
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      ee/app/livechat-enterprise/server/permissions.js
  2. 2
      ee/client/omnichannel/cannedResponses/CannedResponseEdit.tsx
  3. 18
      ee/client/omnichannel/cannedResponses/CannedResponsesRoute.tsx
  4. 7
      ee/client/omnichannel/cannedResponses/components/cannedResponseForm.tsx
  5. 3
      ee/client/omnichannel/components/CannedResponse/modals/CreateCannedResponse/CreateCannedResponseModal.tsx
  6. 5
      ee/client/omnichannel/components/CannedResponse/modals/CreateCannedResponse/SharingOptions.tsx
  7. 2
      ee/client/omnichannel/components/CannedResponse/modals/CreateCannedResponse/index.tsx
  8. 4
      ee/client/omnichannel/components/contextualBar/CannedResponse/WrapCannedResponse.tsx
  9. 1
      server/startup/migrations/index.js
  10. 11
      server/startup/migrations/v228.js

@ -18,5 +18,5 @@ export const createPermissions = () => {
Permissions.create('manage-livechat-monitors', [adminRole, livechatManagerRole]);
Permissions.create('manage-livechat-tags', [adminRole, livechatManagerRole]);
Permissions.create('manage-livechat-priorities', [adminRole, livechatManagerRole]);
Permissions.create('manage-livechat-canned-responses', [adminRole, livechatManagerRole]);
Permissions.create('manage-livechat-canned-responses', [adminRole, livechatManagerRole, livechatMonitorRole]);
};

@ -33,6 +33,7 @@ const CannedResponseEdit: FC<{
const saveCannedResponse = useEndpoint('POST', 'canned-responses');
const hasManagerPermission = usePermission('view-all-canned-responses');
const hasMonitorPermission = usePermission('save-department-canned-responses');
const form = useForm({
_id: data && data.cannedResponse ? data.cannedResponse._id : '',
@ -161,6 +162,7 @@ const CannedResponseEdit: FC<{
<FieldGroup w='full' alignSelf='center' maxWidth='x600' is='form' autoComplete='off'>
<CannedResponseForm
isManager={hasManagerPermission}
isMonitor={hasMonitorPermission}
values={values}
handlers={handlers}
errors={errors}

@ -22,6 +22,7 @@ import RemoveCannedResponseButton from './RemoveCannedResponseButton';
const CannedResponsesRoute: FC = () => {
const t = useTranslation();
const canViewCannedResponses = usePermission('manage-livechat-canned-responses');
const isMonitor = usePermission('save-department-canned-responses');
type CannedResponseFilterValues = {
sharing: string;
@ -80,13 +81,14 @@ const CannedResponsesRoute: FC = () => {
setSort([id, 'asc']);
});
const onRowClick = useMutableCallback(
(id) => (): void =>
const onRowClick = useMutableCallback((id, scope) => (): void => {
if (!(scope === 'global' && isMonitor)) {
cannedResponsesRoute.push({
context: 'edit',
id,
}),
);
});
}
});
const defaultOptions = useMemo(
() => ({
@ -167,7 +169,7 @@ const CannedResponsesRoute: FC = () => {
key={_id}
tabIndex={0}
role='link'
onClick={onRowClick(_id)}
onClick={onRowClick(_id, scope)}
action
qa-user-id={_id}
>
@ -187,10 +189,12 @@ const CannedResponsesRoute: FC = () => {
</Table.Cell>
<Table.Cell withTruncatedText>{getTime(createdAt)}</Table.Cell>
<Table.Cell withTruncatedText>{tags.join(', ')}</Table.Cell>
<RemoveCannedResponseButton _id={_id} reload={reload} totalDataReload={totalDataReload} />
{!(scope === 'global' && isMonitor) && (
<RemoveCannedResponseButton _id={_id} reload={reload} totalDataReload={totalDataReload} />
)}
</Table.Row>
),
[getTime, onRowClick, reload, totalDataReload, defaultOptions],
[getTime, onRowClick, reload, totalDataReload, defaultOptions, isMonitor],
);
if (context === 'edit' && id) {

@ -11,6 +11,7 @@ import SharingOptions from '../../components/CannedResponse/modals/CreateCannedR
const CannedResponseForm: FC<{
isManager: boolean;
isMonitor: boolean;
values: any;
handlers: any;
errors: any;
@ -31,6 +32,7 @@ const CannedResponseForm: FC<{
onPreview,
previewState,
isManager,
isMonitor,
}) => {
const { shortcut, text, scope, tags, departmentId } = values;
const { handleShortcut, handleText, handleTags, handleDepartmentId } = handlers;
@ -71,19 +73,20 @@ const CannedResponseForm: FC<{
<Field mbe='x24'>
<Tags handler={handleTags} tags={tags} />
</Field>
{isManager && (
{(isManager || isMonitor) && (
<>
<Field mbe='x24'>
<Field.Label>{t('Sharing')}</Field.Label>
<Field.Description>{radioDescription}</Field.Description>
<Field.Row mbs='12px' justifyContent='start'>
<SharingOptions scope={scope} radioHandlers={radioHandlers} />
<SharingOptions isMonitor={isMonitor} scope={scope} radioHandlers={radioHandlers} />
</Field.Row>
</Field>
{scope === 'department' && (
<Field mbe='x24'>
<Field.Label>{t('Department')}</Field.Label>
<AutoCompleteDepartment
{...(isMonitor && { onlyMyDepartments: isMonitor })}
value={departmentId}
onChange={handleDepartmentId}
error={errors.departmentId}

@ -6,6 +6,7 @@ import CannedResponseForm from '../../../../cannedResponses/components/cannedRes
const CreateCannedResponseModal: FC<{
isManager: boolean;
isMonitor: boolean;
values: any;
handlers: any;
errors: any;
@ -18,6 +19,7 @@ const CreateCannedResponseModal: FC<{
previewState: boolean;
}> = ({
isManager,
isMonitor,
values,
handlers,
errors,
@ -50,6 +52,7 @@ const CreateCannedResponseModal: FC<{
<Modal.Content fontScale='p1'>
<CannedResponseForm
isManager={isManager}
isMonitor={isMonitor}
values={values}
handlers={handlers}
errors={errors}

@ -3,7 +3,8 @@ import React, { FC, memo } from 'react';
import { useTranslation } from '../../../../../../../client/contexts/TranslationContext';
const SharingOptions: FC<{ scope: string; radioHandlers: any }> = ({
const SharingOptions: FC<{ isMonitor: boolean; scope: string; radioHandlers: any }> = ({
isMonitor,
scope,
radioHandlers: { setPublic, setPrivate, setDepartment },
}) => {
@ -12,7 +13,7 @@ const SharingOptions: FC<{ scope: string; radioHandlers: any }> = ({
return (
<>
<Box display='flex' mie='12px'>
<RadioButton onChange={setPublic} checked={scope === 'global'} />
<RadioButton onChange={setPublic} disabled={isMonitor} checked={scope === 'global'} />
<Box mis='8px'>{t('Public')}</Box>
</Box>
<Box display='flex' mie='12px'>

@ -19,6 +19,7 @@ const WrapCreateCannedResponseModal: FC<{ data?: any; reloadCannedList?: any }>
const saveCannedResponse = useEndpoint('POST', 'canned-responses');
const hasManagerPermission = usePermission('view-all-canned-responses');
const hasMonitorPermission = usePermission('save-department-canned-responses');
const form = useForm({
_id: data ? data._id : '',
@ -116,6 +117,7 @@ const WrapCreateCannedResponseModal: FC<{ data?: any; reloadCannedList?: any }>
return (
<CreateCannedResponseModal
isManager={hasManagerPermission}
isMonitor={hasMonitorPermission}
values={values}
handlers={handlers}
errors={errors}

@ -27,8 +27,10 @@ const WrapCannedResponse: FC<{
};
const hasManagerPermission = usePermission('view-all-canned-responses');
const hasMonitorPermission = usePermission('save-department-canned-responses');
const canEdit = hasManagerPermission || scope === 'user';
const canEdit =
hasManagerPermission || (hasMonitorPermission && scope !== 'global') || scope === 'user';
return (
<CannedResponse

@ -224,4 +224,5 @@ import './v224';
import './v225';
import './v226';
import './v227';
import './v228';
import './xrun';

@ -0,0 +1,11 @@
import { Migrations } from '../../../app/migrations';
import { Permissions } from '../../../app/models';
Migrations.add({
version: 228,
up() {
if (Permissions) {
Permissions.update({ _id: 'manage-livechat-canned-responses' }, { $addToSet: { roles: 'livechat-monitor' } });
}
},
});
Loading…
Cancel
Save