diff --git a/.changeset/good-baboons-shop.md b/.changeset/good-baboons-shop.md new file mode 100644 index 00000000000..5a7230d841f --- /dev/null +++ b/.changeset/good-baboons-shop.md @@ -0,0 +1,13 @@ +--- +"@rocket.chat/meteor": minor +"@rocket.chat/rest-typings": minor +--- + +**Added Livechat's new theming settings to Appearance page (available for Premium workspaces)** + +Newly added settings are: +- `Livechat widget position on the screen`: Changes the widget position between left or right of the viewport +- `Livechat background`: Changes the message list background. Receives the same value as the CSS's background property. +- `Hide system messages`: Changes the visibility of system messages displayed on the widget. +- `Hide "powered by Rocket.Chat"`: Changes the visibility of Rocket.Chat's watermark on the widget. + diff --git a/apps/meteor/app/livechat/imports/server/rest/appearance.ts b/apps/meteor/app/livechat/imports/server/rest/appearance.ts index 5a0a884d97b..55607551ec3 100644 --- a/apps/meteor/app/livechat/imports/server/rest/appearance.ts +++ b/apps/meteor/app/livechat/imports/server/rest/appearance.ts @@ -1,3 +1,4 @@ +import type { ISettingSelectOption } from '@rocket.chat/core-typings'; import { Settings } from '@rocket.chat/models'; import { isPOSTLivechatAppearanceParams } from '@rocket.chat/rest-typings'; @@ -45,6 +46,10 @@ API.v1.addRoute( 'Livechat_name_field_registration_form', 'Livechat_email_field_registration_form', 'Livechat_registration_form_message', + 'Livechat_hide_watermark', + 'Livechat_background', + 'Livechat_widget_position', + 'Livechat_hide_system_messages', ]; const valid = settings.every((setting) => validSettingList.includes(setting._id)); @@ -60,6 +65,10 @@ API.v1.addRoute( return; } + if (dbSetting.type === 'multiSelect' && (!Array.isArray(setting.value) || !validateValues(setting.value, dbSetting.values))) { + return; + } + switch (dbSetting?.type) { case 'boolean': return { @@ -91,7 +100,11 @@ API.v1.addRoute( }, ); -function coerceInt(value: string | number | boolean): number { +function validateValues(values: string[], allowedValues: ISettingSelectOption[] = []): boolean { + return values.every((value) => allowedValues.some((allowedValue) => allowedValue.key === value)); +} + +function coerceInt(value: string | number | boolean | string[]): number { if (typeof value === 'number') { return value; } @@ -100,6 +113,10 @@ function coerceInt(value: string | number | boolean): number { return 0; } + if (Array.isArray(value)) { + return 0; + } + const parsedValue = parseInt(value, 10); if (Number.isNaN(parsedValue)) { return 0; diff --git a/apps/meteor/app/livechat/server/api/lib/appearance.ts b/apps/meteor/app/livechat/server/api/lib/appearance.ts index d0a0a3df6b1..785413ead9d 100644 --- a/apps/meteor/app/livechat/server/api/lib/appearance.ts +++ b/apps/meteor/app/livechat/server/api/lib/appearance.ts @@ -24,6 +24,10 @@ export async function findAppearance(): Promise<{ appearance: ISetting[] }> { 'Livechat_email_field_registration_form', 'Livechat_registration_form_message', 'Livechat_conversation_finished_text', + 'Livechat_hide_watermark', + 'Livechat_background', + 'Livechat_widget_position', + 'Livechat_hide_system_messages', ], }, }; diff --git a/apps/meteor/client/views/omnichannel/appearance/AppearanceFieldLabel.tsx b/apps/meteor/client/views/omnichannel/appearance/AppearanceFieldLabel.tsx new file mode 100644 index 00000000000..ba8b54aeacc --- /dev/null +++ b/apps/meteor/client/views/omnichannel/appearance/AppearanceFieldLabel.tsx @@ -0,0 +1,32 @@ +import { FieldLabel as BaseFieldLabel, Box, Tag } from '@rocket.chat/fuselage'; +import { useTranslation } from '@rocket.chat/ui-contexts'; +import type { ComponentProps } from 'react'; +import React from 'react'; + +import { useHasLicenseModule } from '../../../../ee/client/hooks/useHasLicenseModule'; + +type FieldLabelProps = ComponentProps & { + premium?: boolean; + children: string; +}; + +const FieldLabel = ({ children: label, premium = false }: FieldLabelProps) => { + const t = useTranslation(); + const hasLicense = useHasLicenseModule('livechat-enterprise'); + const shouldDisableEnterprise = premium && !hasLicense; + + if (!shouldDisableEnterprise) { + return {label}; + } + + return ( + + + {label} + + {t('Premium')} + + ); +}; + +export default FieldLabel; diff --git a/apps/meteor/client/views/omnichannel/appearance/AppearanceForm.tsx b/apps/meteor/client/views/omnichannel/appearance/AppearanceForm.tsx index 258cda39e96..91c8d20f49f 100644 --- a/apps/meteor/client/views/omnichannel/appearance/AppearanceForm.tsx +++ b/apps/meteor/client/views/omnichannel/appearance/AppearanceForm.tsx @@ -1,6 +1,5 @@ import { Field, - FieldLabel, FieldRow, TextInput, ToggleSwitch, @@ -9,6 +8,9 @@ import { InputBox, TextAreaInput, NumberInput, + Select, + MultiSelect, + FieldHint, } from '@rocket.chat/fuselage'; import { useUniqueId } from '@rocket.chat/fuselage-hooks'; import { useTranslation } from '@rocket.chat/ui-contexts'; @@ -16,8 +18,13 @@ import type { ChangeEvent } from 'react'; import React from 'react'; import { Controller, useFormContext } from 'react-hook-form'; +import { useHasLicenseModule } from '../../../../ee/client/hooks/useHasLicenseModule'; +import MarkdownText from '../../../components/MarkdownText'; +import FieldLabel from './AppearanceFieldLabel'; + const AppearanceForm = () => { const t = useTranslation(); + const isEnterprise = useHasLicenseModule('livechat-enterprise'); const { control, watch } = useFormContext(); const { Livechat_enable_message_character_limit } = watch(); @@ -41,9 +48,101 @@ const AppearanceForm = () => { const livechatRegistrationFormMessageField = useUniqueId(); const livechatConversationFinishedMessageField = useUniqueId(); const livechatConversationFinishedTextField = useUniqueId(); + const livechatHideWatermarkField = useUniqueId(); + const livechatWidgetPositionField = useUniqueId(); + const livechatBackgroundField = useUniqueId(); + const livechatHideSystemMessagesField = useUniqueId(); return ( + + + + + + {t('Livechat_hide_watermark')} + + ( + + )} + /> + + + + + + {t('Livechat_background')} + + + ( + + )} + /> + + + + + + + + + {t('Livechat_widget_position_on_the_screen')} + + + ( +