snapshot of https://github.com/RocketChat/Rocket.Chat.git (develop, 2026-09-16; blobs > 131072B omitted)
Some checks failed
Create issues from TODOs / todos (push) Failing after 3s
Close inactive issues / close-issues (push) Has been cancelled
Deploy GitHub Pages / deploy-preview (push) Has been cancelled
CI / ⚙️ Variables Setup (push) Has been cancelled
CI / ⚙️ Test Guard (push) Has been cancelled
CI / 🚀 Notify external services - draft (push) Has been cancelled
CI / 📦 Build Packages (push) Has been cancelled
CI / 📦 Meteor Build (coverage) (push) Has been cancelled
CI / 📦 Meteor Build (production) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], fips) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Publish Docker Images (ghcr.io) (push) Has been cancelled
CI / 📦 Track Image Sizes (push) Has been cancelled
CI / 🔎 Code Check - Action Lint (push) Has been cancelled
CI / 🔎 Code Check (push) Has been cancelled
CI / 🔨 Test Storybook (push) Has been cancelled
CI / 🔨 Test Unit (push) Has been cancelled
CI / 🔨 Test API (CE) (push) Has been cancelled
CI / 🔨 Test API Livechat (CE) (push) Has been cancelled
CI / 🔨 Test UI (CE) (push) Has been cancelled
CI / 🔨 Test API (EE) (push) Has been cancelled
CI / 🔨 Test API Livechat (EE) (push) Has been cancelled
CI / 🔨 Test API Apps (deno-runtime - EE) (push) Has been cancelled
CI / 🔨 Test UI (EE) (push) Has been cancelled
CI / 🔨 Test API (FIPS) (push) Has been cancelled
CI / 🔨 Test API Livechat (FIPS) (push) Has been cancelled
CI / 🔨 Test UI (FIPS) (push) Has been cancelled
CI / 🔨 Test Federation Matrix (push) Has been cancelled
CI / 📊 Report Coverage (push) Has been cancelled
CI / ✅ Tests Done (push) Has been cancelled
CI / 🚀 Publish build assets (push) Has been cancelled
CI / 🚀 Publish Docker Images (DockerHub) (push) Has been cancelled
CI / 🚀 Notify external services (push) Has been cancelled
CI / Update Version Durability (push) Has been cancelled
Release / Release (push) Has been cancelled
Auto-close duplicate issues / auto-close-duplicates (push) Failing after 1s
Code scanning - action / CodeQL-Build (push) Failing after 1s

This commit is contained in:
upstream-mirror
2026-09-16 01:21:02 +05:00
commit 30810eecd7
10161 changed files with 987110 additions and 0 deletions

View File

@@ -0,0 +1,63 @@
import { PaginatedSelectFiltered } from '@rocket.chat/fuselage';
import { useDebouncedValue, useStableCallback } from '@rocket.chat/fuselage-hooks';
import type { ComponentProps } from 'react';
import { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import type { UnitOption } from '../hooks/useUnitsList';
import { useUnitsList } from '../hooks/useUnitsList';
export type AutoCompleteUnitProps = Omit<
ComponentProps<typeof PaginatedSelectFiltered>,
'filter' | 'setFilter' | 'options' | 'endReached' | 'renderItem'
> & {
haveNone?: boolean;
value: string | undefined;
onChange: (value: string) => void;
onLoadItems?: (list: UnitOption[]) => void;
};
const AutoCompleteUnit = ({
id,
value,
disabled = false,
error,
placeholder,
haveNone,
onChange,
onLoadItems = () => undefined,
}: AutoCompleteUnitProps) => {
const { t } = useTranslation();
const [unitsFilter, setUnitsFilter] = useState<string>('');
const debouncedUnitFilter = useDebouncedValue(unitsFilter, 500);
const { data: unitsList, fetchNextPage } = useUnitsList({ filter: debouncedUnitFilter, haveNone });
const handleLoadItems = useStableCallback(onLoadItems);
useEffect(() => {
handleLoadItems(unitsList);
}, [handleLoadItems, unitsList]);
return (
<PaginatedSelectFiltered
id={id}
aria-label={t('Unit')} // FIXME: remove this when PaginatedSelectFiltered properly associates the input with the label htmlFor
error={error}
filter={unitsFilter}
flexGrow={0}
flexShrink={0}
disabled={disabled}
onChange={onChange}
options={unitsList}
placeholder={placeholder || t('Select_an_option')}
setFilter={setUnitsFilter as (value: string | number | undefined) => void}
value={value}
width='100%'
endReached={() => fetchNextPage()}
/>
);
};
export default AutoCompleteUnit;

View File

@@ -0,0 +1,38 @@
import { PaginatedMultiSelectFiltered } from '@rocket.chat/fuselage';
import { useDebouncedValue } from '@rocket.chat/fuselage-hooks';
import type { ComponentProps } from 'react';
import { memo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useUnitsList } from '../hooks/useUnitsList';
export type AutoCompleteUnitsProps = Omit<
ComponentProps<typeof PaginatedMultiSelectFiltered>,
'filter' | 'setFilter' | 'options' | 'endReached' | 'renderItem'
>;
const AutoCompleteUnits = ({ value, placeholder, onChange, ...props }: AutoCompleteUnitsProps) => {
const { t } = useTranslation();
const [unitsFilter, setUnitsFilter] = useState<string>('');
const debouncedUnitFilter = useDebouncedValue(unitsFilter, 500);
const { data: unitItems, fetchNextPage } = useUnitsList({ filter: debouncedUnitFilter });
return (
<PaginatedMultiSelectFiltered
{...props}
value={value}
placeholder={placeholder || t('Select_an_option')}
filter={unitsFilter}
width='100%'
flexShrink={0}
flexGrow={0}
setFilter={setUnitsFilter as (value: string | number | undefined) => void}
options={unitItems}
onChange={onChange}
endReached={() => fetchNextPage()}
/>
);
};
export default memo(AutoCompleteUnits);

View File

@@ -0,0 +1,30 @@
import { Box, Skeleton } from '@rocket.chat/fuselage';
import type { StoryObj, Meta } from '@storybook/react';
import BusinessHoursMultiple from './BusinessHoursMultiple';
export default {
component: BusinessHoursMultiple,
parameters: {
layout: 'fullscreen',
},
decorators: [
(fn) => (
<Box maxWidth='x600' alignSelf='center' width='full' margin={24}>
{fn()}
</Box>
),
],
} satisfies Meta<typeof BusinessHoursMultiple>;
export const Default: StoryObj<typeof BusinessHoursMultiple> = {
name: 'BusinessHoursMultiple',
args: {
departmentList: [
[1, 'Support'],
[2, 'Marketing'],
[3, <Skeleton width='x100' key={3} />],
],
} as any,
};

View File

@@ -0,0 +1,83 @@
import { Field, FieldLabel, FieldRow, FieldError, TextInput, ToggleSwitch } from '@rocket.chat/fuselage';
import { useId } from 'react';
import type { ComponentProps } from 'react';
import { Controller, useFormContext } from 'react-hook-form';
import { useTranslation } from 'react-i18next';
import { useHasLicenseModule } from '../../../hooks/useHasLicenseModule';
import type { BusinessHoursFormData } from '../businessHours/BusinessHoursForm';
import AutoCompleteDepartmentMultiple from '../components/AutoCompleteDepartmentMultiple';
export type BusinessHoursMultipleProps = { className?: ComponentProps<typeof Field>['className'] };
const BusinessHoursMultiple = ({ className }: BusinessHoursMultipleProps) => {
const { t } = useTranslation();
const {
control,
formState: { errors },
} = useFormContext<BusinessHoursFormData>();
const { data: hasLicense = false } = useHasLicenseModule('livechat-enterprise');
const enabledField = useId();
const nameField = useId();
const departmentsFieldLabelId = useId();
if (!hasLicense) {
return null;
}
return (
<>
<Field className={className}>
<FieldRow>
<FieldLabel htmlFor={enabledField}>{t('Enabled')}</FieldLabel>
<Controller
name='active'
control={control}
render={({ field: { value, ...field } }) => <ToggleSwitch id={enabledField} {...field} checked={value} />}
/>
</FieldRow>
</Field>
<Field className={className}>
<FieldLabel htmlFor={nameField} required>
{t('Name')}
</FieldLabel>
<FieldRow>
<Controller
name='name'
control={control}
rules={{ required: t('Required_field', { field: t('Name') }) }}
render={({ field }) => <TextInput id={nameField} {...field} aria-describedby={`${nameField}-error`} />}
/>
</FieldRow>
{errors?.name && (
<FieldError aria-live='assertive' id={`${nameField}-error`}>
{errors.name.message}
</FieldError>
)}
</Field>
<Field className={className}>
<FieldLabel id={departmentsFieldLabelId}>{t('Departments')}</FieldLabel>
<FieldRow>
<Controller
name='departments'
control={control}
render={({ field: { value, onChange, name, onBlur } }) => (
<AutoCompleteDepartmentMultiple
withCheckbox
value={value}
onChange={onChange}
name={name}
onBlur={onBlur}
enabled={true}
aria-labelledby={departmentsFieldLabelId}
/>
)}
/>
</FieldRow>
</Field>
</>
);
};
export default BusinessHoursMultiple;

View File

@@ -0,0 +1,27 @@
import { useHasLicenseModule } from '../../../hooks/useHasLicenseModule';
import AutoCompleteAgent from '../components/AutoCompleteAgent';
export type ContactManagerInputProps = {
value: string;
onChange: (currentValue: string) => void;
};
const ContactManagerInput = ({ value: userId, onChange }: ContactManagerInputProps) => {
const { data: hasLicense = false } = useHasLicenseModule('livechat-enterprise');
if (!hasLicense) {
return null;
}
const handleChange = (currentValue: string) => {
if (currentValue === 'no-agent-selected') {
return onChange('');
}
onChange(currentValue);
};
return <AutoCompleteAgent haveNoAgentsSelectedOption value={userId} onChange={handleChange} />;
};
export default ContactManagerInput;

View File

@@ -0,0 +1,23 @@
import type { ComponentProps } from 'react';
import { useHasLicenseModule } from '../../../hooks/useHasLicenseModule';
import AutoCompleteTagsMultiple from '../tags/AutoCompleteTagsMultiple';
export type CurrentChatTagsProps = Pick<ComponentProps<typeof AutoCompleteTagsMultiple>, 'id' | 'aria-labelledby'> & {
value: NonNullable<ComponentProps<typeof AutoCompleteTagsMultiple>['value']>;
handler: NonNullable<ComponentProps<typeof AutoCompleteTagsMultiple>['onChange']>;
department?: string;
viewAll?: boolean;
};
const CurrentChatTags = ({ value, handler, department, viewAll, ...props }: CurrentChatTagsProps) => {
const { data: hasLicense = false } = useHasLicenseModule('livechat-enterprise');
if (!hasLicense) {
return null;
}
return <AutoCompleteTagsMultiple {...props} onChange={handler} value={value} department={department} viewAll={viewAll} />;
};
export default CurrentChatTags;

View File

@@ -0,0 +1,118 @@
import type { SelectOption } from '@rocket.chat/fuselage';
import { Field, FieldLabel, FieldRow, FieldError, FieldHint, ToggleSwitch, TextInput, Select } from '@rocket.chat/fuselage';
import type { ComponentProps } from 'react';
import { useId, useMemo } from 'react';
import { useFormContext, Controller } from 'react-hook-form';
import { useTranslation } from 'react-i18next';
import { useHasLicenseModule } from '../../../hooks/useHasLicenseModule';
import type { EditCustomFieldsFormData } from '../customFields/EditCustomFields';
const checkIsOptionsValid = (value: string) => {
if (!value || value.trim() === '') {
return false;
}
return value.split(',').every((v) => /^[a-zA-Z0-9-_ ]+$/.test(v));
};
export type CustomFieldsAdditionalFormProps = { className?: ComponentProps<typeof Field>['className'] };
const CustomFieldsAdditionalForm = ({ className }: CustomFieldsAdditionalFormProps) => {
const { t } = useTranslation();
const {
control,
watch,
formState: { errors },
} = useFormContext<EditCustomFieldsFormData>();
const { data: hasLicense = false } = useHasLicenseModule('livechat-enterprise');
const { visibility, type } = watch();
const typeOptions: SelectOption[] = useMemo(
() => [
['input', t('Input')],
['select', t('Select')],
],
[t],
);
const requiredField = useId();
const typeField = useId();
const defaultValueField = useId();
const optionsField = useId();
const publicField = useId();
if (!hasLicense) {
return null;
}
return (
<>
<Field className={className}>
<FieldRow>
<FieldLabel htmlFor={requiredField}>{t('Required')}</FieldLabel>
<Controller
name='required'
control={control}
render={({ field: { value, ...field } }) => <ToggleSwitch id={requiredField} {...field} checked={value} />}
/>
</FieldRow>
</Field>
<Field className={className}>
<FieldLabel htmlFor={typeField}>{t('Type')}</FieldLabel>
<FieldRow>
<Controller name='type' control={control} render={({ field }) => <Select id={typeField} options={typeOptions} {...field} />} />
</FieldRow>
</Field>
<Field className={className}>
<FieldLabel htmlFor={defaultValueField}>{t('Default_value')}</FieldLabel>
<FieldRow>
<Controller name='defaultValue' control={control} render={({ field }) => <TextInput id={defaultValueField} {...field} />} />
</FieldRow>
</Field>
<Field className={className}>
<FieldLabel htmlFor={optionsField}>{t('Options')}</FieldLabel>
<FieldRow>
<Controller
name='options'
control={control}
rules={{
validate: (optionsValue) => (type === 'select' && !checkIsOptionsValid(optionsValue) ? t('error-invalid-value') : undefined),
}}
render={({ field }) => (
<TextInput
id={optionsField}
{...field}
disabled={type === 'input'}
aria-invalid={Boolean(errors?.options)}
aria-describedby={`${optionsField}-hint ${optionsField}-error`}
/>
)}
/>
</FieldRow>
<FieldHint id={`${optionsField}-hint`}>{t('Livechat_custom_fields_options_placeholder')}</FieldHint>
{errors.options && (
<FieldError aria-live='assertive' id={`${optionsField}-error`}>
{errors.options.message}
</FieldError>
)}
</Field>
<Field className={className}>
<FieldRow>
<FieldLabel htmlFor={publicField}>{t('Public')}</FieldLabel>
<Controller
name='public'
control={control}
render={({ field: { value, ...field } }) => (
<ToggleSwitch id={publicField} {...field} disabled={!visibility} checked={value} aria-describedby={`${publicField}-hint`} />
)}
/>
</FieldRow>
<FieldHint id={`${publicField}-hint`}>{t('Livechat_custom_fields_public_description')}</FieldHint>
</Field>
</>
);
};
export default CustomFieldsAdditionalForm;

View File

@@ -0,0 +1,35 @@
import { Field, FieldLabel, FieldRow, TextInput } from '@rocket.chat/fuselage';
import { useEndpoint } from '@rocket.chat/ui-contexts';
import { useQuery } from '@tanstack/react-query';
import { useTranslation } from 'react-i18next';
import { useHasLicenseModule } from '../../../hooks/useHasLicenseModule';
export type DepartmentBusinessHoursProps = { bhId: string | undefined };
export const DepartmentBusinessHours = ({ bhId }: DepartmentBusinessHoursProps) => {
const { t } = useTranslation();
const { data: hasLicense = false } = useHasLicenseModule('livechat-enterprise');
const getBusinessHour = useEndpoint('GET', '/v1/livechat/business-hour');
const { data } = useQuery({
queryKey: ['/v1/livechat/business-hour', bhId],
queryFn: () => getBusinessHour({ _id: bhId, type: 'custom' }),
});
const name = data?.businessHour?.name;
if (!hasLicense) {
return null;
}
return (
<Field>
<FieldLabel>{t('Business_Hour')}</FieldLabel>
<FieldRow>
<TextInput readOnly value={name || ''} />
</FieldRow>
</Field>
);
};
export default DepartmentBusinessHours;

View File

@@ -0,0 +1,25 @@
import { NumberInput, Field, FieldLabel, FieldRow } from '@rocket.chat/fuselage';
import type { ComponentProps } from 'react';
import { useHasLicenseModule } from '../../../hooks/useHasLicenseModule';
export type EeNumberInputProps = { label: string } & ComponentProps<typeof NumberInput>;
export const EeNumberInput = ({ label, ...props }: EeNumberInputProps) => {
const { data: hasLicense = false } = useHasLicenseModule('livechat-enterprise');
if (!hasLicense) {
return null;
}
return (
<Field>
<FieldLabel>{label}</FieldLabel>
<FieldRow>
<NumberInput {...props} flexGrow={1} />
</FieldRow>
</Field>
);
};
export default EeNumberInput;

View File

@@ -0,0 +1,25 @@
import { TextAreaInput, Field, FieldLabel, FieldRow } from '@rocket.chat/fuselage';
import type { ComponentProps } from 'react';
import { useHasLicenseModule } from '../../../hooks/useHasLicenseModule';
export type EeTextAreaInputProps = { label: string } & ComponentProps<typeof TextAreaInput>;
export const EeTextAreaInput = ({ label, ...props }: EeTextAreaInputProps) => {
const { data: hasLicense = false } = useHasLicenseModule('livechat-enterprise');
if (!hasLicense) {
return null;
}
return (
<Field>
<FieldLabel>{label}</FieldLabel>
<FieldRow>
<TextAreaInput {...props} />
</FieldRow>
</Field>
);
};
export default EeTextAreaInput;

View File

@@ -0,0 +1,25 @@
import { TextInput, Field, FieldLabel, FieldRow } from '@rocket.chat/fuselage';
import type { ComponentProps } from 'react';
import { useHasLicenseModule } from '../../../hooks/useHasLicenseModule';
export type EeTextInputProps = { label: string } & ComponentProps<typeof TextInput>;
export const EeTextInput = ({ label, ...props }: EeTextInputProps) => {
const { data: hasLicense = false } = useHasLicenseModule('livechat-enterprise');
if (!hasLicense) {
return null;
}
return (
<Field>
<FieldLabel>{label}</FieldLabel>
<FieldRow>
<TextInput {...props} />
</FieldRow>
</Field>
);
};
export default EeTextInput;

View File

@@ -0,0 +1,36 @@
import { NumberInput, Field, FieldLabel, FieldRow } from '@rocket.chat/fuselage';
import { useId } from 'react';
import type { ComponentProps } from 'react';
import { useFormContext, Controller } from 'react-hook-form';
import { useTranslation } from 'react-i18next';
import { useHasLicenseModule } from '../../../hooks/useHasLicenseModule';
export type MaxChatsPerAgentProps = { className?: ComponentProps<typeof Field>['className'] };
const MaxChatsPerAgent = ({ className }: MaxChatsPerAgentProps) => {
const { t } = useTranslation();
const { control } = useFormContext();
const { data: hasLicense = false } = useHasLicenseModule('livechat-enterprise');
const maxChatsField = useId();
if (!hasLicense) {
return null;
}
return (
<Field className={className}>
<FieldLabel htmlFor={maxChatsField}>{t('Max_number_of_chats_per_agent')}</FieldLabel>
<FieldRow>
<Controller
name='maxNumberSimultaneousChat'
control={control}
render={({ field }) => <NumberInput id={maxChatsField} {...field} />}
/>
</FieldRow>
</Field>
);
};
export default MaxChatsPerAgent;

View File

@@ -0,0 +1,22 @@
import { InfoPanelLabel, InfoPanelText } from '@rocket.chat/ui-client';
import { useTranslation } from 'react-i18next';
import { useHasLicenseModule } from '../../../hooks/useHasLicenseModule';
const MaxChatsPerAgentDisplay = ({ maxNumberSimultaneousChat = 0 }) => {
const { t } = useTranslation();
const { data: hasLicense = false } = useHasLicenseModule('livechat-enterprise');
if (!hasLicense) {
return null;
}
return (
<>
<InfoPanelLabel>{t('Max_number_of_chats_per_agent')}</InfoPanelLabel>
<InfoPanelText>{maxNumberSimultaneousChat}</InfoPanelText>
</>
);
};
export default MaxChatsPerAgentDisplay;

View File

@@ -0,0 +1,71 @@
import type { ILivechatPriority, Serialized } from '@rocket.chat/core-typings';
import { LivechatPriorityWeight } from '@rocket.chat/core-typings';
import type { SelectOption } from '@rocket.chat/fuselage';
import { Options, Box, Option, Field, FieldLabel, FieldRow, SelectLegacy } from '@rocket.chat/fuselage';
import type { TranslationKey } from '@rocket.chat/ui-contexts';
import type { ComponentProps } from 'react';
import { useCallback, forwardRef, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useHasLicenseModule } from '../../../hooks/useHasLicenseModule';
import { PriorityIcon } from '../priorities/PriorityIcon';
export type PrioritiesSelectProps = {
value: string;
label: string;
options: Serialized<ILivechatPriority[]>;
onChange: (value: string) => void;
};
export const PrioritiesSelect = ({ value = '', label, options, onChange }: PrioritiesSelectProps) => {
const { t } = useTranslation();
const { data: hasLicense = false } = useHasLicenseModule('livechat-enterprise');
const [sorting] = useState<Record<string, LivechatPriorityWeight>>({});
const formattedOptions = useMemo<SelectOption[]>(() => {
const opts: SelectOption[] = options?.map(({ dirty, name, i18n, _id, sortItem }) => {
const label = dirty && name ? name : t(i18n as TranslationKey);
sorting[_id] = sortItem;
return [_id, label];
});
return [['', t('Unprioritized')], ...opts];
}, [options, sorting, t]);
const renderOption = useCallback(
(label: string, value: string) => {
return (
<>
<PriorityIcon level={sorting[value] || LivechatPriorityWeight.NOT_SPECIFIED} showUnprioritized /> {label}
</>
);
},
[sorting],
);
// eslint-disable-next-line react/no-multi-comp
const renderOptions = forwardRef<HTMLElement, ComponentProps<typeof Options>>(function OptionsWrapper(props, ref) {
return <Options ref={ref} {...props} maxHeight={200} />;
});
if (!hasLicense) {
return null;
}
return (
<Field>
<FieldLabel>{label}</FieldLabel>
<FieldRow>
<SelectLegacy
value={value}
onChange={onChange}
options={formattedOptions}
renderOptions={renderOptions}
renderSelected={({ label, value }) => <Box flexGrow='1'>{renderOption(label, value)}</Box>}
renderItem={({ label, value, ...props }) => <Option {...props} label={renderOption(label, value)} />}
/>
</FieldRow>
</Field>
);
};
export default PrioritiesSelect;

View File

@@ -0,0 +1,34 @@
import type { IOmnichannelServiceLevelAgreements, Serialized } from '@rocket.chat/core-typings';
import type { SelectOption } from '@rocket.chat/fuselage';
import { Field, FieldLabel, FieldRow, Select } from '@rocket.chat/fuselage';
import { useId, useMemo } from 'react';
import { useHasLicenseModule } from '../../../hooks/useHasLicenseModule';
export type SlaPoliciesSelectProps = {
value: string;
label: string;
options: Serialized<IOmnichannelServiceLevelAgreements[]>;
onChange: (value: string) => void;
};
export const SlaPoliciesSelect = ({ value, label, options, onChange }: SlaPoliciesSelectProps) => {
const { data: hasLicense = false } = useHasLicenseModule('livechat-enterprise');
const optionsSelect = useMemo<SelectOption[]>(() => options?.map((option) => [option._id, option.name]), [options]);
const fieldId = useId();
if (!hasLicense) {
return null;
}
return (
<Field>
<FieldLabel id={fieldId}>{label}</FieldLabel>
<FieldRow>
<Select aria-labelledby={fieldId} value={value} options={optionsSelect} onChange={(value) => onChange(String(value))} />
</FieldRow>
</Field>
);
};
export default SlaPoliciesSelect;