From f23e4f6cdddb94a0a722b2470b9804b84ab83ef9 Mon Sep 17 00:00:00 2001 From: Kevin Aleman Date: Thu, 22 Jun 2023 09:07:45 -0600 Subject: [PATCH 01/21] fix: Take seconds to assess if BH is open/closed (#29558) --- .changeset/two-wasps-develop.md | 5 +++++ apps/meteor/app/livechat/server/business-hour/Helper.ts | 8 ++++---- 2 files changed, 9 insertions(+), 4 deletions(-) create mode 100644 .changeset/two-wasps-develop.md diff --git a/.changeset/two-wasps-develop.md b/.changeset/two-wasps-develop.md new file mode 100644 index 0000000000000..5229b7c23bd8b --- /dev/null +++ b/.changeset/two-wasps-develop.md @@ -0,0 +1,5 @@ +--- +"@rocket.chat/meteor": patch +--- + +Fixed Business Hours behavior so they now Take seconds in consideration to assess if BH is open/closed diff --git a/apps/meteor/app/livechat/server/business-hour/Helper.ts b/apps/meteor/app/livechat/server/business-hour/Helper.ts index f0ebf1b0744a3..ba2b48089afb9 100644 --- a/apps/meteor/app/livechat/server/business-hour/Helper.ts +++ b/apps/meteor/app/livechat/server/business-hour/Helper.ts @@ -8,7 +8,7 @@ import { createDefaultBusinessHourRow } from './LivechatBusinessHours'; export const filterBusinessHoursThatMustBeOpened = async ( businessHours: ILivechatBusinessHour[], ): Promise[]> => { - const currentTime = moment(moment().format('dddd:HH:mm'), 'dddd:HH:mm'); + const currentTime = moment(moment().format('dddd:HH:mm:ss'), 'dddd:HH:mm:ss'); return businessHours .filter( @@ -17,9 +17,9 @@ export const filterBusinessHoursThatMustBeOpened = async ( businessHour.workHours .filter((hour) => hour.open) .some((hour) => { - const localTimeStart = moment(`${hour.start.cron.dayOfWeek}:${hour.start.cron.time}`, 'dddd:HH:mm'); - const localTimeFinish = moment(`${hour.finish.cron.dayOfWeek}:${hour.finish.cron.time}`, 'dddd:HH:mm'); - return currentTime.isSameOrAfter(localTimeStart) && currentTime.isSameOrBefore(localTimeFinish); + const localTimeStart = moment(`${hour.start.cron.dayOfWeek}:${hour.start.cron.time}:00`, 'dddd:HH:mm:ss'); + const localTimeFinish = moment(`${hour.finish.cron.dayOfWeek}:${hour.finish.cron.time}:00`, 'dddd:HH:mm:ss'); + return currentTime.isSameOrAfter(localTimeStart) && currentTime.isBefore(localTimeFinish); }), ) .map((businessHour) => ({ From 9a659115aad0a17aaa44dbd53ed21cfe05f48033 Mon Sep 17 00:00:00 2001 From: Martin Schoeler Date: Thu, 22 Jun 2023 13:49:48 -0300 Subject: [PATCH 02/21] fix: livechat translations not loading on refresh (#29607) --- .../livechat/src/components/Alert/index.js | 49 ------------- .../livechat/src/components/Alert/index.tsx | 68 +++++++++++++++++++ packages/livechat/src/definitions/svg.d.ts | 4 ++ packages/livechat/src/i18next.js | 2 + packages/livechat/src/lib/connection.js | 2 +- 5 files changed, 75 insertions(+), 50 deletions(-) delete mode 100644 packages/livechat/src/components/Alert/index.js create mode 100644 packages/livechat/src/components/Alert/index.tsx create mode 100644 packages/livechat/src/definitions/svg.d.ts diff --git a/packages/livechat/src/components/Alert/index.js b/packages/livechat/src/components/Alert/index.js deleted file mode 100644 index 35448684cb8ab..0000000000000 --- a/packages/livechat/src/components/Alert/index.js +++ /dev/null @@ -1,49 +0,0 @@ -import { Component } from 'preact'; -import { withTranslation } from 'react-i18next'; - -import CloseIcon from '../../icons/close.svg'; -import { createClassName } from '../helpers'; -import styles from './styles.scss'; - -class Alert extends Component { - static defaultProps = { - timeout: 3000, - hideCloseButton: false, - }; - - handleDismiss = () => { - const { onDismiss, id } = this.props; - onDismiss && onDismiss(id); - }; - - componentDidMount() { - const { timeout } = this.props; - if (Number.isFinite(timeout) && timeout > 0) { - this.dismissTimeout = setTimeout(this.handleDismiss, timeout); - } - } - - componentWillUnmount() { - clearTimeout(this.dismissTimeout); - } - - render = ({ success, warning, error, color, hideCloseButton, className, style = {}, children, t }) => ( -
-
{children}
- {!hideCloseButton && ( - - )} -
- ); -} - -export default withTranslation()(Alert); diff --git a/packages/livechat/src/components/Alert/index.tsx b/packages/livechat/src/components/Alert/index.tsx new file mode 100644 index 0000000000000..c68c88e5a58d9 --- /dev/null +++ b/packages/livechat/src/components/Alert/index.tsx @@ -0,0 +1,68 @@ +import { useCallback, useEffect } from 'preact/hooks'; +import type { JSXInternal } from 'preact/src/jsx'; +import { useTranslation } from 'react-i18next'; + +import CloseIcon from '../../icons/close.svg'; +import { createClassName } from '../helpers'; +import styles from './styles.scss'; + +type AlertProps = { + id?: string; + onDismiss?: (id?: string) => void; + success?: boolean; + warning?: boolean; + error?: boolean; + color?: string; + hideCloseButton?: boolean; + className?: string; + style?: JSXInternal.CSSProperties; + children?: JSXInternal.Element[]; + timeout?: number; +}; + +const Alert = ({ + id, + onDismiss, + success, + warning, + error, + color, + hideCloseButton = false, + className, + style = {}, + children, + timeout = 3000, +}: AlertProps) => { + const { t } = useTranslation(); + const handleDismiss = useCallback(() => { + onDismiss?.(id); + }, [id, onDismiss]); + + useEffect(() => { + let dismissTimeout: ReturnType | undefined; + if (Number.isFinite(timeout) && timeout > 0) { + dismissTimeout = setTimeout(handleDismiss, timeout); + } + return () => clearTimeout(dismissTimeout); + }, [handleDismiss, timeout]); + + return ( +
+
{children}
+ {!hideCloseButton && ( + + )} +
+ ); +}; + +export default Alert; diff --git a/packages/livechat/src/definitions/svg.d.ts b/packages/livechat/src/definitions/svg.d.ts new file mode 100644 index 0000000000000..2a5f8a94ea058 --- /dev/null +++ b/packages/livechat/src/definitions/svg.d.ts @@ -0,0 +1,4 @@ +declare module '*.svg' { + const content: Preact.FunctionComponent>; + export default content; +} diff --git a/packages/livechat/src/i18next.js b/packages/livechat/src/i18next.js index 5ad7b41248df8..274eecf0708af 100644 --- a/packages/livechat/src/i18next.js +++ b/packages/livechat/src/i18next.js @@ -26,5 +26,7 @@ export default i18next fallbackLng: 'en', react: { useSuspense: false, + bindI18n: 'loaded languageChanged', + bindI18nStore: 'added', } }); diff --git a/packages/livechat/src/lib/connection.js b/packages/livechat/src/lib/connection.js index 8431a529bc0aa..0bd850d6d83e2 100644 --- a/packages/livechat/src/lib/connection.js +++ b/packages/livechat/src/lib/connection.js @@ -26,9 +26,9 @@ const Connection = { async connect() { try { + await import('../i18next'); this.clearListeners(); await loadConfig(); - await import('../i18next'); // await Livechat.connection.connect(); this.addListeners(); this.clearAlerts(); From 0c94802afdfe6fa984e8c1b05e58848e753b7c8b Mon Sep 17 00:00:00 2001 From: Aleksander Nicacio da Silva Date: Thu, 22 Jun 2023 14:30:26 -0300 Subject: [PATCH 03/21] fix: Adjusted to not show 'removed from' notification on Omnichannel rooms (#29610) --- .../body/hooks/useGoToHomeOnRemoved.ts | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/apps/meteor/client/views/room/components/body/hooks/useGoToHomeOnRemoved.ts b/apps/meteor/client/views/room/components/body/hooks/useGoToHomeOnRemoved.ts index 1560758f5a2b5..a087d288d0d76 100644 --- a/apps/meteor/client/views/room/components/body/hooks/useGoToHomeOnRemoved.ts +++ b/apps/meteor/client/views/room/components/body/hooks/useGoToHomeOnRemoved.ts @@ -3,6 +3,8 @@ import { useRoute, useStream, useToastMessageDispatch, useTranslation } from '@r import { useQueryClient } from '@tanstack/react-query'; import { useEffect } from 'react'; +const IGNORED_ROOMS = ['l', 'v']; + export function useGoToHomeOnRemoved(room: IRoom, userId: string | undefined): void { const homeRouter = useRoute('home'); const queryClient = useQueryClient(); @@ -18,16 +20,20 @@ export function useGoToHomeOnRemoved(room: IRoom, userId: string | undefined): v const unSubscribeFromNotifyUser = subscribeToNotifyUser(`${userId}/subscriptions-changed`, (event, subscription) => { if (event === 'removed' && subscription.rid === room._id) { queryClient.invalidateQueries(['rooms', room._id]); - dispatchToastMessage({ - type: 'info', - message: t('You_have_been_removed_from__roomName_', { - roomName: room?.fname || room?.name || '', - }), - }); + + if (!IGNORED_ROOMS.includes(room.t)) { + dispatchToastMessage({ + type: 'info', + message: t('You_have_been_removed_from__roomName_', { + roomName: room?.fname || room?.name || '', + }), + }); + } + homeRouter.push({}); } }); return unSubscribeFromNotifyUser; - }, [userId, homeRouter, subscribeToNotifyUser, room._id, room?.fname, room?.name, t, dispatchToastMessage, queryClient]); + }, [userId, homeRouter, subscribeToNotifyUser, room._id, room?.fname, room?.name, t, dispatchToastMessage, queryClient, room.t]); } From c1976240934dde1e88c57dbca3a64788bd9a4e85 Mon Sep 17 00:00:00 2001 From: Douglas Fabris Date: Thu, 22 Jun 2023 14:38:31 -0300 Subject: [PATCH 04/21] chore: Remove old deprecated `GenericTable` in favor of v2 (#29594) --- .../GenericTable/GenericTable.stories.tsx | 87 +++++-- .../components/GenericTable/GenericTable.tsx | 132 ++-------- .../GenericTable/GenericTableBody.tsx | 5 + .../GenericTable/GenericTableCell.tsx | 5 + .../GenericTable/GenericTableHeader.tsx | 11 + .../{V2 => }/GenericTableHeaderCell.tsx | 8 +- .../{V2 => }/GenericTableLoadingRow.tsx | 20 +- .../{V2 => }/GenericTableLoadingTable.tsx | 0 .../GenericTable/GenericTableRow.tsx | 5 + .../components/GenericTable/HeaderCell.tsx | 27 -- .../GenericTable/V2/GenericTable.tsx | 23 -- .../GenericTable/V2/GenericTableBody.tsx | 5 - .../GenericTable/V2/GenericTableCell.tsx | 5 - .../GenericTable/V2/GenericTableHeader.tsx | 11 - .../GenericTable/V2/GenericTableRow.tsx | 5 - .../client/components/GenericTable/index.ts | 23 +- .../CustomSoundsTable/CustomSoundRow.tsx | 3 +- .../PermissionsTable/RoleHeader.tsx | 6 +- .../groups/voip/VoipExtensionsPage.tsx | 187 ++++++++------ .../businessHours/BusinessHoursPage.js | 5 +- .../currentChats/CurrentChatsRoute.tsx | 2 +- .../omnichannel/directory/calls/CallTable.tsx | 219 ++++++++-------- .../directory/calls/CallTableRow.tsx | 4 +- .../omnichannel/directory/chats/ChatTable.tsx | 241 +++++++++--------- .../{ContactTab.js => ContactTab.tsx} | 6 +- .../directory/contacts/ContactTable.tsx | 158 ++++++------ .../omnichannel/queueList/QueueListPage.tsx | 55 +--- .../omnichannel/queueList/QueueListTable.tsx | 145 +++++++++++ .../views/omnichannel/queueList/index.ts | 1 + .../views/omnichannel/queueList/index.tsx | 114 --------- .../info/Delete/ChannelDeletionTable.js | 81 ------ .../info/Delete/ChannelDeletionTable.tsx | 78 ++++++ .../info/Delete/ChannelDeletionTableRow.tsx | 35 +++ .../contextualBar/info/Delete/ChannelRow.js | 29 --- .../ee/client/omnichannel/BusinessHoursRow.js | 18 +- .../client/omnichannel/BusinessHoursTable.js | 103 ++++++-- .../BusinessHoursTable.stories.tsx | 2 +- .../BusinessHoursTableContainer.js | 43 ---- .../cannedResponses/CannedResponsesPage.tsx | 75 ++---- .../cannedResponses/CannedResponsesRoute.tsx | 219 +--------------- .../cannedResponses/CannedResponsesTable.tsx | 203 +++++++++++++++ .../RemoveCannedResponseButton.tsx | 32 +-- .../omnichannel/priorities/PrioritiesPage.tsx | 4 +- .../priorities/PrioritiesTable.tsx | 72 ++++-- 44 files changed, 1188 insertions(+), 1324 deletions(-) create mode 100644 apps/meteor/client/components/GenericTable/GenericTableBody.tsx create mode 100644 apps/meteor/client/components/GenericTable/GenericTableCell.tsx create mode 100644 apps/meteor/client/components/GenericTable/GenericTableHeader.tsx rename apps/meteor/client/components/GenericTable/{V2 => }/GenericTableHeaderCell.tsx (81%) rename apps/meteor/client/components/GenericTable/{V2 => }/GenericTableLoadingRow.tsx (52%) rename apps/meteor/client/components/GenericTable/{V2 => }/GenericTableLoadingTable.tsx (100%) create mode 100644 apps/meteor/client/components/GenericTable/GenericTableRow.tsx delete mode 100644 apps/meteor/client/components/GenericTable/HeaderCell.tsx delete mode 100644 apps/meteor/client/components/GenericTable/V2/GenericTable.tsx delete mode 100644 apps/meteor/client/components/GenericTable/V2/GenericTableBody.tsx delete mode 100644 apps/meteor/client/components/GenericTable/V2/GenericTableCell.tsx delete mode 100644 apps/meteor/client/components/GenericTable/V2/GenericTableHeader.tsx delete mode 100644 apps/meteor/client/components/GenericTable/V2/GenericTableRow.tsx rename apps/meteor/client/views/omnichannel/directory/contacts/{ContactTab.js => ContactTab.tsx} (82%) create mode 100644 apps/meteor/client/views/omnichannel/queueList/QueueListTable.tsx create mode 100644 apps/meteor/client/views/omnichannel/queueList/index.ts delete mode 100644 apps/meteor/client/views/omnichannel/queueList/index.tsx delete mode 100644 apps/meteor/client/views/teams/contextualBar/info/Delete/ChannelDeletionTable.js create mode 100644 apps/meteor/client/views/teams/contextualBar/info/Delete/ChannelDeletionTable.tsx create mode 100644 apps/meteor/client/views/teams/contextualBar/info/Delete/ChannelDeletionTableRow.tsx delete mode 100644 apps/meteor/client/views/teams/contextualBar/info/Delete/ChannelRow.js delete mode 100644 apps/meteor/ee/client/omnichannel/BusinessHoursTableContainer.js create mode 100644 apps/meteor/ee/client/omnichannel/cannedResponses/CannedResponsesTable.tsx diff --git a/apps/meteor/client/components/GenericTable/GenericTable.stories.tsx b/apps/meteor/client/components/GenericTable/GenericTable.stories.tsx index 3ebb67b6e0956..f563999b0722f 100644 --- a/apps/meteor/client/components/GenericTable/GenericTable.stories.tsx +++ b/apps/meteor/client/components/GenericTable/GenericTable.stories.tsx @@ -1,8 +1,17 @@ -import { TextInput, Box, Icon, Table } from '@rocket.chat/fuselage'; +import { TextInput, Box, Icon } from '@rocket.chat/fuselage'; import type { ComponentMeta, ComponentStory } from '@storybook/react'; import React from 'react'; -import GenericTable from '.'; +import { + GenericTable, + GenericTableHeaderCell, + GenericTableCell, + GenericTableRow, + GenericTableHeader, + GenericTableBody, + GenericTableLoadingTable, +} from '.'; +import GenericNoResults from '../GenericNoResults/GenericNoResults'; export default { title: 'Components/GenericTable', @@ -16,33 +25,59 @@ export default { ], } as ComponentMeta; -const header = [ - Name, - Email, -]; +const headers = ( + <> + Name + Email + +); + +const results = Array.from({ length: 10 }, (_, i) => ({ + _id: i, + name: `John Doe #${i}`, + email: `john.doe.n${i}@example.com`, +})); + +const filter = ( + <> + + } /> + + +); -const renderFilter = () => ( - - } /> - +export const Default: ComponentStory = () => ( + <> + {filter} + + {headers} + + {results?.map(({ _id, name, email }: any) => ( + + {name} + {email} + + ))} + + + ); -const renderRow = ({ _id, name, email }: any) => ( - - {name} - {email} - +export const Loading: ComponentStory = () => ( + <> + {filter} + + {headers} + + + + + ); -export const Default: ComponentStory = (args) => ( - +export const NoResults: ComponentStory = () => ( + <> + {filter} + + ); -Default.storyName = 'GenericTable'; -Default.args = { - results: Array.from({ length: 10 }, (_, i) => ({ - _id: i, - name: `John Doe #${i}`, - email: `john.doe.n${i}@example.com`, - })), - total: 1, -}; diff --git a/apps/meteor/client/components/GenericTable/GenericTable.tsx b/apps/meteor/client/components/GenericTable/GenericTable.tsx index ef01036249016..ae33cce07a3af 100644 --- a/apps/meteor/client/components/GenericTable/GenericTable.tsx +++ b/apps/meteor/client/components/GenericTable/GenericTable.tsx @@ -1,121 +1,23 @@ -import { Pagination, Tile } from '@rocket.chat/fuselage'; -import { useDebouncedValue } from '@rocket.chat/fuselage-hooks'; -import { useTranslation } from '@rocket.chat/ui-contexts'; -import type { ReactNode, ReactElement, Key, Ref, RefAttributes } from 'react'; -import React, { useState, useEffect, forwardRef, useMemo } from 'react'; -import flattenChildren from 'react-keyed-flatten-children'; +import { Box, Table } from '@rocket.chat/fuselage'; +import type { ReactNode, TableHTMLAttributes } from 'react'; +import React, { forwardRef } from 'react'; -import { GenericTable as GenericTableV2 } from './V2/GenericTable'; -import { GenericTableBody } from './V2/GenericTableBody'; -import { GenericTableHeader } from './V2/GenericTableHeader'; -import { GenericTableLoadingTable } from './V2/GenericTableLoadingTable'; -import { usePagination } from './hooks/usePagination'; +import ScrollableContentWrapper from '../ScrollableContentWrapper'; -const defaultParamsValue = { text: '', current: 0, itemsPerPage: 25 } as const; -const defaultSetParamsValue = (): void => undefined; - -export type GenericTableParams = { - text?: string; - current: number; - itemsPerPage: 25 | 50 | 100; -}; - -type GenericTableProps void }, ResultProps> = { +type GenericTableProps = { fixed?: boolean; - header?: ReactNode; - params?: GenericTableParams; - setParams?: React.Dispatch>; - children?: (props: ResultProps, key: number) => ReactElement; - renderFilter?: (props: FilterProps) => ReactElement; - renderRow?: (props: ResultProps) => ReactElement; - results?: ResultProps[]; - total?: number; - pagination?: boolean; -} & FilterProps; - -const GenericTable = forwardRef(function GenericTable< - FilterProps extends { onChange?: (params: GenericTableParams) => void }, - ResultProps extends { _id?: Key } | object, ->( - { - children, - fixed = true, - header, - params: paramsDefault = defaultParamsValue, - setParams = defaultSetParamsValue, - renderFilter, - renderRow: RenderRowComponent, - results, - total, - pagination = true, - ...props - }: GenericTableProps, - ref: Ref, -) { - const t = useTranslation(); - - const [filter, setFilter] = useState(paramsDefault); - - const { itemsPerPage, setItemsPerPage, current, setCurrent, itemsPerPageLabel, showingResultsLabel } = usePagination(); - - const params = useDebouncedValue(filter, 500); - - useEffect(() => { - setParams((prevParams) => { - setCurrent(prevParams.text === params.text ? current : 0); - - return { - ...params, - text: params.text || '', - current: prevParams.text === params.text ? current : 0, - itemsPerPage, - }; - }); - }, [params, current, itemsPerPage, setParams, setCurrent, setItemsPerPage]); - - const headerCells = useMemo(() => flattenChildren(header).length, [header]); - - const isLoading = !results; + children: ReactNode; +} & TableHTMLAttributes; +export const GenericTable = forwardRef(function GenericTable({ fixed = true, children, ...props }, ref) { return ( - <> - {typeof renderFilter === 'function' - ? renderFilter({ ...props, onChange: setFilter } as any) // TODO: ugh - : null} - {results && !results.length ? ( - - {t('No_data_found')} - - ) : ( - <> - - {header && {header}} - - {isLoading && } - {!isLoading && - ((RenderRowComponent && - results?.map((props, index) => )) || - (children && results?.map(children)))} - - - {pagination && ( - - )} - - )} - + + + {/* TODO: Fix fuselage */} + + {children} +
+
+
); -}) as void }, TResultProps extends { _id?: Key } | object>( - props: GenericTableProps & RefAttributes, -) => ReactElement | null; - -export default GenericTable; +}); diff --git a/apps/meteor/client/components/GenericTable/GenericTableBody.tsx b/apps/meteor/client/components/GenericTable/GenericTableBody.tsx new file mode 100644 index 0000000000000..3b68ccff94a1c --- /dev/null +++ b/apps/meteor/client/components/GenericTable/GenericTableBody.tsx @@ -0,0 +1,5 @@ +import { TableBody } from '@rocket.chat/fuselage'; +import type { FC, ComponentProps } from 'react'; +import React from 'react'; + +export const GenericTableBody: FC> = (props) => ; diff --git a/apps/meteor/client/components/GenericTable/GenericTableCell.tsx b/apps/meteor/client/components/GenericTable/GenericTableCell.tsx new file mode 100644 index 0000000000000..8b783c1a7204b --- /dev/null +++ b/apps/meteor/client/components/GenericTable/GenericTableCell.tsx @@ -0,0 +1,5 @@ +import { TableCell } from '@rocket.chat/fuselage'; +import type { ComponentProps, FC } from 'react'; +import React from 'react'; + +export const GenericTableCell: FC> = (props) => ; diff --git a/apps/meteor/client/components/GenericTable/GenericTableHeader.tsx b/apps/meteor/client/components/GenericTable/GenericTableHeader.tsx new file mode 100644 index 0000000000000..2dbbaade6487c --- /dev/null +++ b/apps/meteor/client/components/GenericTable/GenericTableHeader.tsx @@ -0,0 +1,11 @@ +import { TableHead } from '@rocket.chat/fuselage'; +import type { FC, ComponentProps } from 'react'; +import React from 'react'; + +import { GenericTableRow } from './GenericTableRow'; + +export const GenericTableHeader: FC> = ({ children, ...props }) => ( + + {children} + +); diff --git a/apps/meteor/client/components/GenericTable/V2/GenericTableHeaderCell.tsx b/apps/meteor/client/components/GenericTable/GenericTableHeaderCell.tsx similarity index 81% rename from apps/meteor/client/components/GenericTable/V2/GenericTableHeaderCell.tsx rename to apps/meteor/client/components/GenericTable/GenericTableHeaderCell.tsx index 5127d38a834c3..216fb8997d1f7 100644 --- a/apps/meteor/client/components/GenericTable/V2/GenericTableHeaderCell.tsx +++ b/apps/meteor/client/components/GenericTable/GenericTableHeaderCell.tsx @@ -1,8 +1,8 @@ -import { Box, Table } from '@rocket.chat/fuselage'; +import { Box, TableCell } from '@rocket.chat/fuselage'; import type { ComponentProps, ReactElement } from 'react'; import React, { useCallback } from 'react'; -import SortIcon from '../SortIcon'; +import SortIcon from './SortIcon'; type GenericTableHeaderCellProps = Omit, 'onClick'> & { active?: boolean; @@ -21,11 +21,11 @@ export const GenericTableHeaderCell = ({ }: GenericTableHeaderCellProps): ReactElement => { const fn = useCallback(() => onClick && sort && onClick(sort), [sort, onClick]); return ( - + {children} {sort && } - + ); }; diff --git a/apps/meteor/client/components/GenericTable/V2/GenericTableLoadingRow.tsx b/apps/meteor/client/components/GenericTable/GenericTableLoadingRow.tsx similarity index 52% rename from apps/meteor/client/components/GenericTable/V2/GenericTableLoadingRow.tsx rename to apps/meteor/client/components/GenericTable/GenericTableLoadingRow.tsx index c0aee3d68ccbe..5c539e732b3ad 100644 --- a/apps/meteor/client/components/GenericTable/V2/GenericTableLoadingRow.tsx +++ b/apps/meteor/client/components/GenericTable/GenericTableLoadingRow.tsx @@ -1,14 +1,10 @@ -import { Box, Skeleton, Table } from '@rocket.chat/fuselage'; +import { Box, Skeleton, TableRow, TableCell } from '@rocket.chat/fuselage'; import type { ReactElement } from 'react'; import React from 'react'; -type GenericTableLoadingRowRowProps = { - cols: number; -}; - -export const GenericTableLoadingRow = ({ cols }: GenericTableLoadingRowRowProps): ReactElement => ( - - +export const GenericTableLoadingRow = ({ cols }: { cols: number }): ReactElement => ( + + @@ -16,11 +12,11 @@ export const GenericTableLoadingRow = ({ cols }: GenericTableLoadingRowRowProps) - + {Array.from({ length: cols - 1 }, (_, i) => ( - + - + ))} - + ); diff --git a/apps/meteor/client/components/GenericTable/V2/GenericTableLoadingTable.tsx b/apps/meteor/client/components/GenericTable/GenericTableLoadingTable.tsx similarity index 100% rename from apps/meteor/client/components/GenericTable/V2/GenericTableLoadingTable.tsx rename to apps/meteor/client/components/GenericTable/GenericTableLoadingTable.tsx diff --git a/apps/meteor/client/components/GenericTable/GenericTableRow.tsx b/apps/meteor/client/components/GenericTable/GenericTableRow.tsx new file mode 100644 index 0000000000000..6db18a8bfd1fa --- /dev/null +++ b/apps/meteor/client/components/GenericTable/GenericTableRow.tsx @@ -0,0 +1,5 @@ +import { TableRow } from '@rocket.chat/fuselage'; +import type { ComponentProps, FC } from 'react'; +import React from 'react'; + +export const GenericTableRow: FC> = (props) => ; diff --git a/apps/meteor/client/components/GenericTable/HeaderCell.tsx b/apps/meteor/client/components/GenericTable/HeaderCell.tsx deleted file mode 100644 index 22ee663792eb6..0000000000000 --- a/apps/meteor/client/components/GenericTable/HeaderCell.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import { Box, Table } from '@rocket.chat/fuselage'; -import type { ComponentProps, FC } from 'react'; -import React, { useCallback } from 'react'; - -import SortIcon from './SortIcon'; - -type HeaderCellProps = { - active?: boolean; - direction?: 'asc' | 'desc'; - sort?: string; - clickable?: boolean; - onClick?: (sort: string) => void; -} & Omit, 'onClick'>; - -const HeaderCell: FC = ({ children, active, direction, sort, onClick, ...props }) => { - const fn = useCallback(() => onClick && sort && onClick(sort), [sort, onClick]); - return ( - - - {children} - {sort && } - - - ); -}; - -export default HeaderCell; diff --git a/apps/meteor/client/components/GenericTable/V2/GenericTable.tsx b/apps/meteor/client/components/GenericTable/V2/GenericTable.tsx deleted file mode 100644 index 5b99249e3b336..0000000000000 --- a/apps/meteor/client/components/GenericTable/V2/GenericTable.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import { Box, Table } from '@rocket.chat/fuselage'; -import type { ReactNode, TableHTMLAttributes } from 'react'; -import React, { forwardRef } from 'react'; - -import ScrollableContentWrapper from '../../ScrollableContentWrapper'; - -type GenericTableProps = { - fixed?: boolean; - children: ReactNode; -} & TableHTMLAttributes; - -export const GenericTable = forwardRef(function GenericTable({ fixed = true, children, ...props }, ref) { - return ( - - - {/* TODO: Fix fuselage */} - - {children} -
-
-
- ); -}); diff --git a/apps/meteor/client/components/GenericTable/V2/GenericTableBody.tsx b/apps/meteor/client/components/GenericTable/V2/GenericTableBody.tsx deleted file mode 100644 index af57242bbc9e9..0000000000000 --- a/apps/meteor/client/components/GenericTable/V2/GenericTableBody.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import { Table } from '@rocket.chat/fuselage'; -import type { FC } from 'react'; -import React from 'react'; - -export const GenericTableBody: FC = (props) => ; diff --git a/apps/meteor/client/components/GenericTable/V2/GenericTableCell.tsx b/apps/meteor/client/components/GenericTable/V2/GenericTableCell.tsx deleted file mode 100644 index 8558920c54c4f..0000000000000 --- a/apps/meteor/client/components/GenericTable/V2/GenericTableCell.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import { Table } from '@rocket.chat/fuselage'; -import type { ComponentProps, FC } from 'react'; -import React from 'react'; - -export const GenericTableCell: FC> = (props) => ; diff --git a/apps/meteor/client/components/GenericTable/V2/GenericTableHeader.tsx b/apps/meteor/client/components/GenericTable/V2/GenericTableHeader.tsx deleted file mode 100644 index 847f32232d863..0000000000000 --- a/apps/meteor/client/components/GenericTable/V2/GenericTableHeader.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import { Table } from '@rocket.chat/fuselage'; -import type { FC } from 'react'; -import React from 'react'; - -import { GenericTableRow } from './GenericTableRow'; - -export const GenericTableHeader: FC = ({ children, ...props }) => ( - - {children} - -); diff --git a/apps/meteor/client/components/GenericTable/V2/GenericTableRow.tsx b/apps/meteor/client/components/GenericTable/V2/GenericTableRow.tsx deleted file mode 100644 index 56267adfb15fe..0000000000000 --- a/apps/meteor/client/components/GenericTable/V2/GenericTableRow.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import { Table } from '@rocket.chat/fuselage'; -import type { ComponentProps, FC } from 'react'; -import React from 'react'; - -export const GenericTableRow: FC> = (props) => ; diff --git a/apps/meteor/client/components/GenericTable/index.ts b/apps/meteor/client/components/GenericTable/index.ts index 3a51504430245..29855bb106e33 100644 --- a/apps/meteor/client/components/GenericTable/index.ts +++ b/apps/meteor/client/components/GenericTable/index.ts @@ -1,15 +1,8 @@ -import GenericTable from './GenericTable'; -import HeaderCell from './HeaderCell'; - -export default Object.assign(GenericTable, { - HeaderCell, -}); - -export * from './V2/GenericTable'; -export * from './V2/GenericTableBody'; -export * from './V2/GenericTableCell'; -export * from './V2/GenericTableHeader'; -export * from './V2/GenericTableHeaderCell'; -export * from './V2/GenericTableLoadingRow'; -export * from './V2/GenericTableLoadingTable'; -export * from './V2/GenericTableRow'; +export * from './GenericTable'; +export * from './GenericTableBody'; +export * from './GenericTableCell'; +export * from './GenericTableHeader'; +export * from './GenericTableHeaderCell'; +export * from './GenericTableLoadingRow'; +export * from './GenericTableLoadingTable'; +export * from './GenericTableRow'; diff --git a/apps/meteor/client/views/admin/customSounds/CustomSoundsTable/CustomSoundRow.tsx b/apps/meteor/client/views/admin/customSounds/CustomSoundsTable/CustomSoundRow.tsx index 139c27afc07bd..789f07f0c1cdc 100644 --- a/apps/meteor/client/views/admin/customSounds/CustomSoundsTable/CustomSoundRow.tsx +++ b/apps/meteor/client/views/admin/customSounds/CustomSoundsTable/CustomSoundRow.tsx @@ -3,8 +3,7 @@ import { useCustomSound, useTranslation } from '@rocket.chat/ui-contexts'; import type { ReactElement } from 'react'; import React, { useCallback, useState } from 'react'; -import { GenericTableCell } from '../../../../components/GenericTable/V2/GenericTableCell'; -import { GenericTableRow } from '../../../../components/GenericTable/V2/GenericTableRow'; +import { GenericTableCell, GenericTableRow } from '../../../../components/GenericTable'; type CustomSoundRowProps = { onClick: (soundId: string) => () => void; diff --git a/apps/meteor/client/views/admin/permissions/PermissionsTable/RoleHeader.tsx b/apps/meteor/client/views/admin/permissions/PermissionsTable/RoleHeader.tsx index fc801bbd4c5df..f1b637c1e0d40 100644 --- a/apps/meteor/client/views/admin/permissions/PermissionsTable/RoleHeader.tsx +++ b/apps/meteor/client/views/admin/permissions/PermissionsTable/RoleHeader.tsx @@ -5,7 +5,7 @@ import { useRoute } from '@rocket.chat/ui-contexts'; import type { ReactElement } from 'react'; import React, { memo } from 'react'; -import GenericTable from '../../../../components/GenericTable'; +import { GenericTableHeaderCell } from '../../../../components/GenericTable'; type RoleHeaderProps = { _id: IRole['_id']; @@ -24,14 +24,14 @@ const RoleHeader = ({ _id, name, description }: RoleHeaderProps): ReactElement = }); return ( - + - + ); }; diff --git a/apps/meteor/client/views/admin/settings/groups/voip/VoipExtensionsPage.tsx b/apps/meteor/client/views/admin/settings/groups/voip/VoipExtensionsPage.tsx index 62d7144329d7b..a27ea9ac1564a 100644 --- a/apps/meteor/client/views/admin/settings/groups/voip/VoipExtensionsPage.tsx +++ b/apps/meteor/client/views/admin/settings/groups/voip/VoipExtensionsPage.tsx @@ -1,27 +1,31 @@ -import { Box, Chip, Table, Button } from '@rocket.chat/fuselage'; -import { useDebouncedValue } from '@rocket.chat/fuselage-hooks'; -import { useSetModal, useTranslation } from '@rocket.chat/ui-contexts'; -import type { FC } from 'react'; -import React, { useMemo, useCallback, useState } from 'react'; +import { Box, Chip, Button, Pagination } from '@rocket.chat/fuselage'; +import { useSetModal, useTranslation, useEndpoint } from '@rocket.chat/ui-contexts'; +import { useQuery } from '@tanstack/react-query'; +import React, { useMemo } from 'react'; -import GenericTable from '../../../../../components/GenericTable'; +import GenericNoResults from '../../../../../components/GenericNoResults'; +import { + GenericTable, + GenericTableHeaderCell, + GenericTableRow, + GenericTableCell, + GenericTableHeader, + GenericTableBody, + GenericTableLoadingRow, +} from '../../../../../components/GenericTable'; +import { usePagination } from '../../../../../components/GenericTable/hooks/usePagination'; import Page from '../../../../../components/Page'; import UserAvatar from '../../../../../components/avatar/UserAvatar'; -import { useEndpointData } from '../../../../../hooks/useEndpointData'; import AssignAgentButton from './AssignAgentButton'; import AssignAgentModal from './AssignAgentModal'; import RemoveAgentButton from './RemoveAgentButton'; -const VoipExtensionsPage: FC = () => { +const VoipExtensionsPage = () => { const t = useTranslation(); const setModal = useSetModal(); - const [params, setParams] = useState<{ current: number; itemsPerPage: 25 | 50 | 100 }>({ - current: 0, - itemsPerPage: 25, - }); + const { current, itemsPerPage, setItemsPerPage: onSetItemsPerPage, setCurrent: onSetCurrent, ...paginationProps } = usePagination(); - const { itemsPerPage, current } = useDebouncedValue(params, 500); const query = useMemo( () => ({ ...(itemsPerPage && { count: itemsPerPage }), @@ -30,66 +34,27 @@ const VoipExtensionsPage: FC = () => { [itemsPerPage, current], ); - const { value: data, reload } = useEndpointData('/v1/omnichannel/extensions', { params: query }); - - const header = useMemo( - () => - [ - - {t('Extension_Number')} - , - - {t('Agent_Name')} - , - - {t('Extension_Status')} - , - - {t('Queues')} - , - , - ].filter(Boolean), - [t], - ); + const getExtensions = useEndpoint('GET', '/v1/omnichannel/extensions'); + const { data, isSuccess, isLoading, refetch } = useQuery(['omnichannel-extensions', query], async () => getExtensions(query), { + refetchOnWindowFocus: false, + }); - const renderRow = useCallback( - ({ _id, extension, username, name, state, queues }) => ( - - {extension} - - {username ? ( - - - - - - {name || username} - - - - - ) : ( - t('Free') - )} - - {state} - - - {queues?.map( - (queue: string, index: number) => - index <= 1 && ( - - {queue} - - ), - )} - {queues?.length > 2 && `+${(queues.length - 2).toString()}`} - - - {username ? : } - - ), - [reload, t], + const headers = ( + <> + + {t('Extension_Number')} + + + {t('Agent_Name')} + + + {t('Extension_Status')} + + + {t('Queues')} + + + ); return ( @@ -99,20 +64,78 @@ const VoipExtensionsPage: FC = () => { {data?.total} {t('Extensions')} - - ({ _id: extension.extension, ...extension }))} - total={data?.total} - params={params} - setParams={setParams} - // renderFilter={({ onChange, ...props }) => } - /> + {isLoading && ( + + {headers} + + + + + )} + {isSuccess && data?.extensions.length === 0 && } + {isSuccess && data?.extensions.length > 0 && ( + <> + + {headers} + + {data?.extensions.map(({ extension, username, name, state, queues }) => ( + + {extension} + + {username ? ( + + + + + + {name || username} + + + + + ) : ( + t('Free') + )} + + {state} + + + {queues?.map( + (queue: string, index: number) => + index <= 1 && ( + + {queue} + + ), + )} + {queues && queues?.length > 2 && `+${(queues.length - 2).toString()}`} + + + {username ? ( + + ) : ( + + )} + + ))} + + + + + )} ); }; diff --git a/apps/meteor/client/views/omnichannel/businessHours/BusinessHoursPage.js b/apps/meteor/client/views/omnichannel/businessHours/BusinessHoursPage.js index 801001d441ded..8dbcd473bd5c9 100644 --- a/apps/meteor/client/views/omnichannel/businessHours/BusinessHoursPage.js +++ b/apps/meteor/client/views/omnichannel/businessHours/BusinessHoursPage.js @@ -7,10 +7,9 @@ import Page from '../../../components/Page'; const BusinessHoursPage = () => { const t = useTranslation(); - const router = useRoute('omnichannel-businessHours'); - const Table = useMemo(() => lazy(() => import('../../../../ee/client/omnichannel/BusinessHoursTableContainer')), []); + const BusinessHoursTable = useMemo(() => lazy(() => import('../../../../ee/client/omnichannel/BusinessHoursTable')), []); const handleNew = useMutableCallback(() => { router.push({ @@ -28,7 +27,7 @@ const BusinessHoursPage = () => { - + ); diff --git a/apps/meteor/client/views/omnichannel/currentChats/CurrentChatsRoute.tsx b/apps/meteor/client/views/omnichannel/currentChats/CurrentChatsRoute.tsx index a0a268caab940..bccd437a650a0 100644 --- a/apps/meteor/client/views/omnichannel/currentChats/CurrentChatsRoute.tsx +++ b/apps/meteor/client/views/omnichannel/currentChats/CurrentChatsRoute.tsx @@ -10,6 +10,7 @@ import { useOmnichannelPriorities } from '../../../../ee/client/omnichannel/hook import { PriorityIcon } from '../../../../ee/client/omnichannel/priorities/PriorityIcon'; import GenericNoResults from '../../../components/GenericNoResults'; import { + GenericTable, GenericTableBody, GenericTableCell, GenericTableHeader, @@ -17,7 +18,6 @@ import { GenericTableLoadingTable, GenericTableRow, } from '../../../components/GenericTable'; -import { GenericTable } from '../../../components/GenericTable/V2/GenericTable'; import { usePagination } from '../../../components/GenericTable/hooks/usePagination'; import { useSort } from '../../../components/GenericTable/hooks/useSort'; import Page from '../../../components/Page'; diff --git a/apps/meteor/client/views/omnichannel/directory/calls/CallTable.tsx b/apps/meteor/client/views/omnichannel/directory/calls/CallTable.tsx index f666ea310196b..5aa474893476a 100644 --- a/apps/meteor/client/views/omnichannel/directory/calls/CallTable.tsx +++ b/apps/meteor/client/views/omnichannel/directory/calls/CallTable.tsx @@ -1,69 +1,43 @@ -import { useDebouncedValue, useMutableCallback } from '@rocket.chat/fuselage-hooks'; -import { useRoute, useTranslation } from '@rocket.chat/ui-contexts'; -import { Meteor } from 'meteor/meteor'; -import type { FC } from 'react'; -import React, { useState, useMemo, useCallback } from 'react'; +import { Pagination } from '@rocket.chat/fuselage'; +import { useMutableCallback } from '@rocket.chat/fuselage-hooks'; +import { useRoute, useTranslation, useEndpoint, useUserId } from '@rocket.chat/ui-contexts'; +import { useQuery } from '@tanstack/react-query'; +import React, { useState, useMemo } from 'react'; -import GenericTable from '../../../../components/GenericTable'; -import { useEndpointData } from '../../../../hooks/useEndpointData'; +import FilterByText from '../../../../components/FilterByText'; +import GenericNoResults from '../../../../components/GenericNoResults/GenericNoResults'; +import { + GenericTable, + GenericTableBody, + GenericTableHeader, + GenericTableHeaderCell, + GenericTableLoadingRow, +} from '../../../../components/GenericTable'; +import { usePagination } from '../../../../components/GenericTable/hooks/usePagination'; +import { useSort } from '../../../../components/GenericTable/hooks/useSort'; import { CallTableRow } from './CallTableRow'; -const useQuery = ( - { - text, - itemsPerPage, - current, - }: { - text?: string; - itemsPerPage: 25 | 50 | 100; - current: number; - }, - [column, direction]: string[], - userIdLoggedIn: string | null, -): { - sort: string; - open: 'false'; - roomName: string; - agents: string[]; - count?: number; - current?: number; -} => - useMemo( +const CallTable = () => { + const t = useTranslation(); + const userIdLoggedIn = useUserId(); + + const [text, setText] = useState(''); + const directoryRoute = useRoute('omnichannel-directory'); + const { current, itemsPerPage, setItemsPerPage: onSetItemsPerPage, setCurrent: onSetCurrent, ...paginationProps } = usePagination(); + const { sortBy, sortDirection, setSort } = useSort<'fname' | 'phone' | 'queue' | 'ts' | 'callDuration' | 'direction'>('fname'); + + const query = useMemo( () => ({ - sort: JSON.stringify({ [column]: direction === 'asc' ? 1 : -1 }), - open: 'false', + sort: `{ "${sortBy}": ${sortDirection === 'asc' ? 1 : -1} }`, + open: 'false' as const, roomName: text || '', agents: userIdLoggedIn ? [userIdLoggedIn] : [], ...(itemsPerPage && { count: itemsPerPage }), ...(current && { offset: current }), }), - [column, current, direction, itemsPerPage, userIdLoggedIn, text], + [sortBy, current, sortDirection, itemsPerPage, userIdLoggedIn, text], ); -const CallTable: FC = () => { - const [params, setParams] = useState<{ text?: string; current: number; itemsPerPage: 25 | 50 | 100 }>({ - text: '', - current: 0, - itemsPerPage: 25, - }); - const [sort, setSort] = useState<[string, 'asc' | 'desc']>(['closedAt', 'desc']); - const t = useTranslation(); - const debouncedParams = useDebouncedValue(params, 500); - const debouncedSort = useDebouncedValue(sort, 500); - const userIdLoggedIn = Meteor.userId(); - const query = useQuery(debouncedParams, debouncedSort, userIdLoggedIn); - const directoryRoute = useRoute('omnichannel-directory'); - - const onHeaderClick = useMutableCallback((id) => { - const [sortBy, sortDirection] = sort; - - if (sortBy === id) { - setSort([id, sortDirection === 'asc' ? 'desc' : 'asc']); - return; - } - setSort([id, 'asc']); - }); - const onRowClick = useMutableCallback((id, token) => { directoryRoute.push( { @@ -75,74 +49,81 @@ const CallTable: FC = () => { ); }); - const { value: data } = useEndpointData('/v1/voip/rooms', { params: query }); + const getVoipRooms = useEndpoint('GET', '/v1/voip/rooms'); + const { data, isSuccess, isLoading } = useQuery(['voip-rooms', query], async () => getVoipRooms(query)); - const header = useMemo( - () => - [ - - {t('Contact_Name')} - , - - {t('Phone')} - , - - {t('Queue')} - , - - {t('Started_At')} - , - - {t('Talk_Time')} - , - - {t('Direction')} - , - , - ].filter(Boolean), - [sort, onHeaderClick, t], + const headers = ( + <> + + {t('Contact_Name')} + + + {t('Phone')} + + + {t('Queue')} + + + {t('Started_At')} + + + {t('Talk_Time')} + + + {t('Direction')} + + + ); - const renderRow = useCallback((room) => , [onRowClick]); - return ( - } - /> + <> + setText(text)} /> + {isLoading && ( + + {headers} + + + + + )} + {isSuccess && data?.rooms.length === 0 && } + {isSuccess && data?.rooms.length > 0 && ( + <> + + {headers} + + {data?.rooms.map((room) => ( + + ))} + + + + + )} + ); }; diff --git a/apps/meteor/client/views/omnichannel/directory/calls/CallTableRow.tsx b/apps/meteor/client/views/omnichannel/directory/calls/CallTableRow.tsx index 89d0a92013b72..8ead7e104cc76 100644 --- a/apps/meteor/client/views/omnichannel/directory/calls/CallTableRow.tsx +++ b/apps/meteor/client/views/omnichannel/directory/calls/CallTableRow.tsx @@ -1,4 +1,4 @@ -import type { IVoipRoom } from '@rocket.chat/core-typings'; +import type { IVoipRoom, Serialized } from '@rocket.chat/core-typings'; import { Table } from '@rocket.chat/fuselage'; import { useTranslation } from '@rocket.chat/ui-contexts'; import moment from 'moment'; @@ -10,7 +10,7 @@ import { useIsCallReady } from '../../../../contexts/CallContext'; import { CallDialpadButton } from '../components/CallDialpadButton'; type CallTableRowProps = { - room: IVoipRoom; + room: Serialized; onRowClick(_id: string, token?: string): void; }; diff --git a/apps/meteor/client/views/omnichannel/directory/chats/ChatTable.tsx b/apps/meteor/client/views/omnichannel/directory/chats/ChatTable.tsx index 01055e185b9dd..50c1651f69ff8 100644 --- a/apps/meteor/client/views/omnichannel/directory/chats/ChatTable.tsx +++ b/apps/meteor/client/views/omnichannel/directory/chats/ChatTable.tsx @@ -1,71 +1,45 @@ -import { Table, Tag, Box } from '@rocket.chat/fuselage'; -import { useDebouncedValue, useMutableCallback } from '@rocket.chat/fuselage-hooks'; -import { useRoute, useTranslation } from '@rocket.chat/ui-contexts'; -import { Meteor } from 'meteor/meteor'; +import { Tag, Box, Pagination, States, StatesIcon, StatesTitle, StatesActions, StatesAction } from '@rocket.chat/fuselage'; +import { useMutableCallback } from '@rocket.chat/fuselage-hooks'; +import { useRoute, useTranslation, useUserId } from '@rocket.chat/ui-contexts'; import moment from 'moment'; -import type { FC, ReactElement } from 'react'; import React, { useState, useMemo, useCallback } from 'react'; import FilterByText from '../../../../components/FilterByText'; -import GenericTable, { GenericTableLoadingTable } from '../../../../components/GenericTable'; +import GenericNoResults from '../../../../components/GenericNoResults/GenericNoResults'; +import { + GenericTable, + GenericTableBody, + GenericTableCell, + GenericTableHeader, + GenericTableHeaderCell, + GenericTableLoadingTable, + GenericTableRow, +} from '../../../../components/GenericTable'; +import { usePagination } from '../../../../components/GenericTable/hooks/usePagination'; +import { useSort } from '../../../../components/GenericTable/hooks/useSort'; import { useCurrentChats } from '../../currentChats/hooks/useCurrentChats'; -const useQuery = ( - { - text, - itemsPerPage, - current, - }: { - text?: string; - itemsPerPage: 25 | 50 | 100; - current: number; - }, - [column, direction]: string[], - userIdLoggedIn: string | null, -): { - sort: string; - open: boolean; - roomName: string; - agents: string[]; - count?: number; - current?: number; -} => - useMemo( +const ChatTable = () => { + const t = useTranslation(); + const [text, setText] = useState(''); + const userIdLoggedIn = useUserId(); + const directoryRoute = useRoute('omnichannel-directory'); + + const { current, itemsPerPage, setItemsPerPage: onSetItemsPerPage, setCurrent: onSetCurrent, ...paginationProps } = usePagination(); + const { sortBy, sortDirection, setSort } = useSort<'fname' | 'department' | 'ts' | 'chatDuration' | 'closedAt'>('fname'); + + const query = useMemo( () => ({ - sort: JSON.stringify({ [column]: direction === 'asc' ? 1 : -1 }), + sort: `{ "${sortBy}": ${sortDirection === 'asc' ? 1 : -1} }`, open: false, roomName: text || '', agents: userIdLoggedIn ? [userIdLoggedIn] : [], ...(itemsPerPage && { count: itemsPerPage }), ...(current && { offset: current }), }), - [column, current, direction, itemsPerPage, userIdLoggedIn, text], + [sortBy, current, sortDirection, itemsPerPage, userIdLoggedIn, text], ); -const ChatTable: FC = () => { - const [params, setParams] = useState<{ text?: string; current: number; itemsPerPage: 25 | 50 | 100 }>({ - text: '', - current: 0, - itemsPerPage: 25, - }); - const [sort, setSort] = useState<[string, 'asc' | 'desc']>(['closedAt', 'desc']); - const t = useTranslation(); - const debouncedParams = useDebouncedValue(params, 500); - const debouncedSort = useDebouncedValue(sort, 500); - const userIdLoggedIn = Meteor.userId(); - const query = useQuery(debouncedParams, debouncedSort, userIdLoggedIn); - const directoryRoute = useRoute('omnichannel-directory'); - - const onHeaderClick = useMutableCallback((id) => { - const [sortBy, sortDirection] = sort; - - if (sortBy === id) { - setSort([id, sortDirection === 'asc' ? 'desc' : 'asc']); - return; - } - setSort([id, 'asc']); - }); - const onRowClick = useMutableCallback((id) => directoryRoute.push({ page: 'chats', @@ -74,60 +48,53 @@ const ChatTable: FC = () => { }), ); - const header = useMemo( - () => - [ - - {t('Contact_Name')} - , - - {t('Department')} - , - - {t('Started_At')} - , - - {t('Chat_Duration')} - , - - {t('Closed_At')} - , - ].filter(Boolean), - [sort, onHeaderClick, t], + const headers = ( + <> + + {t('Contact_Name')} + + + {t('Department')} + + + {t('Started_At')} + + + {t('Chat_Duration')} + + + {t('Closed_At')} + + ); + const { data, isLoading, isSuccess, isError, refetch } = useCurrentChats(query); + const renderRow = useCallback( ({ _id, fname, ts, closedAt, department, tags }) => ( - onRowClick(_id)} action qa-user-id={_id}> - + onRowClick(_id)} action qa-user-id={_id}> + {fname} {tags && ( @@ -151,35 +118,55 @@ const ChatTable: FC = () => { )} - - {department ? department.name : ''} - {moment(ts).format('L LTS')} - {moment(closedAt).from(moment(ts), true)} - {moment(closedAt).format('L LTS')} - + + {department ? department.name : ''} + {moment(ts).format('L LTS')} + {moment(closedAt).from(moment(ts), true)} + {moment(closedAt).format('L LTS')} + ), [onRowClick], ); - const result = useCurrentChats(query); - - if (result.isLoading) { - return ; - } - if (result.error) { - return {t('Something_went_wrong')}; - } - return ( - } - /> + <> + setText(text)} /> + {isLoading && ( + + {headers} + + + + + )} + {isSuccess && data?.rooms.length === 0 && } + {isSuccess && data?.rooms.length > 0 && ( + <> + + {headers} + {data?.rooms.map((room) => renderRow(room))} + + + + )} + {isError && ( + + + {t('Something_went_wrong')} + + refetch()}>{t('Reload_page')} + + + )} + ); }; diff --git a/apps/meteor/client/views/omnichannel/directory/contacts/ContactTab.js b/apps/meteor/client/views/omnichannel/directory/contacts/ContactTab.tsx similarity index 82% rename from apps/meteor/client/views/omnichannel/directory/contacts/ContactTab.js rename to apps/meteor/client/views/omnichannel/directory/contacts/ContactTab.tsx index d11cdd7839201..6942a33afc370 100644 --- a/apps/meteor/client/views/omnichannel/directory/contacts/ContactTab.js +++ b/apps/meteor/client/views/omnichannel/directory/contacts/ContactTab.tsx @@ -4,14 +4,14 @@ import React from 'react'; import NotAuthorizedPage from '../../../notAuthorized/NotAuthorizedPage'; import ContactTable from './ContactTable'; -function ContactTab(props) { +const ContactTab = () => { const hasAccess = usePermission('view-l-room'); if (hasAccess) { - return ; + return ; } return ; -} +}; export default ContactTab; diff --git a/apps/meteor/client/views/omnichannel/directory/contacts/ContactTable.tsx b/apps/meteor/client/views/omnichannel/directory/contacts/ContactTable.tsx index 1fc33d5b9531d..9fbde9f866bde 100644 --- a/apps/meteor/client/views/omnichannel/directory/contacts/ContactTable.tsx +++ b/apps/meteor/client/views/omnichannel/directory/contacts/ContactTable.tsx @@ -13,7 +13,7 @@ import { GenericTableBody, GenericTableRow, GenericTableHeaderCell, - GenericTableLoadingTable, + GenericTableLoadingRow, } from '../../../../components/GenericTable'; import { usePagination } from '../../../../components/GenericTable/hooks/usePagination'; import { useSort } from '../../../../components/GenericTable/hooks/useSort'; @@ -63,7 +63,35 @@ function ContactTable(): ReactElement { }), ); - const { data: contactResult, isLoading, isError, isSuccess, refetch } = useCurrentContacts(query); + const { data, isLoading, isError, isSuccess, refetch } = useCurrentContacts(query); + + const headers = ( + <> + + {t('Username')} + + + {t('Name')} + + + {t('Phone')} + + + {t('Email')} + + + {t('Last_Chat')} + + + + ); + return ( <> setTerm(text)} /> + {isLoading && ( + + {headers} + + + + + )} + {isSuccess && data?.visitors.length > 0 && ( + <> + + {headers} + + {data?.visitors.map(({ _id, username, fname, name, visitorEmails, phone, lastChat }) => { + const phoneNumber = (phone?.length && phone[0].phoneNumber) || ''; + const visitorEmail = visitorEmails?.length && visitorEmails[0].address; - - - - {t('Username')} - - - {t('Name')} - - - {t('Phone')} - - - {t('Email')} - - - {t('Last_Chat')} - - - - - {contactResult && - contactResult.visitors.map(({ _id, username, fname, name, visitorEmails, phone, lastChat }) => { - const phoneNumber = (phone?.length && phone[0].phoneNumber) || ''; - const visitorEmail = visitorEmails?.length && visitorEmails[0].address; - - return ( - - {username} - {parseOutboundPhoneNumber(fname || name)} - {parseOutboundPhoneNumber(phoneNumber)} - {visitorEmail} - {lastChat && formatDate(lastChat.ts)} - {isCallReady && } - - ); - })} - {isLoading && } - {isError && {t('Something_went_wrong')}} - - - + return ( + + {username} + {parseOutboundPhoneNumber(fname || name)} + {parseOutboundPhoneNumber(phoneNumber)} + {visitorEmail} + {lastChat && formatDate(lastChat.ts)} + {isCallReady && } + + ); + })} + + + + + )} {isError && ( @@ -155,16 +163,6 @@ function ContactTable(): ReactElement { )} - {isSuccess && ( - - )} ); } diff --git a/apps/meteor/client/views/omnichannel/queueList/QueueListPage.tsx b/apps/meteor/client/views/omnichannel/queueList/QueueListPage.tsx index 53e5bdfb81214..315b7afe9a4d9 100644 --- a/apps/meteor/client/views/omnichannel/queueList/QueueListPage.tsx +++ b/apps/meteor/client/views/omnichannel/queueList/QueueListPage.tsx @@ -1,49 +1,20 @@ -import type { Dispatch, Key, ReactElement, ReactNode, SetStateAction } from 'react'; +import { useTranslation } from '@rocket.chat/ui-contexts'; import React from 'react'; -import GenericTable from '../../../components/GenericTable'; import Page from '../../../components/Page'; -import { QueueListFilter } from './QueueListFilter'; +import QueueListTable from './QueueListTable'; -type QueueListPagePropsParamsType = { - servedBy: string; - status: string; - departmentId: string; - itemsPerPage: 25 | 50 | 100; - current: number; -}; +const QueueListPage = () => { + const t = useTranslation(); -type QueueListPagePropsType = { - title: string; - header: ReactNode; - data?: { - queue: { - chats: number; - department: { _id: string; name: string }; - user: { _id: string; username: string; status: string }; - }[]; - count: number; - offset: number; - total: number; - }; - params: QueueListPagePropsParamsType; - setParams: Dispatch>; - renderRow: (props: { _id?: Key }) => ReactElement; + return ( + + + + + + + ); }; -export const QueueListPage = ({ title, header, data, renderRow, params, setParams }: QueueListPagePropsType): ReactElement => ( - - - - } - renderRow={renderRow} - results={data?.queue} - total={data?.total} - params={params} - setParams={setParams as (params: Pick) => void} - /> - - -); +export default QueueListPage; diff --git a/apps/meteor/client/views/omnichannel/queueList/QueueListTable.tsx b/apps/meteor/client/views/omnichannel/queueList/QueueListTable.tsx new file mode 100644 index 0000000000000..c75393fb7f322 --- /dev/null +++ b/apps/meteor/client/views/omnichannel/queueList/QueueListTable.tsx @@ -0,0 +1,145 @@ +import { Box, Pagination } from '@rocket.chat/fuselage'; +import { useMediaQuery } from '@rocket.chat/fuselage-hooks'; +import { useTranslation, useEndpoint } from '@rocket.chat/ui-contexts'; +import { useQuery } from '@tanstack/react-query'; +import type { ReactElement } from 'react'; +import React, { useMemo, useState } from 'react'; + +import GenericNoResults from '../../../components/GenericNoResults'; +import { + GenericTable, + GenericTableHeader, + GenericTableHeaderCell, + GenericTableBody, + GenericTableRow, + GenericTableCell, + GenericTableLoadingRow, +} from '../../../components/GenericTable'; +import { usePagination } from '../../../components/GenericTable/hooks/usePagination'; +import { useSort } from '../../../components/GenericTable/hooks/useSort'; +import UserAvatar from '../../../components/avatar/UserAvatar'; +import { QueueListFilter } from './QueueListFilter'; + +const QueueListTable = (): ReactElement => { + const t = useTranslation(); + const { current, itemsPerPage, setItemsPerPage: onSetItemsPerPage, setCurrent: onSetCurrent, ...paginationProps } = usePagination(); + const { sortBy, sortDirection, setSort } = useSort<'servedBy' | 'department' | 'total' | 'status'>('servedBy'); + + const [filters, setFilters] = useState<{ + servedBy: string; + status: string; + departmentId: string; + }>({ + servedBy: '', + status: '', + departmentId: '', + }); + + const mediaQuery = useMediaQuery('(min-width: 1024px)'); + + const headers = ( + <> + {mediaQuery && ( + + {t('Served_By')} + + )} + + {t('Department')} + + + {t('Total')} + + + {t('Status')} + + + ); + + const query = useMemo(() => { + const query: { + agentId?: string; + includeOfflineAgents?: 'true' | 'false'; + departmentId?: string; + sort: string; + count: number; + } = { + sort: `{ "${sortBy}": ${sortDirection === 'asc' ? 1 : -1} }`, + ...(itemsPerPage && { count: itemsPerPage }), + ...(current && { offset: current }), + }; + + if (filters.status !== 'online') { + query.includeOfflineAgents = 'true'; + } + if (filters.servedBy) { + query.agentId = filters.servedBy; + } + if (filters.departmentId) { + query.departmentId = filters.departmentId; + } + + return query; + }, [sortBy, sortDirection, itemsPerPage, current, filters.status, filters.departmentId, filters.servedBy]); + + const getLivechatQueue = useEndpoint('GET', '/v1/livechat/queue'); + const { data, isSuccess, isLoading } = useQuery(['livechat-queue', query], async () => getLivechatQueue(query), { + refetchOnWindowFocus: false, + }); + + return ( + <> + + {isLoading && ( + + {headers} + + + + + )} + {isSuccess && data?.queue.length === 0 && } + {isSuccess && data?.queue.length > 0 && ( + <> + + {headers} + + {data?.queue.map(({ user, department, chats }) => ( + + + + + + {user.username} + + + + {department ? department.name : ''} + {chats} + {user.status === 'online' ? t('Online') : t('Offline')} + + ))} + + + + + )} + + ); +}; + +export default QueueListTable; diff --git a/apps/meteor/client/views/omnichannel/queueList/index.ts b/apps/meteor/client/views/omnichannel/queueList/index.ts new file mode 100644 index 0000000000000..0622dd44ee801 --- /dev/null +++ b/apps/meteor/client/views/omnichannel/queueList/index.ts @@ -0,0 +1 @@ +export { default } from './QueueListPage'; diff --git a/apps/meteor/client/views/omnichannel/queueList/index.tsx b/apps/meteor/client/views/omnichannel/queueList/index.tsx deleted file mode 100644 index 856aa659641f3..0000000000000 --- a/apps/meteor/client/views/omnichannel/queueList/index.tsx +++ /dev/null @@ -1,114 +0,0 @@ -import { Box, Table } from '@rocket.chat/fuselage'; -import { useDebouncedValue, useMediaQuery, useMutableCallback } from '@rocket.chat/fuselage-hooks'; -import { useTranslation } from '@rocket.chat/ui-contexts'; -import type { ReactElement } from 'react'; -import React, { useCallback, useMemo, useState } from 'react'; - -import GenericTable from '../../../components/GenericTable'; -import UserAvatar from '../../../components/avatar/UserAvatar'; -import { useEndpointData } from '../../../hooks/useEndpointData'; -import { QueueListPage } from './QueueListPage'; -import { useQuery } from './hooks/useQuery'; - -const QueueList = (): ReactElement => { - const t = useTranslation(); - const [sort, setSort] = useState<[string, 'asc' | 'desc']>(['servedBy', 'desc']); - - const onHeaderClick = useMutableCallback((id) => { - const [sortBy, sortDirection] = sort; - - if (sortBy === id) { - setSort([id, sortDirection === 'asc' ? 'desc' : 'asc']); - return; - } - setSort([id, 'asc']); - }); - - const mediaQuery = useMediaQuery('(min-width: 1024px)'); - - const header = useMemo( - () => - [ - mediaQuery && ( - - {t('Served_By')} - - ), - - {t('Department')} - , - - {t('Total')} - , - - {t('Status')} - , - ].filter(Boolean), - [mediaQuery, sort, onHeaderClick, t], - ); - - const renderRow = useCallback( - ({ user, department, chats }) => { - const getStatusText = (): string => { - if (user.status === 'online') { - return t('Online'); - } - - return t('Offline'); - }; - - return ( - - - - - - {user.username} - - - - {department ? department.name : ''} - {chats} - {getStatusText()} - - ); - }, - [mediaQuery, t], - ); - - const [params, setParams] = useState<{ - servedBy: string; - status: string; - departmentId: string; - itemsPerPage: 25 | 50 | 100; - current: number; - }>({ - servedBy: '', - status: '', - departmentId: '', - itemsPerPage: 25, - current: 0, - }); - const debouncedParams = useDebouncedValue(params, 500); - const debouncedSort = useDebouncedValue(sort, 500); - const query = useQuery(debouncedParams, debouncedSort); - const { value: data } = useEndpointData('/v1/livechat/queue', { params: query }); - - return ( - - ); -}; - -export default QueueList; diff --git a/apps/meteor/client/views/teams/contextualBar/info/Delete/ChannelDeletionTable.js b/apps/meteor/client/views/teams/contextualBar/info/Delete/ChannelDeletionTable.js deleted file mode 100644 index c6dfe58619a55..0000000000000 --- a/apps/meteor/client/views/teams/contextualBar/info/Delete/ChannelDeletionTable.js +++ /dev/null @@ -1,81 +0,0 @@ -import { Box, CheckBox } from '@rocket.chat/fuselage'; -import { useTranslation } from '@rocket.chat/ui-contexts'; -import React, { useState, useCallback } from 'react'; - -import GenericTable from '../../../../../components/GenericTable'; -import ChannelRow from './ChannelRow'; - -const ChannelDeletionTable = ({ rooms, params, onChangeParams, onChangeRoomSelection, selectedRooms, onToggleAllRooms }) => { - const [sort, setSort] = useState(['name', 'asc']); - - const t = useTranslation(); - - const selectedRoomsLength = Object.values(selectedRooms).filter(Boolean).length; - - const onHeaderClick = useCallback( - (id) => { - const [sortBy, sortDirection] = sort; - if (sortBy === id) { - setSort([id, sortDirection === 'asc' ? 'desc' : 'asc']); - return; - } - setSort([id, 'asc']); - }, - [sort], - ); - - const getSortedChannels = () => { - if (rooms) { - const sortedRooms = [...rooms]; - const [sortBy, sortOrder] = sort; - if (sortBy === 'name') { - sortedRooms.sort((a, b) => (a.name && b.name ? a.name.localeCompare(b.name) : 0)); - } - if (sortBy === 'usersCount') { - sortedRooms.sort((a, b) => a.usersCount - b.usersCount); - } - if (sortOrder === 'desc') { - return sortedRooms?.reverse(); - } - return sortedRooms; - } - }; - - const checked = rooms.length === selectedRoomsLength; - const indeterminate = rooms.length > selectedRoomsLength && selectedRoomsLength > 0; - - return ( - - - - - {t('Channel_name')} - - - - {t('Members')} - - - - } - results={getSortedChannels()} - params={params} - setParams={onChangeParams} - fixed={false} - pagination={false} - > - {({ key, ...room }) => } - - - ); -}; - -export default ChannelDeletionTable; diff --git a/apps/meteor/client/views/teams/contextualBar/info/Delete/ChannelDeletionTable.tsx b/apps/meteor/client/views/teams/contextualBar/info/Delete/ChannelDeletionTable.tsx new file mode 100644 index 0000000000000..751c5848efeb9 --- /dev/null +++ b/apps/meteor/client/views/teams/contextualBar/info/Delete/ChannelDeletionTable.tsx @@ -0,0 +1,78 @@ +import type { IRoom, Serialized } from '@rocket.chat/core-typings'; +import { Box, CheckBox } from '@rocket.chat/fuselage'; +import { useTranslation } from '@rocket.chat/ui-contexts'; +import React from 'react'; + +import { GenericTable, GenericTableHeaderCell, GenericTableBody, GenericTableHeader } from '../../../../../components/GenericTable'; +import { useSort } from '../../../../../components/GenericTable/hooks/useSort'; +import ChannelDeletionTableRow from './ChannelDeletionTableRow'; + +type ChannelDeletationTable = { + rooms: Serialized[]; + onToggleAllRooms: () => void; + onChangeRoomSelection: (room: Serialized) => void; + selectedRooms: { [key: string]: Serialized }; +}; + +const ChannelDeletionTable = ({ rooms, onChangeRoomSelection, selectedRooms, onToggleAllRooms }: ChannelDeletationTable) => { + const t = useTranslation(); + const { sortBy, sortDirection, setSort } = useSort<'name' | 'usersCount'>('name'); + + const selectedRoomsLength = Object.values(selectedRooms).filter(Boolean).length; + + const getSortedChannels = () => { + if (rooms) { + const sortedRooms = [...rooms]; + if (sortBy === 'name') { + sortedRooms.sort((a, b) => (a.name && b.name ? a.name.localeCompare(b.name) : 0)); + } + if (sortBy === 'usersCount') { + sortedRooms.sort((a, b) => a.usersCount - b.usersCount); + } + if (sortDirection === 'desc') { + return sortedRooms?.reverse(); + } + return sortedRooms; + } + }; + + const sortedRooms = getSortedChannels(); + + const checked = rooms.length === selectedRoomsLength; + const indeterminate = rooms.length > selectedRoomsLength && selectedRoomsLength > 0; + + const headers = ( + <> + + + {t('Channel_name')} + + + + {t('Members')} + + + + ); + + return ( + + + {headers} + + {sortedRooms?.map((room) => ( + + ))} + + + + ); +}; + +export default ChannelDeletionTable; diff --git a/apps/meteor/client/views/teams/contextualBar/info/Delete/ChannelDeletionTableRow.tsx b/apps/meteor/client/views/teams/contextualBar/info/Delete/ChannelDeletionTableRow.tsx new file mode 100644 index 0000000000000..f14d73725e63b --- /dev/null +++ b/apps/meteor/client/views/teams/contextualBar/info/Delete/ChannelDeletionTableRow.tsx @@ -0,0 +1,35 @@ +import type { IRoom, Serialized } from '@rocket.chat/core-typings'; +import { CheckBox, Margins } from '@rocket.chat/fuselage'; +import { useMutableCallback } from '@rocket.chat/fuselage-hooks'; +import React from 'react'; + +import { GenericTableRow, GenericTableCell } from '../../../../../components/GenericTable'; +import { RoomIcon } from '../../../../../components/RoomIcon'; + +type ChannelDeletionTableRowProps = { + room: Serialized; + onChange: (room: Serialized) => void; + selected: boolean; +}; + +const ChannelDeletionTableRow = ({ room, onChange, selected }: ChannelDeletionTableRowProps) => { + const { name, fname, usersCount } = room; + const handleChange = useMutableCallback(() => onChange(room)); + + return ( + + + + + + {fname ?? name} + + + + {usersCount} + + + ); +}; + +export default ChannelDeletionTableRow; diff --git a/apps/meteor/client/views/teams/contextualBar/info/Delete/ChannelRow.js b/apps/meteor/client/views/teams/contextualBar/info/Delete/ChannelRow.js deleted file mode 100644 index 8bd7115414983..0000000000000 --- a/apps/meteor/client/views/teams/contextualBar/info/Delete/ChannelRow.js +++ /dev/null @@ -1,29 +0,0 @@ -import { CheckBox, Table, Icon, Margins } from '@rocket.chat/fuselage'; -import { useMutableCallback } from '@rocket.chat/fuselage-hooks'; -import React from 'react'; - -import { useRoomIcon } from '../../../../../hooks/useRoomIcon'; - -const ChannelRow = ({ onChange, selected, room }) => { - const { name, fname, usersCount } = room; - - const handleChange = useMutableCallback(() => onChange(room)); - - return ( - - - - - - {fname ?? name} - - - - - {usersCount} - - - ); -}; - -export default ChannelRow; diff --git a/apps/meteor/ee/client/omnichannel/BusinessHoursRow.js b/apps/meteor/ee/client/omnichannel/BusinessHoursRow.js index bcbe1dd6ad237..005c3aa464c4d 100644 --- a/apps/meteor/ee/client/omnichannel/BusinessHoursRow.js +++ b/apps/meteor/ee/client/omnichannel/BusinessHoursRow.js @@ -1,7 +1,7 @@ -import { Table } from '@rocket.chat/fuselage'; import { useRoute, useTranslation } from '@rocket.chat/ui-contexts'; import React, { memo, useMemo } from 'react'; +import { GenericTableRow, GenericTableCell } from '../../../client/components/GenericTable'; import RemoveBusinessHourButton from './RemoveBusinessHourButton'; function BusinessHoursRow(props) { @@ -43,17 +43,17 @@ function BusinessHoursRow(props) { }; return ( - - {name || t('Default')} - {t(timezone.name)} - {openDays.join(', ')} - {active ? t('Yes') : t('No')} + + {name || t('Default')} + {t(timezone.name)} + {openDays.join(', ')} + {active ? t('Yes') : t('No')} {name && ( - + - + )} - + ); } diff --git a/apps/meteor/ee/client/omnichannel/BusinessHoursTable.js b/apps/meteor/ee/client/omnichannel/BusinessHoursTable.js index e243b7ab9bc9d..3d2c0a27f167a 100644 --- a/apps/meteor/ee/client/omnichannel/BusinessHoursTable.js +++ b/apps/meteor/ee/client/omnichannel/BusinessHoursTable.js @@ -1,37 +1,92 @@ -import { useTranslation } from '@rocket.chat/ui-contexts'; -import React from 'react'; +import { Pagination, States, StatesIcon, StatesActions, StatesAction, StatesTitle } from '@rocket.chat/fuselage'; +import { useTranslation, useEndpoint } from '@rocket.chat/ui-contexts'; +import { useQuery } from '@tanstack/react-query'; +import React, { useMemo, useState } from 'react'; import FilterByText from '../../../client/components/FilterByText'; -import GenericTable from '../../../client/components/GenericTable'; -import { useResizeInlineBreakpoint } from '../../../client/hooks/useResizeInlineBreakpoint'; +import GenericNoResults from '../../../client/components/GenericNoResults'; +import { + GenericTable, + GenericTableBody, + GenericTableHeaderCell, + GenericTableHeader, + GenericTableLoadingRow, +} from '../../../client/components/GenericTable'; +import { usePagination } from '../../../client/components/GenericTable/hooks/usePagination'; import BusinessHoursRow from './BusinessHoursRow'; -function BusinessHoursTable({ businessHours, totalbusinessHours, params, onChangeParams, reload }) { +const BusinessHoursTable = () => { const t = useTranslation(); + const [text, setText] = useState(''); - const [ref, onMediumBreakpoint] = useResizeInlineBreakpoint([600], 200); + const { current, itemsPerPage, setItemsPerPage: onSetItemsPerPage, setCurrent: onSetCurrent, ...paginationProps } = usePagination(); + + const query = useMemo( + () => ({ + count: itemsPerPage, + offset: current, + name: text, + }), + [itemsPerPage, current, text], + ); + + const getBusinessHours = useEndpoint('GET', '/v1/livechat/business-hours'); + const { data, isLoading, isSuccess, isError, refetch } = useQuery(['livechat-buiness-hours', query], async () => getBusinessHours(query)); + + const headers = ( + <> + {t('Name')} + {t('Timezone')} + {t('Open_Days')} + {t('Enabled')} + {t('Remove')} + + ); return ( - + setText(text)} /> + {isLoading && ( + + {headers} + + + + + )} + {isSuccess && data?.businessHours.length === 0 && } + {isSuccess && data?.businessHours.length > 0 && ( <> - {t('Name')} - {t('Timezone')} - {t('Open_Days')} - {t('Enabled')} - {t('Remove')} + + {headers} + + {data?.businessHours.map((businessHour) => ( + + ))} + + + - } - results={businessHours} - total={totalbusinessHours} - params={params} - setParams={onChangeParams} - renderFilter={({ onChange, ...props }) => } - > - {(props) => } - + )} + {isError && ( + + + {t('Something_went_wrong')} + + refetch()}>{t('Reload_page')} + + + )} + ); -} +}; export default BusinessHoursTable; diff --git a/apps/meteor/ee/client/omnichannel/BusinessHoursTable.stories.tsx b/apps/meteor/ee/client/omnichannel/BusinessHoursTable.stories.tsx index 09c720fddd29f..3e1a8d0371c42 100644 --- a/apps/meteor/ee/client/omnichannel/BusinessHoursTable.stories.tsx +++ b/apps/meteor/ee/client/omnichannel/BusinessHoursTable.stories.tsx @@ -14,7 +14,7 @@ export default { }, } as ComponentMeta; -export const Default: ComponentStory = (args) => ; +export const Default: ComponentStory = (_args) => ; Default.storyName = 'BusinessHoursTable'; Default.args = { businessHours: [ diff --git a/apps/meteor/ee/client/omnichannel/BusinessHoursTableContainer.js b/apps/meteor/ee/client/omnichannel/BusinessHoursTableContainer.js deleted file mode 100644 index 34fa91217e646..0000000000000 --- a/apps/meteor/ee/client/omnichannel/BusinessHoursTableContainer.js +++ /dev/null @@ -1,43 +0,0 @@ -import { Callout } from '@rocket.chat/fuselage'; -import { useTranslation } from '@rocket.chat/ui-contexts'; -import React, { useMemo, useState } from 'react'; - -import { AsyncStatePhase } from '../../../client/hooks/useAsyncState'; -import { useEndpointData } from '../../../client/hooks/useEndpointData'; -import BusinessHoursTable from './BusinessHoursTable'; - -const BusinessHoursTableContainer = () => { - const t = useTranslation(); - const [params, setParams] = useState(() => ({ current: 0, itemsPerPage: 25, text: '' })); - - const { - value: data, - phase: state, - reload, - } = useEndpointData('/v1/livechat/business-hours', { - params: useMemo( - () => ({ - count: params.itemsPerPage, - offset: params.current, - name: params.text, - }), - [params], - ), - }); - - if (state === AsyncStatePhase.REJECTED) { - return {t('Error')}: error; - } - - return ( - - ); -}; - -export default BusinessHoursTableContainer; diff --git a/apps/meteor/ee/client/omnichannel/cannedResponses/CannedResponsesPage.tsx b/apps/meteor/ee/client/omnichannel/cannedResponses/CannedResponsesPage.tsx index e69dd74d1a46a..6a44a799e40a1 100644 --- a/apps/meteor/ee/client/omnichannel/cannedResponses/CannedResponsesPage.tsx +++ b/apps/meteor/ee/client/omnichannel/cannedResponses/CannedResponsesPage.tsx @@ -1,49 +1,41 @@ import { Button, ButtonGroup } from '@rocket.chat/fuselage'; import { useMutableCallback } from '@rocket.chat/fuselage-hooks'; -import { useRoute, useTranslation } from '@rocket.chat/ui-contexts'; -import type { FC, ReactElement, Dispatch, SetStateAction } from 'react'; +import { useRoute, useRouteParameter, useTranslation } from '@rocket.chat/ui-contexts'; +import { useQueryClient } from '@tanstack/react-query'; import React from 'react'; -import GenericNoResults from '../../../../client/components/GenericNoResults'; -import GenericTable from '../../../../client/components/GenericTable'; import Page from '../../../../client/components/Page'; +import CannedResponseEditWithData from './CannedResponseEditWithData'; +import CannedResponseNew from './CannedResponseNew'; +import CannedResponsesTable from './CannedResponsesTable'; -type CannedResponsesPageProps = { - data: any; - header: ReactElement[]; - setParams: Dispatch>; - params: { current: number; itemsPerPage: 25 | 50 | 100 }; - title: string; - renderFilter?: (props: any) => ReactElement; - renderRow?: (props: any) => ReactElement; - totalCannedResponses: number; - busy?: boolean; -}; - -const CannedResponsesPage: FC = ({ - data, - header, - setParams, - params, - title, - renderRow, - renderFilter, - totalCannedResponses, - busy, -}) => { +const CannedResponsesPage = () => { const t = useTranslation(); - - const Route = useRoute('omnichannel-canned-responses'); + const cannedResponseRoute = useRoute('omnichannel-canned-responses'); + const queryClient = useQueryClient(); const handleClick = useMutableCallback(() => - Route.push({ + cannedResponseRoute.push({ context: 'new', }), ); + const context = useRouteParameter('context'); + const id = useRouteParameter('id'); + + const reload = useMutableCallback(() => queryClient.invalidateQueries(['canned-responses'])); + + if (context === 'edit' && id) { + return ; + } + + if (context === 'new') { + return ; + } + return ( - + - - - ), - [verified, t, email, previousEmail, handleSendConfirmationEmail], - )} - - - - - {useMemo( - () => ( - - {t('New_password')} - - } - /> - - {!allowPasswordChange && {t('Password_Change_Disabled')}} - - ), - [t, password, handlePassword, passwordError, allowPasswordChange, showPasswordError], - )} - {useMemo( - () => ( - - - {t('Confirm_password')} - - } - /> - - {passwordError && {showPasswordError ? passwordError : undefined}} - - - ), - [t, confirmationPassword, handleConfirmationPassword, password, passwordError, showPasswordError], + {useMemo( + () => ( + + {t('Email')} + + } + disabled={!allowEmailChange} + /> + {!verified && ( + )} - - - - + + {!allowEmailChange && {t('Email_Change_Disabled')}} + {t(emailError as TranslationKey)} + + ), + [t, email, emailError, handleEmail, verified, allowEmailChange, previousEmail, handleSendConfirmationEmail], + )} + {useMemo( + () => ( + + {t('New_password')} + + } + placeholder={t('Create_a_password')} + /> + + + } + placeholder={t('Confirm_password')} + disabled={!allowPasswordChange} + /> + + {!allowPasswordChange && {t('Password_Change_Disabled')}} + {passwordError && {showPasswordError ? passwordError : undefined}} + {passwordVerifications && allowPasswordChange && ( + + )} + + ), + [ + t, + allowPasswordChange, + showPasswordError, + passwordError, + password, + handlePassword, + confirmationPassword, + handleConfirmationPassword, + passwordVerifications, + ], + )} ); diff --git a/apps/meteor/packages/rocketchat-i18n/i18n/en.i18n.json b/apps/meteor/packages/rocketchat-i18n/i18n/en.i18n.json index 0247cac57adbe..1be1de77221f3 100644 --- a/apps/meteor/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/apps/meteor/packages/rocketchat-i18n/i18n/en.i18n.json @@ -1073,7 +1073,8 @@ "Confirm_new_encryption_password": "Confirm new encryption password", "Confirm_new_password": "Confirm New Password", "Confirm_New_Password_Placeholder": "Please re-enter new password...", - "Confirm_password": "Confirm your password", + "Confirm_password": "Confirm password", + "Confirm_your_password": "Confirm your password", "Confirmation": "Confirmation", "Configure_video_conference": "Configure conference call", "Connect": "Connect", @@ -2390,6 +2391,13 @@ "get-password-policy-mustContainAtLeastOneNumber": "The password should contain at least one number", "get-password-policy-mustContainAtLeastOneSpecialCharacter": "The password should contain at least one special character", "get-password-policy-mustContainAtLeastOneUppercase": "The password should contain at least one uppercase letter", + "get-password-policy-minLength-label": "At least {{limit}} characters", + "get-password-policy-maxLength-label": "At most {{limit}} characters", + "get-password-policy-forbidRepeatingCharactersCount-label": "Max. {{limit}} repeating characters", + "get-password-policy-mustContainAtLeastOneLowercase-label": "At least one lowercase letter", + "get-password-policy-mustContainAtLeastOneUppercase-label": "At least one uppercase letter", + "get-password-policy-mustContainAtLeastOneNumber-label": "At least one number", + "get-password-policy-mustContainAtLeastOneSpecialCharacter-label": "At least one symbol", "get-server-info": "Get Server Info", "get-server-info_description": "Permission to get server info", "github_no_public_email": "You don't have any email as public email in your GitHub account", @@ -3837,6 +3845,7 @@ "Password_History": "Password History", "Password_History_Amount": "Password History Length", "Password_History_Amount_Description": "Amount of most recently used passwords to prevent users from reusing.", + "Password_must_have": "Password must have:", "Password_Policy": "Password Policy", "Password_to_access": "Password to access", "Passwords_do_not_match": "Passwords do not match", @@ -5087,7 +5096,6 @@ "Type_your_job_title": "Type your job title", "Type_your_message": "Type your message", "Type_your_name": "Type your name", - "Type_your_new_password": "Type your new password", "Type_your_password": "Type your password", "Type_your_username": "Type your username", "UI_Allow_room_names_with_special_chars": "Allow Special Characters in Room Names", @@ -5804,6 +5812,7 @@ "Community_Private_apps_limit_exceeded": "Community edition app limit has been exceeded.", "Theme_match_system": "Match system", "Join_your_team": "Join your team", + "Create_a_password": "Create a password", "Create_an_account": "Create an account", "Get_all_apps": "Get all the apps your team needs", "Workspaces_on_community_edition_trial_on": "Workspaces on Community Edition can have up to 5 marketplace apps and 3 private apps enabled. Start a free Enterprise trial to remove these limits today!", diff --git a/apps/meteor/tests/end-to-end/api/00-miscellaneous.js b/apps/meteor/tests/end-to-end/api/00-miscellaneous.js index fb4de93a02467..5b07a0d34b4e1 100644 --- a/apps/meteor/tests/end-to-end/api/00-miscellaneous.js +++ b/apps/meteor/tests/end-to-end/api/00-miscellaneous.js @@ -675,18 +675,6 @@ describe('miscellaneous', function () { }); describe('/pw.getPolicy', () => { - it('should fail if not logged in', (done) => { - request - .get(api('pw.getPolicy')) - .expect('Content-Type', 'application/json') - .expect(401) - .expect((res) => { - expect(res.body).to.have.property('status', 'error'); - expect(res.body).to.have.property('message'); - }) - .end(done); - }); - it('should return policies', (done) => { request .get(api('pw.getPolicy')) diff --git a/packages/rest-typings/src/v1/misc.ts b/packages/rest-typings/src/v1/misc.ts index 228b943c757b6..4af37334e287d 100644 --- a/packages/rest-typings/src/v1/misc.ts +++ b/packages/rest-typings/src/v1/misc.ts @@ -206,7 +206,7 @@ export type MiscEndpoints = { '/v1/pw.getPolicy': { GET: () => { enabled: boolean; - policy: [name: string, options?: Record][]; + policy: [name: string, value?: Record][]; }; }; diff --git a/packages/ui-client/src/components/PasswordVerifier.tsx b/packages/ui-client/src/components/PasswordVerifier.tsx new file mode 100644 index 0000000000000..e564c1668b5cd --- /dev/null +++ b/packages/ui-client/src/components/PasswordVerifier.tsx @@ -0,0 +1,56 @@ +import { Box, Icon } from '@rocket.chat/fuselage'; +import type { useVerifyPassword } from '@rocket.chat/ui-contexts'; +import { useTranslation } from 'react-i18next'; + +type PasswordVerifierProps = { + password: string; + passwordVerifications: ReturnType; +}; + +export const PasswordVerifier = ({ password, passwordVerifications }: PasswordVerifierProps) => { + const { t } = useTranslation(); + + const handleRenderPasswordVerification = (passwordVerifications: ReturnType) => { + const verifications = []; + + if (!passwordVerifications) return null; + + for (const verification in passwordVerifications) { + if (passwordVerifications[verification]) { + const { isValid, limit } = passwordVerifications[verification]; + verifications.push( + + + {t(`${verification}-label`, { limit })} + , + ); + } + } + + return verifications; + }; + + return ( + + + {t('Password_must_have')} + + + {handleRenderPasswordVerification(passwordVerifications)} + + + ); +}; diff --git a/packages/ui-client/src/components/index.ts b/packages/ui-client/src/components/index.ts index 730775d1d41b2..9aa37f5479eb2 100644 --- a/packages/ui-client/src/components/index.ts +++ b/packages/ui-client/src/components/index.ts @@ -1,6 +1,7 @@ export * from './EmojiPicker'; export * from './ExternalLink'; export * from './DotLeader'; +export * from './PasswordVerifier'; export { default as TextSeparator } from './TextSeparator'; export * from './TooltipComponent'; export * as UserStatus from './UserStatus'; diff --git a/packages/ui-contexts/src/hooks/usePasswordPolicy.ts b/packages/ui-contexts/src/hooks/usePasswordPolicy.ts new file mode 100644 index 0000000000000..ca259a2155868 --- /dev/null +++ b/packages/ui-contexts/src/hooks/usePasswordPolicy.ts @@ -0,0 +1,9 @@ +import { useQuery } from '@tanstack/react-query'; + +import { useEndpoint } from './useEndpoint'; + +export const usePasswordPolicy = () => { + const getPasswordPolicy = useEndpoint('GET', '/v1/pw.getPolicy'); + + return useQuery(['login', 'password-policy'], async () => getPasswordPolicy()); +}; diff --git a/packages/ui-contexts/src/hooks/useVerifyPassword.ts b/packages/ui-contexts/src/hooks/useVerifyPassword.ts new file mode 100644 index 0000000000000..bb7f134304a88 --- /dev/null +++ b/packages/ui-contexts/src/hooks/useVerifyPassword.ts @@ -0,0 +1,59 @@ +import { usePasswordPolicy } from './usePasswordPolicy'; + +export const useVerifyPassword = (password?: string) => { + const { data, isLoading } = usePasswordPolicy(); + + if (isLoading) return; + + if (!data?.enabled || password === undefined) return; + + const handleRepeatingChars = (maxRepeatingChars?: number) => { + const repeatingCharsHash = {} as Record; + + for (let i = 0; i < password.length; i++) { + const currentChar = password[i]; + + if (repeatingCharsHash[currentChar]) { + repeatingCharsHash[currentChar]++; + if (repeatingCharsHash[currentChar] === maxRepeatingChars) return false; + } else { + repeatingCharsHash[currentChar] = 1; + } + } + + return true; + }; + + const passwordVerificationsTemplate: Record boolean> = { + 'get-password-policy-minLength': (minLength?: number) => Boolean(minLength && password.length >= minLength), + 'get-password-policy-maxLength': (maxLength?: number) => Boolean(maxLength && password.length <= maxLength), + 'get-password-policy-forbidRepeatingCharactersCount': handleRepeatingChars, + 'get-password-policy-mustContainAtLeastOneLowercase': () => /[a-z]/.test(password), + 'get-password-policy-mustContainAtLeastOneUppercase': () => /[A-Z]/.test(password), + 'get-password-policy-mustContainAtLeastOneNumber': () => /[0-9]/.test(password), + 'get-password-policy-mustContainAtLeastOneSpecialCharacter': () => /[^A-Za-z0-9\s]/.test(password), + }; + + const passwordVerifications = {} as Record; + + data?.policy.forEach((currentPolicy) => { + if (!Array.isArray(currentPolicy)) return; + + if (currentPolicy[0] === 'get-password-policy-forbidRepeatingCharacters') return; + + if (currentPolicy[1]) { + passwordVerifications[currentPolicy[0]] = { + isValid: passwordVerificationsTemplate[currentPolicy[0]](Object.values(currentPolicy[1])[0]), + limit: Object.values(currentPolicy[1])[0], + }; + return; + } + + passwordVerifications[currentPolicy[0]] = { + isValid: passwordVerificationsTemplate[currentPolicy[0]](), + limit: undefined, + }; + }); + + return passwordVerifications; +}; diff --git a/packages/ui-contexts/src/index.ts b/packages/ui-contexts/src/index.ts index 31cc3c5a35a1b..771a34eed36d4 100644 --- a/packages/ui-contexts/src/index.ts +++ b/packages/ui-contexts/src/index.ts @@ -79,6 +79,8 @@ export { useUserRoom } from './hooks/useUserRoom'; export { useUserSubscription } from './hooks/useUserSubscription'; export { useUserSubscriptionByName } from './hooks/useUserSubscriptionByName'; export { useUserSubscriptions } from './hooks/useUserSubscriptions'; +export { usePasswordPolicy } from './hooks/usePasswordPolicy'; +export { useVerifyPassword } from './hooks/useVerifyPassword'; export { useSelectedDevices } from './hooks/useSelectedDevices'; export { useDeviceConstraints } from './hooks/useDeviceConstraints'; export { useAvailableDevices } from './hooks/useAvailableDevices'; diff --git a/packages/web-ui-registration/package.json b/packages/web-ui-registration/package.json index bba768ce6d8ab..fdd007d1cacb4 100644 --- a/packages/web-ui-registration/package.json +++ b/packages/web-ui-registration/package.json @@ -4,6 +4,7 @@ "private": true, "devDependencies": { "@rocket.chat/layout": "next", + "@rocket.chat/ui-client": "workspace:^", "@rocket.chat/ui-contexts": "workspace:^", "@tanstack/react-query": "^4.16.1", "@testing-library/react": "^13.3.0", diff --git a/packages/web-ui-registration/src/RegisterForm.tsx b/packages/web-ui-registration/src/RegisterForm.tsx index f2a880a7db6b7..8870832991e45 100644 --- a/packages/web-ui-registration/src/RegisterForm.tsx +++ b/packages/web-ui-registration/src/RegisterForm.tsx @@ -1,7 +1,8 @@ import { useUniqueId } from '@rocket.chat/fuselage-hooks'; import { FieldGroup, TextInput, Field, PasswordInput, ButtonGroup, Button, TextAreaInput } from '@rocket.chat/fuselage'; import { Form, ActionLink } from '@rocket.chat/layout'; -import { useSetting, useToastMessageDispatch } from '@rocket.chat/ui-contexts'; +import { useSetting, useVerifyPassword, useToastMessageDispatch } from '@rocket.chat/ui-contexts'; +import { PasswordVerifier } from '@rocket.chat/ui-client'; import type { ReactElement } from 'react'; import { useForm } from 'react-hook-form'; import { Trans, useTranslation } from 'react-i18next'; @@ -19,6 +20,7 @@ type LoginRegisterPayload = { reason: string; }; +// eslint-disable-next-line complexity export const RegisterForm = ({ setLoginRoute }: { setLoginRoute: DispatchLoginRouter }): ReactElement => { const { t } = useTranslation(); @@ -45,6 +47,8 @@ export const RegisterForm = ({ setLoginRoute }: { setLoginRoute: DispatchLoginRo formState: { errors }, } = useForm(); + const passwordVerifications = useVerifyPassword(watch('password')); + const handleRegister = async ({ password, passwordConfirmation: _, ...formData }: LoginRegisterPayload) => { registerUser.mutate( { pass: password, ...formData }, @@ -98,6 +102,7 @@ export const RegisterForm = ({ setLoginRoute }: { setLoginRoute: DispatchLoginRo })} error={errors.name && t('registration.component.form.requiredField')} aria-invalid={errors.name ? 'true' : 'false'} + placeholder={t('onboarding.form.adminInfoForm.fields.fullName.placeholder')} id='name' /> @@ -149,14 +154,10 @@ export const RegisterForm = ({ setLoginRoute }: { setLoginRoute: DispatchLoginRo error={errors.password && (errors.password?.message || t('registration.component.form.requiredField'))} aria-invalid={errors.password ? 'true' : undefined} id='password' - placeholder={passwordPlaceholder} + placeholder={passwordPlaceholder || t('Create_a_password')} /> - {errors.password && {errors.password.message}} - - {requiresPasswordConfirmation && ( - - {t('registration.component.form.confirmPassword')}* + {requiresPasswordConfirmation && ( - {errors.passwordConfirmation?.type === 'validate' && ( - {t('registration.component.form.invalidConfirmPass')} - )} - {errors.passwordConfirmation?.type === 'required' && ( - {t('registration.component.form.requiredField')} - )} - - )} + )} + {errors.passwordConfirmation?.type === 'validate' && requiresPasswordConfirmation && ( + {t('registration.component.form.invalidConfirmPass')} + )} + {errors.passwordConfirmation?.type === 'required' && requiresPasswordConfirmation && ( + {t('registration.component.form.requiredField')} + )} + {passwordVerifications && } + {manuallyApproveNewUsersRequired && ( {t('registration.component.form.reasonToJoin')}* diff --git a/packages/web-ui-registration/src/ResetPassword/ResetPasswordPage.tsx b/packages/web-ui-registration/src/ResetPassword/ResetPasswordPage.tsx index c8d13360eb0eb..c392f1376ac8b 100644 --- a/packages/web-ui-registration/src/ResetPassword/ResetPasswordPage.tsx +++ b/packages/web-ui-registration/src/ResetPassword/ResetPasswordPage.tsx @@ -1,12 +1,21 @@ -import { Button, Field, Modal, Box, PasswordInput, InputBoxSkeleton } from '@rocket.chat/fuselage'; +import { Button, Field, Modal, PasswordInput } from '@rocket.chat/fuselage'; import type { TranslationKey } from '@rocket.chat/ui-contexts'; -import { useRouteParameter, useRoute, useUser, useMethod, useTranslation, useLoginWithToken } from '@rocket.chat/ui-contexts'; +import { + useSetting, + useVerifyPassword, + useRouteParameter, + useRoute, + useUser, + useMethod, + useTranslation, + useLoginWithToken, +} from '@rocket.chat/ui-contexts'; import type { ReactElement } from 'react'; import { Form } from '@rocket.chat/layout'; import { useForm } from 'react-hook-form'; +import { PasswordVerifier } from '@rocket.chat/ui-client'; import HorizontalTemplate from '../template/HorizontalTemplate'; -import { usePasswordPolicy } from '../hooks/usePasswordPolicy'; const getChangePasswordReason = ({ requirePasswordChange, @@ -20,9 +29,7 @@ const ResetPasswordPage = (): ReactElement => { const resetPassword = useMethod('resetPassword'); const token = useRouteParameter('token'); - const policies = usePasswordPolicy({ - token: user ? undefined : token, - }); + const requiresPasswordConfirmation = useSetting('Accounts_RequirePasswordConfirmation'); const homeRouter = useRoute('home'); @@ -36,12 +43,16 @@ const ResetPasswordPage = (): ReactElement => { setError, formState: { errors }, formState, + watch, } = useForm<{ password: string; + passwordConfirmation: string; }>({ mode: 'onChange', }); + const passwordVerifications = useVerifyPassword(watch('password')); + const submit = handleSubmit(async (data) => { try { if (token) { @@ -61,7 +72,7 @@ const ResetPasswordPage = (): ReactElement => {
- {t('Password')} + {t('Reset_password')} @@ -74,22 +85,28 @@ const ResetPasswordPage = (): ReactElement => { error={errors.password?.message} aria-invalid={errors.password ? 'true' : 'false'} id='password' - placeholder={t('Type_your_new_password')} + placeholder={t('Create_a_password')} name='password' autoComplete='off' /> + {requiresPasswordConfirmation && ( + + watch('password') === val, + })} + error={errors.passwordConfirmation?.type === 'validate' ? t('registration.component.form.invalidConfirmPass') : undefined} + aria-invalid={errors.passwordConfirmation ? 'true' : false} + id='passwordConfirmation' + placeholder={t('Confirm_password')} + /> + + )} {errors && {errors.password?.message}} - - {policies.isLoading && } - {policies.isSuccess && - policies.data.enabled && - policies.data.policy?.map((policy, index) => ( - - {t(...(policy as unknown as [name: TranslationKey, options?: Record]))} - - ))} - + {passwordVerifications && } diff --git a/packages/web-ui-registration/src/hooks/usePasswordPolicy.ts b/packages/web-ui-registration/src/hooks/usePasswordPolicy.ts deleted file mode 100644 index 7b0d0401bf479..0000000000000 --- a/packages/web-ui-registration/src/hooks/usePasswordPolicy.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { useEndpoint } from '@rocket.chat/ui-contexts'; -import { useQuery } from '@tanstack/react-query'; - -export const usePasswordPolicy = ({ token }: { token?: string }) => { - const getPasswordPolicy = useEndpoint('GET', '/v1/pw.getPolicy'); - const getPasswordPolicyRest = useEndpoint('GET', '/v1/pw.getPolicyReset'); - - return useQuery(['login', 'password-policy', token], async () => (!token ? getPasswordPolicy() : getPasswordPolicyRest({ token }))); -}; diff --git a/password-verification-front.md b/password-verification-front.md new file mode 100644 index 0000000000000..3df0799752bff --- /dev/null +++ b/password-verification-front.md @@ -0,0 +1,9 @@ +--- +"@rocket.chat/meteor": patch +"@rocket.chat/rest-typings": patch +"@rocket.chat/ui-client": patch +"@rocket.chat/ui-contexts": patch +"@rocket.chat/web-ui-registration": patch +--- + +Implemented a visual password verification in the Register User form, My Profile page, and reset password page. With this, the user will know exactly why their password is weak and how to improve it. \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 4b6079b241855..2f88c99b10e65 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11116,6 +11116,7 @@ __metadata: resolution: "@rocket.chat/web-ui-registration@workspace:packages/web-ui-registration" dependencies: "@rocket.chat/layout": next + "@rocket.chat/ui-client": "workspace:^" "@rocket.chat/ui-contexts": "workspace:^" "@tanstack/react-query": ^4.16.1 "@testing-library/react": ^13.3.0 From 9e59265f66a02254a6060f28606f3085e8d30741 Mon Sep 17 00:00:00 2001 From: Tasso Evangelista Date: Thu, 22 Jun 2023 20:46:15 -0300 Subject: [PATCH 08/21] ci(lint): Broken ESLint (#29599) --- .../incoming/updateIncomingIntegration.ts | 4 +- .../outgoing/updateOutgoingIntegration.ts | 4 +- apps/meteor/ee/server/services/package.json | 2 +- apps/meteor/package.json | 18 +- .../server/lib/parseMessageSearchQuery.ts | 4 +- apps/meteor/server/models/raw/Analytics.ts | 4 +- .../server/models/raw/VideoConference.ts | 2 +- ee/apps/account-service/package.json | 6 +- ee/apps/authorization-service/package.json | 6 +- ee/apps/ddp-streamer/package.json | 6 +- ee/apps/omnichannel-transcript/package.json | 6 +- ee/apps/presence-service/package.json | 6 +- ee/apps/queue-worker/package.json | 6 +- ee/apps/stream-hub-service/package.json | 6 +- ee/packages/omnichannel-services/package.json | 4 +- ee/packages/pdf-worker/package.json | 4 +- ee/packages/presence/package.json | 4 +- ee/packages/ui-theming/package.json | 6 +- packages/account-utils/package.json | 4 +- packages/agenda/package.json | 4 +- packages/api-client/package.json | 6 +- packages/base64/package.json | 8 +- packages/cas-validate/package.json | 4 +- packages/core-services/package.json | 4 +- packages/core-typings/package.json | 4 +- packages/cron/package.json | 4 +- packages/ddp-client/package.json | 6 +- packages/eslint-config/package.json | 8 +- packages/favicon/package.json | 4 +- packages/fuselage-ui-kit/package.json | 4 +- packages/gazzodown/package.json | 10 +- packages/i18n/package.json | 4 +- packages/instance-status/package.json | 4 +- packages/livechat/package.json | 8 +- packages/log-format/package.json | 4 +- packages/model-typings/package.json | 4 +- packages/models/package.json | 4 +- packages/node-poplib/package.json | 4 +- packages/random/package.json | 8 +- packages/release-action/package.json | 2 +- packages/rest-typings/package.json | 4 +- packages/server-fetch/package.json | 4 +- packages/sha256/package.json | 8 +- packages/tools/package.json | 4 +- packages/ui-client/package.json | 6 +- packages/ui-composer/package.json | 4 +- packages/ui-contexts/package.json | 4 +- packages/ui-video-conf/package.json | 4 +- packages/uikit-playground/package.json | 10 +- packages/web-ui-registration/package.json | 4 +- yarn.lock | 802 ++++++------------ 51 files changed, 376 insertions(+), 688 deletions(-) diff --git a/apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts b/apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts index b541c776e0f7c..4e0fa6bf423d6 100644 --- a/apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts +++ b/apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts @@ -80,7 +80,7 @@ Meteor.methods({ $set: { scriptCompiled, }, - $unset: { scriptError: 1 }, + $unset: { scriptError: 1 as const }, }, ); } catch (e) { @@ -96,7 +96,7 @@ Meteor.methods({ scriptError, }, $unset: { - scriptCompiled: 1, + scriptCompiled: 1 as const, }, }, ); diff --git a/apps/meteor/app/integrations/server/methods/outgoing/updateOutgoingIntegration.ts b/apps/meteor/app/integrations/server/methods/outgoing/updateOutgoingIntegration.ts index 63ccdb80d0a1f..a297fd980897c 100644 --- a/apps/meteor/app/integrations/server/methods/outgoing/updateOutgoingIntegration.ts +++ b/apps/meteor/app/integrations/server/methods/outgoing/updateOutgoingIntegration.ts @@ -56,7 +56,7 @@ Meteor.methods({ { _id: integrationId }, { $set: { scriptCompiled: integration.scriptCompiled }, - $unset: { scriptError: 1 }, + $unset: { scriptError: 1 as const }, }, ); } else { @@ -64,7 +64,7 @@ Meteor.methods({ { _id: integrationId }, { $set: { scriptError: integration.scriptError }, - $unset: { scriptCompiled: 1 }, + $unset: { scriptCompiled: 1 as const }, }, ); } diff --git a/apps/meteor/ee/server/services/package.json b/apps/meteor/ee/server/services/package.json index 10e1467a71796..7934b3dc5f65f 100644 --- a/apps/meteor/ee/server/services/package.json +++ b/apps/meteor/ee/server/services/package.json @@ -62,7 +62,7 @@ "pino-pretty": "^7.6.1", "pm2": "^5.2.0", "ts-node": "^10.9.1", - "typescript": "~5.0.4" + "typescript": "~5.1.3" }, "volta": { "extends": "../../../package.json" diff --git a/apps/meteor/package.json b/apps/meteor/package.json index b8d6391ad9e3a..0b1f19e2b46f9 100644 --- a/apps/meteor/package.json +++ b/apps/meteor/package.json @@ -63,7 +63,7 @@ }, "devDependencies": { "@babel/core": "^7.20.5", - "@babel/eslint-parser": "^7.19.1", + "@babel/eslint-parser": "^7.22.5", "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6", "@babel/plugin-proposal-optional-chaining": "^7.18.9", "@babel/preset-env": "^7.20.2", @@ -80,7 +80,7 @@ "@storybook/addons": "~6.5.16", "@storybook/react": "~6.5.16", "@storybook/testing-library": "0.0.13", - "@swc/core": "^1.3.64", + "@swc/core": "^1.3.66", "@tanstack/react-query-devtools": "^4.19.1", "@testing-library/react": "~12.1.5", "@testing-library/react-hooks": "^8.0.1", @@ -151,8 +151,8 @@ "@types/uuid": "^8.3.4", "@types/xml-crypto": "~1.4.2", "@types/xml-encryption": "~1.2.1", - "@typescript-eslint/eslint-plugin": "~5.58.0", - "@typescript-eslint/parser": "~5.58.0", + "@typescript-eslint/eslint-plugin": "~5.60.0", + "@typescript-eslint/parser": "~5.60.0", "autoprefixer": "^9.8.8", "babel-loader": "^8.3.0", "babel-plugin-array-includes": "^2.0.3", @@ -164,15 +164,16 @@ "chai-spies": "~1.0.0", "cross-env": "^7.0.3", "emojione-assets": "^4.5.0", - "eslint": "^8.29.0", + "eslint": "~8.43.0", "eslint-config-prettier": "~8.8.0", + "eslint-plugin-anti-trojan-source": "~1.1.1", "eslint-plugin-import": "~2.26.0", "eslint-plugin-no-floating-promise": "~1.0.2", - "eslint-plugin-playwright": "~0.12.0", + "eslint-plugin-playwright": "~0.15.0", "eslint-plugin-prettier": "~4.2.1", "eslint-plugin-react": "~7.32.2", "eslint-plugin-react-hooks": "~4.6.0", - "eslint-plugin-testing-library": "~5.10.3", + "eslint-plugin-testing-library": "~5.11.0", "eslint-plugin-you-dont-need-lodash-underscore": "~6.12.0", "fast-glob": "^3.2.12", "i18next": "^20.6.1", @@ -200,7 +201,7 @@ "supertest": "^6.2.3", "template-file": "^6.0.1", "ts-node": "^10.9.1", - "typescript": "~5.0.4" + "typescript": "~5.1.3" }, "dependencies": { "@babel/runtime": "~7.22.5", @@ -312,7 +313,6 @@ "emailreplyparser": "^0.0.5", "emoji-toolkit": "^7.0.1", "emojione": "^4.5.0", - "eslint-plugin-anti-trojan-source": "~1.1.1", "eventemitter3": "^4.0.7", "exif-be-gone": "^1.3.2", "express": "^4.17.3", diff --git a/apps/meteor/server/lib/parseMessageSearchQuery.ts b/apps/meteor/server/lib/parseMessageSearchQuery.ts index 48d70bf6ba5b7..70bd6c8625c35 100644 --- a/apps/meteor/server/lib/parseMessageSearchQuery.ts +++ b/apps/meteor/server/lib/parseMessageSearchQuery.ts @@ -214,12 +214,12 @@ class MessageSearchQueryParser { return text.replace(/(?:order|sort):(asc|ascend|ascending|desc|descend|descending)/g, (_: string, direction: string) => { if (direction.startsWith('asc')) { this.options.sort = { - ...(typeof this.options.sort === 'object' ? this.options.sort : {}), + ...(typeof this.options.sort === 'object' && !Array.isArray(this.options.sort) ? this.options.sort : {}), ts: 1, }; } else if (direction.startsWith('desc')) { this.options.sort = { - ...(typeof this.options.sort === 'object' ? this.options.sort : {}), + ...(typeof this.options.sort === 'object' && !Array.isArray(this.options.sort) ? this.options.sort : {}), ts: -1, }; } diff --git a/apps/meteor/server/models/raw/Analytics.ts b/apps/meteor/server/models/raw/Analytics.ts index e3ecf52a954b7..e0e10fc9566e5 100644 --- a/apps/meteor/server/models/raw/Analytics.ts +++ b/apps/meteor/server/models/raw/Analytics.ts @@ -32,7 +32,7 @@ export class AnalyticsRaw extends BaseRaw implements IAnalyticsModel $setOnInsert: { _id: Random.id(), date, - type: 'messages', + type: 'messages' as const, }, $inc: { messages: 1 }, }, @@ -47,7 +47,7 @@ export class AnalyticsRaw extends BaseRaw implements IAnalyticsModel $setOnInsert: { _id: Random.id(), date, - type: 'users', + type: 'users' as const, }, $inc: { users: 1 }, }, diff --git a/apps/meteor/server/models/raw/VideoConference.ts b/apps/meteor/server/models/raw/VideoConference.ts index 40e6c9a898502..972a91806fc7e 100644 --- a/apps/meteor/server/models/raw/VideoConference.ts +++ b/apps/meteor/server/models/raw/VideoConference.ts @@ -183,7 +183,7 @@ export class VideoConferenceRaw extends BaseRaw implements IVid } : { $unset: { - providerData: 1, + providerData: 1 as const, }, }), }); diff --git a/ee/apps/account-service/package.json b/ee/apps/account-service/package.json index 2cfa4db5ceee3..97887c29431d9 100644 --- a/ee/apps/account-service/package.json +++ b/ee/apps/account-service/package.json @@ -38,11 +38,11 @@ "devDependencies": { "@rocket.chat/eslint-config": "workspace:^", "@types/bcrypt": "^5.0.0", - "@types/eslint": "~8.37.0", + "@types/eslint": "~8.40.2", "@types/polka": "^0.5.4", - "eslint": "~8.38.0", + "eslint": "~8.43.0", "ts-node": "^10.9.1", - "typescript": "~5.0.4" + "typescript": "~5.1.3" }, "main": "./dist/ee/apps/account-service/src/service.js", "files": [ diff --git a/ee/apps/authorization-service/package.json b/ee/apps/authorization-service/package.json index 29811012a52ea..63fde92bc4c65 100644 --- a/ee/apps/authorization-service/package.json +++ b/ee/apps/authorization-service/package.json @@ -35,11 +35,11 @@ }, "devDependencies": { "@rocket.chat/eslint-config": "workspace:^", - "@types/eslint": "~8.37.0", + "@types/eslint": "~8.40.2", "@types/polka": "^0.5.4", - "eslint": "~8.38.0", + "eslint": "~8.43.0", "ts-node": "^10.9.1", - "typescript": "~5.0.4" + "typescript": "~5.1.3" }, "main": "./dist/ee/apps/authorization-service/src/service.js", "files": [ diff --git a/ee/apps/ddp-streamer/package.json b/ee/apps/ddp-streamer/package.json index e6bad02b1c5a0..b6e4956292f62 100644 --- a/ee/apps/ddp-streamer/package.json +++ b/ee/apps/ddp-streamer/package.json @@ -44,17 +44,17 @@ "devDependencies": { "@rocket.chat/eslint-config": "workspace:^", "@types/ejson": "^2.2.0", - "@types/eslint": "~8.37.0", + "@types/eslint": "~8.40.2", "@types/meteor": "^2.9.2", "@types/node": "^14.18.51", "@types/polka": "^0.5.4", "@types/sharp": "^0.30.5", "@types/uuid": "^8.3.4", "@types/ws": "^8.5.5", - "eslint": "~8.38.0", + "eslint": "~8.43.0", "pino-pretty": "^7.6.1", "ts-node": "^10.9.1", - "typescript": "~5.0.4" + "typescript": "~5.1.3" }, "main": "./dist/service.js", "files": [ diff --git a/ee/apps/omnichannel-transcript/package.json b/ee/apps/omnichannel-transcript/package.json index c255c0b6362cb..8194c1a621aec 100644 --- a/ee/apps/omnichannel-transcript/package.json +++ b/ee/apps/omnichannel-transcript/package.json @@ -41,11 +41,11 @@ "devDependencies": { "@rocket.chat/eslint-config": "workspace:^", "@rocket.chat/ui-contexts": "workspace:^", - "@types/eslint": "~8.37.0", + "@types/eslint": "~8.40.2", "@types/polka": "^0.5.4", - "eslint": "~8.38.0", + "eslint": "~8.43.0", "ts-node": "^10.9.1", - "typescript": "~5.0.4" + "typescript": "~5.1.3" }, "main": "./dist/ee/apps/omnichannel-transcript/src/service.js", "files": [ diff --git a/ee/apps/presence-service/package.json b/ee/apps/presence-service/package.json index 1bf8ccdaa0d38..41f43f7f9b3ac 100644 --- a/ee/apps/presence-service/package.json +++ b/ee/apps/presence-service/package.json @@ -35,11 +35,11 @@ }, "devDependencies": { "@rocket.chat/eslint-config": "workspace:^", - "@types/eslint": "~8.37.0", + "@types/eslint": "~8.40.2", "@types/polka": "^0.5.4", - "eslint": "~8.38.0", + "eslint": "~8.43.0", "ts-node": "^10.9.1", - "typescript": "~5.0.4" + "typescript": "~5.1.3" }, "main": "./dist/ee/apps/presence-service/src/service.js", "files": [ diff --git a/ee/apps/queue-worker/package.json b/ee/apps/queue-worker/package.json index fad23518733e1..ea52aad874e44 100644 --- a/ee/apps/queue-worker/package.json +++ b/ee/apps/queue-worker/package.json @@ -38,11 +38,11 @@ }, "devDependencies": { "@rocket.chat/eslint-config": "workspace:^", - "@types/eslint": "~8.37.0", + "@types/eslint": "~8.40.2", "@types/polka": "^0.5.4", - "eslint": "~8.38.0", + "eslint": "~8.43.0", "ts-node": "^10.9.1", - "typescript": "~5.0.4" + "typescript": "~5.1.3" }, "main": "./dist/ee/apps/queue-worker/src/service.js", "files": [ diff --git a/ee/apps/stream-hub-service/package.json b/ee/apps/stream-hub-service/package.json index 9d3b44e37358e..4a83f8819657c 100644 --- a/ee/apps/stream-hub-service/package.json +++ b/ee/apps/stream-hub-service/package.json @@ -36,11 +36,11 @@ "@rocket.chat/eslint-config": "workspace:^", "@rocket.chat/rest-typings": "workspace:^", "@types/bcrypt": "^5.0.0", - "@types/eslint": "~8.37.0", + "@types/eslint": "~8.40.2", "@types/polka": "^0.5.4", - "eslint": "~8.38.0", + "eslint": "~8.43.0", "ts-node": "^10.9.1", - "typescript": "~5.0.4" + "typescript": "~5.1.3" }, "main": "./dist/ee/apps/stream-hub-service/src/service.js", "files": [ diff --git a/ee/packages/omnichannel-services/package.json b/ee/packages/omnichannel-services/package.json index 2fbc6171cf68f..f51b75908d84b 100644 --- a/ee/packages/omnichannel-services/package.json +++ b/ee/packages/omnichannel-services/package.json @@ -5,10 +5,10 @@ "devDependencies": { "@rocket.chat/eslint-config": "workspace:^", "@types/jest": "~29.5.2", - "eslint": "~8.38.0", + "eslint": "~8.43.0", "jest": "~29.5.0", "ts-jest": "~29.0.5", - "typescript": "~5.0.4" + "typescript": "~5.1.3" }, "dependencies": { "@rocket.chat/core-services": "workspace:^", diff --git a/ee/packages/pdf-worker/package.json b/ee/packages/pdf-worker/package.json index 7c794db3a24c1..a013a48433733 100644 --- a/ee/packages/pdf-worker/package.json +++ b/ee/packages/pdf-worker/package.json @@ -11,12 +11,12 @@ "@types/jest": "~29.5.2", "@types/react-dom": "^18.2.5", "@types/testing-library__jest-dom": "~5.14.6", - "eslint": "~8.38.0", + "eslint": "~8.43.0", "jest": "~29.5.0", "jest-environment-jsdom": "~29.5.0", "react-dom": "^18.2.0", "ts-jest": "~29.0.5", - "typescript": "~5.0.4" + "typescript": "~5.1.3" }, "scripts": { "lint": "eslint --ext .js,.jsx,.ts,.tsx .", diff --git a/ee/packages/presence/package.json b/ee/packages/presence/package.json index f1a2d2d006d21..b23637cc0049e 100644 --- a/ee/packages/presence/package.json +++ b/ee/packages/presence/package.json @@ -11,9 +11,9 @@ "@rocket.chat/rest-typings": "workspace:^", "@types/node": "^14.18.51", "babel-jest": "^29.0.3", - "eslint": "~8.38.0", + "eslint": "~8.43.0", "jest": "~29.5.0", - "typescript": "~5.0.4" + "typescript": "~5.1.3" }, "scripts": { "lint": "eslint src", diff --git a/ee/packages/ui-theming/package.json b/ee/packages/ui-theming/package.json index 4a86febf0c805..b16a3c8168495 100644 --- a/ee/packages/ui-theming/package.json +++ b/ee/packages/ui-theming/package.json @@ -20,16 +20,16 @@ "@storybook/testing-library": "~0.0.13", "@types/jest": "~29.5.2", "@types/react": "~17.0.62", - "eslint": "~8.38.0", + "eslint": "~8.43.0", "eslint-plugin-anti-trojan-source": "~1.1.1", "eslint-plugin-react": "~7.32.2", "eslint-plugin-react-hooks": "~4.6.0", - "eslint-plugin-testing-library": "^5.9.1", + "eslint-plugin-testing-library": "^5.11.0", "jest": "~29.5.0", "react": "~17.0.2", "react-docgen-typescript-plugin": "~1.0.5", "ts-jest": "~29.0.5", - "typescript": "~5.0.4" + "typescript": "~5.1.3" }, "scripts": { "lint": "eslint --ext .js,.jsx,.ts,.tsx .", diff --git a/packages/account-utils/package.json b/packages/account-utils/package.json index a959c50d4258b..235f0314647b5 100644 --- a/packages/account-utils/package.json +++ b/packages/account-utils/package.json @@ -4,10 +4,10 @@ "private": true, "devDependencies": { "@types/jest": "~29.5.2", - "eslint": "~8.38.0", + "eslint": "~8.43.0", "jest": "~29.5.0", "ts-jest": "~29.0.5", - "typescript": "~5.0.4" + "typescript": "~5.1.3" }, "scripts": { "lint": "eslint --ext .js,.jsx,.ts,.tsx .", diff --git a/packages/agenda/package.json b/packages/agenda/package.json index 82ab2dd3754af..434566005aee5 100644 --- a/packages/agenda/package.json +++ b/packages/agenda/package.json @@ -14,10 +14,10 @@ "devDependencies": { "@types/debug": "^4.1.8", "@types/jest": "~29.5.2", - "eslint": "~8.38.0", + "eslint": "~8.43.0", "jest": "~29.5.0", "ts-jest": "~29.0.5", - "typescript": "~5.0.4" + "typescript": "~5.1.3" }, "scripts": { "lint": "eslint --ext .js,.jsx,.ts,.tsx .", diff --git a/packages/api-client/package.json b/packages/api-client/package.json index c057f1a2cd086..0d0e86d573c44 100644 --- a/packages/api-client/package.json +++ b/packages/api-client/package.json @@ -3,15 +3,15 @@ "version": "0.0.2", "private": true, "devDependencies": { - "@swc/core": "^1.3.64", + "@swc/core": "^1.3.66", "@swc/jest": "^0.2.26", "@types/jest": "~29.5.2", "@types/strict-uri-encode": "^2.0.0", - "eslint": "~8.38.0", + "eslint": "~8.43.0", "jest": "~29.5.0", "jest-fetch-mock": "^3.0.3", "ts-jest": "~29.0.5", - "typescript": "~5.0.4" + "typescript": "~5.1.3" }, "scripts": { "lint": "eslint --ext .js,.jsx,.ts,.tsx .", diff --git a/packages/base64/package.json b/packages/base64/package.json index 30aa732502b70..cf8d03b65c04b 100644 --- a/packages/base64/package.json +++ b/packages/base64/package.json @@ -16,12 +16,12 @@ "@babel/core": "~7.22.5", "@babel/preset-env": "~7.22.5", "@rocket.chat/eslint-config": "workspace:^", - "@typescript-eslint/eslint-plugin": "~5.58.0", - "@typescript-eslint/parser": "~5.58.0", - "eslint": "~8.38.0", + "@typescript-eslint/eslint-plugin": "~5.60.0", + "@typescript-eslint/parser": "~5.60.0", + "eslint": "~8.43.0", "jest": "~29.5.0", "ts-jest": "~29.0.5", - "typescript": "~5.0.4" + "typescript": "~5.1.3" }, "volta": { "extends": "../../package.json" diff --git a/packages/cas-validate/package.json b/packages/cas-validate/package.json index 610758cf2a986..2ee9412e5665c 100644 --- a/packages/cas-validate/package.json +++ b/packages/cas-validate/package.json @@ -5,10 +5,10 @@ "private": true, "devDependencies": { "@types/jest": "~29.5.2", - "eslint": "~8.38.0", + "eslint": "~8.43.0", "jest": "~29.5.0", "ts-jest": "~29.0.5", - "typescript": "~5.0.4" + "typescript": "~5.1.3" }, "scripts": { "lint": "eslint --ext .js,.jsx,.ts,.tsx .", diff --git a/packages/core-services/package.json b/packages/core-services/package.json index bd081d6512d61..9aea8fa0e1154 100644 --- a/packages/core-services/package.json +++ b/packages/core-services/package.json @@ -4,10 +4,10 @@ "private": true, "devDependencies": { "@rocket.chat/eslint-config": "workspace:^", - "eslint": "~8.38.0", + "eslint": "~8.43.0", "mongodb": "^4.12.1", "prettier": "~2.8.8", - "typescript": "~5.0.4" + "typescript": "~5.1.3" }, "scripts": { "lint": "eslint --ext .js,.jsx,.ts,.tsx .", diff --git a/packages/core-typings/package.json b/packages/core-typings/package.json index ce37630d0a425..1e049be63ca11 100644 --- a/packages/core-typings/package.json +++ b/packages/core-typings/package.json @@ -4,10 +4,10 @@ "private": true, "devDependencies": { "@rocket.chat/eslint-config": "workspace:^", - "eslint": "~8.38.0", + "eslint": "~8.43.0", "mongodb": "^4.12.1", "prettier": "~2.8.8", - "typescript": "~5.0.4" + "typescript": "~5.1.3" }, "scripts": { "lint": "eslint --ext .js,.jsx,.ts,.tsx .", diff --git a/packages/cron/package.json b/packages/cron/package.json index cc3ae5e3eed62..9f009d83baa61 100644 --- a/packages/cron/package.json +++ b/packages/cron/package.json @@ -4,10 +4,10 @@ "private": true, "devDependencies": { "@types/jest": "^27.4.1", - "eslint": "^8.12.0", + "eslint": "^8.43.0", "jest": "~29.5.0", "ts-jest": "~29.0.5", - "typescript": "~5.0.4" + "typescript": "~5.1.3" }, "scripts": { "lint": "eslint --ext .js,.jsx,.ts,.tsx .", diff --git a/packages/ddp-client/package.json b/packages/ddp-client/package.json index df90a412ad144..83c45259e5e6c 100644 --- a/packages/ddp-client/package.json +++ b/packages/ddp-client/package.json @@ -3,15 +3,15 @@ "version": "0.0.1", "private": true, "devDependencies": { - "@swc/core": "^1.3.64", + "@swc/core": "^1.3.66", "@swc/jest": "^0.2.26", "@types/jest": "^29.5.2", "@types/ws": "^8.5.5", - "eslint": "^8.12.0", + "eslint": "^8.43.0", "jest": "^29.5.0", "jest-environment-jsdom": "~29.5.0", "jest-websocket-mock": "^2.4.0", - "typescript": "~5.0.4", + "typescript": "~5.1.3", "ws": "^8.13.0" }, "peerDependencies": { diff --git a/packages/eslint-config/package.json b/packages/eslint-config/package.json index 8d8ba62e781b7..a2333c4443566 100644 --- a/packages/eslint-config/package.json +++ b/packages/eslint-config/package.json @@ -5,13 +5,13 @@ "devDependencies": { "@babel/eslint-parser": "~7.22.5", "@types/prettier": "^2.6.3", - "@typescript-eslint/eslint-plugin": "~5.58.0", - "@typescript-eslint/parser": "~5.58.0", - "eslint": "~8.38.0", + "@typescript-eslint/eslint-plugin": "~5.60.0", + "@typescript-eslint/parser": "~5.60.0", + "eslint": "~8.43.0", "eslint-config-prettier": "~8.8.0", "eslint-plugin-anti-trojan-source": "~1.1.1", "eslint-plugin-import": "~2.26.0", - "eslint-plugin-jest": "~27.2.1", + "eslint-plugin-jest": "~27.2.2", "eslint-plugin-prettier": "~4.2.1", "prettier": "~2.8.8" }, diff --git a/packages/favicon/package.json b/packages/favicon/package.json index 4a314f9fa324b..cf44e160d13b3 100644 --- a/packages/favicon/package.json +++ b/packages/favicon/package.json @@ -3,8 +3,8 @@ "version": "0.0.1", "private": true, "devDependencies": { - "eslint": "~8.38.0", - "typescript": "~5.0.4" + "eslint": "~8.43.0", + "typescript": "~5.1.3" }, "scripts": { "lint": "eslint --ext .js,.jsx,.ts,.tsx .", diff --git a/packages/fuselage-ui-kit/package.json b/packages/fuselage-ui-kit/package.json index d0df0a3eb670b..5b3145dce4ac5 100644 --- a/packages/fuselage-ui-kit/package.json +++ b/packages/fuselage-ui-kit/package.json @@ -78,7 +78,7 @@ "@types/react-dom": "~17.0.20", "babel-loader": "~8.2.5", "cross-env": "^7.0.3", - "eslint": "~8.38.0", + "eslint": "~8.43.0", "normalize.css": "^8.0.1", "npm-run-all": "^4.1.5", "prettier": "~2.8.8", @@ -86,7 +86,7 @@ "react-dom": "^17.0.2", "rimraf": "^3.0.2", "tslib": "^2.5.3", - "typescript": "~5.0.4" + "typescript": "~5.1.3" }, "dependencies": { "@rocket.chat/gazzodown": "workspace:^", diff --git a/packages/gazzodown/package.json b/packages/gazzodown/package.json index 3fb8ab032b1d1..cb195dd486543 100644 --- a/packages/gazzodown/package.json +++ b/packages/gazzodown/package.json @@ -21,7 +21,7 @@ "@storybook/manager-webpack4": "~6.5.16", "@storybook/react": "~6.5.16", "@storybook/testing-library": "~0.0.13", - "@swc/core": "^1.3.64", + "@swc/core": "^1.3.66", "@swc/jest": "^0.2.26", "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "~12.1.5", @@ -30,10 +30,10 @@ "@types/react": "~17.0.62", "@types/react-dom": "~17.0.20", "@types/testing-library__jest-dom": "~5.14.6", - "@typescript-eslint/eslint-plugin": "~5.58.0", - "@typescript-eslint/parser": "~5.58.0", + "@typescript-eslint/eslint-plugin": "~5.60.0", + "@typescript-eslint/parser": "~5.60.0", "babel-loader": "^8.3.0", - "eslint": "~8.38.0", + "eslint": "~8.43.0", "eslint-plugin-anti-trojan-source": "~1.1.1", "eslint-plugin-react": "~7.32.2", "eslint-plugin-react-hooks": "~4.6.0", @@ -46,7 +46,7 @@ "react-docgen-typescript-plugin": "~1.0.5", "react-dom": "~17.0.2", "ts-jest": "~29.0.5", - "typescript": "~5.0.4" + "typescript": "~5.1.3" }, "scripts": { "lint": "eslint --ext .js,.jsx,.ts,.tsx .", diff --git a/packages/i18n/package.json b/packages/i18n/package.json index 0d043009d4840..bc913f9e10b16 100644 --- a/packages/i18n/package.json +++ b/packages/i18n/package.json @@ -10,11 +10,11 @@ "@types/babel__preset-env": "~7.9.2", "@types/jest": "^29.5.2", "babel-jest": "^29.5.0", - "eslint": "^8.12.0", + "eslint": "^8.43.0", "jest": "^29.5.0", "ts-jest": "~29.0.5", "tsup": "^6.7.0", - "typescript": "~5.0.4" + "typescript": "~5.1.3" }, "scripts": { "build": "node ./src/index.mjs", diff --git a/packages/instance-status/package.json b/packages/instance-status/package.json index 7d3c3cb2c4dbd..36f510de08486 100644 --- a/packages/instance-status/package.json +++ b/packages/instance-status/package.json @@ -4,10 +4,10 @@ "private": true, "devDependencies": { "@rocket.chat/eslint-config": "workspace:^", - "eslint": "~8.38.0", + "eslint": "~8.43.0", "mongodb": "^4.12.1", "prettier": "~2.8.8", - "typescript": "~5.0.4" + "typescript": "~5.1.3" }, "scripts": { "lint": "eslint --ext .js,.jsx,.ts,.tsx .", diff --git a/packages/livechat/package.json b/packages/livechat/package.json index 5e455bfff06b3..26940f22c846d 100644 --- a/packages/livechat/package.json +++ b/packages/livechat/package.json @@ -38,8 +38,8 @@ "@storybook/addon-viewport": "~6.5.16", "@storybook/react": "~6.5.16", "@storybook/theming": "~6.5.16", - "@typescript-eslint/eslint-plugin": "~5.58.0", - "@typescript-eslint/parser": "~5.58.0", + "@typescript-eslint/eslint-plugin": "~5.60.0", + "@typescript-eslint/parser": "~5.60.0", "autoprefixer": "^9.8.8", "babel-loader": "^8.3.0", "babel-plugin-jsx-pragmatic": "^1.0.2", @@ -47,7 +47,7 @@ "css-loader": "^4.3.0", "cssnano": "^4.1.11", "desvg-loader": "^0.1.0", - "eslint": "~8.38.0", + "eslint": "~8.43.0", "eslint-plugin-import": "~2.26.0", "eslint-plugin-react": "~7.32.2", "eslint-plugin-react-hooks": "~4.6.0", @@ -77,7 +77,7 @@ "stylelint": "^14.9.1", "stylelint-order": "^5.0.0", "svg-loader": "^0.0.2", - "typescript": "~5.0.4", + "typescript": "~5.1.3", "url-loader": "^4.1.1", "webpack": "~4.46.0", "webpack-cli": "~4.10.0", diff --git a/packages/log-format/package.json b/packages/log-format/package.json index ca6fe87034bdb..497a3913a8f97 100644 --- a/packages/log-format/package.json +++ b/packages/log-format/package.json @@ -6,10 +6,10 @@ "@types/chalk": "^2.2.0", "@types/ejson": "^2.2.0", "@types/jest": "^27.4.1", - "eslint": "^8.12.0", + "eslint": "^8.43.0", "jest": "~29.5.0", "ts-jest": "~29.0.5", - "typescript": "~5.0.4" + "typescript": "~5.1.3" }, "scripts": { "lint": "eslint --ext .js,.jsx,.ts,.tsx .", diff --git a/packages/model-typings/package.json b/packages/model-typings/package.json index 15a2f261a5a98..6dfeec5aadc04 100644 --- a/packages/model-typings/package.json +++ b/packages/model-typings/package.json @@ -5,11 +5,11 @@ "devDependencies": { "@types/jest": "~29.5.2", "@types/node-rsa": "^1.1.1", - "eslint": "~8.38.0", + "eslint": "~8.43.0", "jest": "~29.5.0", "mongodb": "^4.12.1", "ts-jest": "~29.0.5", - "typescript": "~5.0.4" + "typescript": "~5.1.3" }, "scripts": { "lint": "eslint --ext .js,.jsx,.ts,.tsx .", diff --git a/packages/models/package.json b/packages/models/package.json index bd912cc82443a..289613aca9c86 100644 --- a/packages/models/package.json +++ b/packages/models/package.json @@ -4,10 +4,10 @@ "private": true, "devDependencies": { "@types/jest": "~29.5.2", - "eslint": "~8.38.0", + "eslint": "~8.43.0", "jest": "~29.5.0", "ts-jest": "~29.0.5", - "typescript": "~5.0.4" + "typescript": "~5.1.3" }, "dependencies": { "@rocket.chat/model-typings": "workspace:^" diff --git a/packages/node-poplib/package.json b/packages/node-poplib/package.json index bbdb3cf5cffa8..0d51c8c9f1a02 100644 --- a/packages/node-poplib/package.json +++ b/packages/node-poplib/package.json @@ -4,10 +4,10 @@ "private": true, "devDependencies": { "@types/jest": "~29.5.2", - "eslint": "~8.38.0", + "eslint": "~8.43.0", "jest": "~29.5.0", "ts-jest": "~29.0.5", - "typescript": "~5.0.4" + "typescript": "~5.1.3" }, "scripts": { "test": "jest" diff --git a/packages/random/package.json b/packages/random/package.json index 075c034832d0b..f436db859d997 100644 --- a/packages/random/package.json +++ b/packages/random/package.json @@ -17,13 +17,13 @@ "@babel/core": "~7.22.5", "@babel/preset-env": "~7.22.5", "@rocket.chat/eslint-config": "workspace:^", - "@typescript-eslint/eslint-plugin": "~5.58.0", - "@typescript-eslint/parser": "~5.58.0", - "eslint": "~8.38.0", + "@typescript-eslint/eslint-plugin": "~5.60.0", + "@typescript-eslint/parser": "~5.60.0", + "eslint": "~8.43.0", "jest": "~29.5.0", "jest-environment-jsdom": "~29.5.0", "ts-jest": "~29.0.5", - "typescript": "~5.0.4" + "typescript": "~5.1.3" }, "volta": { "extends": "../../package.json" diff --git a/packages/release-action/package.json b/packages/release-action/package.json index 0e90c3b5120d9..2ad3bf8887302 100644 --- a/packages/release-action/package.json +++ b/packages/release-action/package.json @@ -20,7 +20,7 @@ "@actions/github": "^5.1.1", "@octokit/plugin-throttling": "^6.0.0", "@rocket.chat/eslint-config": "workspace:^", - "eslint": "^8.42.0", + "eslint": "^8.43.0", "mdast-util-to-string": "2.0.0", "remark-parse": "9.0.0", "remark-stringify": "9.0.1", diff --git a/packages/rest-typings/package.json b/packages/rest-typings/package.json index 89090dde43616..98cfd1bf67f67 100644 --- a/packages/rest-typings/package.json +++ b/packages/rest-typings/package.json @@ -5,12 +5,12 @@ "devDependencies": { "@rocket.chat/eslint-config": "workspace:^", "@types/jest": "~29.5.2", - "eslint": "~8.38.0", + "eslint": "~8.43.0", "jest": "~29.5.0", "jest-environment-jsdom": "~29.5.0", "mongodb": "^4.12.1", "ts-jest": "~29.0.5", - "typescript": "~5.0.4" + "typescript": "~5.1.3" }, "scripts": { "lint": "eslint --ext .js,.jsx,.ts,.tsx .", diff --git a/packages/server-fetch/package.json b/packages/server-fetch/package.json index 75d692ea1cb84..35c1a5a0747fe 100644 --- a/packages/server-fetch/package.json +++ b/packages/server-fetch/package.json @@ -4,10 +4,10 @@ "private": true, "devDependencies": { "@types/jest": "^27.4.1", - "eslint": "^8.12.0", + "eslint": "^8.43.0", "jest": "~29.5.0", "ts-jest": "~29.0.5", - "typescript": "~5.0.4" + "typescript": "~5.1.3" }, "scripts": { "lint": "eslint --ext .js,.jsx,.ts,.tsx .", diff --git a/packages/sha256/package.json b/packages/sha256/package.json index 1d951da3a9acc..b57662c664c3a 100644 --- a/packages/sha256/package.json +++ b/packages/sha256/package.json @@ -16,12 +16,12 @@ "@babel/core": "~7.22.5", "@babel/preset-env": "~7.22.5", "@rocket.chat/eslint-config": "workspace:^", - "@typescript-eslint/eslint-plugin": "~5.58.0", - "@typescript-eslint/parser": "~5.58.0", - "eslint": "~8.38.0", + "@typescript-eslint/eslint-plugin": "~5.60.0", + "@typescript-eslint/parser": "~5.60.0", + "eslint": "~8.43.0", "jest": "~29.5.0", "ts-jest": "~29.0.5", - "typescript": "~5.0.4" + "typescript": "~5.1.3" }, "volta": { "extends": "../../package.json" diff --git a/packages/tools/package.json b/packages/tools/package.json index 43b884c75e17b..833a627023ef2 100644 --- a/packages/tools/package.json +++ b/packages/tools/package.json @@ -4,10 +4,10 @@ "private": true, "devDependencies": { "@types/jest": "~29.5.2", - "eslint": "~8.38.0", + "eslint": "~8.43.0", "jest": "~29.5.0", "ts-jest": "~29.0.5", - "typescript": "~5.0.4" + "typescript": "~5.1.3" }, "scripts": { "lint": "eslint --ext .js,.jsx,.ts,.tsx .", diff --git a/packages/ui-client/package.json b/packages/ui-client/package.json index d9e5a7a6a827a..e1c6be800205a 100644 --- a/packages/ui-client/package.json +++ b/packages/ui-client/package.json @@ -23,16 +23,16 @@ "@types/jest": "~29.5.2", "@types/react": "~17.0.62", "@types/react-dom": "~17.0.20", - "eslint": "~8.38.0", + "eslint": "~8.43.0", "eslint-plugin-anti-trojan-source": "~1.1.1", "eslint-plugin-react": "~7.32.2", "eslint-plugin-react-hooks": "~4.6.0", "eslint-plugin-storybook": "~0.6.12", - "eslint-plugin-testing-library": "~5.10.3", + "eslint-plugin-testing-library": "~5.11.0", "jest": "~29.5.0", "react": "~17.0.2", "ts-jest": "~29.0.5", - "typescript": "~5.0.4" + "typescript": "~5.1.3" }, "scripts": { "lint": "eslint --ext .js,.jsx,.ts,.tsx .", diff --git a/packages/ui-composer/package.json b/packages/ui-composer/package.json index 56ab8c4c4a1ae..74790595a41c8 100644 --- a/packages/ui-composer/package.json +++ b/packages/ui-composer/package.json @@ -16,14 +16,14 @@ "@storybook/testing-library": "~0.0.13", "@types/babel__core": "~7.20.1", "@types/jest": "~29.5.2", - "eslint": "~8.38.0", + "eslint": "~8.43.0", "eslint-plugin-react": "~7.32.2", "eslint-plugin-react-hooks": "~4.6.0", "eslint-plugin-storybook": "~0.6.12", "jest": "~29.5.0", "react-docgen-typescript-plugin": "~1.0.5", "ts-jest": "~29.0.5", - "typescript": "~5.0.4" + "typescript": "~5.1.3" }, "peerDependencies": { "@rocket.chat/fuselage": "*", diff --git a/packages/ui-contexts/package.json b/packages/ui-contexts/package.json index 03d86a8e027d0..ab5c03750ab45 100644 --- a/packages/ui-contexts/package.json +++ b/packages/ui-contexts/package.json @@ -11,12 +11,12 @@ "@types/react": "~17.0.62", "@types/react-dom": "~17.0.20", "@types/use-sync-external-store": "^0.0.3", - "eslint": "~8.38.0", + "eslint": "~8.43.0", "jest": "~29.5.0", "mongodb": "^4.12.1", "react": "~17.0.2", "ts-jest": "~29.0.5", - "typescript": "~5.0.4", + "typescript": "~5.1.3", "use-sync-external-store": "^1.2.0" }, "peerDependencies": { diff --git a/packages/ui-video-conf/package.json b/packages/ui-video-conf/package.json index 762208a695e3c..0df5acf7d2692 100644 --- a/packages/ui-video-conf/package.json +++ b/packages/ui-video-conf/package.json @@ -20,14 +20,14 @@ "@storybook/testing-library": "~0.0.13", "@types/babel__core": "~7.20.1", "@types/jest": "~29.5.2", - "eslint": "~8.38.0", + "eslint": "~8.43.0", "eslint-plugin-react": "~7.32.2", "eslint-plugin-react-hooks": "~4.6.0", "eslint-plugin-storybook": "~0.6.12", "jest": "~29.5.0", "react-docgen-typescript-plugin": "~1.0.5", "ts-jest": "~29.0.5", - "typescript": "~5.0.4" + "typescript": "~5.1.3" }, "peerDependencies": { "@rocket.chat/css-in-js": "*", diff --git a/packages/uikit-playground/package.json b/packages/uikit-playground/package.json index 06f4114ad9afc..a309352c04f44 100644 --- a/packages/uikit-playground/package.json +++ b/packages/uikit-playground/package.json @@ -39,13 +39,13 @@ "@types/react-beautiful-dnd": "^13.1.4", "@types/react-dom": "^17.0.20", "@types/use-subscription": "^1.0.0", - "@typescript-eslint/eslint-plugin": "^5.57.1", - "@typescript-eslint/parser": "^5.57.1", + "@typescript-eslint/eslint-plugin": "~5.60.0", + "@typescript-eslint/parser": "~5.60.0", "@vitejs/plugin-react": "^4.0.0", - "eslint": "^8.38.0", + "eslint": "^8.43.0", "eslint-plugin-react-hooks": "^4.6.0", - "eslint-plugin-react-refresh": "^0.3.5", - "typescript": "^5.0.2", + "eslint-plugin-react-refresh": "^0.4.1", + "typescript": "^5.1.3", "vite": "^4.3.9" }, "volta": { diff --git a/packages/web-ui-registration/package.json b/packages/web-ui-registration/package.json index fdd007d1cacb4..2eadd13319c33 100644 --- a/packages/web-ui-registration/package.json +++ b/packages/web-ui-registration/package.json @@ -9,11 +9,11 @@ "@tanstack/react-query": "^4.16.1", "@testing-library/react": "^13.3.0", "@types/jest": "~29.5.2", - "eslint": "~8.38.0", + "eslint": "~8.43.0", "jest": "~29.5.0", "react-hook-form": "^7.34.2", "ts-jest": "~29.0.5", - "typescript": "~5.0.4" + "typescript": "~5.1.3" }, "peerDependencies": { "@rocket.chat/layout": "*", diff --git a/yarn.lock b/yarn.lock index 2f88c99b10e65..1b84a773319d1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1089,7 +1089,7 @@ __metadata: languageName: node linkType: hard -"@babel/eslint-parser@npm:^7.19.1, @babel/eslint-parser@npm:~7.22.5": +"@babel/eslint-parser@npm:^7.22.5, @babel/eslint-parser@npm:~7.22.5": version: 7.22.5 resolution: "@babel/eslint-parser@npm:7.22.5" dependencies: @@ -5054,23 +5054,6 @@ __metadata: languageName: node linkType: hard -"@eslint/eslintrc@npm:^2.0.2": - version: 2.0.2 - resolution: "@eslint/eslintrc@npm:2.0.2" - dependencies: - ajv: ^6.12.4 - debug: ^4.3.2 - espree: ^9.5.1 - globals: ^13.19.0 - ignore: ^5.2.0 - import-fresh: ^3.2.1 - js-yaml: ^4.1.0 - minimatch: ^3.1.2 - strip-json-comments: ^3.1.1 - checksum: cfcf5e12c7b2c4476482e7f12434e76eae16fcd163ee627309adb10b761e5caa4a4e52ed7be464423320ff3d11eca5b50de5bf8be3e25834222470835dd5c801 - languageName: node - linkType: hard - "@eslint/eslintrc@npm:^2.0.3": version: 2.0.3 resolution: "@eslint/eslintrc@npm:2.0.3" @@ -5088,27 +5071,6 @@ __metadata: languageName: node linkType: hard -"@eslint/js@npm:8.38.0": - version: 8.38.0 - resolution: "@eslint/js@npm:8.38.0" - checksum: 1f28987aa8c9cd93e23384e16c7220863b39b5dc4b66e46d7cdbccce868040f455a98d24cd8b567a884f26545a0555b761f7328d4a00c051e7ef689cbea5fce1 - languageName: node - linkType: hard - -"@eslint/js@npm:8.41.0": - version: 8.41.0 - resolution: "@eslint/js@npm:8.41.0" - checksum: af013d70fe8d0429cdf5cd8b5dcc6fc384ed026c1eccb0cfe30f5849b968ab91645111373fd1b83282b38955b1bdfbe667c1a7dbda3b06cae753521223cad775 - languageName: node - linkType: hard - -"@eslint/js@npm:8.42.0": - version: 8.42.0 - resolution: "@eslint/js@npm:8.42.0" - checksum: 750558843ac458f7da666122083ee05306fc087ecc1e5b21e7e14e23885775af6c55bcc92283dff1862b7b0d8863ec676c0f18c7faf1219c722fe91a8ece56b6 - languageName: node - linkType: hard - "@eslint/js@npm:8.43.0": version: 8.43.0 resolution: "@eslint/js@npm:8.43.0" @@ -5239,17 +5201,6 @@ __metadata: languageName: node linkType: hard -"@humanwhocodes/config-array@npm:^0.11.8": - version: 0.11.8 - resolution: "@humanwhocodes/config-array@npm:0.11.8" - dependencies: - "@humanwhocodes/object-schema": ^1.2.1 - debug: ^4.1.1 - minimatch: ^3.0.5 - checksum: 0fd6b3c54f1674ce0a224df09b9c2f9846d20b9e54fabae1281ecfc04f2e6ad69bf19e1d6af6a28f88e8aa3990168b6cb9e1ef755868c3256a630605ec2cb1d3 - languageName: node - linkType: hard - "@humanwhocodes/config-array@npm:^0.5.0": version: 0.5.0 resolution: "@humanwhocodes/config-array@npm:0.5.0" @@ -9245,12 +9196,12 @@ __metadata: "@rocket.chat/rest-typings": "workspace:^" "@rocket.chat/string-helpers": next "@types/bcrypt": ^5.0.0 - "@types/eslint": ~8.37.0 + "@types/eslint": ~8.40.2 "@types/node": ^14.18.51 "@types/polka": ^0.5.4 bcrypt: ^5.0.1 ejson: ^2.2.3 - eslint: ~8.38.0 + eslint: ~8.43.0 eventemitter3: ^4.0.7 fibers: ^5.0.3 mem: ^8.1.1 @@ -9260,7 +9211,7 @@ __metadata: pino: ^8.4.2 polka: ^0.5.2 ts-node: ^10.9.1 - typescript: ~5.0.4 + typescript: ~5.1.3 uuid: ^9.0.0 languageName: unknown linkType: soft @@ -9270,10 +9221,10 @@ __metadata: resolution: "@rocket.chat/account-utils@workspace:packages/account-utils" dependencies: "@types/jest": ~29.5.2 - eslint: ~8.38.0 + eslint: ~8.43.0 jest: ~29.5.0 ts-jest: ~29.0.5 - typescript: ~5.0.4 + typescript: ~5.1.3 languageName: unknown linkType: soft @@ -9286,13 +9237,13 @@ __metadata: cron: ~1.8.2 date.js: ~0.3.3 debug: ~4.1.1 - eslint: ~8.38.0 + eslint: ~8.43.0 human-interval: ^2.0.1 jest: ~29.5.0 moment-timezone: ~0.5.43 mongodb: ^4.12.1 ts-jest: ~29.0.5 - typescript: ~5.0.4 + typescript: ~5.1.3 languageName: unknown linkType: soft @@ -9302,11 +9253,11 @@ __metadata: dependencies: "@rocket.chat/core-typings": "workspace:^" "@rocket.chat/rest-typings": "workspace:^" - "@swc/core": ^1.3.64 + "@swc/core": ^1.3.66 "@swc/jest": ^0.2.26 "@types/jest": ~29.5.2 "@types/strict-uri-encode": ^2.0.0 - eslint: ~8.38.0 + eslint: ~8.43.0 filter-obj: ^3.0.0 jest: ~29.5.0 jest-fetch-mock: ^3.0.3 @@ -9314,7 +9265,7 @@ __metadata: split-on-first: ^3.0.0 strict-uri-encode: ^2.0.0 ts-jest: ~29.0.5 - typescript: ~5.0.4 + typescript: ~5.1.3 languageName: unknown linkType: soft @@ -9366,11 +9317,11 @@ __metadata: "@rocket.chat/models": "workspace:^" "@rocket.chat/rest-typings": "workspace:^" "@rocket.chat/string-helpers": next - "@types/eslint": ~8.37.0 + "@types/eslint": ~8.40.2 "@types/node": ^14.18.51 "@types/polka": ^0.5.4 ejson: ^2.2.3 - eslint: ~8.38.0 + eslint: ~8.43.0 eventemitter3: ^4.0.7 fibers: ^5.0.3 mem: ^8.1.1 @@ -9380,7 +9331,7 @@ __metadata: pino: ^8.4.2 polka: ^0.5.2 ts-node: ^10.9.1 - typescript: ~5.0.4 + typescript: ~5.1.3 languageName: unknown linkType: soft @@ -9391,12 +9342,12 @@ __metadata: "@babel/core": ~7.22.5 "@babel/preset-env": ~7.22.5 "@rocket.chat/eslint-config": "workspace:^" - "@typescript-eslint/eslint-plugin": ~5.58.0 - "@typescript-eslint/parser": ~5.58.0 - eslint: ~8.38.0 + "@typescript-eslint/eslint-plugin": ~5.60.0 + "@typescript-eslint/parser": ~5.60.0 + eslint: ~8.43.0 jest: ~29.5.0 ts-jest: ~29.0.5 - typescript: ~5.0.4 + typescript: ~5.1.3 languageName: unknown linkType: soft @@ -9406,10 +9357,10 @@ __metadata: dependencies: "@types/jest": ~29.5.2 cheerio: 1.0.0-rc.10 - eslint: ~8.38.0 + eslint: ~8.43.0 jest: ~29.5.0 ts-jest: ~29.0.5 - typescript: ~5.0.4 + typescript: ~5.1.3 languageName: unknown linkType: soft @@ -9426,11 +9377,11 @@ __metadata: "@rocket.chat/rest-typings": "workspace:^" "@rocket.chat/ui-kit": next "@types/fibers": ^3.1.1 - eslint: ~8.38.0 + eslint: ~8.43.0 fibers: ^5.0.3 mongodb: ^4.12.1 prettier: ~2.8.8 - typescript: ~5.0.4 + typescript: ~5.1.3 languageName: unknown linkType: soft @@ -9443,10 +9394,10 @@ __metadata: "@rocket.chat/icons": next "@rocket.chat/message-parser": next "@rocket.chat/ui-kit": next - eslint: ~8.38.0 + eslint: ~8.43.0 mongodb: ^4.12.1 prettier: ~2.8.8 - typescript: ~5.0.4 + typescript: ~5.1.3 languageName: unknown linkType: soft @@ -9459,11 +9410,11 @@ __metadata: "@rocket.chat/models": "workspace:^" "@rocket.chat/random": "workspace:^" "@types/jest": ^27.4.1 - eslint: ^8.12.0 + eslint: ^8.43.0 jest: ~29.5.0 mongodb: ^4.12.1 ts-jest: ~29.0.5 - typescript: ~5.0.4 + typescript: ~5.1.3 languageName: unknown linkType: soft @@ -9509,15 +9460,15 @@ __metadata: "@rocket.chat/api-client": "workspace:^" "@rocket.chat/rest-typings": "workspace:^" "@rocket.chat/ui-contexts": "workspace:^" - "@swc/core": ^1.3.64 + "@swc/core": ^1.3.66 "@swc/jest": ^0.2.26 "@types/jest": ^29.5.2 "@types/ws": ^8.5.5 - eslint: ^8.12.0 + eslint: ^8.43.0 jest: ^29.5.0 jest-environment-jsdom: ~29.5.0 jest-websocket-mock: ^2.4.0 - typescript: ~5.0.4 + typescript: ~5.1.3 ws: ^8.13.0 peerDependencies: "@rocket.chat/emitter": "*" @@ -9540,7 +9491,7 @@ __metadata: "@rocket.chat/string-helpers": next "@rocket.chat/ui-contexts": "workspace:^" "@types/ejson": ^2.2.0 - "@types/eslint": ~8.37.0 + "@types/eslint": ~8.40.2 "@types/meteor": ^2.9.2 "@types/node": ^14.18.51 "@types/polka": ^0.5.4 @@ -9549,7 +9500,7 @@ __metadata: "@types/ws": ^8.5.5 colorette: ^1.4.0 ejson: ^2.2.3 - eslint: ~8.38.0 + eslint: ~8.43.0 eventemitter3: ^4.0.7 fibers: ^5.0.3 jaeger-client: ^3.19.0 @@ -9562,7 +9513,7 @@ __metadata: polka: ^0.5.2 sharp: ^0.30.7 ts-node: ^10.9.1 - typescript: ~5.0.4 + typescript: ~5.1.3 underscore: ^1.13.6 uuid: ^7.0.3 ws: ^8.8.1 @@ -9582,13 +9533,13 @@ __metadata: dependencies: "@babel/eslint-parser": ~7.22.5 "@types/prettier": ^2.6.3 - "@typescript-eslint/eslint-plugin": ~5.58.0 - "@typescript-eslint/parser": ~5.58.0 - eslint: ~8.38.0 + "@typescript-eslint/eslint-plugin": ~5.60.0 + "@typescript-eslint/parser": ~5.60.0 + eslint: ~8.43.0 eslint-config-prettier: ~8.8.0 eslint-plugin-anti-trojan-source: ~1.1.1 eslint-plugin-import: ~2.26.0 - eslint-plugin-jest: ~27.2.1 + eslint-plugin-jest: ~27.2.2 eslint-plugin-prettier: ~4.2.1 prettier: ~2.8.8 languageName: unknown @@ -9598,8 +9549,8 @@ __metadata: version: 0.0.0-use.local resolution: "@rocket.chat/favicon@workspace:packages/favicon" dependencies: - eslint: ~8.38.0 - typescript: ~5.0.4 + eslint: ~8.43.0 + typescript: ~5.1.3 languageName: unknown linkType: soft @@ -9757,7 +9708,7 @@ __metadata: "@types/react-dom": ~17.0.20 babel-loader: ~8.2.5 cross-env: ^7.0.3 - eslint: ~8.38.0 + eslint: ~8.43.0 normalize.css: ^8.0.1 npm-run-all: ^4.1.5 prettier: ~2.8.8 @@ -9765,7 +9716,7 @@ __metadata: react-dom: ^17.0.2 rimraf: ^3.0.2 tslib: ^2.5.3 - typescript: ~5.0.4 + typescript: ~5.1.3 peerDependencies: "@rocket.chat/apps-engine": "*" "@rocket.chat/eslint-config": "*" @@ -9830,7 +9781,7 @@ __metadata: "@storybook/manager-webpack4": ~6.5.16 "@storybook/react": ~6.5.16 "@storybook/testing-library": ~0.0.13 - "@swc/core": ^1.3.64 + "@swc/core": ^1.3.66 "@swc/jest": ^0.2.26 "@testing-library/jest-dom": ^5.16.5 "@testing-library/react": ~12.1.5 @@ -9839,10 +9790,10 @@ __metadata: "@types/react": ~17.0.62 "@types/react-dom": ~17.0.20 "@types/testing-library__jest-dom": ~5.14.6 - "@typescript-eslint/eslint-plugin": ~5.58.0 - "@typescript-eslint/parser": ~5.58.0 + "@typescript-eslint/eslint-plugin": ~5.60.0 + "@typescript-eslint/parser": ~5.60.0 babel-loader: ^8.3.0 - eslint: ~8.38.0 + eslint: ~8.43.0 eslint-plugin-anti-trojan-source: ~1.1.1 eslint-plugin-react: ~7.32.2 eslint-plugin-react-hooks: ~4.6.0 @@ -9857,7 +9808,7 @@ __metadata: react-dom: ~17.0.2 react-error-boundary: ^3.1.4 ts-jest: ~29.0.5 - typescript: ~5.0.4 + typescript: ~5.1.3 peerDependencies: "@rocket.chat/core-typings": "*" "@rocket.chat/css-in-js": "*" @@ -9883,11 +9834,11 @@ __metadata: "@types/babel__preset-env": ~7.9.2 "@types/jest": ^29.5.2 babel-jest: ^29.5.0 - eslint: ^8.12.0 + eslint: ^8.43.0 jest: ^29.5.0 ts-jest: ~29.0.5 tsup: ^6.7.0 - typescript: ~5.0.4 + typescript: ~5.1.3 languageName: unknown linkType: soft @@ -9904,10 +9855,10 @@ __metadata: dependencies: "@rocket.chat/eslint-config": "workspace:^" "@rocket.chat/models": "workspace:^" - eslint: ~8.38.0 + eslint: ~8.43.0 mongodb: ^4.12.1 prettier: ~2.8.8 - typescript: ~5.0.4 + typescript: ~5.1.3 languageName: unknown linkType: soft @@ -9943,8 +9894,8 @@ __metadata: "@storybook/addon-viewport": ~6.5.16 "@storybook/react": ~6.5.16 "@storybook/theming": ~6.5.16 - "@typescript-eslint/eslint-plugin": ~5.58.0 - "@typescript-eslint/parser": ~5.58.0 + "@typescript-eslint/eslint-plugin": ~5.60.0 + "@typescript-eslint/parser": ~5.60.0 autoprefixer: ^9.8.8 babel-loader: ^8.3.0 babel-plugin-jsx-pragmatic: ^1.0.2 @@ -9956,7 +9907,7 @@ __metadata: date-fns: ^2.15.0 desvg-loader: ^0.1.0 emoji-mart: ^3.0.1 - eslint: ~8.38.0 + eslint: ~8.43.0 eslint-plugin-import: ~2.26.0 eslint-plugin-react: ~7.32.2 eslint-plugin-react-hooks: ~4.6.0 @@ -9995,7 +9946,7 @@ __metadata: stylelint: ^14.9.1 stylelint-order: ^5.0.0 svg-loader: ^0.0.2 - typescript: ~5.0.4 + typescript: ~5.1.3 url-loader: ^4.1.1 webpack: ~4.46.0 webpack-cli: ~4.10.0 @@ -10016,10 +9967,10 @@ __metadata: "@types/jest": ^27.4.1 chalk: ^4.0.0 ejson: ^2.2.3 - eslint: ^8.12.0 + eslint: ^8.43.0 jest: ~29.5.0 ts-jest: ~29.0.5 - typescript: ~5.0.4 + typescript: ~5.1.3 languageName: unknown linkType: soft @@ -10064,7 +10015,7 @@ __metadata: resolution: "@rocket.chat/meteor@workspace:apps/meteor" dependencies: "@babel/core": ^7.20.5 - "@babel/eslint-parser": ^7.19.1 + "@babel/eslint-parser": ^7.22.5 "@babel/plugin-proposal-nullish-coalescing-operator": ^7.18.6 "@babel/plugin-proposal-optional-chaining": ^7.18.9 "@babel/preset-env": ^7.20.2 @@ -10144,7 +10095,7 @@ __metadata: "@storybook/addons": ~6.5.16 "@storybook/react": ~6.5.16 "@storybook/testing-library": 0.0.13 - "@swc/core": ^1.3.64 + "@swc/core": ^1.3.66 "@tanstack/react-query": ^4.16.1 "@tanstack/react-query-devtools": ^4.19.1 "@testing-library/react": ~12.1.5 @@ -10223,8 +10174,8 @@ __metadata: "@types/uuid": ^8.3.4 "@types/xml-crypto": ~1.4.2 "@types/xml-encryption": ~1.2.1 - "@typescript-eslint/eslint-plugin": ~5.58.0 - "@typescript-eslint/parser": ~5.58.0 + "@typescript-eslint/eslint-plugin": ~5.60.0 + "@typescript-eslint/parser": ~5.60.0 "@xmldom/xmldom": ^0.8.8 adm-zip: 0.5.10 ajv: ^8.11.0 @@ -10274,16 +10225,16 @@ __metadata: emoji-toolkit: ^7.0.1 emojione: ^4.5.0 emojione-assets: ^4.5.0 - eslint: ^8.29.0 + eslint: ~8.43.0 eslint-config-prettier: ~8.8.0 eslint-plugin-anti-trojan-source: ~1.1.1 eslint-plugin-import: ~2.26.0 eslint-plugin-no-floating-promise: ~1.0.2 - eslint-plugin-playwright: ~0.12.0 + eslint-plugin-playwright: ~0.15.0 eslint-plugin-prettier: ~4.2.1 eslint-plugin-react: ~7.32.2 eslint-plugin-react-hooks: ~4.6.0 - eslint-plugin-testing-library: ~5.10.3 + eslint-plugin-testing-library: ~5.11.0 eslint-plugin-you-dont-need-lodash-underscore: ~6.12.0 eventemitter3: ^4.0.7 exif-be-gone: ^1.3.2 @@ -10410,7 +10361,7 @@ __metadata: turndown: ^7.1.2 twilio: ^3.76.1 twit: ^2.2.11 - typescript: ~5.0.4 + typescript: ~5.1.3 ua-parser-js: ^1.0.35 underscore: ^1.13.6 universal-perf-hooks: ^1.0.1 @@ -10434,11 +10385,11 @@ __metadata: "@rocket.chat/core-typings": "workspace:^" "@types/jest": ~29.5.2 "@types/node-rsa": ^1.1.1 - eslint: ~8.38.0 + eslint: ~8.43.0 jest: ~29.5.0 mongodb: ^4.12.1 ts-jest: ~29.0.5 - typescript: ~5.0.4 + typescript: ~5.1.3 languageName: unknown linkType: soft @@ -10448,10 +10399,10 @@ __metadata: dependencies: "@rocket.chat/model-typings": "workspace:^" "@types/jest": ~29.5.2 - eslint: ~8.38.0 + eslint: ~8.43.0 jest: ~29.5.0 ts-jest: ~29.0.5 - typescript: ~5.0.4 + typescript: ~5.1.3 languageName: unknown linkType: soft @@ -10482,7 +10433,7 @@ __metadata: "@types/node": ^14.18.51 ejson: ^2.2.3 emoji-toolkit: ^7.0.1 - eslint: ~8.38.0 + eslint: ~8.43.0 eventemitter3: ^4.0.7 fibers: ^5.0.3 jest: ~29.5.0 @@ -10492,7 +10443,7 @@ __metadata: mongodb: ^4.12.1 pino: ^8.4.2 ts-jest: ~29.0.5 - typescript: ~5.0.4 + typescript: ~5.1.3 languageName: unknown linkType: soft @@ -10511,12 +10462,12 @@ __metadata: "@rocket.chat/pdf-worker": "workspace:^" "@rocket.chat/tools": "workspace:^" "@rocket.chat/ui-contexts": "workspace:^" - "@types/eslint": ~8.37.0 + "@types/eslint": ~8.40.2 "@types/node": ^14.18.51 "@types/polka": ^0.5.4 ejson: ^2.2.3 emoji-toolkit: ^7.0.1 - eslint: ~8.38.0 + eslint: ~8.43.0 eventemitter3: ^4.0.7 fibers: ^5.0.3 mem: ^8.1.1 @@ -10528,7 +10479,7 @@ __metadata: pino: ^8.4.2 polka: ^0.5.2 ts-node: ^10.9.1 - typescript: ~5.0.4 + typescript: ~5.1.3 languageName: unknown linkType: soft @@ -10571,7 +10522,7 @@ __metadata: "@types/testing-library__jest-dom": ~5.14.6 emoji-assets: ^7.0.1 emoji-toolkit: ^7.0.1 - eslint: ~8.38.0 + eslint: ~8.43.0 jest: ~29.5.0 jest-environment-jsdom: ~29.5.0 moment: ^2.29.4 @@ -10579,7 +10530,7 @@ __metadata: react: ^18.2.0 react-dom: ^18.2.0 ts-jest: ~29.0.5 - typescript: ~5.0.4 + typescript: ~5.1.3 languageName: unknown linkType: soft @@ -10588,10 +10539,10 @@ __metadata: resolution: "@rocket.chat/poplib@workspace:packages/node-poplib" dependencies: "@types/jest": ~29.5.2 - eslint: ~8.38.0 + eslint: ~8.43.0 jest: ~29.5.0 ts-jest: ~29.0.5 - typescript: ~5.0.4 + typescript: ~5.1.3 languageName: unknown linkType: soft @@ -10607,11 +10558,11 @@ __metadata: "@rocket.chat/models": "workspace:^" "@rocket.chat/presence": "workspace:^" "@rocket.chat/string-helpers": next - "@types/eslint": ~8.37.0 + "@types/eslint": ~8.40.2 "@types/node": ^14.18.51 "@types/polka": ^0.5.4 ejson: ^2.2.3 - eslint: ~8.38.0 + eslint: ~8.43.0 eventemitter3: ^4.0.7 fibers: ^5.0.3 mem: ^8.1.1 @@ -10621,7 +10572,7 @@ __metadata: pino: ^8.4.2 polka: ^0.5.2 ts-node: ^10.9.1 - typescript: ~5.0.4 + typescript: ~5.1.3 languageName: unknown linkType: soft @@ -10640,10 +10591,10 @@ __metadata: "@rocket.chat/rest-typings": "workspace:^" "@types/node": ^14.18.51 babel-jest: ^29.0.3 - eslint: ~8.38.0 + eslint: ~8.43.0 jest: ~29.5.0 mongodb: ^4.12.1 - typescript: ~5.0.4 + typescript: ~5.1.3 languageName: unknown linkType: soft @@ -10668,12 +10619,12 @@ __metadata: "@rocket.chat/model-typings": "workspace:^" "@rocket.chat/models": "workspace:^" "@rocket.chat/omnichannel-services": "workspace:^" - "@types/eslint": ~8.37.0 + "@types/eslint": ~8.40.2 "@types/node": ^14.18.51 "@types/polka": ^0.5.4 ejson: ^2.2.3 emoji-toolkit: ^7.0.1 - eslint: ~8.38.0 + eslint: ~8.43.0 eventemitter3: ^4.0.7 fibers: ^5.0.3 mem: ^8.1.1 @@ -10685,7 +10636,7 @@ __metadata: pino: ^8.4.2 polka: ^0.5.2 ts-node: ^10.9.1 - typescript: ~5.0.4 + typescript: ~5.1.3 languageName: unknown linkType: soft @@ -10696,13 +10647,13 @@ __metadata: "@babel/core": ~7.22.5 "@babel/preset-env": ~7.22.5 "@rocket.chat/eslint-config": "workspace:^" - "@typescript-eslint/eslint-plugin": ~5.58.0 - "@typescript-eslint/parser": ~5.58.0 - eslint: ~8.38.0 + "@typescript-eslint/eslint-plugin": ~5.60.0 + "@typescript-eslint/parser": ~5.60.0 + eslint: ~8.43.0 jest: ~29.5.0 jest-environment-jsdom: ~29.5.0 ts-jest: ~29.0.5 - typescript: ~5.0.4 + typescript: ~5.1.3 languageName: unknown linkType: soft @@ -10717,7 +10668,7 @@ __metadata: "@rocket.chat/eslint-config": "workspace:^" "@types/eslint": ^8.40.2 "@types/node": ^16.18.36 - eslint: ^8.42.0 + eslint: ^8.43.0 mdast-util-to-string: 2.0.0 remark-parse: 9.0.0 remark-stringify: 9.0.1 @@ -10739,12 +10690,12 @@ __metadata: "@types/jest": ~29.5.2 ajv: ^8.11.0 ajv-formats: ^2.1.1 - eslint: ~8.38.0 + eslint: ~8.43.0 jest: ~29.5.0 jest-environment-jsdom: ~29.5.0 mongodb: ^4.12.1 ts-jest: ~29.0.5 - typescript: ~5.0.4 + typescript: ~5.1.3 languageName: unknown linkType: soft @@ -10767,14 +10718,14 @@ __metadata: dependencies: "@types/jest": ^27.4.1 "@types/proxy-from-env": ^1.0.1 - eslint: ^8.12.0 + eslint: ^8.43.0 http-proxy-agent: ^5.0.0 https-proxy-agent: ^5.0.1 jest: ~29.5.0 node-fetch: 2.3.0 proxy-from-env: ^1.1.0 ts-jest: ~29.0.5 - typescript: ~5.0.4 + typescript: ~5.1.3 languageName: unknown linkType: soft @@ -10785,12 +10736,12 @@ __metadata: "@babel/core": ~7.22.5 "@babel/preset-env": ~7.22.5 "@rocket.chat/eslint-config": "workspace:^" - "@typescript-eslint/eslint-plugin": ~5.58.0 - "@typescript-eslint/parser": ~5.58.0 - eslint: ~8.38.0 + "@typescript-eslint/eslint-plugin": ~5.60.0 + "@typescript-eslint/parser": ~5.60.0 + eslint: ~8.43.0 jest: ~29.5.0 ts-jest: ~29.0.5 - typescript: ~5.0.4 + typescript: ~5.1.3 languageName: unknown linkType: soft @@ -10807,11 +10758,11 @@ __metadata: "@rocket.chat/rest-typings": "workspace:^" "@rocket.chat/string-helpers": next "@types/bcrypt": ^5.0.0 - "@types/eslint": ~8.37.0 + "@types/eslint": ~8.40.2 "@types/node": ^14.18.51 "@types/polka": ^0.5.4 ejson: ^2.2.3 - eslint: ~8.38.0 + eslint: ~8.43.0 eventemitter3: ^4.0.7 fibers: ^5.0.3 mem: ^8.1.1 @@ -10821,7 +10772,7 @@ __metadata: pino: ^8.4.2 polka: ^0.5.2 ts-node: ^10.9.1 - typescript: ~5.0.4 + typescript: ~5.1.3 languageName: unknown linkType: soft @@ -10866,11 +10817,11 @@ __metadata: resolution: "@rocket.chat/tools@workspace:packages/tools" dependencies: "@types/jest": ~29.5.2 - eslint: ~8.38.0 + eslint: ~8.43.0 jest: ~29.5.0 moment-timezone: ^0.5.43 ts-jest: ~29.0.5 - typescript: ~5.0.4 + typescript: ~5.1.3 languageName: unknown linkType: soft @@ -10898,16 +10849,16 @@ __metadata: "@types/jest": ~29.5.2 "@types/react": ~17.0.62 "@types/react-dom": ~17.0.20 - eslint: ~8.38.0 + eslint: ~8.43.0 eslint-plugin-anti-trojan-source: ~1.1.1 eslint-plugin-react: ~7.32.2 eslint-plugin-react-hooks: ~4.6.0 eslint-plugin-storybook: ~0.6.12 - eslint-plugin-testing-library: ~5.10.3 + eslint-plugin-testing-library: ~5.11.0 jest: ~29.5.0 react: ~17.0.2 ts-jest: ~29.0.5 - typescript: ~5.0.4 + typescript: ~5.1.3 peerDependencies: "@rocket.chat/css-in-js": "*" "@rocket.chat/fuselage": "*" @@ -10935,14 +10886,14 @@ __metadata: "@storybook/testing-library": ~0.0.13 "@types/babel__core": ~7.20.1 "@types/jest": ~29.5.2 - eslint: ~8.38.0 + eslint: ~8.43.0 eslint-plugin-react: ~7.32.2 eslint-plugin-react-hooks: ~4.6.0 eslint-plugin-storybook: ~0.6.12 jest: ~29.5.0 react-docgen-typescript-plugin: ~1.0.5 ts-jest: ~29.0.5 - typescript: ~5.0.4 + typescript: ~5.1.3 peerDependencies: "@rocket.chat/fuselage": "*" "@rocket.chat/icons": "*" @@ -10963,12 +10914,12 @@ __metadata: "@types/react": ~17.0.62 "@types/react-dom": ~17.0.20 "@types/use-sync-external-store": ^0.0.3 - eslint: ~8.38.0 + eslint: ~8.43.0 jest: ~29.5.0 mongodb: ^4.12.1 react: ~17.0.2 ts-jest: ~29.0.5 - typescript: ~5.0.4 + typescript: ~5.1.3 use-sync-external-store: ^1.2.0 peerDependencies: "@rocket.chat/core-typings": "workspace:^" @@ -11008,16 +10959,16 @@ __metadata: "@storybook/testing-library": ~0.0.13 "@types/jest": ~29.5.2 "@types/react": ~17.0.62 - eslint: ~8.38.0 + eslint: ~8.43.0 eslint-plugin-anti-trojan-source: ~1.1.1 eslint-plugin-react: ~7.32.2 eslint-plugin-react-hooks: ~4.6.0 - eslint-plugin-testing-library: ^5.9.1 + eslint-plugin-testing-library: ^5.11.0 jest: ~29.5.0 react: ~17.0.2 react-docgen-typescript-plugin: ~1.0.5 ts-jest: ~29.0.5 - typescript: ~5.0.4 + typescript: ~5.1.3 peerDependencies: "@rocket.chat/css-in-js": "*" "@rocket.chat/fuselage": "*" @@ -11049,14 +11000,14 @@ __metadata: "@storybook/testing-library": ~0.0.13 "@types/babel__core": ~7.20.1 "@types/jest": ~29.5.2 - eslint: ~8.38.0 + eslint: ~8.43.0 eslint-plugin-react: ~7.32.2 eslint-plugin-react-hooks: ~4.6.0 eslint-plugin-storybook: ~0.6.12 jest: ~29.5.0 react-docgen-typescript-plugin: ~1.0.5 ts-jest: ~29.0.5 - typescript: ~5.0.4 + typescript: ~5.1.3 peerDependencies: "@rocket.chat/css-in-js": "*" "@rocket.chat/fuselage": "*" @@ -11091,13 +11042,13 @@ __metadata: "@types/react-beautiful-dnd": ^13.1.4 "@types/react-dom": ^17.0.20 "@types/use-subscription": ^1.0.0 - "@typescript-eslint/eslint-plugin": ^5.57.1 - "@typescript-eslint/parser": ^5.57.1 + "@typescript-eslint/eslint-plugin": ~5.60.0 + "@typescript-eslint/parser": ~5.60.0 "@vitejs/plugin-react": ^4.0.0 codemirror: ^6.0.1 - eslint: ^8.38.0 + eslint: ^8.43.0 eslint-plugin-react-hooks: ^4.6.0 - eslint-plugin-react-refresh: ^0.3.5 + eslint-plugin-react-refresh: ^0.4.1 eslint4b-prebuilt: ^6.7.2 react: ^17.0.2 react-beautiful-dnd: ^13.1.1 @@ -11105,7 +11056,7 @@ __metadata: react-router-dom: ^6.11.2 react-split-pane: ^0.1.92 react-virtuoso: ^4.3.10 - typescript: ^5.0.2 + typescript: ^5.1.3 use-subscription: ^1.8.0 vite: ^4.3.9 languageName: unknown @@ -11121,11 +11072,11 @@ __metadata: "@tanstack/react-query": ^4.16.1 "@testing-library/react": ^13.3.0 "@types/jest": ~29.5.2 - eslint: ~8.38.0 + eslint: ~8.43.0 jest: ~29.5.0 react-hook-form: ^7.34.2 ts-jest: ~29.0.5 - typescript: ~5.0.4 + typescript: ~5.1.3 peerDependencies: "@rocket.chat/layout": "*" "@rocket.chat/ui-contexts": "*" @@ -12612,90 +12563,90 @@ __metadata: languageName: node linkType: hard -"@swc/core-darwin-arm64@npm:1.3.64": - version: 1.3.64 - resolution: "@swc/core-darwin-arm64@npm:1.3.64" +"@swc/core-darwin-arm64@npm:1.3.66": + version: 1.3.66 + resolution: "@swc/core-darwin-arm64@npm:1.3.66" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@swc/core-darwin-x64@npm:1.3.64": - version: 1.3.64 - resolution: "@swc/core-darwin-x64@npm:1.3.64" +"@swc/core-darwin-x64@npm:1.3.66": + version: 1.3.66 + resolution: "@swc/core-darwin-x64@npm:1.3.66" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@swc/core-linux-arm-gnueabihf@npm:1.3.64": - version: 1.3.64 - resolution: "@swc/core-linux-arm-gnueabihf@npm:1.3.64" +"@swc/core-linux-arm-gnueabihf@npm:1.3.66": + version: 1.3.66 + resolution: "@swc/core-linux-arm-gnueabihf@npm:1.3.66" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@swc/core-linux-arm64-gnu@npm:1.3.64": - version: 1.3.64 - resolution: "@swc/core-linux-arm64-gnu@npm:1.3.64" +"@swc/core-linux-arm64-gnu@npm:1.3.66": + version: 1.3.66 + resolution: "@swc/core-linux-arm64-gnu@npm:1.3.66" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-arm64-musl@npm:1.3.64": - version: 1.3.64 - resolution: "@swc/core-linux-arm64-musl@npm:1.3.64" +"@swc/core-linux-arm64-musl@npm:1.3.66": + version: 1.3.66 + resolution: "@swc/core-linux-arm64-musl@npm:1.3.66" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@swc/core-linux-x64-gnu@npm:1.3.64": - version: 1.3.64 - resolution: "@swc/core-linux-x64-gnu@npm:1.3.64" +"@swc/core-linux-x64-gnu@npm:1.3.66": + version: 1.3.66 + resolution: "@swc/core-linux-x64-gnu@npm:1.3.66" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-x64-musl@npm:1.3.64": - version: 1.3.64 - resolution: "@swc/core-linux-x64-musl@npm:1.3.64" +"@swc/core-linux-x64-musl@npm:1.3.66": + version: 1.3.66 + resolution: "@swc/core-linux-x64-musl@npm:1.3.66" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@swc/core-win32-arm64-msvc@npm:1.3.64": - version: 1.3.64 - resolution: "@swc/core-win32-arm64-msvc@npm:1.3.64" +"@swc/core-win32-arm64-msvc@npm:1.3.66": + version: 1.3.66 + resolution: "@swc/core-win32-arm64-msvc@npm:1.3.66" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@swc/core-win32-ia32-msvc@npm:1.3.64": - version: 1.3.64 - resolution: "@swc/core-win32-ia32-msvc@npm:1.3.64" +"@swc/core-win32-ia32-msvc@npm:1.3.66": + version: 1.3.66 + resolution: "@swc/core-win32-ia32-msvc@npm:1.3.66" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@swc/core-win32-x64-msvc@npm:1.3.64": - version: 1.3.64 - resolution: "@swc/core-win32-x64-msvc@npm:1.3.64" +"@swc/core-win32-x64-msvc@npm:1.3.66": + version: 1.3.66 + resolution: "@swc/core-win32-x64-msvc@npm:1.3.66" conditions: os=win32 & cpu=x64 languageName: node linkType: hard -"@swc/core@npm:^1.3.64": - version: 1.3.64 - resolution: "@swc/core@npm:1.3.64" +"@swc/core@npm:^1.3.66": + version: 1.3.66 + resolution: "@swc/core@npm:1.3.66" dependencies: - "@swc/core-darwin-arm64": 1.3.64 - "@swc/core-darwin-x64": 1.3.64 - "@swc/core-linux-arm-gnueabihf": 1.3.64 - "@swc/core-linux-arm64-gnu": 1.3.64 - "@swc/core-linux-arm64-musl": 1.3.64 - "@swc/core-linux-x64-gnu": 1.3.64 - "@swc/core-linux-x64-musl": 1.3.64 - "@swc/core-win32-arm64-msvc": 1.3.64 - "@swc/core-win32-ia32-msvc": 1.3.64 - "@swc/core-win32-x64-msvc": 1.3.64 + "@swc/core-darwin-arm64": 1.3.66 + "@swc/core-darwin-x64": 1.3.66 + "@swc/core-linux-arm-gnueabihf": 1.3.66 + "@swc/core-linux-arm64-gnu": 1.3.66 + "@swc/core-linux-arm64-musl": 1.3.66 + "@swc/core-linux-x64-gnu": 1.3.66 + "@swc/core-linux-x64-musl": 1.3.66 + "@swc/core-win32-arm64-msvc": 1.3.66 + "@swc/core-win32-ia32-msvc": 1.3.66 + "@swc/core-win32-x64-msvc": 1.3.66 peerDependencies: "@swc/helpers": ^0.5.0 dependenciesMeta: @@ -12722,7 +12673,7 @@ __metadata: peerDependenciesMeta: "@swc/helpers": optional: true - checksum: ea77168089a34dcec088ab81aef99301eba003b5ed3dca4039803050ba9344e754687f7d4fb4b3e40d22509658bdbdbac2f94f99c6f94051970566c857774371 + checksum: e6029c648ba47c522bed51a9f2fee606f82de1f9233e2e89197e43b0a4867054174ca05e825e688cdc4de332221c0da2e12ba7ba875549e8b5432aa70fe19263 languageName: node linkType: hard @@ -13272,7 +13223,7 @@ __metadata: languageName: node linkType: hard -"@types/eslint@npm:*, @types/eslint@npm:~8.37.0": +"@types/eslint@npm:*": version: 8.37.0 resolution: "@types/eslint@npm:8.37.0" dependencies: @@ -13282,7 +13233,7 @@ __metadata: languageName: node linkType: hard -"@types/eslint@npm:^8.40.2": +"@types/eslint@npm:^8.40.2, @types/eslint@npm:~8.40.2": version: 8.40.2 resolution: "@types/eslint@npm:8.40.2" dependencies: @@ -14578,14 +14529,14 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:^5.57.1": - version: 5.59.7 - resolution: "@typescript-eslint/eslint-plugin@npm:5.59.7" +"@typescript-eslint/eslint-plugin@npm:~5.60.0": + version: 5.60.0 + resolution: "@typescript-eslint/eslint-plugin@npm:5.60.0" dependencies: "@eslint-community/regexpp": ^4.4.0 - "@typescript-eslint/scope-manager": 5.59.7 - "@typescript-eslint/type-utils": 5.59.7 - "@typescript-eslint/utils": 5.59.7 + "@typescript-eslint/scope-manager": 5.60.0 + "@typescript-eslint/type-utils": 5.60.0 + "@typescript-eslint/utils": 5.60.0 debug: ^4.3.4 grapheme-splitter: ^1.0.4 ignore: ^5.2.0 @@ -14598,65 +14549,24 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 10d28bac7a5af9e41767be0bb9c270ee3dcdfeaa38d1b036c6822e7260b88821c460699ba943664eb1ef272d00de6a81b99d7d955332044ea87b624e7ead84a1 + checksum: 61dd70a1ea9787e69d0d4cd14f6a4c94ba786b535a3f519ade7926d965ee1d4f8fefa8bf0224ee57c5c6517eec3674c0fd06f9226536aa428c2bdddeed1e70f4 languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:~5.58.0": - version: 5.58.0 - resolution: "@typescript-eslint/eslint-plugin@npm:5.58.0" +"@typescript-eslint/parser@npm:~5.60.0": + version: 5.60.0 + resolution: "@typescript-eslint/parser@npm:5.60.0" dependencies: - "@eslint-community/regexpp": ^4.4.0 - "@typescript-eslint/scope-manager": 5.58.0 - "@typescript-eslint/type-utils": 5.58.0 - "@typescript-eslint/utils": 5.58.0 + "@typescript-eslint/scope-manager": 5.60.0 + "@typescript-eslint/types": 5.60.0 + "@typescript-eslint/typescript-estree": 5.60.0 debug: ^4.3.4 - grapheme-splitter: ^1.0.4 - ignore: ^5.2.0 - natural-compare-lite: ^1.4.0 - semver: ^7.3.7 - tsutils: ^3.21.0 peerDependencies: - "@typescript-eslint/parser": ^5.0.0 eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 peerDependenciesMeta: typescript: optional: true - checksum: e5d76d43c466ebd4b552e3307eff72ab5ae8a0c09a1d35fa13b62769ac3336df94d9281728ab5aafd2c14a0a644133583edcd708fce60a9a82df1db3ca3b8e14 - languageName: node - linkType: hard - -"@typescript-eslint/parser@npm:^5.57.1": - version: 5.59.7 - resolution: "@typescript-eslint/parser@npm:5.59.7" - dependencies: - "@typescript-eslint/scope-manager": 5.59.7 - "@typescript-eslint/types": 5.59.7 - "@typescript-eslint/typescript-estree": 5.59.7 - debug: ^4.3.4 - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - peerDependenciesMeta: - typescript: - optional: true - checksum: bc44f37a11a44f84ae5f0156213f3e2e49aef2ecac94d9e161a0c721acd29462e288f306ad4648095ac1c0e5a5f62b78280c1735883cf39f79ee3afcba312119 - languageName: node - linkType: hard - -"@typescript-eslint/parser@npm:~5.58.0": - version: 5.58.0 - resolution: "@typescript-eslint/parser@npm:5.58.0" - dependencies: - "@typescript-eslint/scope-manager": 5.58.0 - "@typescript-eslint/types": 5.58.0 - "@typescript-eslint/typescript-estree": 5.58.0 - debug: ^4.3.4 - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - peerDependenciesMeta: - typescript: - optional: true - checksum: 38681da48a40132c0538579c818ceef9ba2793ab8f79236c3f64980ba1649bb87cb367cd79d37bf2982b8bfbc28f91846b8676f9bd333e8b691c9befffd8874a + checksum: 94e7931a5b356b16638b281b8e1d661f8b1660f0c75a323537f68b311dae91b7a575a0a019d4ea05a79cc5d42b5cb41cc367205691cdfd292ef96a3b66b1e58b languageName: node linkType: hard @@ -14670,32 +14580,22 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:5.59.7": - version: 5.59.7 - resolution: "@typescript-eslint/scope-manager@npm:5.59.7" - dependencies: - "@typescript-eslint/types": 5.59.7 - "@typescript-eslint/visitor-keys": 5.59.7 - checksum: 43f7ea93fddbe2902122a41050677fe3eff2ea468f435b981592510cfc6136e8c28ac7d3a3e05fb332c0b3078a29bd0c91c35b2b1f4e788b4eb9aaeb70e21583 - languageName: node - linkType: hard - -"@typescript-eslint/type-utils@npm:5.58.0": - version: 5.58.0 - resolution: "@typescript-eslint/type-utils@npm:5.58.0" +"@typescript-eslint/scope-manager@npm:5.60.0": + version: 5.60.0 + resolution: "@typescript-eslint/scope-manager@npm:5.60.0" dependencies: - "@typescript-eslint/types": 5.36.2 - "@typescript-eslint/visitor-keys": 5.36.2 - checksum: 803f24daed185152bf86952d4acebb5ea18ff03db5f28750368edf76fdea46b4b0f8803ae0b61c0282b47181c9977113457b16e33d5d2cb33b13855f55c5e5b2 + "@typescript-eslint/types": 5.60.0 + "@typescript-eslint/visitor-keys": 5.60.0 + checksum: b21ee1ef57be948a806aa31fd65a9186766b3e1a727030dc47025edcadc54bd1aa6133a439acd5f44a93e2b983dd55bc5571bb01cb834461dab733682d66256a languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:5.59.7": - version: 5.59.7 - resolution: "@typescript-eslint/type-utils@npm:5.59.7" +"@typescript-eslint/type-utils@npm:5.60.0": + version: 5.60.0 + resolution: "@typescript-eslint/type-utils@npm:5.60.0" dependencies: - "@typescript-eslint/typescript-estree": 5.59.7 - "@typescript-eslint/utils": 5.59.7 + "@typescript-eslint/typescript-estree": 5.60.0 + "@typescript-eslint/utils": 5.60.0 debug: ^4.3.4 tsutils: ^3.21.0 peerDependencies: @@ -14703,14 +14603,7 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 9cbeffad27b145b478e4cbbab2b44c5b246a9b922f01fd06d401ea4c41a4fa6dc8ba75d13a6409b3b4474ccaf2018770a4c6c599172e22ec2004110e00f4e721 - languageName: node - linkType: hard - -"@typescript-eslint/types@npm:5.36.2": - version: 5.36.2 - resolution: "@typescript-eslint/types@npm:5.36.2" - checksum: 736cb8a76b58f2f9a7d066933094c5510ffe31479ea8b804a829ec85942420f1b55e0eb2688fbdaaaa9c0e5b3b590fb8f14bbd745353696b4fd33fda620d417b + checksum: b90ce97592f2db899d88d7a325fec4d2ea11a7b8b4306787310890c27fb51862a6c003675252e9dc465908f791ad5320ea7307260ecd10e89ca1d209fbf8616d languageName: node linkType: hard @@ -14728,10 +14621,10 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/types@npm:5.59.7": - version: 5.59.7 - resolution: "@typescript-eslint/types@npm:5.59.7" - checksum: 52eccec9e2d631eb2808e48b5dc33a837b5e242fa9eddace89fc707c9f2283b5364f1d38b33d418a08d64f45f6c22f051800898e1881a912f8aac0c3ae300d0a +"@typescript-eslint/types@npm:5.60.0": + version: 5.60.0 + resolution: "@typescript-eslint/types@npm:5.60.0" + checksum: 48f29e5c084c5663cfed1a6c4458799a6690a213e7861a24501f9b96698ae59e89a1df1c77e481777e4da78f1b0a5573a549f7b8880e3f4071a7a8b686254db8 languageName: node linkType: hard @@ -14770,12 +14663,12 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:5.59.7": - version: 5.59.7 - resolution: "@typescript-eslint/typescript-estree@npm:5.59.7" +"@typescript-eslint/typescript-estree@npm:5.60.0": + version: 5.60.0 + resolution: "@typescript-eslint/typescript-estree@npm:5.60.0" dependencies: - "@typescript-eslint/types": 5.59.7 - "@typescript-eslint/visitor-keys": 5.59.7 + "@typescript-eslint/types": 5.60.0 + "@typescript-eslint/visitor-keys": 5.60.0 debug: ^4.3.4 globby: ^11.1.0 is-glob: ^4.0.3 @@ -14784,7 +14677,7 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: eefe82eedf9ee2e14463c3f2b5b18df084c1328a859b245ee897a9a7075acce7cca0216a21fd7968b75aa64189daa008bfde1e2f9afbcc336f3dfe856e7f342e + checksum: 0f4f342730ead42ba60b5fca4bf1950abebd83030010c38b5df98ff9fd95d0ce1cfc3974a44c90c65f381f4f172adcf1a540e018d7968cc845d937bf6c734dae languageName: node linkType: hard @@ -14806,49 +14699,39 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/utils@npm:5.58.0, @typescript-eslint/utils@npm:^5.10.0, @typescript-eslint/utils@npm:^5.45.0, @typescript-eslint/utils@npm:^5.58.0": - version: 5.58.0 - resolution: "@typescript-eslint/utils@npm:5.58.0" +"@typescript-eslint/utils@npm:5.60.0": + version: 5.60.0 + resolution: "@typescript-eslint/utils@npm:5.60.0" dependencies: "@eslint-community/eslint-utils": ^4.2.0 "@types/json-schema": ^7.0.9 "@types/semver": ^7.3.12 - "@typescript-eslint/scope-manager": 5.58.0 - "@typescript-eslint/types": 5.58.0 - "@typescript-eslint/typescript-estree": 5.58.0 + "@typescript-eslint/scope-manager": 5.60.0 + "@typescript-eslint/types": 5.60.0 + "@typescript-eslint/typescript-estree": 5.60.0 eslint-scope: ^5.1.1 semver: ^7.3.7 peerDependencies: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - checksum: c618ae67963ecf96b1492c09afaeb363f542f0d6780bcac4af3c26034e3b20034666b2d523aa94821df813aafb57a0b150a7d5c2224fe8257452ad1de2237a58 + checksum: cbe56567f0b53e24ad7ef7d2fb4cdc8596e2559c21ee639aa0560879b6216208550e51e9d8ae4b388ff21286809c6dc985cec66738294871051396a8ae5bccbc languageName: node linkType: hard -"@typescript-eslint/utils@npm:5.59.7": - version: 5.59.7 - resolution: "@typescript-eslint/utils@npm:5.59.7" +"@typescript-eslint/utils@npm:^5.10.0, @typescript-eslint/utils@npm:^5.45.0, @typescript-eslint/utils@npm:^5.58.0": + version: 5.58.0 + resolution: "@typescript-eslint/utils@npm:5.58.0" dependencies: "@eslint-community/eslint-utils": ^4.2.0 "@types/json-schema": ^7.0.9 "@types/semver": ^7.3.12 - "@typescript-eslint/scope-manager": 5.59.7 - "@typescript-eslint/types": 5.59.7 - "@typescript-eslint/typescript-estree": 5.59.7 + "@typescript-eslint/scope-manager": 5.58.0 + "@typescript-eslint/types": 5.58.0 + "@typescript-eslint/typescript-estree": 5.58.0 eslint-scope: ^5.1.1 semver: ^7.3.7 peerDependencies: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - checksum: d8682700187ca94cc6441480cb6b87d0514a9748103c15dd93206c5b1c6fefa59063662f27a4103e16abbcfb654a61d479bc55af8f23d96f342431b87f31bb4e - languageName: node - linkType: hard - -"@typescript-eslint/visitor-keys@npm:5.36.2": - version: 5.36.2 - resolution: "@typescript-eslint/visitor-keys@npm:5.36.2" - dependencies: - "@typescript-eslint/types": 5.36.2 - eslint-visitor-keys: ^3.3.0 - checksum: 87ccdcfa5cdedaa3a1aac30d656969f4f5910b62bcaacdf80a514dbf0cbbd8e79b55f8e987eab34cc79ece8ce4b8c19d5caf8b0afb74e0b0d7ab39fb29aa8eba + checksum: c618ae67963ecf96b1492c09afaeb363f542f0d6780bcac4af3c26034e3b20034666b2d523aa94821df813aafb57a0b150a7d5c2224fe8257452ad1de2237a58 languageName: node linkType: hard @@ -14872,13 +14755,13 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:5.59.7": - version: 5.59.7 - resolution: "@typescript-eslint/visitor-keys@npm:5.59.7" +"@typescript-eslint/visitor-keys@npm:5.60.0": + version: 5.60.0 + resolution: "@typescript-eslint/visitor-keys@npm:5.60.0" dependencies: - "@typescript-eslint/types": 5.59.7 + "@typescript-eslint/types": 5.60.0 eslint-visitor-keys: ^3.3.0 - checksum: 4367f2ea68dd96a0520485434ad11e1bd26239eeeb3a2150bee7478a0f1df3c2099a39f96486722932be0456bcb7a47a483b452876d1d30bdeb9b81d354eef3d + checksum: d39b2485d030f9755820d0f6f3748a8ec44e1ca23cb36ddcba67a9eb1f258c8ec83c61fc015c50e8f4a00d05df62d719dbda445625e3e71a64a659f1d248157e languageName: node linkType: hard @@ -22134,20 +22017,21 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-jest@npm:~27.2.1": - version: 27.2.1 - resolution: "eslint-plugin-jest@npm:27.2.1" +"eslint-plugin-jest@npm:~27.2.2": + version: 27.2.2 + resolution: "eslint-plugin-jest@npm:27.2.2" dependencies: "@typescript-eslint/utils": ^5.10.0 peerDependencies: "@typescript-eslint/eslint-plugin": ^5.0.0 eslint: ^7.0.0 || ^8.0.0 + jest: "*" peerDependenciesMeta: "@typescript-eslint/eslint-plugin": optional: true jest: optional: true - checksum: 579a4d26304cc6748b2e6dff6c965ea7a21b618d8b051eb02727d25cf5c7767f6db8ef5237531635ff77e242b983b973e7cb8c820a4d20d5bda73358c452a8ab + checksum: 98b63252d985f5dedf36ce9587dd4a0d24daf71ca8a997258343402c0d33ddd5070502378dafd9ac7fc0ef2e0d557b5c77f18e09ad73c71a52de8061db88293f languageName: node linkType: hard @@ -22160,16 +22044,16 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-playwright@npm:~0.12.0": - version: 0.12.0 - resolution: "eslint-plugin-playwright@npm:0.12.0" +"eslint-plugin-playwright@npm:~0.15.0": + version: 0.15.0 + resolution: "eslint-plugin-playwright@npm:0.15.0" peerDependencies: eslint: ">=7" - eslint-plugin-jest: ">=24" + eslint-plugin-jest: ">=25" peerDependenciesMeta: eslint-plugin-jest: optional: true - checksum: f7a6f28ea6ad8c3ba81a37bc7cf1d50a762365719f0f87888c8a6b3220be6baac4fb63bf9590227f28beb6d5bc748afe730ce68040be6846c329e41994debdd5 + checksum: fe772ee1f611802f70310cd02d2048f64b244644fcb00b47e935aac8cfab800612b122fe50deb3e1ea6bde1d1d635a745f3574cc316fcccbeaaa278be9c2e20f languageName: node linkType: hard @@ -22197,12 +22081,12 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-react-refresh@npm:^0.3.5": - version: 0.3.5 - resolution: "eslint-plugin-react-refresh@npm:0.3.5" +"eslint-plugin-react-refresh@npm:^0.4.1": + version: 0.4.1 + resolution: "eslint-plugin-react-refresh@npm:0.4.1" peerDependencies: eslint: ">=7" - checksum: 8d44201968838ad0ac13311fe593bc422ce80d9143d104c7485e8bcdeb4f8c3b4cda21322a7e360129f14912a980d23e2fb1f9f10d9701c623901e359bd7dd17 + checksum: 932f982797ef54a87e20039c32739c1a6df8355165d17ba851620b4690632432f511605e20c30e6abdb4c58d2bd926e96347f9253db724dcf3dae92bd1258d1d languageName: node linkType: hard @@ -22245,14 +22129,14 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-testing-library@npm:^5.9.1, eslint-plugin-testing-library@npm:~5.10.3": - version: 5.10.3 - resolution: "eslint-plugin-testing-library@npm:5.10.3" +"eslint-plugin-testing-library@npm:^5.11.0, eslint-plugin-testing-library@npm:~5.11.0": + version: 5.11.0 + resolution: "eslint-plugin-testing-library@npm:5.11.0" dependencies: "@typescript-eslint/utils": ^5.58.0 peerDependencies: eslint: ^7.5.0 || ^8.0.0 - checksum: 3033121a0040b98280cd41856273ad1b268f56083759401e7af72ac8a96dcb213892f1248983aa9a18988b44913263e93f0d182dbb0c5b27b00242bfffc9cdcc + checksum: 7f19d3dedd7788b411ca3d9045de682feb26025b9c26d97d4e2f0bf62f5eaa276147d946bd5d0cd967b822e546a954330fdb7ef80485301264f646143f011a02 languageName: node linkType: hard @@ -22285,16 +22169,6 @@ __metadata: languageName: node linkType: hard -"eslint-scope@npm:^7.1.1": - version: 7.1.1 - resolution: "eslint-scope@npm:7.1.1" - dependencies: - esrecurse: ^4.3.0 - estraverse: ^5.2.0 - checksum: 9f6e974ab2db641ca8ab13508c405b7b859e72afe9f254e8131ff154d2f40c99ad4545ce326fd9fde3212ff29707102562a4834f1c48617b35d98c71a97fbf3e - languageName: node - linkType: hard - "eslint-scope@npm:^7.2.0": version: 7.2.0 resolution: "eslint-scope@npm:7.2.0" @@ -22328,7 +22202,7 @@ __metadata: languageName: node linkType: hard -"eslint-visitor-keys@npm:^3.3.0, eslint-visitor-keys@npm:^3.4.0": +"eslint-visitor-keys@npm:^3.3.0": version: 3.4.0 resolution: "eslint-visitor-keys@npm:3.4.0" checksum: 33159169462d3989321a1ec1e9aaaf6a24cc403d5d347e9886d1b5bfe18ffa1be73bdc6203143a28a606b142b1af49787f33cff0d6d0813eb5f2e8d2e1a6043c @@ -22399,57 +22273,7 @@ __metadata: languageName: node linkType: hard -"eslint@npm:^8.12.0, eslint@npm:~8.38.0": - version: 8.38.0 - resolution: "eslint@npm:8.38.0" - dependencies: - "@eslint-community/eslint-utils": ^4.2.0 - "@eslint-community/regexpp": ^4.4.0 - "@eslint/eslintrc": ^2.0.2 - "@eslint/js": 8.38.0 - "@humanwhocodes/config-array": ^0.11.8 - "@humanwhocodes/module-importer": ^1.0.1 - "@nodelib/fs.walk": ^1.2.8 - ajv: ^6.10.0 - chalk: ^4.0.0 - cross-spawn: ^7.0.2 - debug: ^4.3.2 - doctrine: ^3.0.0 - escape-string-regexp: ^4.0.0 - eslint-scope: ^7.1.1 - eslint-visitor-keys: ^3.4.0 - espree: ^9.5.1 - esquery: ^1.4.2 - esutils: ^2.0.2 - fast-deep-equal: ^3.1.3 - file-entry-cache: ^6.0.1 - find-up: ^5.0.0 - glob-parent: ^6.0.2 - globals: ^13.19.0 - grapheme-splitter: ^1.0.4 - ignore: ^5.2.0 - import-fresh: ^3.0.0 - imurmurhash: ^0.1.4 - is-glob: ^4.0.0 - is-path-inside: ^3.0.3 - js-sdsl: ^4.1.4 - js-yaml: ^4.1.0 - json-stable-stringify-without-jsonify: ^1.0.1 - levn: ^0.4.1 - lodash.merge: ^4.6.2 - minimatch: ^3.1.2 - natural-compare: ^1.4.0 - optionator: ^0.9.1 - strip-ansi: ^6.0.1 - strip-json-comments: ^3.1.0 - text-table: ^0.2.0 - bin: - eslint: bin/eslint.js - checksum: 73b6d9b650d0434aa7c07d0a1802f099b086ee70a8d8ba7be730439a26572a5eb71def12125c82942be2ec8ee5be38a6f1b42a13e40d4b67f11a148ec9e263eb - languageName: node - linkType: hard - -"eslint@npm:^8.29.0": +"eslint@npm:^8.43.0, eslint@npm:~8.43.0": version: 8.43.0 resolution: "eslint@npm:8.43.0" dependencies: @@ -22498,104 +22322,6 @@ __metadata: languageName: node linkType: hard -"eslint@npm:^8.38.0": - version: 8.41.0 - resolution: "eslint@npm:8.41.0" - dependencies: - "@eslint-community/eslint-utils": ^4.2.0 - "@eslint-community/regexpp": ^4.4.0 - "@eslint/eslintrc": ^2.0.3 - "@eslint/js": 8.41.0 - "@humanwhocodes/config-array": ^0.11.8 - "@humanwhocodes/module-importer": ^1.0.1 - "@nodelib/fs.walk": ^1.2.8 - ajv: ^6.10.0 - chalk: ^4.0.0 - cross-spawn: ^7.0.2 - debug: ^4.3.2 - doctrine: ^3.0.0 - escape-string-regexp: ^4.0.0 - eslint-scope: ^7.2.0 - eslint-visitor-keys: ^3.4.1 - espree: ^9.5.2 - esquery: ^1.4.2 - esutils: ^2.0.2 - fast-deep-equal: ^3.1.3 - file-entry-cache: ^6.0.1 - find-up: ^5.0.0 - glob-parent: ^6.0.2 - globals: ^13.19.0 - graphemer: ^1.4.0 - ignore: ^5.2.0 - import-fresh: ^3.0.0 - imurmurhash: ^0.1.4 - is-glob: ^4.0.0 - is-path-inside: ^3.0.3 - js-yaml: ^4.1.0 - json-stable-stringify-without-jsonify: ^1.0.1 - levn: ^0.4.1 - lodash.merge: ^4.6.2 - minimatch: ^3.1.2 - natural-compare: ^1.4.0 - optionator: ^0.9.1 - strip-ansi: ^6.0.1 - strip-json-comments: ^3.1.0 - text-table: ^0.2.0 - bin: - eslint: bin/eslint.js - checksum: 09979a6f8451dcc508a7005b6670845c8a518376280b3fd96657a406b8b6ef29d0e480d1ba11b4eb48da93d607e0c55c9b877676fe089d09973ec152354e23b2 - languageName: node - linkType: hard - -"eslint@npm:^8.42.0": - version: 8.42.0 - resolution: "eslint@npm:8.42.0" - dependencies: - "@eslint-community/eslint-utils": ^4.2.0 - "@eslint-community/regexpp": ^4.4.0 - "@eslint/eslintrc": ^2.0.3 - "@eslint/js": 8.42.0 - "@humanwhocodes/config-array": ^0.11.10 - "@humanwhocodes/module-importer": ^1.0.1 - "@nodelib/fs.walk": ^1.2.8 - ajv: ^6.10.0 - chalk: ^4.0.0 - cross-spawn: ^7.0.2 - debug: ^4.3.2 - doctrine: ^3.0.0 - escape-string-regexp: ^4.0.0 - eslint-scope: ^7.2.0 - eslint-visitor-keys: ^3.4.1 - espree: ^9.5.2 - esquery: ^1.4.2 - esutils: ^2.0.2 - fast-deep-equal: ^3.1.3 - file-entry-cache: ^6.0.1 - find-up: ^5.0.0 - glob-parent: ^6.0.2 - globals: ^13.19.0 - graphemer: ^1.4.0 - ignore: ^5.2.0 - import-fresh: ^3.0.0 - imurmurhash: ^0.1.4 - is-glob: ^4.0.0 - is-path-inside: ^3.0.3 - js-yaml: ^4.1.0 - json-stable-stringify-without-jsonify: ^1.0.1 - levn: ^0.4.1 - lodash.merge: ^4.6.2 - minimatch: ^3.1.2 - natural-compare: ^1.4.0 - optionator: ^0.9.1 - strip-ansi: ^6.0.1 - strip-json-comments: ^3.1.0 - text-table: ^0.2.0 - bin: - eslint: bin/eslint.js - checksum: 07105397b5f2ff4064b983b8971e8c379ec04b1dfcc9d918976b3e00377189000161dac991d82ba14f8759e466091b8c71146f602930ca810c290ee3fcb3faf0 - languageName: node - linkType: hard - "espree@npm:^7.3.0, espree@npm:^7.3.1": version: 7.3.1 resolution: "espree@npm:7.3.1" @@ -22607,17 +22333,6 @@ __metadata: languageName: node linkType: hard -"espree@npm:^9.5.1": - version: 9.5.1 - resolution: "espree@npm:9.5.1" - dependencies: - acorn: ^8.8.0 - acorn-jsx: ^5.3.2 - eslint-visitor-keys: ^3.4.0 - checksum: cdf6e43540433d917c4f2ee087c6e987b2063baa85a1d9cdaf51533d78275ebd5910c42154e7baf8e3e89804b386da0a2f7fad2264d8f04420e7506bf87b3b88 - languageName: node - linkType: hard - "espree@npm:^9.5.2": version: 9.5.2 resolution: "espree@npm:9.5.2" @@ -28138,13 +27853,6 @@ __metadata: languageName: node linkType: hard -"js-sdsl@npm:^4.1.4": - version: 4.1.4 - resolution: "js-sdsl@npm:4.1.4" - checksum: 1977cea4ab18e0e03e28bdf0371d8b443fad65ca0988e0faa216406faf6bb943714fe8f7cc7a5bfe5f35ba3d94ddae399f4d10200f547f2c3320688b0670d726 - languageName: node - linkType: hard - "js-sha256@npm:^0.9.0": version: 0.9.0 resolution: "js-sha256@npm:0.9.0" @@ -36406,7 +36114,7 @@ __metadata: sodium-native: ^3.3.0 sodium-plus: ^0.9.0 ts-node: ^10.9.1 - typescript: ~5.0.4 + typescript: ~5.1.3 uuid: ^8.3.2 ws: ^8.8.1 languageName: unknown @@ -40063,17 +39771,7 @@ __metadata: languageName: node linkType: hard -"typescript@npm:^5.0.2, typescript@npm:~5.0.4": - version: 5.0.4 - resolution: "typescript@npm:5.0.4" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: 82b94da3f4604a8946da585f7d6c3025fff8410779e5bde2855ab130d05e4fd08938b9e593b6ebed165bda6ad9292b230984f10952cf82f0a0ca07bbeaa08172 - languageName: node - linkType: hard - -"typescript@npm:^5.1.3": +"typescript@npm:^5.1.3, typescript@npm:~5.1.3": version: 5.1.3 resolution: "typescript@npm:5.1.3" bin: @@ -40083,17 +39781,7 @@ __metadata: languageName: node linkType: hard -"typescript@patch:typescript@^5.0.2#~builtin, typescript@patch:typescript@~5.0.4#~builtin": - version: 5.0.4 - resolution: "typescript@patch:typescript@npm%3A5.0.4#~builtin::version=5.0.4&hash=f456af" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: 6a1fe9a77bb9c5176ead919cc4a1499ee63e46b4e05bf667079f11bf3a8f7887f135aa72460a4c3b016e6e6bb65a822cb8689a6d86cbfe92d22cc9f501f09213 - languageName: node - linkType: hard - -"typescript@patch:typescript@^5.1.3#~builtin": +"typescript@patch:typescript@^5.1.3#~builtin, typescript@patch:typescript@~5.1.3#~builtin": version: 5.1.3 resolution: "typescript@patch:typescript@npm%3A5.1.3#~builtin::version=5.1.3&hash=f456af" bin: From 0fb7d90708ed4f89f74357952550ad6046239252 Mon Sep 17 00:00:00 2001 From: gabriellsh <40830821+gabriellsh@users.noreply.github.com> Date: Thu, 22 Jun 2023 20:46:57 -0300 Subject: [PATCH 09/21] fix(meteor): Message composer keeps recording even though permission was denied (#29526) --- .changeset/soft-carrots-add.md | 5 +++++ apps/meteor/app/ui/client/lib/recorderjs/AudioRecorder.ts | 1 + 2 files changed, 6 insertions(+) create mode 100644 .changeset/soft-carrots-add.md diff --git a/.changeset/soft-carrots-add.md b/.changeset/soft-carrots-add.md new file mode 100644 index 0000000000000..80aba278f3a82 --- /dev/null +++ b/.changeset/soft-carrots-add.md @@ -0,0 +1,5 @@ +--- +"@rocket.chat/meteor": patch +--- + +fixed an error on mobile ios browser where if you started recording audio and denied permission, it would look like it is still recording diff --git a/apps/meteor/app/ui/client/lib/recorderjs/AudioRecorder.ts b/apps/meteor/app/ui/client/lib/recorderjs/AudioRecorder.ts index 27eb996e9da60..d8bd8cbb323cb 100644 --- a/apps/meteor/app/ui/client/lib/recorderjs/AudioRecorder.ts +++ b/apps/meteor/app/ui/client/lib/recorderjs/AudioRecorder.ts @@ -76,6 +76,7 @@ export class AudioRecorder { this.destroyStream(); this.destroyAudioContext(); cb?.call(this, false); + throw error; } } From 0f0b8e17bff70942463179b7a57685675b0e5eac Mon Sep 17 00:00:00 2001 From: Martin Schoeler Date: Thu, 22 Jun 2023 20:48:22 -0300 Subject: [PATCH 10/21] fix: hidden custom fields being validated on some cases (#29556) Co-authored-by: Kevin Aleman --- .changeset/pretty-clocks-add.md | 6 ++++++ .../meteor/app/livechat/server/lib/Contacts.ts | 10 +++++++--- .../server/models/raw/LivechatCustomField.ts | 8 ++++++-- .../e2e/omnichannel-contact-center.spec.ts | 18 ++++++++++++++++++ .../src/models/ILivechatCustomFieldModel.ts | 12 ++++++++++-- 5 files changed, 47 insertions(+), 7 deletions(-) create mode 100644 .changeset/pretty-clocks-add.md diff --git a/.changeset/pretty-clocks-add.md b/.changeset/pretty-clocks-add.md new file mode 100644 index 0000000000000..cea893b285d7b --- /dev/null +++ b/.changeset/pretty-clocks-add.md @@ -0,0 +1,6 @@ +--- +"@rocket.chat/meteor": patch +"@rocket.chat/model-typings": patch +--- + +fix: hidden custom fields being required in some cases diff --git a/apps/meteor/app/livechat/server/lib/Contacts.ts b/apps/meteor/app/livechat/server/lib/Contacts.ts index 74ea04fb19e54..9fa441bd5a60a 100644 --- a/apps/meteor/app/livechat/server/lib/Contacts.ts +++ b/apps/meteor/app/livechat/server/lib/Contacts.ts @@ -72,9 +72,13 @@ export const Contacts = { } } - const allowedCF = LivechatCustomField.findByScope>('visitor', { - projection: { _id: 1, label: 1, regexp: 1, required: 1 }, - }); + const allowedCF = LivechatCustomField.findByScope>( + 'visitor', + { + projection: { _id: 1, label: 1, regexp: 1, required: 1 }, + }, + false, + ); const livechatData: Record = {}; diff --git a/apps/meteor/server/models/raw/LivechatCustomField.ts b/apps/meteor/server/models/raw/LivechatCustomField.ts index be37341a84646..46bc32c52177c 100644 --- a/apps/meteor/server/models/raw/LivechatCustomField.ts +++ b/apps/meteor/server/models/raw/LivechatCustomField.ts @@ -13,8 +13,12 @@ export class LivechatCustomFieldRaw extends BaseRaw implem return [{ key: { scope: 1 } }]; } - findByScope(scope: ILivechatCustomField['scope'], options?: FindOptions): FindCursor { - return this.find({ scope }, options || {}); + findByScope( + scope: ILivechatCustomField['scope'], + options?: FindOptions, + includeHidden = true, + ): FindCursor { + return this.find({ scope, ...(includeHidden === true ? {} : { visibility: { $ne: 'hidden' } }) }, options); } findMatchingCustomFields( diff --git a/apps/meteor/tests/e2e/omnichannel-contact-center.spec.ts b/apps/meteor/tests/e2e/omnichannel-contact-center.spec.ts index 8cb47b0556a32..54a1ecf35a512 100644 --- a/apps/meteor/tests/e2e/omnichannel-contact-center.spec.ts +++ b/apps/meteor/tests/e2e/omnichannel-contact-center.spec.ts @@ -1,6 +1,7 @@ import { faker } from '@faker-js/faker'; import { createToken } from '../../client/lib/utils/createToken'; +import { IS_EE } from './config/constants'; import { Users } from './fixtures/userStates'; import { OmnichannelContacts } from './page-objects/omnichannel-contacts-list'; import { OmnichannelSection } from './page-objects/omnichannel-section'; @@ -18,6 +19,16 @@ const createContact = (generateToken = false) => ({ const NEW_CONTACT = createContact(); const EDIT_CONTACT = createContact(); const EXISTING_CONTACT = createContact(true); +const NEW_CUSTOM_FIELD = { + searchable: true, + field: 'hiddenCustomField', + label: 'hiddenCustomField', + defaultValue: 'test_contact_center_hidden_customField', + scope: 'visitor', + visibility: 'hidden', + required: true, + regexp: '', +} const URL = { contactCenter: '/omnichannel-directory/contacts', @@ -47,12 +58,19 @@ test.describe('Omnichannel Contact Center', () => { // Add a contact const { id: _, ...data } = EXISTING_CONTACT; await api.post('/omnichannel/contact', data); + + if (IS_EE) { + await api.post('/livechat/custom.field', NEW_CUSTOM_FIELD); + } }); test.afterAll(async ({ api }) => { // Remove added contacts await api.delete('/livechat/visitor', { token: EXISTING_CONTACT.token }); await api.delete('/livechat/visitor', { token: NEW_CONTACT.token }); + if (IS_EE) { + await api.post('method.call/livechat:removeCustomField', { message: NEW_CUSTOM_FIELD.field }); + } }); test.beforeEach(async ({ page }) => { diff --git a/packages/model-typings/src/models/ILivechatCustomFieldModel.ts b/packages/model-typings/src/models/ILivechatCustomFieldModel.ts index 55fc49cde002f..856d39c2dd4d0 100644 --- a/packages/model-typings/src/models/ILivechatCustomFieldModel.ts +++ b/packages/model-typings/src/models/ILivechatCustomFieldModel.ts @@ -5,8 +5,16 @@ import type { IBaseModel } from './IBaseModel'; // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface ILivechatCustomFieldModel extends IBaseModel { - findByScope(scope: ILivechatCustomField['scope'], options?: FindOptions): FindCursor; - findByScope(scope: ILivechatCustomField['scope'], options?: FindOptions): FindCursor; + findByScope( + scope: ILivechatCustomField['scope'], + options?: FindOptions, + includeHidden?: boolean, + ): FindCursor; + findByScope( + scope: ILivechatCustomField['scope'], + options?: FindOptions, + includeHidden?: boolean, + ): FindCursor; findMatchingCustomFields( scope: ILivechatCustomField['scope'], searchable: boolean, From fef33034e48ab56b9c0bffda91a66f6aa4fc7177 Mon Sep 17 00:00:00 2001 From: Kevin Aleman Date: Thu, 22 Jun 2023 19:39:24 -0600 Subject: [PATCH 11/21] fix: Show agent email not being passed to model calls (#29455) --- .changeset/brown-forks-fry.md | 5 +++++ apps/meteor/app/apps/server/bridges/livechat.ts | 3 ++- apps/meteor/app/livechat/server/lib/Helper.js | 2 +- apps/meteor/app/livechat/server/methods/getAgentData.ts | 4 +++- apps/meteor/app/livechat/server/methods/getNextAgent.ts | 3 ++- apps/meteor/ee/app/livechat-enterprise/server/lib/Helper.ts | 2 +- apps/meteor/server/models/raw/Users.js | 5 +---- 7 files changed, 15 insertions(+), 9 deletions(-) create mode 100644 .changeset/brown-forks-fry.md diff --git a/.changeset/brown-forks-fry.md b/.changeset/brown-forks-fry.md new file mode 100644 index 0000000000000..1b0bc4883823e --- /dev/null +++ b/.changeset/brown-forks-fry.md @@ -0,0 +1,5 @@ +--- +"@rocket.chat/meteor": patch +--- + +Fixed a problem where the setting `Show Agent Email` from Omnichannel was not being used by the back when returning agent's info diff --git a/apps/meteor/app/apps/server/bridges/livechat.ts b/apps/meteor/app/apps/server/bridges/livechat.ts index 43790c9139a56..c4d6d90996439 100644 --- a/apps/meteor/app/apps/server/bridges/livechat.ts +++ b/apps/meteor/app/apps/server/bridges/livechat.ts @@ -20,6 +20,7 @@ import type { AppServerOrchestrator } from '../../../../ee/server/apps/orchestra import { Livechat as LivechatTyped } from '../../../livechat/server/lib/LivechatTyped'; import { callbacks } from '../../../../lib/callbacks'; import { deasyncPromise } from '../../../../server/deasync/deasync'; +import { settings } from '../../../settings/server'; export class AppLivechatBridge extends LivechatBridge { // eslint-disable-next-line no-empty-function @@ -90,7 +91,7 @@ export class AppLivechatBridge extends LivechatBridge { let agentRoom: SelectedAgent | undefined; if (agent?.id) { - const user = await Users.getAgentInfo(agent.id); + const user = await Users.getAgentInfo(agent.id, settings.get('Livechat_show_agent_email')); if (!user) { throw new Error(`The agent with id "${agent.id}" was not found.`); } diff --git a/apps/meteor/app/livechat/server/lib/Helper.js b/apps/meteor/app/livechat/server/lib/Helper.js index 98a03ce3001d6..f1d30d9100631 100644 --- a/apps/meteor/app/livechat/server/lib/Helper.js +++ b/apps/meteor/app/livechat/server/lib/Helper.js @@ -258,7 +258,7 @@ export const normalizeAgent = async (agentId) => { return { hiddenInfo: true }; } - const agent = await Users.getAgentInfo(agentId); + const agent = await Users.getAgentInfo(agentId, settings.get('Livechat_show_agent_email')); const { customFields: agentCustomFields, ...extraData } = agent; const customFields = parseAgentCustomFields(agentCustomFields); diff --git a/apps/meteor/app/livechat/server/methods/getAgentData.ts b/apps/meteor/app/livechat/server/methods/getAgentData.ts index 42ab31081fc20..991be42434bfc 100644 --- a/apps/meteor/app/livechat/server/methods/getAgentData.ts +++ b/apps/meteor/app/livechat/server/methods/getAgentData.ts @@ -4,6 +4,8 @@ import { LivechatVisitors, LivechatRooms, Users } from '@rocket.chat/models'; import type { ServerMethods } from '@rocket.chat/ui-contexts'; import type { ILivechatAgent } from '@rocket.chat/core-typings'; +import { settings } from '../../../settings/server'; + declare module '@rocket.chat/ui-contexts' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { @@ -30,6 +32,6 @@ Meteor.methods({ return; } - return Users.getAgentInfo(room.servedBy._id); + return Users.getAgentInfo(room.servedBy._id, settings.get('Livechat_show_agent_email')); }, }); diff --git a/apps/meteor/app/livechat/server/methods/getNextAgent.ts b/apps/meteor/app/livechat/server/methods/getNextAgent.ts index 7d79572c2d20d..94961a8985435 100644 --- a/apps/meteor/app/livechat/server/methods/getNextAgent.ts +++ b/apps/meteor/app/livechat/server/methods/getNextAgent.ts @@ -6,6 +6,7 @@ import type { ILivechatAgent } from '@rocket.chat/core-typings'; import { Livechat } from '../lib/LivechatTyped'; import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger'; +import { settings } from '../../../settings/server'; import { callbacks } from '../../../../lib/callbacks'; declare module '@rocket.chat/ui-contexts' { @@ -42,6 +43,6 @@ Meteor.methods({ return; } - return Users.getAgentInfo(agent.agentId); + return Users.getAgentInfo(agent.agentId, settings.get('Livechat_show_agent_email')); }, }); diff --git a/apps/meteor/ee/app/livechat-enterprise/server/lib/Helper.ts b/apps/meteor/ee/app/livechat-enterprise/server/lib/Helper.ts index e300bbdb286fd..44a88a0da328f 100644 --- a/apps/meteor/ee/app/livechat-enterprise/server/lib/Helper.ts +++ b/apps/meteor/ee/app/livechat-enterprise/server/lib/Helper.ts @@ -42,7 +42,7 @@ export const getMaxNumberSimultaneousChat = async ({ agentId, departmentId }: { } if (agentId) { - const user = await Users.getAgentInfo(agentId); + const user = await Users.getAgentInfo(agentId, settings.get('Livechat_show_agent_info')); const { livechat: { maxNumberSimultaneousChat = 0 } = {} } = user || {}; if (maxNumberSimultaneousChat > 0) { return maxNumberSimultaneousChat; diff --git a/apps/meteor/server/models/raw/Users.js b/apps/meteor/server/models/raw/Users.js index 1c91d59f34ec8..afcca73f81e89 100644 --- a/apps/meteor/server/models/raw/Users.js +++ b/apps/meteor/server/models/raw/Users.js @@ -1640,13 +1640,10 @@ export class UsersRaw extends BaseRaw { customFields: 1, status: 1, livechat: 1, + ...(showAgentEmail && { emails: 1 }), }, }; - if (showAgentEmail) { - options.fields.emails = 1; - } - return this.findOne(query, options); } From 702a196b3725522a5a6df64881b118ae758622ef Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Thu, 22 Jun 2023 22:53:33 -0300 Subject: [PATCH 12/21] chore: load dialpad modal lazy (#29629) --- apps/meteor/client/hooks/useDialModal.tsx | 11 ++++++++--- apps/meteor/client/startup/customOAuth.ts | 4 ++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/apps/meteor/client/hooks/useDialModal.tsx b/apps/meteor/client/hooks/useDialModal.tsx index 47b8727f04daf..ac7ad1e81514a 100644 --- a/apps/meteor/client/hooks/useDialModal.tsx +++ b/apps/meteor/client/hooks/useDialModal.tsx @@ -1,10 +1,11 @@ import { useSetModal, useTranslation } from '@rocket.chat/ui-contexts'; -import React, { useCallback, useMemo } from 'react'; +import React, { Suspense, lazy, useCallback, useMemo } from 'react'; -import DialPadModal from '../../ee/client/voip/modal/DialPad/DialPadModal'; import { useIsVoipEnterprise } from '../contexts/CallContext'; import { dispatchToastMessage } from '../lib/toast'; +const DialPadModal = lazy(() => import('../../ee/client/voip/modal/DialPad/DialPadModal')); + type DialModalProps = { initialValue?: string; errorMessage?: string; @@ -29,7 +30,11 @@ export const useDialModal = (): DialModalControls => { return; } - setModal(); + setModal( + + + , + ); }, [setModal, isEnterprise, t, closeDialModal], ); diff --git a/apps/meteor/client/startup/customOAuth.ts b/apps/meteor/client/startup/customOAuth.ts index f5ca87d93ff55..5b0e3dfb42615 100644 --- a/apps/meteor/client/startup/customOAuth.ts +++ b/apps/meteor/client/startup/customOAuth.ts @@ -1,4 +1,3 @@ -import { isOauthCustomConfiguration } from '@rocket.chat/rest-typings'; import { Meteor } from 'meteor/meteor'; import { ServiceConfiguration } from 'meteor/service-configuration'; @@ -10,7 +9,8 @@ Meteor.startup(() => { custom: true, }) .observe({ - added(record) { + async added(record) { + const { isOauthCustomConfiguration } = await import('@rocket.chat/rest-typings'); if (!isOauthCustomConfiguration(record)) { return; } From 28d207f0bbd8c5f2be94ec7f251a29781e6c5cf6 Mon Sep 17 00:00:00 2001 From: Marcos Spessatto Defendi Date: Thu, 22 Jun 2023 22:58:57 -0300 Subject: [PATCH 13/21] fix: Events listeners were not being removed when services (local) were destroyed (#28240) --- apps/meteor/ee/server/NetworkBroker.ts | 4 +- packages/core-services/babel.config.js | 3 + packages/core-services/package.json | 11 +- packages/core-services/src/LocalBroker.ts | 11 +- .../core-services/src/types/ServiceClass.ts | 14 +- .../core-services/tests/LocalBroker.test.ts | 82 +++++++++ .../core-services/tests/ServiceClass.test.ts | 60 +++++++ yarn.lock | 166 ++++++++++++++---- 8 files changed, 298 insertions(+), 53 deletions(-) create mode 100644 packages/core-services/babel.config.js create mode 100644 packages/core-services/tests/LocalBroker.test.ts create mode 100644 packages/core-services/tests/ServiceClass.test.ts diff --git a/apps/meteor/ee/server/NetworkBroker.ts b/apps/meteor/ee/server/NetworkBroker.ts index 3390847058cf9..76dbeeb8a6cf1 100644 --- a/apps/meteor/ee/server/NetworkBroker.ts +++ b/apps/meteor/ee/server/NetworkBroker.ts @@ -76,6 +76,7 @@ export class NetworkBroker implements IBroker { return; } void this.broker.destroyService(name); + instance.removeAllListeners(); } createService(instance: IServiceClass, serviceDependencies?: string[]): void { @@ -99,13 +100,12 @@ export class NetworkBroker implements IBroker { // Allow services to depend on other services too const dependencies = name !== 'license' ? { dependencies: ['license', ...(serviceDependencies || [])] } : {}; - const service: ServiceSchema = { name, actions: {}, mixins: !instance.isInternal() ? [EnterpriseCheck] : [], ...dependencies, - events: instanceEvents.reduce void>>((map, eventName) => { + events: instanceEvents.reduce void>>((map, { eventName }) => { map[eventName] = /^\$/.test(eventName) ? (ctx: Context): void => { // internal events params are not an array diff --git a/packages/core-services/babel.config.js b/packages/core-services/babel.config.js new file mode 100644 index 0000000000000..7672dadf24ca2 --- /dev/null +++ b/packages/core-services/babel.config.js @@ -0,0 +1,3 @@ +module.exports = { + presets: [['@babel/preset-env', { targets: { node: 'current' } }], '@babel/preset-typescript'], +}; diff --git a/packages/core-services/package.json b/packages/core-services/package.json index 9aea8fa0e1154..5603b95319d6f 100644 --- a/packages/core-services/package.json +++ b/packages/core-services/package.json @@ -3,8 +3,16 @@ "version": "0.0.2", "private": true, "devDependencies": { + "@babel/core": "^7.21.4", + "@babel/preset-env": "^7.21.4", + "@babel/preset-typescript": "^7.21.4", "@rocket.chat/eslint-config": "workspace:^", + "@types/babel__core": "^7", + "@types/babel__preset-env": "^7", + "@types/jest": "^29.5.1", + "babel-jest": "^29.5.0", "eslint": "~8.43.0", + "jest": "^29.5.0", "mongodb": "^4.12.1", "prettier": "~2.8.8", "typescript": "~5.1.3" @@ -12,7 +20,8 @@ "scripts": { "lint": "eslint --ext .js,.jsx,.ts,.tsx .", "lint:fix": "eslint --ext .js,.jsx,.ts,.tsx . --fix", - "test": "echo \"Error: no test specified\" && exit 1", + "jest": "jest", + "testunit": "jest --verbose tests/**/*.test.ts", "dev": "tsc --watch --preserveWatchOutput -p tsconfig.json", "build": "rm -rf dist && tsc -p tsconfig.json" }, diff --git a/packages/core-services/src/LocalBroker.ts b/packages/core-services/src/LocalBroker.ts index c63915909397e..4ac66254b9c06 100644 --- a/packages/core-services/src/LocalBroker.ts +++ b/packages/core-services/src/LocalBroker.ts @@ -35,9 +35,7 @@ export class LocalBroker implements IBroker { destroyService(instance: ServiceClass): void { const namespace = instance.getName(); - instance.getEvents().forEach((eventName) => { - this.events.removeListener(eventName, instance.emit); - }); + instance.getEvents().forEach((event) => event.listeners.forEach((listener) => this.events.removeListener(event.eventName, listener))); const methods = instance.constructor?.name === 'Object' @@ -50,6 +48,7 @@ export class LocalBroker implements IBroker { this.methods.delete(`${namespace}.${method}`); } + instance.removeAllListeners(); instance.stopped(); } @@ -60,11 +59,7 @@ export class LocalBroker implements IBroker { instance.created(); - instance.getEvents().forEach((eventName) => { - this.events.on(eventName, (...args) => { - instance.emit(eventName, ...(args as Parameters)); - }); - }); + instance.getEvents().forEach((event) => event.listeners.forEach((listener) => this.events.on(event.eventName, listener))); const methods = instance.constructor?.name === 'Object' diff --git a/packages/core-services/src/types/ServiceClass.ts b/packages/core-services/src/types/ServiceClass.ts index 427d9d7b7d0bf..33a4f4a901628 100644 --- a/packages/core-services/src/types/ServiceClass.ts +++ b/packages/core-services/src/types/ServiceClass.ts @@ -30,7 +30,8 @@ export interface IServiceClass { onNodeConnected?({ node, reconnected }: { node: IBrokerNode; reconnected: boolean }): void; onNodeUpdated?({ node }: { node: IBrokerNode }): void; onNodeDisconnected?({ node, unexpected }: { node: IBrokerNode; unexpected: boolean }): Promise; - getEvents(): Array; + getEvents(): { eventName: keyof EventSignatures; listeners: { (...args: any[]): void }[] }[]; + removeAllListeners(): void; setApi(api: IApiService): void; @@ -61,8 +62,15 @@ export abstract class ServiceClass implements IServiceClass { this.api = api; } - getEvents(): Array { - return this.events.eventNames() as unknown as Array; + getEvents(): { eventName: keyof EventSignatures; listeners: { (...args: any[]): void }[] }[] { + return this.events.eventNames().map((eventName) => ({ + eventName: eventName as unknown as keyof EventSignatures, + listeners: this.events.rawListeners(eventName) as { (...args: any[]): void }[], + })); + } + + removeAllListeners(): void { + this.events.removeAllListeners(); } getName(): string | undefined { diff --git a/packages/core-services/tests/LocalBroker.test.ts b/packages/core-services/tests/LocalBroker.test.ts new file mode 100644 index 0000000000000..fa4d288f3947b --- /dev/null +++ b/packages/core-services/tests/LocalBroker.test.ts @@ -0,0 +1,82 @@ +import { ServiceClass } from '../src'; +import { LocalBroker } from '../src/LocalBroker'; + +describe('LocalBroker', () => { + describe('#createService()', () => { + it('should call all the expected lifecycle hooks when creating a service', () => { + const createdStub = jest.fn(); + const instance = new (class extends ServiceClass { + async created() { + createdStub(); + } + })(); + + const broker = new LocalBroker(); + broker.createService(instance); + + expect(createdStub).toBeCalled(); + }); + }); + + describe('#destroyService()', () => { + it('should call all the expected lifecycle hooks when destroying a service', () => { + const removeAllListenersStub = jest.fn(); + const stoppedStub = jest.fn(); + const instance = new (class extends ServiceClass { + removeAllListeners() { + removeAllListenersStub(); + } + + async stopped() { + stoppedStub(); + } + })(); + + const broker = new LocalBroker(); + broker.createService(instance); + broker.destroyService(instance); + + expect(removeAllListenersStub).toBeCalled(); + expect(stoppedStub).toBeCalled(); + }); + }); + + describe('#broadcast()', () => { + it('should call all the ServiceClass instance registered events', () => { + const instance = new (class extends ServiceClass {})(); + const testListener = jest.fn(); + const testListener2 = jest.fn(); + const test2Listener = jest.fn(); + instance.onEvent('test' as any, testListener); + instance.onEvent('test' as any, testListener2); + instance.onEvent('test2' as any, test2Listener); + + const broker = new LocalBroker(); + broker.createService(instance); + broker.broadcast('test' as any, 'test'); + broker.broadcast('test2' as any, 'test2'); + + expect(testListener).toBeCalledWith('test'); + expect(testListener2).toBeCalledWith('test'); + expect(test2Listener).toBeCalledWith('test2'); + }); + + it('should NOT call any instance event anymore after the service being destroyed', () => { + const instance = new (class extends ServiceClass {})(); + const testListener = jest.fn(); + const test2Listener = jest.fn(); + instance.onEvent('test' as any, testListener); + instance.onEvent('test2' as any, test2Listener); + + const broker = new LocalBroker(); + broker.createService(instance); + broker.destroyService(instance); + + broker.broadcast('test' as any, 'test'); + broker.broadcast('test2' as any, 'test2'); + + expect(testListener).not.toBeCalled(); + expect(test2Listener).not.toBeCalled(); + }); + }); +}); diff --git a/packages/core-services/tests/ServiceClass.test.ts b/packages/core-services/tests/ServiceClass.test.ts new file mode 100644 index 0000000000000..48b8abc923d67 --- /dev/null +++ b/packages/core-services/tests/ServiceClass.test.ts @@ -0,0 +1,60 @@ +/* eslint-disable @typescript-eslint/no-empty-function */ +import { ServiceClass } from '../src/types/ServiceClass'; + +describe('ServiceClass', () => { + describe('#onEvent()', () => { + it('should add one event to the internal event emitter instance', () => { + const instance = new (class extends ServiceClass {})(); + + instance.onEvent('test' as any, () => {}); + + expect(instance.getEvents()).toHaveLength(1); + expect(instance.getEvents()[0].eventName).toBe('test'); + }); + }); + describe('#getEvents()', () => { + it('should return an array of events with all of their listeners', () => { + const instance = new (class extends ServiceClass {})(); + const listener1 = () => {}; + const listener2 = () => {}; + const listener3 = () => {}; + const listeners = [listener1, listener2, listener3]; + + instance.onEvent('test' as any, listener1); + instance.onEvent('test' as any, listener2); + instance.onEvent('test' as any, listener3); + + expect(instance.getEvents()).toHaveLength(1); + expect(instance.getEvents()[0].listeners).toEqual(listeners); + }); + }); + + describe('#removeAllListeners()', () => { + it('should remove all listeners', () => { + const instance = new (class extends ServiceClass {})(); + const listener1 = () => {}; + const listener2 = () => {}; + const listener3 = () => {}; + + instance.onEvent('test' as any, listener1); + instance.onEvent('test' as any, listener2); + instance.onEvent('test' as any, listener3); + + expect(instance.getEvents()).toHaveLength(1); + instance.removeAllListeners(); + expect(instance.getEvents()).toHaveLength(0); + }); + + it('should not be possible to receive any event after remove them all', () => { + const instance = new (class extends ServiceClass {})(); + const listener1 = jest.fn(); + + instance.onEvent('test' as any, listener1); + instance.emit('test' as any, 'test'); + instance.removeAllListeners(); + instance.emit('test' as any, 'test'); + + expect(listener1).toHaveBeenCalledTimes(1); + }); + }); +}); diff --git a/yarn.lock b/yarn.lock index 1b84a773319d1..6d50fb8fa28a6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1221,7 +1221,7 @@ __metadata: languageName: node linkType: hard -"@babel/helper-create-class-features-plugin@npm:^7.17.6, @babel/helper-create-class-features-plugin@npm:^7.18.6, @babel/helper-create-class-features-plugin@npm:^7.21.0": +"@babel/helper-create-class-features-plugin@npm:^7.17.6, @babel/helper-create-class-features-plugin@npm:^7.18.6": version: 7.21.8 resolution: "@babel/helper-create-class-features-plugin@npm:7.21.8" dependencies: @@ -1240,6 +1240,24 @@ __metadata: languageName: node linkType: hard +"@babel/helper-create-class-features-plugin@npm:^7.21.0": + version: 7.21.4 + resolution: "@babel/helper-create-class-features-plugin@npm:7.21.4" + dependencies: + "@babel/helper-annotate-as-pure": ^7.18.6 + "@babel/helper-environment-visitor": ^7.18.9 + "@babel/helper-function-name": ^7.21.0 + "@babel/helper-member-expression-to-functions": ^7.21.0 + "@babel/helper-optimise-call-expression": ^7.18.6 + "@babel/helper-replace-supers": ^7.20.7 + "@babel/helper-skip-transparent-expression-wrappers": ^7.20.0 + "@babel/helper-split-export-declaration": ^7.18.6 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 9123ca80a4894aafdb1f0bc08e44f6be7b12ed1fbbe99c501b484f9b1a17ff296b6c90c18c222047d53c276f07f17b4de857946fa9d0aa207023b03e4cc716f2 + languageName: node + linkType: hard + "@babel/helper-create-class-features-plugin@npm:^7.22.5": version: 7.22.5 resolution: "@babel/helper-create-class-features-plugin@npm:7.22.5" @@ -1259,7 +1277,7 @@ __metadata: languageName: node linkType: hard -"@babel/helper-create-regexp-features-plugin@npm:^7.18.6, @babel/helper-create-regexp-features-plugin@npm:^7.20.5": +"@babel/helper-create-regexp-features-plugin@npm:^7.18.6": version: 7.21.8 resolution: "@babel/helper-create-regexp-features-plugin@npm:7.21.8" dependencies: @@ -1272,6 +1290,18 @@ __metadata: languageName: node linkType: hard +"@babel/helper-create-regexp-features-plugin@npm:^7.20.5": + version: 7.21.4 + resolution: "@babel/helper-create-regexp-features-plugin@npm:7.21.4" + dependencies: + "@babel/helper-annotate-as-pure": ^7.18.6 + regexpu-core: ^5.3.1 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 78334865db2cd1d64d103bd0d96dee2818b0387d10aa973c084e245e829df32652bca530803e397b7158af4c02b9b21d5a9601c29bdfbb8d54a3d4ad894e067b + languageName: node + linkType: hard + "@babel/helper-create-regexp-features-plugin@npm:^7.22.5": version: 7.22.5 resolution: "@babel/helper-create-regexp-features-plugin@npm:7.22.5" @@ -1396,6 +1426,15 @@ __metadata: languageName: node linkType: hard +"@babel/helper-member-expression-to-functions@npm:^7.20.7, @babel/helper-member-expression-to-functions@npm:^7.21.0": + version: 7.21.0 + resolution: "@babel/helper-member-expression-to-functions@npm:7.21.0" + dependencies: + "@babel/types": ^7.21.0 + checksum: 49cbb865098195fe82ba22da3a8fe630cde30dcd8ebf8ad5f9a24a2b685150c6711419879cf9d99b94dad24cff9244d8c2a890d3d7ec75502cd01fe58cff5b5d + languageName: node + linkType: hard + "@babel/helper-member-expression-to-functions@npm:^7.21.5": version: 7.21.5 resolution: "@babel/helper-member-expression-to-functions@npm:7.21.5" @@ -1432,9 +1471,9 @@ __metadata: languageName: node linkType: hard -"@babel/helper-module-transforms@npm:^7.12.1, @babel/helper-module-transforms@npm:^7.18.6, @babel/helper-module-transforms@npm:^7.20.11, @babel/helper-module-transforms@npm:^7.21.2": - version: 7.21.2 - resolution: "@babel/helper-module-transforms@npm:7.21.2" +"@babel/helper-module-transforms@npm:^7.12.1, @babel/helper-module-transforms@npm:^7.18.6, @babel/helper-module-transforms@npm:^7.21.5": + version: 7.21.5 + resolution: "@babel/helper-module-transforms@npm:7.21.5" dependencies: "@babel/helper-environment-visitor": ^7.21.5 "@babel/helper-module-imports": ^7.21.4 @@ -1442,25 +1481,25 @@ __metadata: "@babel/helper-split-export-declaration": ^7.18.6 "@babel/helper-validator-identifier": ^7.19.1 "@babel/template": ^7.20.7 - "@babel/traverse": ^7.21.2 - "@babel/types": ^7.21.2 - checksum: 8a1c129a4f90bdf97d8b6e7861732c9580f48f877aaaafbc376ce2482febebcb8daaa1de8bc91676d12886487603f8c62a44f9e90ee76d6cac7f9225b26a49e1 + "@babel/traverse": ^7.21.5 + "@babel/types": ^7.21.5 + checksum: 1ccfc88830675a5d485d198e918498f9683cdd46f973fdd4fe1c85b99648fb70f87fca07756c7a05dc201bd9b248c74ced06ea80c9991926ac889f53c3659675 languageName: node linkType: hard -"@babel/helper-module-transforms@npm:^7.21.5": - version: 7.21.5 - resolution: "@babel/helper-module-transforms@npm:7.21.5" +"@babel/helper-module-transforms@npm:^7.20.11, @babel/helper-module-transforms@npm:^7.21.2": + version: 7.21.2 + resolution: "@babel/helper-module-transforms@npm:7.21.2" dependencies: - "@babel/helper-environment-visitor": ^7.21.5 - "@babel/helper-module-imports": ^7.21.4 - "@babel/helper-simple-access": ^7.21.5 + "@babel/helper-environment-visitor": ^7.18.9 + "@babel/helper-module-imports": ^7.18.6 + "@babel/helper-simple-access": ^7.20.2 "@babel/helper-split-export-declaration": ^7.18.6 "@babel/helper-validator-identifier": ^7.19.1 "@babel/template": ^7.20.7 - "@babel/traverse": ^7.21.5 - "@babel/types": ^7.21.5 - checksum: 1ccfc88830675a5d485d198e918498f9683cdd46f973fdd4fe1c85b99648fb70f87fca07756c7a05dc201bd9b248c74ced06ea80c9991926ac889f53c3659675 + "@babel/traverse": ^7.21.2 + "@babel/types": ^7.21.2 + checksum: 8a1c129a4f90bdf97d8b6e7861732c9580f48f877aaaafbc376ce2482febebcb8daaa1de8bc91676d12886487603f8c62a44f9e90ee76d6cac7f9225b26a49e1 languageName: node linkType: hard @@ -1547,7 +1586,7 @@ __metadata: languageName: node linkType: hard -"@babel/helper-replace-supers@npm:^7.16.7, @babel/helper-replace-supers@npm:^7.18.6, @babel/helper-replace-supers@npm:^7.20.7, @babel/helper-replace-supers@npm:^7.21.5": +"@babel/helper-replace-supers@npm:^7.16.7, @babel/helper-replace-supers@npm:^7.18.6, @babel/helper-replace-supers@npm:^7.21.5": version: 7.21.5 resolution: "@babel/helper-replace-supers@npm:7.21.5" dependencies: @@ -1561,6 +1600,20 @@ __metadata: languageName: node linkType: hard +"@babel/helper-replace-supers@npm:^7.20.7": + version: 7.20.7 + resolution: "@babel/helper-replace-supers@npm:7.20.7" + dependencies: + "@babel/helper-environment-visitor": ^7.18.9 + "@babel/helper-member-expression-to-functions": ^7.20.7 + "@babel/helper-optimise-call-expression": ^7.18.6 + "@babel/template": ^7.20.7 + "@babel/traverse": ^7.20.7 + "@babel/types": ^7.20.7 + checksum: b8e0087c9b0c1446e3c6f3f72b73b7e03559c6b570e2cfbe62c738676d9ebd8c369a708cf1a564ef88113b4330750a50232ee1131d303d478b7a5e65e46fbc7c + languageName: node + linkType: hard + "@babel/helper-replace-supers@npm:^7.22.5": version: 7.22.5 resolution: "@babel/helper-replace-supers@npm:7.22.5" @@ -3500,7 +3553,7 @@ __metadata: languageName: node linkType: hard -"@babel/preset-env@npm:^7.12.11": +"@babel/preset-env@npm:^7.12.11, @babel/preset-env@npm:^7.21.4": version: 7.21.4 resolution: "@babel/preset-env@npm:7.21.4" dependencies: @@ -3735,7 +3788,7 @@ __metadata: languageName: node linkType: hard -"@babel/preset-typescript@npm:^7.12.7": +"@babel/preset-typescript@npm:^7.12.7, @babel/preset-typescript@npm:^7.21.4": version: 7.21.4 resolution: "@babel/preset-typescript@npm:7.21.4" dependencies: @@ -3766,8 +3819,8 @@ __metadata: linkType: hard "@babel/register@npm:^7.12.1": - version: 7.21.0 - resolution: "@babel/register@npm:7.21.0" + version: 7.18.9 + resolution: "@babel/register@npm:7.18.9" dependencies: clone-deep: ^4.0.1 find-cache-dir: ^2.0.0 @@ -3776,7 +3829,7 @@ __metadata: source-map-support: ^0.5.16 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 9745cc7520b4c5e64cc54f4851c3b78af82e1f8cffc9041f5cc0b9aef62d86a9a8617327fc975b5e0e39cb5cc0aba7ae02429884390ee93e0de29152fa849b4f + checksum: 4aeaff97e061a397f632659082ba86c539ef8194697b236d991c10d1c2ea8f73213d3b5b3b2c24625951a1ef726b7a7d2e70f70ffcb37f79ef0c1a745eebef21 languageName: node linkType: hard @@ -3878,7 +3931,7 @@ __metadata: languageName: node linkType: hard -"@babel/traverse@npm:^7.1.6, @babel/traverse@npm:^7.12.11, @babel/traverse@npm:^7.12.9, @babel/traverse@npm:^7.13.0, @babel/traverse@npm:^7.19.0, @babel/traverse@npm:^7.21.0, @babel/traverse@npm:^7.21.2, @babel/traverse@npm:^7.21.4, @babel/traverse@npm:^7.7.2": +"@babel/traverse@npm:^7.1.6, @babel/traverse@npm:^7.12.11, @babel/traverse@npm:^7.12.9, @babel/traverse@npm:^7.13.0, @babel/traverse@npm:^7.19.0, @babel/traverse@npm:^7.20.7, @babel/traverse@npm:^7.21.0, @babel/traverse@npm:^7.21.2, @babel/traverse@npm:^7.21.4, @babel/traverse@npm:^7.7.2": version: 7.21.4 resolution: "@babel/traverse@npm:7.21.4" dependencies: @@ -3932,25 +3985,25 @@ __metadata: languageName: node linkType: hard -"@babel/types@npm:^7.0.0, @babel/types@npm:^7.12.11, @babel/types@npm:^7.12.7, @babel/types@npm:^7.18.6, @babel/types@npm:^7.18.9, @babel/types@npm:^7.19.0, @babel/types@npm:^7.2.0, @babel/types@npm:^7.20.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.21.0, @babel/types@npm:^7.21.2, @babel/types@npm:^7.21.4, @babel/types@npm:^7.3.0, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3": - version: 7.21.4 - resolution: "@babel/types@npm:7.21.4" +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.12.11, @babel/types@npm:^7.12.7, @babel/types@npm:^7.18.6, @babel/types@npm:^7.18.9, @babel/types@npm:^7.19.0, @babel/types@npm:^7.2.0, @babel/types@npm:^7.21.5, @babel/types@npm:^7.3.0, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3": + version: 7.21.5 + resolution: "@babel/types@npm:7.21.5" dependencies: - "@babel/helper-string-parser": ^7.19.4 + "@babel/helper-string-parser": ^7.21.5 "@babel/helper-validator-identifier": ^7.19.1 to-fast-properties: ^2.0.0 - checksum: 587bc55a91ce003b0f8aa10d70070f8006560d7dc0360dc0406d306a2cb2a10154e2f9080b9c37abec76907a90b330a536406cb75e6bdc905484f37b75c73219 + checksum: 43242a99c612d13285ee4af46cc0f1066bcb6ffd38307daef7a76e8c70f36cfc3255eb9e75c8e768b40e761176c313aec4d5c0b9d97a21e494d49d5fd123a9f7 languageName: node linkType: hard -"@babel/types@npm:^7.21.5": - version: 7.21.5 - resolution: "@babel/types@npm:7.21.5" +"@babel/types@npm:^7.20.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.21.0, @babel/types@npm:^7.21.2, @babel/types@npm:^7.21.4": + version: 7.21.4 + resolution: "@babel/types@npm:7.21.4" dependencies: - "@babel/helper-string-parser": ^7.21.5 + "@babel/helper-string-parser": ^7.19.4 "@babel/helper-validator-identifier": ^7.19.1 to-fast-properties: ^2.0.0 - checksum: 43242a99c612d13285ee4af46cc0f1066bcb6ffd38307daef7a76e8c70f36cfc3255eb9e75c8e768b40e761176c313aec4d5c0b9d97a21e494d49d5fd123a9f7 + checksum: 587bc55a91ce003b0f8aa10d70070f8006560d7dc0360dc0406d306a2cb2a10154e2f9080b9c37abec76907a90b330a536406cb75e6bdc905484f37b75c73219 languageName: node linkType: hard @@ -5665,13 +5718,20 @@ __metadata: languageName: node linkType: hard -"@jridgewell/resolve-uri@npm:3.1.0, @jridgewell/resolve-uri@npm:^3.0.3": +"@jridgewell/resolve-uri@npm:3.1.0": version: 3.1.0 resolution: "@jridgewell/resolve-uri@npm:3.1.0" checksum: b5ceaaf9a110fcb2780d1d8f8d4a0bfd216702f31c988d8042e5f8fbe353c55d9b0f55a1733afdc64806f8e79c485d2464680ac48a0d9fcadb9548ee6b81d267 languageName: node linkType: hard +"@jridgewell/resolve-uri@npm:^3.0.3": + version: 3.0.5 + resolution: "@jridgewell/resolve-uri@npm:3.0.5" + checksum: 1ee652b693da7979ac4007926cc3f0a32b657ffeb913e111f44e5b67153d94a2f28a1d560101cc0cf8087625468293a69a00f634a2914e1a6d0817ba2039a913 + languageName: node + linkType: hard + "@jridgewell/set-array@npm:^1.0.1": version: 1.1.2 resolution: "@jridgewell/set-array@npm:1.1.2" @@ -5699,13 +5759,20 @@ __metadata: languageName: node linkType: hard -"@jridgewell/sourcemap-codec@npm:1.4.14, @jridgewell/sourcemap-codec@npm:^1.4.10": +"@jridgewell/sourcemap-codec@npm:1.4.14": version: 1.4.14 resolution: "@jridgewell/sourcemap-codec@npm:1.4.14" checksum: 61100637b6d173d3ba786a5dff019e1a74b1f394f323c1fee337ff390239f053b87266c7a948777f4b1ee68c01a8ad0ab61e5ff4abb5a012a0b091bec391ab97 languageName: node linkType: hard +"@jridgewell/sourcemap-codec@npm:^1.4.10": + version: 1.4.11 + resolution: "@jridgewell/sourcemap-codec@npm:1.4.11" + checksum: 3b2afaf8400fb07a36db60e901fcce6a746cdec587310ee9035939d89878e57b2dec8173b0b8f63176f647efa352294049a53c49739098eb907ff81fec2547c8 + languageName: node + linkType: hard + "@jridgewell/trace-mapping@npm:0.3.9": version: 0.3.9 resolution: "@jridgewell/trace-mapping@npm:0.3.9" @@ -9368,6 +9435,9 @@ __metadata: version: 0.0.0-use.local resolution: "@rocket.chat/core-services@workspace:packages/core-services" dependencies: + "@babel/core": ^7.21.4 + "@babel/preset-env": ^7.21.4 + "@babel/preset-typescript": ^7.21.4 "@rocket.chat/apps-engine": 1.39.1 "@rocket.chat/core-typings": "workspace:^" "@rocket.chat/eslint-config": "workspace:^" @@ -9376,9 +9446,14 @@ __metadata: "@rocket.chat/models": "workspace:^" "@rocket.chat/rest-typings": "workspace:^" "@rocket.chat/ui-kit": next + "@types/babel__core": ^7 + "@types/babel__preset-env": ^7 "@types/fibers": ^3.1.1 + "@types/jest": ^29.5.1 + babel-jest: ^29.5.0 eslint: ~8.43.0 fibers: ^5.0.3 + jest: ^29.5.0 mongodb: ^4.12.1 prettier: ~2.8.8 typescript: ~5.1.3 @@ -12923,7 +12998,7 @@ __metadata: languageName: node linkType: hard -"@types/babel__core@npm:^7.1.14": +"@types/babel__core@npm:^7": version: 7.20.0 resolution: "@types/babel__core@npm:7.20.0" dependencies: @@ -12936,6 +13011,19 @@ __metadata: languageName: node linkType: hard +"@types/babel__core@npm:^7.1.14": + version: 7.1.20 + resolution: "@types/babel__core@npm:7.1.20" + dependencies: + "@babel/parser": ^7.20.7 + "@babel/types": ^7.20.7 + "@types/babel__generator": "*" + "@types/babel__template": "*" + "@types/babel__traverse": "*" + checksum: a09c4f0456552547a5b8a5a009a3daec4d362f622168f8e08bda0ded2da0a65ab0b1642e23c433b3616721f5701dc34a996c5bde5baeaea53eda98f438043f2c + languageName: node + linkType: hard + "@types/babel__core@npm:~7.20.1": version: 7.20.1 resolution: "@types/babel__core@npm:7.20.1" @@ -12958,7 +13046,7 @@ __metadata: languageName: node linkType: hard -"@types/babel__preset-env@npm:~7.9.2": +"@types/babel__preset-env@npm:^7, @types/babel__preset-env@npm:~7.9.2": version: 7.9.2 resolution: "@types/babel__preset-env@npm:7.9.2" checksum: a905ed92a3f602384966153e74a94790425e98af54e392a7fcfb5c5ded2f2a58c49a9fa64a0cb506fbffb8169ad25b56ea87983c812a4fb880f0716668c8c085 @@ -13490,7 +13578,7 @@ __metadata: languageName: node linkType: hard -"@types/jest@npm:^29.5.2, @types/jest@npm:~29.5.2": +"@types/jest@npm:^29.5.1, @types/jest@npm:^29.5.2, @types/jest@npm:~29.5.2": version: 29.5.2 resolution: "@types/jest@npm:29.5.2" dependencies: From e22dfc15ef2aed2700eac5b1f224a01464bdc579 Mon Sep 17 00:00:00 2001 From: Aleksander Nicacio da Silva Date: Thu, 22 Jun 2023 23:52:38 -0300 Subject: [PATCH 14/21] chore: improve omnichannel tests reliability (#29572) Co-authored-by: Guilherme Gazzo --- .../{ => omnichannel}/omnichannel-agents.spec.ts | 6 +++--- .../omnichannel-auto-onhold-chat-closing.spec.ts | 10 +++++----- ...channel-auto-transfer-unanswered-chat.spec.ts | 10 +++++----- .../omnichannel-canned-responses-sidebar.spec.ts | 10 +++++----- ...hannel-changing-room-priority-and-sla.spec.ts | 14 +++++++------- .../omnichannel-chat-history.spec.ts | 8 ++++---- .../omnichannel-close-chat.spec.ts | 8 ++++---- .../omnichannel-close-inquiry.spec.ts | 8 ++++---- .../omnichannel-contact-center.spec.ts | 16 ++++++++-------- .../omnichannel-contact-info.spec.ts | 8 ++++---- .../omnichannel-currentChats.spec.ts | 4 ++-- .../omnichannel-custom-fields.spec.ts | 6 +++--- .../omnichannel-departaments-ce.spec.ts | 8 ++++---- .../omnichannel-departaments.spec.ts | 8 ++++---- .../omnichannel-livechat.spec.ts | 8 ++++---- .../omnichannel-manager.spec.ts | 6 +++--- .../omnichannel-priorities.spec.ts | 8 ++++---- .../omnichannel-send-transcript.spec.ts | 10 +++++----- .../omnichannel-sla-policies.spec.ts | 12 ++++++------ .../omnichannel-takeChat.spec.ts | 8 ++++---- ...mnichannel-transfer-to-another-agents.spec.ts | 14 +++++++------- .../omnichannel-triggers.spec.ts | 8 ++++---- .../e2e/page-objects/omnichannel-triggers.ts | 2 +- 23 files changed, 100 insertions(+), 100 deletions(-) rename apps/meteor/tests/e2e/{ => omnichannel}/omnichannel-agents.spec.ts (90%) rename apps/meteor/tests/e2e/{ => omnichannel}/omnichannel-auto-onhold-chat-closing.spec.ts (92%) rename apps/meteor/tests/e2e/{ => omnichannel}/omnichannel-auto-transfer-unanswered-chat.spec.ts (90%) rename apps/meteor/tests/e2e/{ => omnichannel}/omnichannel-canned-responses-sidebar.spec.ts (87%) rename apps/meteor/tests/e2e/{ => omnichannel}/omnichannel-changing-room-priority-and-sla.spec.ts (90%) rename apps/meteor/tests/e2e/{ => omnichannel}/omnichannel-chat-history.spec.ts (92%) rename apps/meteor/tests/e2e/{ => omnichannel}/omnichannel-close-chat.spec.ts (89%) rename apps/meteor/tests/e2e/{ => omnichannel}/omnichannel-close-inquiry.spec.ts (92%) rename apps/meteor/tests/e2e/{ => omnichannel}/omnichannel-contact-center.spec.ts (96%) rename apps/meteor/tests/e2e/{ => omnichannel}/omnichannel-contact-info.spec.ts (89%) rename apps/meteor/tests/e2e/{ => omnichannel}/omnichannel-currentChats.spec.ts (96%) rename apps/meteor/tests/e2e/{ => omnichannel}/omnichannel-custom-fields.spec.ts (91%) rename apps/meteor/tests/e2e/{ => omnichannel}/omnichannel-departaments-ce.spec.ts (88%) rename apps/meteor/tests/e2e/{ => omnichannel}/omnichannel-departaments.spec.ts (97%) rename apps/meteor/tests/e2e/{ => omnichannel}/omnichannel-livechat.spec.ts (93%) rename apps/meteor/tests/e2e/{ => omnichannel}/omnichannel-manager.spec.ts (87%) rename apps/meteor/tests/e2e/{ => omnichannel}/omnichannel-priorities.spec.ts (96%) rename apps/meteor/tests/e2e/{ => omnichannel}/omnichannel-send-transcript.spec.ts (89%) rename apps/meteor/tests/e2e/{ => omnichannel}/omnichannel-sla-policies.spec.ts (94%) rename apps/meteor/tests/e2e/{ => omnichannel}/omnichannel-takeChat.spec.ts (93%) rename apps/meteor/tests/e2e/{ => omnichannel}/omnichannel-transfer-to-another-agents.spec.ts (88%) rename apps/meteor/tests/e2e/{ => omnichannel}/omnichannel-triggers.spec.ts (92%) diff --git a/apps/meteor/tests/e2e/omnichannel-agents.spec.ts b/apps/meteor/tests/e2e/omnichannel/omnichannel-agents.spec.ts similarity index 90% rename from apps/meteor/tests/e2e/omnichannel-agents.spec.ts rename to apps/meteor/tests/e2e/omnichannel/omnichannel-agents.spec.ts index b5cfa4b848ef5..263c5660ec181 100644 --- a/apps/meteor/tests/e2e/omnichannel-agents.spec.ts +++ b/apps/meteor/tests/e2e/omnichannel/omnichannel-agents.spec.ts @@ -1,6 +1,6 @@ -import { Users } from './fixtures/userStates'; -import { OmnichannelAgents } from './page-objects'; -import { test, expect } from './utils/test'; +import { Users } from '../fixtures/userStates'; +import { OmnichannelAgents } from '../page-objects'; +import { test, expect } from '../utils/test'; test.use({ storageState: Users.admin.state }); diff --git a/apps/meteor/tests/e2e/omnichannel-auto-onhold-chat-closing.spec.ts b/apps/meteor/tests/e2e/omnichannel/omnichannel-auto-onhold-chat-closing.spec.ts similarity index 92% rename from apps/meteor/tests/e2e/omnichannel-auto-onhold-chat-closing.spec.ts rename to apps/meteor/tests/e2e/omnichannel/omnichannel-auto-onhold-chat-closing.spec.ts index f75839241acc8..a20ccf05006a7 100644 --- a/apps/meteor/tests/e2e/omnichannel-auto-onhold-chat-closing.spec.ts +++ b/apps/meteor/tests/e2e/omnichannel/omnichannel-auto-onhold-chat-closing.spec.ts @@ -1,11 +1,11 @@ import { faker } from '@faker-js/faker'; import type { Page } from '@playwright/test'; -import { IS_EE } from './config/constants'; -import { createAuxContext } from './fixtures/createAuxContext'; -import { Users } from './fixtures/userStates'; -import { OmnichannelLiveChat, HomeChannel } from './page-objects'; -import { test, expect } from './utils/test'; +import { IS_EE } from '../config/constants'; +import { createAuxContext } from '../fixtures/createAuxContext'; +import { Users } from '../fixtures/userStates'; +import { OmnichannelLiveChat, HomeChannel } from '../page-objects'; +import { test, expect } from '../utils/test'; test.describe('omnichannel-auto-onhold-chat-closing', () => { test.skip(!IS_EE, 'Enterprise Only'); diff --git a/apps/meteor/tests/e2e/omnichannel-auto-transfer-unanswered-chat.spec.ts b/apps/meteor/tests/e2e/omnichannel/omnichannel-auto-transfer-unanswered-chat.spec.ts similarity index 90% rename from apps/meteor/tests/e2e/omnichannel-auto-transfer-unanswered-chat.spec.ts rename to apps/meteor/tests/e2e/omnichannel/omnichannel-auto-transfer-unanswered-chat.spec.ts index ef3203c91cc66..67bef3dbac527 100644 --- a/apps/meteor/tests/e2e/omnichannel-auto-transfer-unanswered-chat.spec.ts +++ b/apps/meteor/tests/e2e/omnichannel/omnichannel-auto-transfer-unanswered-chat.spec.ts @@ -1,11 +1,11 @@ import { faker } from '@faker-js/faker'; import type { Page } from '@playwright/test'; -import { IS_EE } from './config/constants'; -import { createAuxContext } from './fixtures/createAuxContext'; -import { Users } from './fixtures/userStates'; -import { OmnichannelLiveChat, HomeChannel } from './page-objects'; -import { test, expect } from './utils/test'; +import { IS_EE } from '../config/constants'; +import { createAuxContext } from '../fixtures/createAuxContext'; +import { Users } from '../fixtures/userStates'; +import { OmnichannelLiveChat, HomeChannel } from '../page-objects'; +import { test, expect } from '../utils/test'; test.describe('omnichannel-auto-transfer-unanswered-chat', () => { test.skip(!IS_EE, 'Enterprise Only'); diff --git a/apps/meteor/tests/e2e/omnichannel-canned-responses-sidebar.spec.ts b/apps/meteor/tests/e2e/omnichannel/omnichannel-canned-responses-sidebar.spec.ts similarity index 87% rename from apps/meteor/tests/e2e/omnichannel-canned-responses-sidebar.spec.ts rename to apps/meteor/tests/e2e/omnichannel/omnichannel-canned-responses-sidebar.spec.ts index b34d0bfc0f744..4df5ee1dc8d13 100644 --- a/apps/meteor/tests/e2e/omnichannel-canned-responses-sidebar.spec.ts +++ b/apps/meteor/tests/e2e/omnichannel/omnichannel-canned-responses-sidebar.spec.ts @@ -1,11 +1,11 @@ import { faker } from '@faker-js/faker'; import type { Page } from '@playwright/test'; -import { IS_EE } from './config/constants'; -import { createAuxContext } from './fixtures/createAuxContext'; -import { Users } from './fixtures/userStates'; -import { OmnichannelLiveChat, HomeChannel } from './page-objects'; -import { test } from './utils/test'; +import { IS_EE } from '../config/constants'; +import { createAuxContext } from '../fixtures/createAuxContext'; +import { Users } from '../fixtures/userStates'; +import { OmnichannelLiveChat, HomeChannel } from '../page-objects'; +import { test } from '../utils/test'; test.describe('Omnichannel Canned Responses Sidebar', () => { test.skip(!IS_EE, 'Enterprise Only'); diff --git a/apps/meteor/tests/e2e/omnichannel-changing-room-priority-and-sla.spec.ts b/apps/meteor/tests/e2e/omnichannel/omnichannel-changing-room-priority-and-sla.spec.ts similarity index 90% rename from apps/meteor/tests/e2e/omnichannel-changing-room-priority-and-sla.spec.ts rename to apps/meteor/tests/e2e/omnichannel/omnichannel-changing-room-priority-and-sla.spec.ts index 28ac6205978db..042e43c5cc5ea 100644 --- a/apps/meteor/tests/e2e/omnichannel-changing-room-priority-and-sla.spec.ts +++ b/apps/meteor/tests/e2e/omnichannel/omnichannel-changing-room-priority-and-sla.spec.ts @@ -1,13 +1,13 @@ import { faker } from '@faker-js/faker'; import type { Page } from '@playwright/test'; -import { ADMIN_CREDENTIALS, IS_EE } from './config/constants'; -import { createAuxContext } from './fixtures/createAuxContext'; -import { Users } from './fixtures/userStates'; -import { OmnichannelLiveChat, HomeChannel } from './page-objects'; -import { getPriorityByi18nLabel } from './utils/omnichannel/priority'; -import { createSLA } from './utils/omnichannel/sla'; -import { test, expect } from './utils/test'; +import { ADMIN_CREDENTIALS, IS_EE } from '../config/constants'; +import { createAuxContext } from '../fixtures/createAuxContext'; +import { Users } from '../fixtures/userStates'; +import { OmnichannelLiveChat, HomeChannel } from '../page-objects'; +import { getPriorityByi18nLabel } from '../utils/omnichannel/priority'; +import { createSLA } from '../utils/omnichannel/sla'; +import { test, expect } from '../utils/test'; const getRoomId = (page: Page): string => { // url is of the form: http://localhost:3000/live/:rid/room-info diff --git a/apps/meteor/tests/e2e/omnichannel-chat-history.spec.ts b/apps/meteor/tests/e2e/omnichannel/omnichannel-chat-history.spec.ts similarity index 92% rename from apps/meteor/tests/e2e/omnichannel-chat-history.spec.ts rename to apps/meteor/tests/e2e/omnichannel/omnichannel-chat-history.spec.ts index b2406b15249e9..303285db35237 100644 --- a/apps/meteor/tests/e2e/omnichannel-chat-history.spec.ts +++ b/apps/meteor/tests/e2e/omnichannel/omnichannel-chat-history.spec.ts @@ -1,10 +1,10 @@ import { faker } from '@faker-js/faker'; import type { Page } from '@playwright/test'; -import { createAuxContext } from './fixtures/createAuxContext'; -import { Users } from './fixtures/userStates'; -import { OmnichannelLiveChat, HomeOmnichannel } from './page-objects'; -import { test, expect } from './utils/test'; +import { createAuxContext } from '../fixtures/createAuxContext'; +import { Users } from '../fixtures/userStates'; +import { OmnichannelLiveChat, HomeOmnichannel } from '../page-objects'; +import { test, expect } from '../utils/test'; test.describe('Omnichannel chat histr', () => { let poLiveChat: OmnichannelLiveChat; diff --git a/apps/meteor/tests/e2e/omnichannel-close-chat.spec.ts b/apps/meteor/tests/e2e/omnichannel/omnichannel-close-chat.spec.ts similarity index 89% rename from apps/meteor/tests/e2e/omnichannel-close-chat.spec.ts rename to apps/meteor/tests/e2e/omnichannel/omnichannel-close-chat.spec.ts index 72ea2620c2091..a69ccb1751f7f 100644 --- a/apps/meteor/tests/e2e/omnichannel-close-chat.spec.ts +++ b/apps/meteor/tests/e2e/omnichannel/omnichannel-close-chat.spec.ts @@ -1,10 +1,10 @@ import { faker } from '@faker-js/faker'; import type { Page } from '@playwright/test'; -import { createAuxContext } from './fixtures/createAuxContext'; -import { Users } from './fixtures/userStates'; -import { OmnichannelLiveChat, HomeOmnichannel } from './page-objects'; -import { test, expect } from './utils/test'; +import { createAuxContext } from '../fixtures/createAuxContext'; +import { Users } from '../fixtures/userStates'; +import { OmnichannelLiveChat, HomeOmnichannel } from '../page-objects'; +import { test, expect } from '../utils/test'; test.describe('Omnichannel close chat', () => { let poLiveChat: OmnichannelLiveChat; diff --git a/apps/meteor/tests/e2e/omnichannel-close-inquiry.spec.ts b/apps/meteor/tests/e2e/omnichannel/omnichannel-close-inquiry.spec.ts similarity index 92% rename from apps/meteor/tests/e2e/omnichannel-close-inquiry.spec.ts rename to apps/meteor/tests/e2e/omnichannel/omnichannel-close-inquiry.spec.ts index 3ce0fb83c9278..f61da31329981 100644 --- a/apps/meteor/tests/e2e/omnichannel-close-inquiry.spec.ts +++ b/apps/meteor/tests/e2e/omnichannel/omnichannel-close-inquiry.spec.ts @@ -1,10 +1,10 @@ import { faker } from '@faker-js/faker'; import type { Page } from '@playwright/test'; -import { createAuxContext } from './fixtures/createAuxContext'; -import { Users } from './fixtures/userStates'; -import { OmnichannelLiveChat, HomeOmnichannel } from './page-objects'; -import { test, expect } from './utils/test'; +import { createAuxContext } from '../fixtures/createAuxContext'; +import { Users } from '../fixtures/userStates'; +import { OmnichannelLiveChat, HomeOmnichannel } from '../page-objects'; +import { test, expect } from '../utils/test'; test.describe('Omnichannel close inquiry', () => { let poLiveChat: OmnichannelLiveChat; diff --git a/apps/meteor/tests/e2e/omnichannel-contact-center.spec.ts b/apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center.spec.ts similarity index 96% rename from apps/meteor/tests/e2e/omnichannel-contact-center.spec.ts rename to apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center.spec.ts index 54a1ecf35a512..b9ac92d67a9a8 100644 --- a/apps/meteor/tests/e2e/omnichannel-contact-center.spec.ts +++ b/apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center.spec.ts @@ -1,11 +1,11 @@ import { faker } from '@faker-js/faker'; -import { createToken } from '../../client/lib/utils/createToken'; -import { IS_EE } from './config/constants'; -import { Users } from './fixtures/userStates'; -import { OmnichannelContacts } from './page-objects/omnichannel-contacts-list'; -import { OmnichannelSection } from './page-objects/omnichannel-section'; -import { test, expect } from './utils/test'; +import { createToken } from '../../../client/lib/utils/createToken'; +import { IS_EE } from '../config/constants'; +import { Users } from '../fixtures/userStates'; +import { OmnichannelContacts } from '../page-objects/omnichannel-contacts-list'; +import { OmnichannelSection } from '../page-objects/omnichannel-section'; +import { test, expect } from '../utils/test'; const createContact = (generateToken = false) => ({ id: null, @@ -28,7 +28,7 @@ const NEW_CUSTOM_FIELD = { visibility: 'hidden', required: true, regexp: '', -} +}; const URL = { contactCenter: '/omnichannel-directory/contacts', @@ -58,7 +58,7 @@ test.describe('Omnichannel Contact Center', () => { // Add a contact const { id: _, ...data } = EXISTING_CONTACT; await api.post('/omnichannel/contact', data); - + if (IS_EE) { await api.post('/livechat/custom.field', NEW_CUSTOM_FIELD); } diff --git a/apps/meteor/tests/e2e/omnichannel-contact-info.spec.ts b/apps/meteor/tests/e2e/omnichannel/omnichannel-contact-info.spec.ts similarity index 89% rename from apps/meteor/tests/e2e/omnichannel-contact-info.spec.ts rename to apps/meteor/tests/e2e/omnichannel/omnichannel-contact-info.spec.ts index e0ffab80aff66..6f3daaffe964e 100644 --- a/apps/meteor/tests/e2e/omnichannel-contact-info.spec.ts +++ b/apps/meteor/tests/e2e/omnichannel/omnichannel-contact-info.spec.ts @@ -1,10 +1,10 @@ import { faker } from '@faker-js/faker'; import type { Page } from '@playwright/test'; -import { createAuxContext } from './fixtures/createAuxContext'; -import { Users } from './fixtures/userStates'; -import { OmnichannelLiveChat, HomeChannel } from './page-objects'; -import { test } from './utils/test'; +import { createAuxContext } from '../fixtures/createAuxContext'; +import { Users } from '../fixtures/userStates'; +import { OmnichannelLiveChat, HomeChannel } from '../page-objects'; +import { test } from '../utils/test'; test.describe('Omnichannel contact info', () => { let poLiveChat: OmnichannelLiveChat; diff --git a/apps/meteor/tests/e2e/omnichannel-currentChats.spec.ts b/apps/meteor/tests/e2e/omnichannel/omnichannel-currentChats.spec.ts similarity index 96% rename from apps/meteor/tests/e2e/omnichannel-currentChats.spec.ts rename to apps/meteor/tests/e2e/omnichannel/omnichannel-currentChats.spec.ts index 36b91a6297bf9..fa606025c83ee 100644 --- a/apps/meteor/tests/e2e/omnichannel-currentChats.spec.ts +++ b/apps/meteor/tests/e2e/omnichannel/omnichannel-currentChats.spec.ts @@ -1,7 +1,7 @@ import { test, expect } from '@playwright/test'; -import { Users } from './fixtures/userStates'; -import { OmnichannelCurrentChats } from './page-objects'; +import { Users } from '../fixtures/userStates'; +import { OmnichannelCurrentChats } from '../page-objects'; test.use({ storageState: Users.admin.state }); diff --git a/apps/meteor/tests/e2e/omnichannel-custom-fields.spec.ts b/apps/meteor/tests/e2e/omnichannel/omnichannel-custom-fields.spec.ts similarity index 91% rename from apps/meteor/tests/e2e/omnichannel-custom-fields.spec.ts rename to apps/meteor/tests/e2e/omnichannel/omnichannel-custom-fields.spec.ts index e17864cd0d741..dd5c93609f6e6 100644 --- a/apps/meteor/tests/e2e/omnichannel-custom-fields.spec.ts +++ b/apps/meteor/tests/e2e/omnichannel/omnichannel-custom-fields.spec.ts @@ -1,6 +1,6 @@ -import { Users } from './fixtures/userStates'; -import { OmnichannelCustomFields } from './page-objects'; -import { test, expect } from './utils/test'; +import { Users } from '../fixtures/userStates'; +import { OmnichannelCustomFields } from '../page-objects'; +import { test, expect } from '../utils/test'; test.use({ storageState: Users.admin.state }); diff --git a/apps/meteor/tests/e2e/omnichannel-departaments-ce.spec.ts b/apps/meteor/tests/e2e/omnichannel/omnichannel-departaments-ce.spec.ts similarity index 88% rename from apps/meteor/tests/e2e/omnichannel-departaments-ce.spec.ts rename to apps/meteor/tests/e2e/omnichannel/omnichannel-departaments-ce.spec.ts index af060db8899d6..f839b837a9572 100644 --- a/apps/meteor/tests/e2e/omnichannel-departaments-ce.spec.ts +++ b/apps/meteor/tests/e2e/omnichannel/omnichannel-departaments-ce.spec.ts @@ -1,10 +1,10 @@ import { faker } from '@faker-js/faker'; import type { Page } from '@playwright/test'; -import { IS_EE } from './config/constants'; -import { Users } from './fixtures/userStates'; -import { OmnichannelDepartments } from './page-objects'; -import { test, expect } from './utils/test'; +import { IS_EE } from '../config/constants'; +import { Users } from '../fixtures/userStates'; +import { OmnichannelDepartments } from '../page-objects'; +import { test, expect } from '../utils/test'; test.use({ storageState: Users.admin.state }); diff --git a/apps/meteor/tests/e2e/omnichannel-departaments.spec.ts b/apps/meteor/tests/e2e/omnichannel/omnichannel-departaments.spec.ts similarity index 97% rename from apps/meteor/tests/e2e/omnichannel-departaments.spec.ts rename to apps/meteor/tests/e2e/omnichannel/omnichannel-departaments.spec.ts index 8962ed8aecd60..36e2b54601f96 100644 --- a/apps/meteor/tests/e2e/omnichannel-departaments.spec.ts +++ b/apps/meteor/tests/e2e/omnichannel/omnichannel-departaments.spec.ts @@ -1,10 +1,10 @@ import { faker } from '@faker-js/faker'; import type { Page } from '@playwright/test'; -import { IS_EE } from './config/constants'; -import { Users } from './fixtures/userStates'; -import { OmnichannelDepartments } from './page-objects'; -import { test, expect } from './utils/test'; +import { IS_EE } from '../config/constants'; +import { Users } from '../fixtures/userStates'; +import { OmnichannelDepartments } from '../page-objects'; +import { test, expect } from '../utils/test'; const ERROR = { requiredName: 'The field name is required.', diff --git a/apps/meteor/tests/e2e/omnichannel-livechat.spec.ts b/apps/meteor/tests/e2e/omnichannel/omnichannel-livechat.spec.ts similarity index 93% rename from apps/meteor/tests/e2e/omnichannel-livechat.spec.ts rename to apps/meteor/tests/e2e/omnichannel/omnichannel-livechat.spec.ts index 339daba8ffde8..77ab9cf8d635e 100644 --- a/apps/meteor/tests/e2e/omnichannel-livechat.spec.ts +++ b/apps/meteor/tests/e2e/omnichannel/omnichannel-livechat.spec.ts @@ -1,10 +1,10 @@ import { faker } from '@faker-js/faker'; import type { Page } from '@playwright/test'; -import { createAuxContext } from './fixtures/createAuxContext'; -import { Users } from './fixtures/userStates'; -import { HomeOmnichannel, OmnichannelLiveChat } from './page-objects'; -import { test, expect } from './utils/test'; +import { createAuxContext } from '../fixtures/createAuxContext'; +import { Users } from '../fixtures/userStates'; +import { HomeOmnichannel, OmnichannelLiveChat } from '../page-objects'; +import { test, expect } from '../utils/test'; const newUser = { name: `${faker.person.firstName()} ${faker.string.uuid()}}`, diff --git a/apps/meteor/tests/e2e/omnichannel-manager.spec.ts b/apps/meteor/tests/e2e/omnichannel/omnichannel-manager.spec.ts similarity index 87% rename from apps/meteor/tests/e2e/omnichannel-manager.spec.ts rename to apps/meteor/tests/e2e/omnichannel/omnichannel-manager.spec.ts index 01802fb434076..85c0f518d3623 100644 --- a/apps/meteor/tests/e2e/omnichannel-manager.spec.ts +++ b/apps/meteor/tests/e2e/omnichannel/omnichannel-manager.spec.ts @@ -1,6 +1,6 @@ -import { Users } from './fixtures/userStates'; -import { OmnichannelManager } from './page-objects'; -import { test, expect } from './utils/test'; +import { Users } from '../fixtures/userStates'; +import { OmnichannelManager } from '../page-objects'; +import { test, expect } from '../utils/test'; test.use({ storageState: Users.admin.state }); diff --git a/apps/meteor/tests/e2e/omnichannel-priorities.spec.ts b/apps/meteor/tests/e2e/omnichannel/omnichannel-priorities.spec.ts similarity index 96% rename from apps/meteor/tests/e2e/omnichannel-priorities.spec.ts rename to apps/meteor/tests/e2e/omnichannel/omnichannel-priorities.spec.ts index 56d2ee02d8b24..cd66c7b164a42 100644 --- a/apps/meteor/tests/e2e/omnichannel-priorities.spec.ts +++ b/apps/meteor/tests/e2e/omnichannel/omnichannel-priorities.spec.ts @@ -1,9 +1,9 @@ import { faker } from '@faker-js/faker'; -import { IS_EE } from './config/constants'; -import { Users } from './fixtures/userStates'; -import { OmnichannelPriorities } from './page-objects/omnichannel-priorities'; -import { test, expect } from './utils/test'; +import { IS_EE } from '../config/constants'; +import { Users } from '../fixtures/userStates'; +import { OmnichannelPriorities } from '../page-objects/omnichannel-priorities'; +import { test, expect } from '../utils/test'; const PRIORITY_NAME = faker.person.firstName(); diff --git a/apps/meteor/tests/e2e/omnichannel-send-transcript.spec.ts b/apps/meteor/tests/e2e/omnichannel/omnichannel-send-transcript.spec.ts similarity index 89% rename from apps/meteor/tests/e2e/omnichannel-send-transcript.spec.ts rename to apps/meteor/tests/e2e/omnichannel/omnichannel-send-transcript.spec.ts index 517fadc7c0197..a1c15e44df947 100644 --- a/apps/meteor/tests/e2e/omnichannel-send-transcript.spec.ts +++ b/apps/meteor/tests/e2e/omnichannel/omnichannel-send-transcript.spec.ts @@ -1,11 +1,11 @@ import { faker } from '@faker-js/faker'; import type { Page } from '@playwright/test'; -import { IS_EE } from './config/constants'; -import { createAuxContext } from './fixtures/createAuxContext'; -import { Users } from './fixtures/userStates'; -import { OmnichannelLiveChat, HomeChannel } from './page-objects'; -import { test, expect } from './utils/test'; +import { IS_EE } from '../config/constants'; +import { createAuxContext } from '../fixtures/createAuxContext'; +import { Users } from '../fixtures/userStates'; +import { OmnichannelLiveChat, HomeChannel } from '../page-objects'; +import { test, expect } from '../utils/test'; test.describe('omnichannel-transcript', () => { let poLiveChat: OmnichannelLiveChat; diff --git a/apps/meteor/tests/e2e/omnichannel-sla-policies.spec.ts b/apps/meteor/tests/e2e/omnichannel/omnichannel-sla-policies.spec.ts similarity index 94% rename from apps/meteor/tests/e2e/omnichannel-sla-policies.spec.ts rename to apps/meteor/tests/e2e/omnichannel/omnichannel-sla-policies.spec.ts index 1485236f9a9b2..5932f1b48d40a 100644 --- a/apps/meteor/tests/e2e/omnichannel-sla-policies.spec.ts +++ b/apps/meteor/tests/e2e/omnichannel/omnichannel-sla-policies.spec.ts @@ -1,9 +1,9 @@ import { faker } from '@faker-js/faker'; -import { IS_EE } from './config/constants'; -import { Users } from './fixtures/userStates'; -import { OmnichannelSlaPolicies } from './page-objects/omnichannel-sla-policies'; -import { test, expect } from './utils/test'; +import { IS_EE } from '../config/constants'; +import { Users } from '../fixtures/userStates'; +import { OmnichannelSlaPolicies } from '../page-objects/omnichannel-sla-policies'; +import { test, expect } from '../utils/test'; const ERROR = { nameRequired: 'The field Name is required.', @@ -13,13 +13,13 @@ const ERROR = { const INITIAL_SLA = { name: faker.person.firstName(), description: faker.lorem.sentence(), - estimatedWaitTime: faker.string.numeric(), + estimatedWaitTime: faker.string.numeric({ length: 1, exclude: '0' }), }; const EDITED_SLA = { name: faker.person.firstName(), description: faker.lorem.sentence(), - estimatedWaitTime: faker.string.numeric(), + estimatedWaitTime: faker.string.numeric({ length: 1, exclude: '0' }), }; test.skip(!IS_EE, 'Omnichannel SLA Policies > Enterprise Only'); diff --git a/apps/meteor/tests/e2e/omnichannel-takeChat.spec.ts b/apps/meteor/tests/e2e/omnichannel/omnichannel-takeChat.spec.ts similarity index 93% rename from apps/meteor/tests/e2e/omnichannel-takeChat.spec.ts rename to apps/meteor/tests/e2e/omnichannel/omnichannel-takeChat.spec.ts index 4190958f5e27c..6314ee395f456 100644 --- a/apps/meteor/tests/e2e/omnichannel-takeChat.spec.ts +++ b/apps/meteor/tests/e2e/omnichannel/omnichannel-takeChat.spec.ts @@ -1,10 +1,10 @@ import { faker } from '@faker-js/faker'; import type { Page } from '@playwright/test'; -import { createAuxContext } from './fixtures/createAuxContext'; -import { Users } from './fixtures/userStates'; -import { OmnichannelLiveChat, HomeChannel } from './page-objects'; -import { test, expect } from './utils/test'; +import { createAuxContext } from '../fixtures/createAuxContext'; +import { Users } from '../fixtures/userStates'; +import { OmnichannelLiveChat, HomeChannel } from '../page-objects'; +import { test, expect } from '../utils/test'; test.describe('omnichannel-takeChat', () => { let poLiveChat: OmnichannelLiveChat; diff --git a/apps/meteor/tests/e2e/omnichannel-transfer-to-another-agents.spec.ts b/apps/meteor/tests/e2e/omnichannel/omnichannel-transfer-to-another-agents.spec.ts similarity index 88% rename from apps/meteor/tests/e2e/omnichannel-transfer-to-another-agents.spec.ts rename to apps/meteor/tests/e2e/omnichannel/omnichannel-transfer-to-another-agents.spec.ts index 49aba43d5c5cf..1a968253deffa 100644 --- a/apps/meteor/tests/e2e/omnichannel-transfer-to-another-agents.spec.ts +++ b/apps/meteor/tests/e2e/omnichannel/omnichannel-transfer-to-another-agents.spec.ts @@ -1,10 +1,10 @@ import { faker } from '@faker-js/faker'; import type { Page } from '@playwright/test'; -import { createAuxContext } from './fixtures/createAuxContext'; -import { Users } from './fixtures/userStates'; -import { OmnichannelLiveChat, HomeOmnichannel } from './page-objects'; -import { test, expect } from './utils/test'; +import { createAuxContext } from '../fixtures/createAuxContext'; +import { Users } from '../fixtures/userStates'; +import { OmnichannelLiveChat, HomeOmnichannel } from '../page-objects'; +import { test, expect } from '../utils/test'; test.describe('omnichannel-transfer-to-another-agent', () => { let poLiveChat: OmnichannelLiveChat; @@ -58,7 +58,7 @@ test.describe('omnichannel-transfer-to-another-agent', () => { test('transfer omnichannel chat to another agent', async () => { await test.step('Expect to have 1 omnichannel assigned to agent 1', async () => { - await agent1.poHomeOmnichannel.sidenav.openChat(newVisitor.name); + await agent1.poHomeOmnichannel.sidenav.getSidebarItemByName(newVisitor.name).click(); }); await test.step('Expect to not be able to transfer chat to "user-2" when that user is offline', async () => { @@ -74,7 +74,7 @@ test.describe('omnichannel-transfer-to-another-agent', () => { await test.step('Expect to be able to transfer an omnichannel to conversation to agent 2 as agent 1 when agent 2 is online', async () => { await agent2.poHomeOmnichannel.sidenav.switchStatus('online'); - await agent1.poHomeOmnichannel.sidenav.openChat(newVisitor.name); + await agent1.poHomeOmnichannel.sidenav.getSidebarItemByName(newVisitor.name).click(); await agent1.poHomeOmnichannel.content.btnForwardChat.click(); await agent1.poHomeOmnichannel.content.inputModalAgentUserName.type('user2'); await agent1.page.locator('.rcx-option .rcx-option__wrapper >> text="user2"').click(); @@ -84,7 +84,7 @@ test.describe('omnichannel-transfer-to-another-agent', () => { }); await test.step('Expect to have 1 omnichannel assigned to agent 2', async () => { - await agent2.poHomeOmnichannel.sidenav.openChat(newVisitor.name); + await agent2.poHomeOmnichannel.sidenav.getSidebarItemByName(newVisitor.name).click(); }); }); }); diff --git a/apps/meteor/tests/e2e/omnichannel-triggers.spec.ts b/apps/meteor/tests/e2e/omnichannel/omnichannel-triggers.spec.ts similarity index 92% rename from apps/meteor/tests/e2e/omnichannel-triggers.spec.ts rename to apps/meteor/tests/e2e/omnichannel/omnichannel-triggers.spec.ts index 57ef369445c5d..f1a863d8fc9d3 100644 --- a/apps/meteor/tests/e2e/omnichannel-triggers.spec.ts +++ b/apps/meteor/tests/e2e/omnichannel/omnichannel-triggers.spec.ts @@ -1,10 +1,10 @@ import { faker } from '@faker-js/faker'; import type { Page } from '@playwright/test'; -import { createAuxContext } from './fixtures/createAuxContext'; -import { Users } from './fixtures/userStates'; -import { OmnichannelLiveChat, HomeOmnichannel } from './page-objects'; -import { test, expect } from './utils/test'; +import { createAuxContext } from '../fixtures/createAuxContext'; +import { Users } from '../fixtures/userStates'; +import { OmnichannelLiveChat, HomeOmnichannel } from '../page-objects'; +import { test, expect } from '../utils/test'; test.describe.serial('omnichannel-triggers', () => { let triggersName: string; diff --git a/apps/meteor/tests/e2e/page-objects/omnichannel-triggers.ts b/apps/meteor/tests/e2e/page-objects/omnichannel-triggers.ts index b5a928ea79ed9..3435b28314d04 100644 --- a/apps/meteor/tests/e2e/page-objects/omnichannel-triggers.ts +++ b/apps/meteor/tests/e2e/page-objects/omnichannel-triggers.ts @@ -13,7 +13,7 @@ export class OmnichannelTriggers { } get btnNew(): Locator { - return this.page.locator('text=New'); + return this.page.locator('role=button[name="New"]'); } get Name(): Locator { From bc33bf5ab7cdf4412ea191cb7809fb54720131db Mon Sep 17 00:00:00 2001 From: Kevin Aleman Date: Fri, 23 Jun 2023 00:35:52 -0600 Subject: [PATCH 15/21] refactor: convert routing manager to ts (#29406) --- .../app/livechat/server/api/lib/livechat.ts | 2 +- .../server/hooks/saveLastMessageToInquiry.ts | 2 +- .../{RoutingManager.js => RoutingManager.ts} | 81 ++++++++++++++++--- .../server/methods/getRoutingConfig.ts | 2 +- .../livechat/server/methods/takeInquiry.ts | 7 +- .../roomAccessValidator.compatibility.ts | 3 +- .../hooks/handleNextAgentPreferredEvents.ts | 4 +- .../server/lib/AutoTransferChatScheduler.ts | 2 +- .../livechat-enterprise/server/lib/Helper.ts | 1 + .../server/lib/LivechatEnterprise.ts | 2 +- apps/meteor/lib/callbacks.ts | 17 +--- packages/core-typings/src/IInquiry.ts | 7 +- .../core-typings/src/omnichannel/routing.ts | 1 + 13 files changed, 90 insertions(+), 41 deletions(-) rename apps/meteor/app/livechat/server/lib/{RoutingManager.js => RoutingManager.ts} (71%) diff --git a/apps/meteor/app/livechat/server/api/lib/livechat.ts b/apps/meteor/app/livechat/server/api/lib/livechat.ts index 1629685a3e1b7..8f2719f885516 100644 --- a/apps/meteor/app/livechat/server/api/lib/livechat.ts +++ b/apps/meteor/app/livechat/server/api/lib/livechat.ts @@ -126,7 +126,7 @@ export function getRoom({ return LivechatTyped.getRoom(guest, message, roomInfo, agent, extraParams); } -export async function findAgent(agentId: string): Promise { +export async function findAgent(agentId?: string): Promise { return normalizeAgent(agentId); } diff --git a/apps/meteor/app/livechat/server/hooks/saveLastMessageToInquiry.ts b/apps/meteor/app/livechat/server/hooks/saveLastMessageToInquiry.ts index af50ee5527e5f..648337a8c2a10 100644 --- a/apps/meteor/app/livechat/server/hooks/saveLastMessageToInquiry.ts +++ b/apps/meteor/app/livechat/server/hooks/saveLastMessageToInquiry.ts @@ -12,7 +12,7 @@ callbacks.add( return message; } - if (!RoutingManager.getConfig().showQueue) { + if (!RoutingManager.getConfig()?.showQueue) { // since last message is only getting used on UI as preview message when queue is enabled return message; } diff --git a/apps/meteor/app/livechat/server/lib/RoutingManager.js b/apps/meteor/app/livechat/server/lib/RoutingManager.ts similarity index 71% rename from apps/meteor/app/livechat/server/lib/RoutingManager.js rename to apps/meteor/app/livechat/server/lib/RoutingManager.ts index 1419ac73868d8..aed24ad928dde 100644 --- a/apps/meteor/app/livechat/server/lib/RoutingManager.js +++ b/apps/meteor/app/livechat/server/lib/RoutingManager.ts @@ -2,6 +2,16 @@ import { Meteor } from 'meteor/meteor'; import { Match, check } from 'meteor/check'; import { LivechatInquiry, LivechatRooms, Subscriptions, Rooms, Users } from '@rocket.chat/models'; import { Message } from '@rocket.chat/core-services'; +import type { + ILivechatInquiryRecord, + ILivechatVisitor, + IOmnichannelRoom, + IRoutingMethod, + IRoutingMethodConstructor, + RoutingMethodConfig, + SelectedAgent, + InquiryWithAgentInfo, +} from '@rocket.chat/core-typings'; import { createLivechatSubscription, @@ -19,7 +29,45 @@ import { Apps, AppEvents } from '../../../../ee/server/apps'; const logger = new Logger('RoutingManager'); -export const RoutingManager = { +type Routing = { + methodName: string | null; + methods: Record; + startQueue(): void; + isMethodSet(): boolean; + setMethodNameAndStartQueue(name: string): void; + registerMethod(name: string, Method: IRoutingMethodConstructor): void; + getMethod(): IRoutingMethod; + getConfig(): RoutingMethodConfig | undefined; + getNextAgent(department?: string, ignoreAgentId?: string): Promise; + delegateInquiry( + inquiry: InquiryWithAgentInfo, + agent?: SelectedAgent | null, + options?: { clientAction?: boolean; forwardingToDepartment?: { oldDepartmentId: string; transferData: any } }, + ): Promise; + assignAgent(inquiry: InquiryWithAgentInfo, agent: SelectedAgent): Promise; + unassignAgent(inquiry: ILivechatInquiryRecord, departmentId?: string): Promise; + takeInquiry( + inquiry: Omit< + ILivechatInquiryRecord, + 'estimatedInactivityCloseTimeAt' | 'message' | 't' | 'source' | 'estimatedWaitingTimeQueue' | 'priorityWeight' | '_updatedAt' + >, + agent: SelectedAgent | null, + options?: { clientAction?: boolean; forwardingToDepartment?: { oldDepartmentId: string; transferData: any } }, + ): Promise; + transferRoom( + room: IOmnichannelRoom, + guest: ILivechatVisitor, + transferData: { + departmentId?: string; + userId?: string; + transferredBy: { _id: string }; + }, + ): Promise; + delegateAgent(agent: SelectedAgent, inquiry: ILivechatInquiryRecord): Promise; + removeAllRoomSubscriptions(room: Pick, ignoreUser?: { _id: string }): Promise; +}; + +export const RoutingManager: Routing = { methodName: null, methods: {}, @@ -44,12 +92,16 @@ export const RoutingManager = { this.startQueue(); }, + // eslint-disable-next-line @typescript-eslint/naming-convention registerMethod(name, Method) { logger.debug(`Registering new routing method with name ${name}`); this.methods[name] = new Method(); }, getMethod() { + if (!this.methodName) { + throw new Meteor.Error('error-routing-method-not-set'); + } if (!this.methods[this.methodName]) { throw new Meteor.Error('error-routing-method-not-available'); } @@ -57,7 +109,7 @@ export const RoutingManager = { }, getConfig() { - return this.getMethod().config || {}; + return this.getMethod().config; }, async getNextAgent(department, ignoreAgentId) { @@ -71,7 +123,7 @@ export const RoutingManager = { if (!agent || (agent.username && !(await Users.findOneOnlineAgentByUserList(agent.username)) && !(await allowAgentSkipQueue(agent)))) { logger.debug(`Agent offline or invalid. Using routing method to get next agent for inquiry ${inquiry._id}`); agent = await this.getNextAgent(department); - logger.debug(`Routing method returned agent ${agent && agent.agentId} for inquiry ${inquiry._id}`); + logger.debug(`Routing method returned agent ${agent?.agentId} for inquiry ${inquiry._id}`); } if (!agent) { @@ -101,17 +153,19 @@ export const RoutingManager = { } await LivechatRooms.changeAgentByRoomId(rid, agent); - await Rooms.incUsersCountById(rid); + await Rooms.incUsersCountById(rid, 1); const user = await Users.findOneById(agent.agentId); const room = await LivechatRooms.findOneById(rid); - await Promise.all([Message.saveSystemMessage('command', rid, 'connected', user), Message.saveSystemMessage('uj', rid, '', user)]); + if (user) { + await Promise.all([Message.saveSystemMessage('command', rid, 'connected', user), Message.saveSystemMessage('uj', rid, '', user)]); + } await dispatchAgentDelegated(rid, agent.agentId); logger.debug(`Agent ${agent.agentId} assigned to inquriy ${inquiry._id}. Instances notified`); - Apps.getBridges().getListenerBridge().livechatEvent(AppEvents.IPostLivechatAgentAssigned, { room, user }); + void Apps.getBridges()?.getListenerBridge().livechatEvent(AppEvents.IPostLivechatAgentAssigned, { room, user }); return inquiry; }, @@ -120,7 +174,7 @@ export const RoutingManager = { const room = await LivechatRooms.findOneById(rid); logger.debug(`Removing assignations of inquiry ${inquiry._id}`); - if (!room || !room.open) { + if (!room?.open) { logger.debug(`Cannot unassign agent from inquiry ${inquiry._id}: Room already closed`); return false; } @@ -171,7 +225,7 @@ export const RoutingManager = { const { _id, rid } = inquiry; const room = await LivechatRooms.findOneById(rid); - if (!room || !room.open) { + if (!room?.open) { logger.debug(`Cannot take Inquiry ${inquiry._id}: Room is closed`); return room; } @@ -196,12 +250,16 @@ export const RoutingManager = { if (!agent) { logger.debug(`Cannot take Inquiry ${inquiry._id}: Precondition failed for agent`); - const cbRoom = await callbacks.run('livechat.onAgentAssignmentFailed', { inquiry, room, options }); + const cbRoom = await callbacks.run<'livechat.onAgentAssignmentFailed'>('livechat.onAgentAssignmentFailed', { + inquiry, + room, + options, + }); return cbRoom; } await LivechatInquiry.takeInquiry(_id); - const inq = await this.assignAgent(inquiry, agent); + const inq = await this.assignAgent(inquiry as InquiryWithAgentInfo, agent); logger.debug(`Inquiry ${inquiry._id} taken by agent ${agent.agentId}`); callbacks.runAsync('livechat.afterTakeInquiry', inq, agent); @@ -249,7 +307,8 @@ export const RoutingManager = { if (ignoreUser && ignoreUser._id === u._id) { return; } - removeAgentFromSubscription(roomId, u); + // @ts-expect-error - File still in JS, expecting error for now on `u` types + void removeAgentFromSubscription(roomId, u); }); }, }; diff --git a/apps/meteor/app/livechat/server/methods/getRoutingConfig.ts b/apps/meteor/app/livechat/server/methods/getRoutingConfig.ts index da54882f588b3..364853a74511d 100644 --- a/apps/meteor/app/livechat/server/methods/getRoutingConfig.ts +++ b/apps/meteor/app/livechat/server/methods/getRoutingConfig.ts @@ -7,7 +7,7 @@ import { RoutingManager } from '../lib/RoutingManager'; declare module '@rocket.chat/ui-contexts' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { - 'livechat:getRoutingConfig'(): OmichannelRoutingConfig; + 'livechat:getRoutingConfig'(): OmichannelRoutingConfig | undefined; } } diff --git a/apps/meteor/app/livechat/server/methods/takeInquiry.ts b/apps/meteor/app/livechat/server/methods/takeInquiry.ts index dcc400c1a9d21..1bf84347b0ffe 100644 --- a/apps/meteor/app/livechat/server/methods/takeInquiry.ts +++ b/apps/meteor/app/livechat/server/methods/takeInquiry.ts @@ -9,14 +9,17 @@ import { settings } from '../../../settings/server'; declare module '@rocket.chat/ui-contexts' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { - 'livechat:takeInquiry'(inquiryId: string, options?: { clientAction: boolean; forwardingToDepartment?: boolean }): unknown; + 'livechat:takeInquiry'( + inquiryId: string, + options?: { clientAction: boolean; forwardingToDepartment?: { oldDepartmentId: string; transferData: any } }, + ): unknown; } } export const takeInquiry = async ( userId: string, inquiryId: string, - options?: { clientAction: boolean; forwardingToDepartment?: boolean }, + options?: { clientAction: boolean; forwardingToDepartment?: { oldDepartmentId: string; transferData: any } }, ): Promise => { if (!userId || !(await hasPermissionAsync(userId, 'view-l-room'))) { throw new Meteor.Error('error-not-allowed', 'Not allowed', { diff --git a/apps/meteor/app/livechat/server/roomAccessValidator.compatibility.ts b/apps/meteor/app/livechat/server/roomAccessValidator.compatibility.ts index 931451ad120c1..0bad086e738b7 100644 --- a/apps/meteor/app/livechat/server/roomAccessValidator.compatibility.ts +++ b/apps/meteor/app/livechat/server/roomAccessValidator.compatibility.ts @@ -41,8 +41,7 @@ export const validators: OmnichannelRoomAccessValidator[] = [ if (!user?._id) { return false; } - const { previewRoom } = RoutingManager.getConfig(); - if (!previewRoom) { + if (!RoutingManager.getConfig()?.previewRoom) { return; } diff --git a/apps/meteor/ee/app/livechat-enterprise/server/hooks/handleNextAgentPreferredEvents.ts b/apps/meteor/ee/app/livechat-enterprise/server/hooks/handleNextAgentPreferredEvents.ts index 60fdc144c950f..cf47347717818 100644 --- a/apps/meteor/ee/app/livechat-enterprise/server/hooks/handleNextAgentPreferredEvents.ts +++ b/apps/meteor/ee/app/livechat-enterprise/server/hooks/handleNextAgentPreferredEvents.ts @@ -40,7 +40,7 @@ settings.watch('Livechat_last_chatted_agent_routing', function (value) return inquiry; } - if (!RoutingManager.getConfig().autoAssignAgent) { + if (!RoutingManager.getConfig()?.autoAssignAgent) { return inquiry; } @@ -64,7 +64,7 @@ settings.watch('Livechat_last_chatted_agent_routing', function (value) return inquiry; } - if (!RoutingManager.getConfig().autoAssignAgent) { + if (!RoutingManager.getConfig()?.autoAssignAgent) { return inquiry; } diff --git a/apps/meteor/ee/app/livechat-enterprise/server/lib/AutoTransferChatScheduler.ts b/apps/meteor/ee/app/livechat-enterprise/server/lib/AutoTransferChatScheduler.ts index 8434fcce07f05..d73c2e4d59490 100644 --- a/apps/meteor/ee/app/livechat-enterprise/server/lib/AutoTransferChatScheduler.ts +++ b/apps/meteor/ee/app/livechat-enterprise/server/lib/AutoTransferChatScheduler.ts @@ -89,7 +89,7 @@ class AutoTransferChatSchedulerClass { const timeoutDuration = settings.get('Livechat_auto_transfer_chat_timeout').toString(); - if (!RoutingManager.getConfig().autoAssignAgent) { + if (!RoutingManager.getConfig()?.autoAssignAgent) { this.logger.debug(`Auto-assign agent is disabled, returning room ${roomId} as inquiry`); await Livechat.returnRoomAsInquiry(room._id, departmentId, { diff --git a/apps/meteor/ee/app/livechat-enterprise/server/lib/Helper.ts b/apps/meteor/ee/app/livechat-enterprise/server/lib/Helper.ts index 44a88a0da328f..d6a6c8f07d343 100644 --- a/apps/meteor/ee/app/livechat-enterprise/server/lib/Helper.ts +++ b/apps/meteor/ee/app/livechat-enterprise/server/lib/Helper.ts @@ -32,6 +32,7 @@ type QueueInfo = { statistics: Document; numberMostRecentChats: number; }; + export const getMaxNumberSimultaneousChat = async ({ agentId, departmentId }: { agentId?: string; departmentId?: string }) => { if (departmentId) { const department = await LivechatDepartmentRaw.findOneById(departmentId); diff --git a/apps/meteor/ee/app/livechat-enterprise/server/lib/LivechatEnterprise.ts b/apps/meteor/ee/app/livechat-enterprise/server/lib/LivechatEnterprise.ts index 15dd04e335ebb..995ac4f8cabad 100644 --- a/apps/meteor/ee/app/livechat-enterprise/server/lib/LivechatEnterprise.ts +++ b/apps/meteor/ee/app/livechat-enterprise/server/lib/LivechatEnterprise.ts @@ -378,7 +378,7 @@ function shouldQueueStart() { return; } - const routingSupportsAutoAssign = RoutingManager.getConfig().autoAssignAgent; + const routingSupportsAutoAssign = RoutingManager.getConfig()?.autoAssignAgent; queueLogger.debug( `Routing method ${RoutingManager.methodName} supports auto assignment: ${routingSupportsAutoAssign}. ${ routingSupportsAutoAssign ? 'Starting' : 'Stopping' diff --git a/apps/meteor/lib/callbacks.ts b/apps/meteor/lib/callbacks.ts index 8a8f1bb43842b..32a4e59a7b4b3 100644 --- a/apps/meteor/lib/callbacks.ts +++ b/apps/meteor/lib/callbacks.ts @@ -18,6 +18,7 @@ import type { IOmnichannelRoom, ILivechatTag, SelectedAgent, + InquiryWithAgentInfo, } from '@rocket.chat/core-typings'; import { Random } from '@rocket.chat/random'; @@ -60,7 +61,7 @@ interface EventLikeCallbackSignatures { 'livechat:afterReturnRoomAsInquiry': (params: { room: IRoom }) => void; 'livechat.setUserStatusLivechat': (params: { userId: IUser['_id']; status: OmnichannelAgentStatus }) => void; 'livechat.agentStatusChanged': (params: { userId: IUser['_id']; status: OmnichannelAgentStatus }) => void; - 'livechat.afterTakeInquiry': (inq: ILivechatInquiryRecord, agent: { agentId: string; username: string }) => void; + 'livechat.afterTakeInquiry': (inq: InquiryWithAgentInfo, agent: { agentId: string; username: string }) => void; 'afterAddedToRoom': (params: { user: IUser; inviter?: IUser }, room: IRoom) => void; 'beforeAddedToRoom': (params: { user: IUser; inviter: IUser }) => void; 'afterCreateDirectRoom': (params: IRoom, second: { members: IUser[]; creatorId: IUser['_id'] }) => void; @@ -156,19 +157,7 @@ type ChainedCallbackSignatures = { agentsId: ILivechatAgent['_id'][]; }; 'livechat.applySimultaneousChatRestrictions': (_: undefined, params: { departmentId?: ILivechatDepartmentRecord['_id'] }) => undefined; - 'livechat.beforeDelegateAgent': ( - agent: { - agentId: string; - username: string; - }, - params?: { department?: string }, - ) => - | { - agentId: string; - username: string; - } - | null - | undefined; + 'livechat.beforeDelegateAgent': (agent: SelectedAgent | undefined, params?: { department?: string }) => SelectedAgent | null | undefined; 'livechat.applyDepartmentRestrictions': ( query: FilterOperators, params: { userId: IUser['_id'] }, diff --git a/packages/core-typings/src/IInquiry.ts b/packages/core-typings/src/IInquiry.ts index 056d770002c90..26ba2bc321886 100644 --- a/packages/core-typings/src/IInquiry.ts +++ b/packages/core-typings/src/IInquiry.ts @@ -1,7 +1,7 @@ import type { ILivechatPriority } from './ILivechatPriority'; import type { IOmnichannelRoom, OmnichannelSourceType } from './IRoom'; import type { IOmnichannelServiceLevelAgreements } from './IOmnichannelServiceLevelAgreements'; -import type { IUser } from './IUser'; +import type { SelectedAgent } from './omnichannel/routing'; import type { IMessage } from './IMessage'; import type { IRocketChatRecord } from './IRocketChatRecord'; @@ -41,10 +41,7 @@ export interface ILivechatInquiryRecord extends IRocketChatRecord { locked?: boolean; lockedAt?: Date; lastMessage?: IMessage & { token?: string }; - defaultAgent?: { - agentId: IUser['_id']; - username?: IUser['username']; - }; + defaultAgent?: SelectedAgent; source: { type: OmnichannelSourceType; }; diff --git a/packages/core-typings/src/omnichannel/routing.ts b/packages/core-typings/src/omnichannel/routing.ts index e105b9e913c9d..bef2a7946f6e6 100644 --- a/packages/core-typings/src/omnichannel/routing.ts +++ b/packages/core-typings/src/omnichannel/routing.ts @@ -18,4 +18,5 @@ export type SelectedAgent = { }; export interface IRoutingMethod { getNextAgent(departmentId?: string, ignoreAgentId?: string): Promise; + config?: RoutingMethodConfig; } From bc115050ae44c173871be9fc414142c13dd1ebf9 Mon Sep 17 00:00:00 2001 From: gabriellsh <40830821+gabriellsh@users.noreply.github.com> Date: Fri, 23 Jun 2023 08:50:53 -0300 Subject: [PATCH 16/21] fix(meteor): Autotranslate encoding message (#29625) --- .changeset/hungry-oranges-explode.md | 5 +++++ apps/meteor/app/autotranslate/server/deeplTranslate.ts | 5 ++--- apps/meteor/app/autotranslate/server/googleTranslate.ts | 6 ++---- 3 files changed, 9 insertions(+), 7 deletions(-) create mode 100644 .changeset/hungry-oranges-explode.md diff --git a/.changeset/hungry-oranges-explode.md b/.changeset/hungry-oranges-explode.md new file mode 100644 index 0000000000000..dfd8aa405c10f --- /dev/null +++ b/.changeset/hungry-oranges-explode.md @@ -0,0 +1,5 @@ +--- +"@rocket.chat/meteor": patch +--- + +fixed a bug with autotranslation encoding text diff --git a/apps/meteor/app/autotranslate/server/deeplTranslate.ts b/apps/meteor/app/autotranslate/server/deeplTranslate.ts index ece6dcc08cdab..73c71b0768909 100644 --- a/apps/meteor/app/autotranslate/server/deeplTranslate.ts +++ b/apps/meteor/app/autotranslate/server/deeplTranslate.ts @@ -198,8 +198,7 @@ class DeeplAutoTranslate extends AutoTranslate { */ async _translateMessage(message: IMessage, targetLanguages: string[]): Promise { const translations: { [k: string]: string } = {}; - let msgs = message.msg.split('\n'); - msgs = msgs.map((msg) => encodeURIComponent(msg)); + const msgs = message.msg.split('\n'); const supportedLanguages = await this.getSupportedLanguages('en'); for await (let language of targetLanguages) { if (language.indexOf('-') !== -1 && !_.findWhere(supportedLanguages, { language })) { @@ -250,7 +249,7 @@ class DeeplAutoTranslate extends AutoTranslate { params: { auth_key: this.apiKey, target_lang: language, - text: encodeURIComponent(attachment.description || attachment.text || ''), + text: attachment.description || attachment.text || '', }, }); if (!result.ok) { diff --git a/apps/meteor/app/autotranslate/server/googleTranslate.ts b/apps/meteor/app/autotranslate/server/googleTranslate.ts index 8966a64905299..36891fe954c1b 100644 --- a/apps/meteor/app/autotranslate/server/googleTranslate.ts +++ b/apps/meteor/app/autotranslate/server/googleTranslate.ts @@ -126,8 +126,6 @@ class GoogleAutoTranslate extends AutoTranslate { */ async _translateMessage(message: IMessage, targetLanguages: string[]): Promise { const translations: { [k: string]: string } = {}; - let msgs = message.msg.split('\n'); - msgs = msgs.map((msg) => encodeURIComponent(msg)); const supportedLanguages = await this.getSupportedLanguages('en'); @@ -142,7 +140,7 @@ class GoogleAutoTranslate extends AutoTranslate { key: this.apiKey, target: language, format: 'text', - q: msgs, + q: message.msg.split('\n'), }, }); if (!result.ok) { @@ -189,7 +187,7 @@ class GoogleAutoTranslate extends AutoTranslate { key: this.apiKey, target: language, format: 'text', - q: encodeURIComponent(attachment.description || attachment.text || ''), + q: attachment.description || attachment.text || '', }, }); if (!result.ok) { From e14ec50816ef34ee1df61cb8e824cb2a55ff6db9 Mon Sep 17 00:00:00 2001 From: Hugo Costa Date: Fri, 23 Jun 2023 09:45:07 -0300 Subject: [PATCH 17/21] feat: custom fields component to registration form (#29202) Co-authored-by: Douglas Fabris <27704687+dougfabris@users.noreply.github.com> --- .changeset/custom-fields.md | 10 ++ apps/meteor/app/api/server/v1/users.ts | 13 ++ .../AccountsCustomFieldsAssembler.tsx | 71 -------- .../components/AccountsCustomFields/index.ts | 1 - .../client/components/CustomFieldsForm.js | 152 ------------------ .../account/profile/AccountProfileForm.tsx | 45 +++++- .../account/profile/AccountProfilePage.tsx | 2 +- .../client/views/admin/users/AddUser.js | 2 +- .../client/views/admin/users/EditUser.js | 2 +- .../client/views/admin/users/UserForm.js | 36 +++-- .../customFields/CustomFieldsForm.stories.tsx | 10 +- .../customFields/EditCustomFieldsPage.js | 4 +- ...omFieldsForm.js => NewCustomFieldsForm.js} | 4 +- .../customFields/NewCustomFieldsPage.js | 4 +- .../chats/contextualBar/RoomEdit/RoomEdit.tsx | 2 +- .../contacts/contextualBar/ContactNewEdit.tsx | 2 +- .../utils/formatCustomFieldsMetadata.tsx | 4 +- .../root/MainLayout/RegisterUsername.tsx | 72 +++++---- .../core-typings/src/CustomFieldMetadata.ts | 12 ++ packages/core-typings/src/index.ts | 1 + .../src/v1/users/UserRegisterParamsPOST.ts | 5 + packages/ui-client/package.json | 1 + .../src/components/CustomFieldsForm.tsx | 52 +++--- packages/ui-client/src/components/index.ts | 1 + .../src}/hooks/useAccountsCustomFields.ts | 14 +- packages/ui-contexts/src/index.ts | 1 + .../web-ui-registration/src/RegisterForm.tsx | 16 +- yarn.lock | 1 + 28 files changed, 209 insertions(+), 331 deletions(-) create mode 100644 .changeset/custom-fields.md delete mode 100644 apps/meteor/client/components/AccountsCustomFields/AccountsCustomFieldsAssembler.tsx delete mode 100644 apps/meteor/client/components/AccountsCustomFields/index.ts delete mode 100644 apps/meteor/client/components/CustomFieldsForm.js rename apps/meteor/client/views/omnichannel/customFields/{CustomFieldsForm.js => NewCustomFieldsForm.js} (94%) create mode 100644 packages/core-typings/src/CustomFieldMetadata.ts rename apps/meteor/client/components/CustomFieldsFormV2.tsx => packages/ui-client/src/components/CustomFieldsForm.tsx (51%) rename {apps/meteor/client => packages/ui-contexts/src}/hooks/useAccountsCustomFields.ts (64%) diff --git a/.changeset/custom-fields.md b/.changeset/custom-fields.md new file mode 100644 index 0000000000000..c4598efb5f718 --- /dev/null +++ b/.changeset/custom-fields.md @@ -0,0 +1,10 @@ +--- +"@rocket.chat/meteor": patch +"@rocket.chat/core-typings": patch +"@rocket.chat/rest-typings": patch +"@rocket.chat/ui-client": patch +"@rocket.chat/ui-contexts": patch +"@rocket.chat/web-ui-registration": patch +--- + +Added and Improved Custom Fields form to Registration Flow diff --git a/apps/meteor/app/api/server/v1/users.ts b/apps/meteor/app/api/server/v1/users.ts index 8c0a8aea8e121..56c15c6e35c81 100644 --- a/apps/meteor/app/api/server/v1/users.ts +++ b/apps/meteor/app/api/server/v1/users.ts @@ -564,6 +564,15 @@ API.v1.addRoute( } const { secret: secretURL, ...params } = this.bodyParams; + + if (this.bodyParams.customFields) { + try { + await validateCustomFields(this.bodyParams.customFields); + } catch (e) { + return API.v1.failure(e); + } + } + // Register the user const userId = await Meteor.callAsync('registerUser', { ...params, @@ -579,6 +588,10 @@ API.v1.addRoute( return API.v1.failure('User not found'); } + if (this.bodyParams.customFields) { + await saveCustomFields(userId, this.bodyParams.customFields); + } + return API.v1.success({ user }); }, }, diff --git a/apps/meteor/client/components/AccountsCustomFields/AccountsCustomFieldsAssembler.tsx b/apps/meteor/client/components/AccountsCustomFields/AccountsCustomFieldsAssembler.tsx deleted file mode 100644 index 7598fefb47bf0..0000000000000 --- a/apps/meteor/client/components/AccountsCustomFields/AccountsCustomFieldsAssembler.tsx +++ /dev/null @@ -1,71 +0,0 @@ -import { TextInput, Field, Select } from '@rocket.chat/fuselage'; -import { useTranslation } from '@rocket.chat/ui-contexts'; -import React from 'react'; -import type { FieldError } from 'react-hook-form'; -import { useFormContext } from 'react-hook-form'; - -import { useAccountsCustomFields } from '../../hooks/useAccountsCustomFields'; - -const AccountsCustomFieldsAssembler = () => { - const t = useTranslation(); - const customFields = useAccountsCustomFields(); - - const { register, getFieldState, setValue } = useFormContext(); - - return ( - <> - {customFields?.map((customField, index) => { - const getErrorMessage = (error: FieldError | undefined) => { - switch (error?.type) { - case 'required': - return t('The_field_is_required', customField.name); - case 'minLength': - return t('Min_length_is', customField.minLength); - case 'maxLength': - return t('Max_length_is', customField.maxLength); - } - }; - - const { onChange, ...handlers } = register(customField.name, { - required: customField.required, - minLength: customField.minLength, - maxLength: customField.maxLength, - }); - - const error = getErrorMessage(getFieldState(customField.name).error); - return ( - - - {t.has(customField.name) ? t(customField.name) : customField.name} - {customField.required && '*'} - - - {customField.type === 'select' && ( - /* - the Select component is a controlled component, - the onchange handler are not compatible among them, - so we need to setValue on the onChange handler - - Select also doesn't follow the ideal implementation, but is what we have for now - */ - setState(val)} /> - - {selectError} - - ), - [className, label, t, name, required, selectError, state, mappedOptions, setState], - ); -}; - -const CustomFieldsAssembler = ({ formValues, formHandlers, customFields, ...props }) => - Object.entries(customFields).map(([key, value]) => { - const extraProps = { - name: key, - setState: formHandlers[`handle${capitalize(key)}`], - state: formValues[key], - ...value, - }; - - if (value.type === 'select') { - return ; - } - - if (value.type === 'text') { - return ; - } - - return null; - }); - -export default function CustomFieldsForm({ jsonCustomFields, customFieldsData, setCustomFieldsData, onLoadFields = () => {}, ...props }) { - const accountsCustomFieldsJson = useSetting('Accounts_CustomFields'); - - const [customFields] = useState(() => { - try { - return jsonCustomFields || JSON.parse(accountsCustomFieldsJson || '{}'); - } catch { - return {}; - } - }); - - const hasCustomFields = useMemo(() => Object.values(customFields).length > 0, [customFields]); - const defaultFields = useMemo( - () => - Object.entries(customFields).reduce((data, [key, value]) => { - data[key] = value.defaultValue ?? ''; - return data; - }, {}), - [customFields], - ); - - const { values, handlers } = useForm({ ...defaultFields, ...customFieldsData }); - - useEffect(() => { - onLoadFields?.(hasCustomFields); - }, [onLoadFields, hasCustomFields]); - - useEffect(() => { - if (hasCustomFields) { - setCustomFieldsData(values); - } - }, [hasCustomFields, setCustomFieldsData, values]); - - if (!hasCustomFields) { - return null; - } - - return ; -} diff --git a/apps/meteor/client/views/account/profile/AccountProfileForm.tsx b/apps/meteor/client/views/account/profile/AccountProfileForm.tsx index aa0b23849ae1d..23381a6341247 100644 --- a/apps/meteor/client/views/account/profile/AccountProfileForm.tsx +++ b/apps/meteor/client/views/account/profile/AccountProfileForm.tsx @@ -2,15 +2,15 @@ import type { IUser } from '@rocket.chat/core-typings'; import { Field, FieldGroup, TextInput, TextAreaInput, Box, Icon, PasswordInput, Button } from '@rocket.chat/fuselage'; import { useDebouncedCallback, useSafely } from '@rocket.chat/fuselage-hooks'; -import { PasswordVerifier } from '@rocket.chat/ui-client'; +import { CustomFieldsForm, PasswordVerifier } from '@rocket.chat/ui-client'; +import { useAccountsCustomFields, useVerifyPassword, useToastMessageDispatch, useTranslation, useEndpoint } from '@rocket.chat/ui-contexts'; import type { TranslationKey } from '@rocket.chat/ui-contexts'; -import { useVerifyPassword, useToastMessageDispatch, useTranslation, useEndpoint } from '@rocket.chat/ui-contexts'; import type { Dispatch, ReactElement, SetStateAction } from 'react'; import React, { useCallback, useMemo, useEffect, useState } from 'react'; +import { useForm } from 'react-hook-form'; import { validateEmail } from '../../../../lib/emailValidator'; import { getUserEmailAddress } from '../../../../lib/getUserEmailAddress'; -import CustomFieldsForm from '../../../components/CustomFieldsForm'; import UserStatusMenu from '../../../components/UserStatusMenu'; import UserAvatarEditor from '../../../components/avatar/UserAvatarEditor'; import { USER_STATUS_TEXT_MAX_LENGTH, BIO_TEXT_MAX_LENGTH } from '../../../lib/constants'; @@ -33,6 +33,8 @@ const AccountProfileForm = ({ values, handlers, user, settings, onSaveStateChang const getAvatarSuggestions = useEndpoint('GET', '/v1/users.getAvatarSuggestion'); const sendConfirmationEmail = useEndpoint('POST', '/v1/users.sendConfirmationEmail'); + const customFieldsMetadata = useAccountsCustomFields(); + const [usernameError, setUsernameError] = useState(); const [avatarSuggestions, setAvatarSuggestions] = useSafely( useState<{ @@ -71,10 +73,19 @@ const AccountProfileForm = ({ values, handlers, user, settings, onSaveStateChang handleStatusText, handleStatusType, handleBio, - handleCustomFields, handleNickname, + handleCustomFields, } = handlers; + const { + control, + watch, + formState: { errors: customFieldsErrors }, + } = useForm({ + defaultValues: { customFields: { ...customFields } }, + mode: 'onBlur', + }); + const previousEmail = user ? getUserEmailAddress(user) : ''; const handleSendConfirmationEmail = useCallback(async () => { @@ -123,6 +134,11 @@ const AccountProfileForm = ({ values, handlers, user, settings, onSaveStateChang [namesRegex, t, user?.username, checkUsernameAvailability, setUsernameError], ); + useEffect(() => { + const subscription = watch((value) => handleCustomFields({ ...value.customFields })); + return () => subscription.unsubscribe(); + }, [watch, handleCustomFields]); + useEffect(() => { const getSuggestions = async (): Promise => { const { suggestions } = await getAvatarSuggestions(); @@ -166,9 +182,25 @@ const AccountProfileForm = ({ values, handlers, user, settings, onSaveStateChang return undefined; }, [bio, t]); + const customFieldsError = useMemo(() => { + if (customFieldsErrors) { + return customFieldsErrors; + } + + return undefined; + }, [customFieldsErrors]); + const verified = user?.emails?.[0]?.verified ?? false; - const canSave = !(!!passwordError || !!emailError || !!usernameError || !!nameError || !!statusTextError || !!bioError); + const canSave = !( + !!passwordError || + !!emailError || + !!usernameError || + !!nameError || + !!statusTextError || + !!bioError || + !customFieldsError + ); useEffect(() => { onSaveStateChange(canSave); @@ -358,7 +390,8 @@ const AccountProfileForm = ({ values, handlers, user, settings, onSaveStateChang passwordVerifications, ], )} - + + {customFieldsMetadata && } ); }; diff --git a/apps/meteor/client/views/account/profile/AccountProfilePage.tsx b/apps/meteor/client/views/account/profile/AccountProfilePage.tsx index 4d424167643a3..b2f629dd38fa8 100644 --- a/apps/meteor/client/views/account/profile/AccountProfilePage.tsx +++ b/apps/meteor/client/views/account/profile/AccountProfilePage.tsx @@ -248,7 +248,7 @@ const AccountProfilePage = (): ReactElement => { - - diff --git a/apps/meteor/client/views/admin/users/EditUser.js b/apps/meteor/client/views/admin/users/EditUser.js index 984a6e1552bfe..ae216dd4114a9 100644 --- a/apps/meteor/client/views/admin/users/EditUser.js +++ b/apps/meteor/client/views/admin/users/EditUser.js @@ -134,7 +134,7 @@ function EditUser({ data, roles, onReload, ...props }) { - diff --git a/apps/meteor/client/views/admin/users/UserForm.js b/apps/meteor/client/views/admin/users/UserForm.js index d530a0b498164..b0ce0cfdfbf64 100644 --- a/apps/meteor/client/views/admin/users/UserForm.js +++ b/apps/meteor/client/views/admin/users/UserForm.js @@ -10,16 +10,16 @@ import { Divider, FieldGroup, } from '@rocket.chat/fuselage'; -import { useTranslation } from '@rocket.chat/ui-contexts'; -import React, { useCallback, useMemo, useState } from 'react'; +import { CustomFieldsForm } from '@rocket.chat/ui-client'; +import { useTranslation, useAccountsCustomFields } from '@rocket.chat/ui-contexts'; +import React, { useCallback, useMemo, useEffect } from 'react'; +import { useForm } from 'react-hook-form'; import { validateEmail } from '../../../../lib/emailValidator'; import { ContextualbarScrollableContent } from '../../../components/Contextualbar'; -import CustomFieldsForm from '../../../components/CustomFieldsForm'; export default function UserForm({ formValues, formHandlers, availableRoles, append, prepend, errors, isSmtpEnabled, ...props }) { const t = useTranslation(); - const [hasCustomFields, setHasCustomFields] = useState(false); const { name, @@ -55,7 +55,17 @@ export default function UserForm({ formValues, formHandlers, availableRoles, app handleSendWelcomeEmail, } = formHandlers; - const onLoadCustomFields = useCallback((hasCustomFields) => setHasCustomFields(hasCustomFields), []); + const customFieldsMetadata = useAccountsCustomFields(); + + const { control, watch } = useForm({ + defaultValues: { customFields: { ...customFields } }, + mode: 'onBlur', + }); + + useEffect(() => { + const subscription = watch((value) => handleCustomFields({ ...value.customFields })); + return () => subscription.unsubscribe(); + }, [watch, handleCustomFields]); return ( e.preventDefault(), [])} autoComplete='off'> @@ -274,13 +284,17 @@ export default function UserForm({ formValues, formHandlers, availableRoles, app ), [handleSendWelcomeEmail, t, sendWelcomeEmail, isSmtpEnabled], )} - {hasCustomFields && ( - <> - - {t('Custom_Fields')} - + {useMemo( + () => + customFieldsMetadata && ( + <> + + {t('Custom_Fields')} + + + ), + [customFieldsMetadata, control, t], )} - {append} diff --git a/apps/meteor/client/views/omnichannel/customFields/CustomFieldsForm.stories.tsx b/apps/meteor/client/views/omnichannel/customFields/CustomFieldsForm.stories.tsx index f8c6320e6615f..55bd3ee4e2551 100644 --- a/apps/meteor/client/views/omnichannel/customFields/CustomFieldsForm.stories.tsx +++ b/apps/meteor/client/views/omnichannel/customFields/CustomFieldsForm.stories.tsx @@ -3,11 +3,11 @@ import { action } from '@storybook/addon-actions'; import type { ComponentMeta, ComponentStory } from '@storybook/react'; import React from 'react'; -import CustomFieldsForm from './CustomFieldsForm'; +import NewCustomFieldsForm from './NewCustomFieldsForm'; export default { - title: 'Omnichannel/CustomFieldsForm', - component: CustomFieldsForm, + title: 'Omnichannel/NewCustomFieldsForm', + component: NewCustomFieldsForm, decorators: [ (fn) => ( @@ -15,9 +15,9 @@ export default { ), ], -} as ComponentMeta; +} as ComponentMeta; -export const Default: ComponentStory = (args) => ; +export const Default: ComponentStory = (args) => ; Default.storyName = 'CustomFieldsForm'; Default.args = { values: { diff --git a/apps/meteor/client/views/omnichannel/customFields/EditCustomFieldsPage.js b/apps/meteor/client/views/omnichannel/customFields/EditCustomFieldsPage.js index 9b5854b299136..45bbe78a97241 100644 --- a/apps/meteor/client/views/omnichannel/customFields/EditCustomFieldsPage.js +++ b/apps/meteor/client/views/omnichannel/customFields/EditCustomFieldsPage.js @@ -6,7 +6,7 @@ import React, { useCallback, useState } from 'react'; import Page from '../../../components/Page'; import { useForm } from '../../../hooks/useForm'; import { useFormsSubscription } from '../additionalForms'; -import CustomFieldsForm from './CustomFieldsForm'; +import NewCustomFieldsForm from './NewCustomFieldsForm'; const getInitialValues = (cf) => ({ id: cf._id, @@ -79,7 +79,7 @@ const EditCustomFieldsPage = ({ customField, id, reload }) => { - + {AdditionalForm && } diff --git a/apps/meteor/client/views/omnichannel/customFields/CustomFieldsForm.js b/apps/meteor/client/views/omnichannel/customFields/NewCustomFieldsForm.js similarity index 94% rename from apps/meteor/client/views/omnichannel/customFields/CustomFieldsForm.js rename to apps/meteor/client/views/omnichannel/customFields/NewCustomFieldsForm.js index 5ab6f4a19dfdc..5ef97a6e8e3d9 100644 --- a/apps/meteor/client/views/omnichannel/customFields/CustomFieldsForm.js +++ b/apps/meteor/client/views/omnichannel/customFields/NewCustomFieldsForm.js @@ -2,7 +2,7 @@ import { Box, Field, TextInput, ToggleSwitch, Select } from '@rocket.chat/fusela import { useTranslation } from '@rocket.chat/ui-contexts'; import React, { useMemo } from 'react'; -const CustomFieldsForm = ({ values = {}, handlers = {}, className }) => { +const NewCustomFieldsForm = ({ values = {}, handlers = {}, className }) => { const t = useTranslation(); const { id, field, label, scope, visibility, searchable, regexp } = values; @@ -63,4 +63,4 @@ const CustomFieldsForm = ({ values = {}, handlers = {}, className }) => { ); }; -export default CustomFieldsForm; +export default NewCustomFieldsForm; diff --git a/apps/meteor/client/views/omnichannel/customFields/NewCustomFieldsPage.js b/apps/meteor/client/views/omnichannel/customFields/NewCustomFieldsPage.js index ee00c92427781..c4185758dbc49 100644 --- a/apps/meteor/client/views/omnichannel/customFields/NewCustomFieldsPage.js +++ b/apps/meteor/client/views/omnichannel/customFields/NewCustomFieldsPage.js @@ -6,7 +6,7 @@ import React, { useCallback, useState } from 'react'; import Page from '../../../components/Page'; import { useForm } from '../../../hooks/useForm'; import { useFormsSubscription } from '../additionalForms'; -import CustomFieldsForm from './CustomFieldsForm'; +import NewCustomFieldsForm from './NewCustomFieldsForm'; const initialValues = { field: '', @@ -78,7 +78,7 @@ const NewCustomFieldsPage = ({ reload }) => { - + {AdditionalForm && } diff --git a/apps/meteor/client/views/omnichannel/directory/chats/contextualBar/RoomEdit/RoomEdit.tsx b/apps/meteor/client/views/omnichannel/directory/chats/contextualBar/RoomEdit/RoomEdit.tsx index 71e7ec57ca423..435e29743469f 100644 --- a/apps/meteor/client/views/omnichannel/directory/chats/contextualBar/RoomEdit/RoomEdit.tsx +++ b/apps/meteor/client/views/omnichannel/directory/chats/contextualBar/RoomEdit/RoomEdit.tsx @@ -1,5 +1,6 @@ import type { ILivechatVisitor, IOmnichannelRoom, Serialized } from '@rocket.chat/core-typings'; import { Field, TextInput, ButtonGroup, Button } from '@rocket.chat/fuselage'; +import { CustomFieldsForm } from '@rocket.chat/ui-client'; import { useToastMessageDispatch, useTranslation, useEndpoint } from '@rocket.chat/ui-contexts'; import { useQueryClient } from '@tanstack/react-query'; import React, { useCallback } from 'react'; @@ -8,7 +9,6 @@ import { useController, useForm } from 'react-hook-form'; import { hasAtLeastOnePermission } from '../../../../../../../app/authorization/client'; import { useOmnichannelPriorities } from '../../../../../../../ee/client/omnichannel/hooks/useOmnichannelPriorities'; import { ContextualbarFooter, ContextualbarScrollableContent } from '../../../../../../components/Contextualbar'; -import { CustomFieldsForm } from '../../../../../../components/CustomFieldsFormV2'; import Tags from '../../../../../../components/Omnichannel/Tags'; import { useFormsSubscription } from '../../../../additionalForms'; import { FormSkeleton } from '../../../components/FormSkeleton'; diff --git a/apps/meteor/client/views/omnichannel/directory/contacts/contextualBar/ContactNewEdit.tsx b/apps/meteor/client/views/omnichannel/directory/contacts/contextualBar/ContactNewEdit.tsx index c98d9ccb22578..53c30d49a0d4a 100644 --- a/apps/meteor/client/views/omnichannel/directory/contacts/contextualBar/ContactNewEdit.tsx +++ b/apps/meteor/client/views/omnichannel/directory/contacts/contextualBar/ContactNewEdit.tsx @@ -1,5 +1,6 @@ import type { ILivechatVisitor, Serialized } from '@rocket.chat/core-typings'; import { Field, TextInput, ButtonGroup, Button } from '@rocket.chat/fuselage'; +import { CustomFieldsForm } from '@rocket.chat/ui-client'; import { useToastMessageDispatch, useEndpoint, useTranslation } from '@rocket.chat/ui-contexts'; import { useQueryClient } from '@tanstack/react-query'; import type { ReactElement } from 'react'; @@ -9,7 +10,6 @@ import { useForm } from 'react-hook-form'; import { hasAtLeastOnePermission } from '../../../../../../app/authorization/client'; import { validateEmail } from '../../../../../../lib/emailValidator'; import { ContextualbarScrollableContent, ContextualbarFooter } from '../../../../../components/Contextualbar'; -import { CustomFieldsForm } from '../../../../../components/CustomFieldsFormV2'; import { createToken } from '../../../../../lib/utils/createToken'; import { useFormsSubscription } from '../../../additionalForms'; import { FormSkeleton } from '../../components/FormSkeleton'; diff --git a/apps/meteor/client/views/omnichannel/directory/utils/formatCustomFieldsMetadata.tsx b/apps/meteor/client/views/omnichannel/directory/utils/formatCustomFieldsMetadata.tsx index a4f84f45f91ed..b5648d67199f2 100644 --- a/apps/meteor/client/views/omnichannel/directory/utils/formatCustomFieldsMetadata.tsx +++ b/apps/meteor/client/views/omnichannel/directory/utils/formatCustomFieldsMetadata.tsx @@ -1,6 +1,4 @@ -import type { ILivechatCustomField, Serialized } from '@rocket.chat/core-typings'; - -import type { CustomFieldMetadata } from '../../../../components/CustomFieldsFormV2'; +import type { ILivechatCustomField, Serialized, CustomFieldMetadata } from '@rocket.chat/core-typings'; export const formatCustomFieldsMetadata = ( customFields: Serialized[], diff --git a/apps/meteor/client/views/root/MainLayout/RegisterUsername.tsx b/apps/meteor/client/views/root/MainLayout/RegisterUsername.tsx index 92dab6f3db08d..e7dae770c4444 100644 --- a/apps/meteor/client/views/root/MainLayout/RegisterUsername.tsx +++ b/apps/meteor/client/views/root/MainLayout/RegisterUsername.tsx @@ -2,6 +2,7 @@ import type { IUser } from '@rocket.chat/core-typings'; import { TextInput, ButtonGroup, Button, FieldGroup, Field, Box } from '@rocket.chat/fuselage'; import { useUniqueId } from '@rocket.chat/fuselage-hooks'; import { VerticalWizardLayout, Form } from '@rocket.chat/layout'; +import { CustomFieldsForm } from '@rocket.chat/ui-client'; import { useSetting, useTranslation, @@ -11,12 +12,12 @@ import { useToastMessageDispatch, useAssetWithDarkModePath, useMethod, + useAccountsCustomFields, } from '@rocket.chat/ui-contexts'; import { useQuery, useMutation } from '@tanstack/react-query'; import React, { useEffect } from 'react'; -import { FormProvider, useForm } from 'react-hook-form'; +import { useForm } from 'react-hook-form'; -import AccountsCustomFields from '../../../components/AccountsCustomFields'; import { queryClient } from '../../../lib/queryClient'; type RegisterUsernamePayload = { @@ -32,6 +33,7 @@ const RegisterUsername = () => { const customLogo = useAssetWithDarkModePath('logo'); const customBackground = useAssetWithDarkModePath('background'); const dispatchToastMessage = useToastMessageDispatch(); + const customFields = useAccountsCustomFields(); if (!uid) { throw new Error('Invalid user'); @@ -42,15 +44,17 @@ const RegisterUsername = () => { const usernameSuggestion = useEndpoint('GET', '/v1/users.getUsernameSuggestion'); const { data, isLoading } = useQuery(['suggestion'], async () => usernameSuggestion()); - const methods = useForm(); const { register, handleSubmit, setValue, getValues, setError, + control, formState: { errors }, - } = methods; + } = useForm({ + mode: 'onBlur', + }); useEffect(() => { if (data?.result && getValues('username') === '') { @@ -89,37 +93,35 @@ const RegisterUsername = () => { background={customBackground} logo={!hideLogo && customLogo ? : <>} > - - registerUsernameMutation.mutate(data))}> - - {t('Username_title')} - {t('Username_description')} - - - {!isLoading && ( - - - {t('Username')} - - - - {errors.username && {errors.username.message}} - - - )} - {isLoading && t('Loading_suggestion')} - - - - - - - - - - +
registerUsernameMutation.mutate(data))}> + + {t('Username_title')} + {t('Username_description')} + + + {!isLoading && ( + + + {t('Username')} + + + + {errors.username && {errors.username.message}} + + + )} + {isLoading && t('Loading_suggestion')} + + + + + + + + + ); }; diff --git a/packages/core-typings/src/CustomFieldMetadata.ts b/packages/core-typings/src/CustomFieldMetadata.ts new file mode 100644 index 0000000000000..bd351c9e37d12 --- /dev/null +++ b/packages/core-typings/src/CustomFieldMetadata.ts @@ -0,0 +1,12 @@ +import type { SelectOption } from '@rocket.chat/fuselage'; + +export type CustomFieldMetadata = { + name: string; + label?: string; + type: 'select' | 'text'; + required?: boolean; + defaultValue?: any; + minLength?: number; + maxLength?: number; + options?: SelectOption[]; +}; diff --git a/packages/core-typings/src/index.ts b/packages/core-typings/src/index.ts index d2c35b3a4a8f6..9ba91eb373b45 100644 --- a/packages/core-typings/src/index.ts +++ b/packages/core-typings/src/index.ts @@ -133,3 +133,4 @@ export * from './migrations/IControl'; export * from './ICustomOAuthConfig'; export * from './IModerationReport'; +export * from './CustomFieldMetadata'; diff --git a/packages/rest-typings/src/v1/users/UserRegisterParamsPOST.ts b/packages/rest-typings/src/v1/users/UserRegisterParamsPOST.ts index 236f7136966a1..a0475042c9413 100644 --- a/packages/rest-typings/src/v1/users/UserRegisterParamsPOST.ts +++ b/packages/rest-typings/src/v1/users/UserRegisterParamsPOST.ts @@ -11,6 +11,7 @@ export type UserRegisterParamsPOST = { pass: string; secret?: string; reason?: string; + customFields?: object; }; const UserRegisterParamsPostSchema = { @@ -38,6 +39,10 @@ const UserRegisterParamsPostSchema = { type: 'string', nullable: true, }, + customFields: { + type: 'object', + nullable: true, + }, }, required: ['username', 'email', 'pass'], additionalProperties: false, diff --git a/packages/ui-client/package.json b/packages/ui-client/package.json index e1c6be800205a..8fbb4d6acd212 100644 --- a/packages/ui-client/package.json +++ b/packages/ui-client/package.json @@ -31,6 +31,7 @@ "eslint-plugin-testing-library": "~5.11.0", "jest": "~29.5.0", "react": "~17.0.2", + "react-hook-form": "^7.30.0", "ts-jest": "~29.0.5", "typescript": "~5.1.3" }, diff --git a/apps/meteor/client/components/CustomFieldsFormV2.tsx b/packages/ui-client/src/components/CustomFieldsForm.tsx similarity index 51% rename from apps/meteor/client/components/CustomFieldsFormV2.tsx rename to packages/ui-client/src/components/CustomFieldsForm.tsx index 8125c14fa4572..dee63d50106ea 100644 --- a/apps/meteor/client/components/CustomFieldsFormV2.tsx +++ b/packages/ui-client/src/components/CustomFieldsForm.tsx @@ -1,20 +1,10 @@ -/* eslint-disable react/no-multi-comp */ +import type { CustomFieldMetadata } from '@rocket.chat/core-typings'; import type { SelectOption } from '@rocket.chat/fuselage'; import { Field, Select, TextInput } from '@rocket.chat/fuselage'; import type { TranslationKey } from '@rocket.chat/ui-contexts'; import { useTranslation } from '@rocket.chat/ui-contexts'; -import React from 'react'; import type { Control, FieldValues } from 'react-hook-form'; -import { Controller, get } from 'react-hook-form'; - -export type CustomFieldMetadata = { - name: string; - label: string; - type: 'select' | 'text'; - required?: boolean; - defaultValue?: any; - options?: SelectOption[]; -}; +import { Controller } from 'react-hook-form'; type CustomFieldFormProps = { metadata: CustomFieldMetadata[]; @@ -43,36 +33,54 @@ const CustomField = ({ ...props }: CustomFieldProps) => { const t = useTranslation(); + const { getFieldState } = control; + const Component = FIELD_TYPES[type] ?? null; + const selectOptions = + options.length > 0 && options[0] instanceof Array ? options : options.map((option) => [option, option, defaultValue === option]); + + const getErrorMessage = (error: any) => { + switch (error?.type) { + case 'required': + return t('The_field_is_required', label || name); + case 'minLength': + return t('Min_length_is', props?.minLength); + case 'maxLength': + return t('Max_length_is', props?.maxLength); + } + }; + + const error = getErrorMessage(getFieldState(name as any).error); + return ( name={name} control={control} defaultValue={defaultValue ?? ''} - rules={{ required: required && t('The_field_is_required', label || name) }} - render={({ field, formState: { errors } }) => ( - + rules={{ required, minLength: props.minLength, maxLength: props.maxLength }} + render={({ field }) => ( + {label || t(name as TranslationKey)} {required && '*'} - + - {get(errors, name)?.message} + {error} )} /> ); }; -CustomField.displayName = 'CustomField'; - +// eslint-disable-next-line react/no-multi-comp export const CustomFieldsForm = ({ formName, formControl, metadata }: CustomFieldFormProps) => ( <> - {metadata.map(({ name: fieldName, ...props }) => ( - - ))} + {metadata.map(({ name: fieldName, ...props }) => { + props.label = props.label ?? fieldName; + return ; + })} ); diff --git a/packages/ui-client/src/components/index.ts b/packages/ui-client/src/components/index.ts index 9aa37f5479eb2..5a0f1463be808 100644 --- a/packages/ui-client/src/components/index.ts +++ b/packages/ui-client/src/components/index.ts @@ -1,6 +1,7 @@ export * from './EmojiPicker'; export * from './ExternalLink'; export * from './DotLeader'; +export * from './CustomFieldsForm'; export * from './PasswordVerifier'; export { default as TextSeparator } from './TextSeparator'; export * from './TooltipComponent'; diff --git a/apps/meteor/client/hooks/useAccountsCustomFields.ts b/packages/ui-contexts/src/hooks/useAccountsCustomFields.ts similarity index 64% rename from apps/meteor/client/hooks/useAccountsCustomFields.ts rename to packages/ui-contexts/src/hooks/useAccountsCustomFields.ts index 66786fdceb6ec..8daa51b240ffe 100644 --- a/apps/meteor/client/hooks/useAccountsCustomFields.ts +++ b/packages/ui-contexts/src/hooks/useAccountsCustomFields.ts @@ -1,17 +1,9 @@ -import { useSetting } from '@rocket.chat/ui-contexts'; import { useMemo } from 'react'; +import type { CustomFieldMetadata } from '@rocket.chat/core-typings'; -type AccountsCustomField = { - type: 'text' | 'select'; - required: boolean; - defaultValue: string; - minLength: number; - maxLength: number; - options: string[]; - name: string; -}; +import { useSetting } from './useSetting'; -export const useAccountsCustomFields = (): AccountsCustomField[] => { +export const useAccountsCustomFields = (): CustomFieldMetadata[] => { const accountsCustomFieldsJSON = useSetting('Accounts_CustomFields'); return useMemo(() => { diff --git a/packages/ui-contexts/src/index.ts b/packages/ui-contexts/src/index.ts index 771a34eed36d4..7780e6fa7fa16 100644 --- a/packages/ui-contexts/src/index.ts +++ b/packages/ui-contexts/src/index.ts @@ -87,6 +87,7 @@ export { useAvailableDevices } from './hooks/useAvailableDevices'; export { useIsDeviceManagementEnabled } from './hooks/useIsDeviceManagementEnabled'; export { useSetOutputMediaDevice } from './hooks/useSetOutputMediaDevice'; export { useSetInputMediaDevice } from './hooks/useSetInputMediaDevice'; +export { useAccountsCustomFields } from './hooks/useAccountsCustomFields'; export { ServerMethods, ServerMethodName, ServerMethodParameters, ServerMethodReturn, ServerMethodFunction } from './ServerContext/methods'; export { StreamerEvents, StreamNames, StreamKeys, StreamerConfigs, StreamerConfig, StreamerCallbackArgs } from './ServerContext/streams'; diff --git a/packages/web-ui-registration/src/RegisterForm.tsx b/packages/web-ui-registration/src/RegisterForm.tsx index 8870832991e45..5400dccce79f5 100644 --- a/packages/web-ui-registration/src/RegisterForm.tsx +++ b/packages/web-ui-registration/src/RegisterForm.tsx @@ -1,9 +1,10 @@ import { useUniqueId } from '@rocket.chat/fuselage-hooks'; -import { FieldGroup, TextInput, Field, PasswordInput, ButtonGroup, Button, TextAreaInput } from '@rocket.chat/fuselage'; +import { FieldGroup, TextInput, Field, PasswordInput, ButtonGroup, Button, TextAreaInput, Callout } from '@rocket.chat/fuselage'; import { Form, ActionLink } from '@rocket.chat/layout'; -import { useSetting, useVerifyPassword, useToastMessageDispatch } from '@rocket.chat/ui-contexts'; -import { PasswordVerifier } from '@rocket.chat/ui-client'; +import { useAccountsCustomFields, useVerifyPassword, useSetting, useToastMessageDispatch } from '@rocket.chat/ui-contexts'; +import { PasswordVerifier, CustomFieldsForm } from '@rocket.chat/ui-client'; import type { ReactElement } from 'react'; +import { useState } from 'react'; import { useForm } from 'react-hook-form'; import { Trans, useTranslation } from 'react-i18next'; @@ -34,6 +35,9 @@ export const RegisterForm = ({ setLoginRoute }: { setLoginRoute: DispatchLoginRo const formLabelId = useUniqueId(); const registerUser = useRegisterMethod(); + const customFields = useAccountsCustomFields(); + + const [serverError, setServerError] = useState(undefined); const dispatchToastMessage = useToastMessageDispatch(); @@ -44,6 +48,7 @@ export const RegisterForm = ({ setLoginRoute }: { setLoginRoute: DispatchLoginRo watch, getValues, clearErrors, + control, formState: { errors }, } = useForm(); @@ -75,6 +80,9 @@ export const RegisterForm = ({ setLoginRoute }: { setLoginRoute: DispatchLoginRo dispatchToastMessage({ type: 'info', message: t('registration.page.registration.waitActivationWarning') }); setLoginRoute('login'); } + if (error.error === 'error-user-registration-custom-field') { + setServerError(error.message); + } }, }, ); @@ -196,6 +204,8 @@ export const RegisterForm = ({ setLoginRoute }: { setLoginRoute: DispatchLoginRo {errors.reason && {t('registration.component.form.requiredField')}} )} + {customFields.length > 0 && } + {serverError && {serverError}} diff --git a/yarn.lock b/yarn.lock index 6d50fb8fa28a6..a0de900e478f0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10932,6 +10932,7 @@ __metadata: eslint-plugin-testing-library: ~5.11.0 jest: ~29.5.0 react: ~17.0.2 + react-hook-form: ^7.30.0 ts-jest: ~29.0.5 typescript: ~5.1.3 peerDependencies: From 67a299b3546d702620c17b72cb81e31981b96de5 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Fri, 23 Jun 2023 11:29:01 -0300 Subject: [PATCH 18/21] ci: uikit loglevel silent (#29633) --- .github/workflows/ci.yml | 8 ++++++++ packages/uikit-playground/vite.config.ts | 1 + 2 files changed, 9 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4038c09f09b86..d9c250ebcc045 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -116,6 +116,14 @@ jobs: # docker rmi $(docker image ls -aq) # df -h + - name: Cache vite + uses: actions/cache@v3 + with: + path: ./node_modules/.vite + key: vite-local-cache-${{ runner.OS }}-${{ hashFiles('package.json') }} + restore-keys: | + vite-local-cache-${{ runner.os }}- + - name: Cache meteor local uses: actions/cache@v3 with: diff --git a/packages/uikit-playground/vite.config.ts b/packages/uikit-playground/vite.config.ts index 778656d61f41e..36f78a6ecda25 100644 --- a/packages/uikit-playground/vite.config.ts +++ b/packages/uikit-playground/vite.config.ts @@ -3,6 +3,7 @@ import react from '@vitejs/plugin-react'; // https://vitejs.dev/config/ export default defineConfig(({ mode }) => ({ + logLevel: 'error', esbuild: { drop: mode === 'development' ? ['console', 'debugger'] : [], }, From f7d2e27eec6aef11a72bc479ec86cde3a0565306 Mon Sep 17 00:00:00 2001 From: Douglas Fabris Date: Fri, 23 Jun 2023 23:44:15 -0300 Subject: [PATCH 19/21] chore: `Table` in favor of `GenericTable` (#29628) --- .../AccountTokensTable/AccountTokensRow.tsx | 21 +++--- .../CustomUserStatusRow.tsx | 14 ++-- .../views/admin/emailInbox/SendTestButton.tsx | 8 ++- .../views/admin/import/ImportHistoryPage.tsx | 54 +++++++-------- .../admin/import/ImportOperationSummary.js | 22 +++---- .../import/ImportOperationSummary.stories.tsx | 4 +- .../import/ImportOperationSummarySkeleton.js | 38 +++++------ .../views/admin/import/PrepareChannels.tsx | 34 +++++----- .../views/admin/import/PrepareUsers.tsx | 38 +++++------ .../moderation/ModerationConsoleTableRow.tsx | 27 ++++---- .../PermissionsTable/PermissionRow.tsx | 10 +-- .../permissions/PermissionsTable/RoleCell.tsx | 7 +- .../UsersInRoleTable/UsersInRoleTableRow.tsx | 17 ++--- .../groups/voip/AssignAgentButton.tsx | 7 +- .../groups/voip/RemoveAgentButton.tsx | 7 +- .../admin/users/UsersTable/UsersTableRow.tsx | 30 +++++---- .../ChannelsTable/ChannelsTableRow.tsx | 27 ++++---- .../tabs/teams/TeamsTable/TeamsTableRow.tsx | 19 +++--- .../tabs/users/UsersTable/UsersTableRow.tsx | 21 +++--- .../omnichannel/analytics/AgentOverview.tsx | 24 +++---- .../DepartmentAgentsTable/AgentRow.tsx | 23 +++---- .../directory/calls/CallTableRow.tsx | 20 +++--- .../managers/RemoveManagerButton.tsx | 7 +- .../ChannelDesertionTableRow.tsx | 15 +++-- .../omnichannel/RemoveBusinessHourButton.js | 7 +- .../DeviceManagementAccountRow.tsx | 21 +++--- .../DeviceManagementAdminRow.tsx | 25 +++---- .../channels/ChannelsOverview.tsx | 66 +++++++++---------- .../messages/MessagesPerChannelSection.tsx | 62 ++++++++++------- .../views/audit/components/AuditLogEntry.tsx | 23 +++---- yarn.lock | 40 +++++------ 31 files changed, 390 insertions(+), 348 deletions(-) diff --git a/apps/meteor/client/views/account/tokens/AccountTokensTable/AccountTokensRow.tsx b/apps/meteor/client/views/account/tokens/AccountTokensTable/AccountTokensRow.tsx index 33a5b3855b5e8..39c8c6f1cc28a 100644 --- a/apps/meteor/client/views/account/tokens/AccountTokensTable/AccountTokensRow.tsx +++ b/apps/meteor/client/views/account/tokens/AccountTokensTable/AccountTokensRow.tsx @@ -1,9 +1,10 @@ import type { IPersonalAccessToken, Serialized } from '@rocket.chat/core-typings'; -import { ButtonGroup, IconButton, TableRow, TableCell } from '@rocket.chat/fuselage'; +import { ButtonGroup, IconButton } from '@rocket.chat/fuselage'; import { useTranslation } from '@rocket.chat/ui-contexts'; import type { FC } from 'react'; import React, { useCallback } from 'react'; +import { GenericTableRow, GenericTableCell } from '../../../../components/GenericTable'; import { useFormatDateAndTime } from '../../../../hooks/useFormatDateAndTime'; type AccountTokensRowProps = { @@ -27,20 +28,20 @@ const AccountTokensRow: FC = ({ const handleRemove = useCallback(() => onRemove(name), [name, onRemove]); return ( - - + + {name} - - {isMedium && {formatDateAndTime(createdAt)}} - ...{lastTokenPart} - {bypassTwoFactor ? t('Ignore') : t('Require')} - + + {isMedium && {formatDateAndTime(createdAt)}} + ...{lastTokenPart} + {bypassTwoFactor ? t('Ignore') : t('Require')} + - - + + ); }; diff --git a/apps/meteor/client/views/admin/customUserStatus/CustomUserStatusTable/CustomUserStatusRow.tsx b/apps/meteor/client/views/admin/customUserStatus/CustomUserStatusTable/CustomUserStatusRow.tsx index 179071c7bff31..fb85f20eca292 100644 --- a/apps/meteor/client/views/admin/customUserStatus/CustomUserStatusTable/CustomUserStatusRow.tsx +++ b/apps/meteor/client/views/admin/customUserStatus/CustomUserStatusTable/CustomUserStatusRow.tsx @@ -1,8 +1,8 @@ import type { IUserStatus } from '@rocket.chat/core-typings'; -import { TableRow, TableCell } from '@rocket.chat/fuselage'; import type { CSSProperties, ReactElement } from 'react'; import React from 'react'; +import { GenericTableRow, GenericTableCell } from '../../../../components/GenericTable'; import MarkdownText from '../../../../components/MarkdownText'; const style: CSSProperties = { whiteSpace: 'nowrap', textOverflow: 'ellipsis', overflow: 'hidden' }; @@ -16,7 +16,7 @@ const CustomUserStatusRow = ({ status, onClick }: CustomUserStatusRowProps): Rea const { _id, name, statusType } = status; return ( - onClick(_id)} onClick={(): void => onClick(_id)} @@ -25,13 +25,13 @@ const CustomUserStatusRow = ({ status, onClick }: CustomUserStatusRowProps): Rea action qa-user-id={_id} > - + - - + + {statusType} - - + + ); }; diff --git a/apps/meteor/client/views/admin/emailInbox/SendTestButton.tsx b/apps/meteor/client/views/admin/emailInbox/SendTestButton.tsx index 4f4fa8215901b..ed44621137bfa 100644 --- a/apps/meteor/client/views/admin/emailInbox/SendTestButton.tsx +++ b/apps/meteor/client/views/admin/emailInbox/SendTestButton.tsx @@ -1,9 +1,11 @@ import type { IEmailInboxPayload } from '@rocket.chat/core-typings'; -import { Box, Button, TableCell, Icon } from '@rocket.chat/fuselage'; +import { Box, Button, Icon } from '@rocket.chat/fuselage'; import { useToastMessageDispatch, useEndpoint, useTranslation } from '@rocket.chat/ui-contexts'; import type { ReactElement } from 'react'; import React from 'react'; +import { GenericTableCell } from '../../../components/GenericTable'; + const SendTestButton = ({ id }: { id: IEmailInboxPayload['_id'] }): ReactElement => { const t = useTranslation(); const dispatchToastMessage = useToastMessageDispatch(); @@ -28,14 +30,14 @@ const SendTestButton = ({ id }: { id: IEmailInboxPayload['_id'] }): ReactElement }; return ( - + - + ); }; diff --git a/apps/meteor/client/views/admin/import/ImportHistoryPage.tsx b/apps/meteor/client/views/admin/import/ImportHistoryPage.tsx index 2c924e3b580f1..b1d514a076c7e 100644 --- a/apps/meteor/client/views/admin/import/ImportHistoryPage.tsx +++ b/apps/meteor/client/views/admin/import/ImportHistoryPage.tsx @@ -1,4 +1,4 @@ -import { Button, ButtonGroup, Table } from '@rocket.chat/fuselage'; +import { Button, ButtonGroup, Table, TableHead, TableCell, TableRow, TableBody } from '@rocket.chat/fuselage'; import { useMediaQuery } from '@rocket.chat/fuselage-hooks'; import { useToastMessageDispatch, useRoute, useEndpoint, useTranslation } from '@rocket.chat/ui-contexts'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; @@ -115,46 +115,46 @@ function ImportHistoryPage() {
- - - + + + {t('Import_Type')} - - + + {t('Last_Updated')} - + {!small && ( <> - + {t('Last_Status')} - - + + {t('File')} - - + + {t('Counters')} - + )} - + {!small && ( - - + + {t('Users')} - - + + {t('Channels')} - - + + {t('Messages')} - - + + {t('Total')} - - + + )} - - + + {isLoading && ( <> {Array.from({ length: 20 }, (_, i) => ( @@ -176,7 +176,7 @@ function ImportHistoryPage() { ))} )} - +
diff --git a/apps/meteor/client/views/admin/import/ImportOperationSummary.js b/apps/meteor/client/views/admin/import/ImportOperationSummary.js index a95e03d75c146..79e88ddbe358b 100644 --- a/apps/meteor/client/views/admin/import/ImportOperationSummary.js +++ b/apps/meteor/client/views/admin/import/ImportOperationSummary.js @@ -1,4 +1,4 @@ -import { Table } from '@rocket.chat/fuselage'; +import { TableRow, TableCell } from '@rocket.chat/fuselage'; import { useRoute, useTranslation } from '@rocket.chat/ui-contexts'; import React, { useMemo } from 'react'; @@ -81,20 +81,20 @@ function ImportOperationSummary({ : {}; return ( - - {type} - {formatDateAndTime(_updatedAt)} + + {type} + {formatDateAndTime(_updatedAt)} {!small && ( <> - {status && t(status.replace('importer_', 'importer_status_'))} - {fileName} - {users} - {channels} - {messages} - {total} + {status && t(status.replace('importer_', 'importer_status_'))} + {fileName} + {users} + {channels} + {messages} + {total} )} - +
); } diff --git a/apps/meteor/client/views/admin/import/ImportOperationSummary.stories.tsx b/apps/meteor/client/views/admin/import/ImportOperationSummary.stories.tsx index 0e41058b5f90a..39972c78fa2da 100644 --- a/apps/meteor/client/views/admin/import/ImportOperationSummary.stories.tsx +++ b/apps/meteor/client/views/admin/import/ImportOperationSummary.stories.tsx @@ -1,4 +1,4 @@ -import { Table } from '@rocket.chat/fuselage'; +import { Table, TableBody } from '@rocket.chat/fuselage'; import type { ComponentMeta, ComponentStory } from '@storybook/react'; import React from 'react'; @@ -16,7 +16,7 @@ export default { decorators: [ (fn) => ( - {fn()} + {fn()}
), ], diff --git a/apps/meteor/client/views/admin/import/ImportOperationSummarySkeleton.js b/apps/meteor/client/views/admin/import/ImportOperationSummarySkeleton.js index 401f30aed3f58..81509516d234c 100644 --- a/apps/meteor/client/views/admin/import/ImportOperationSummarySkeleton.js +++ b/apps/meteor/client/views/admin/import/ImportOperationSummarySkeleton.js @@ -1,38 +1,38 @@ -import { Skeleton, Table } from '@rocket.chat/fuselage'; +import { Skeleton, TableRow, TableCell } from '@rocket.chat/fuselage'; import React from 'react'; function ImportOperationSummarySkeleton({ small }) { return ( - - + + - - + + - + {!small && ( <> - + - - + + - - + + - - + + - - + + - - + + - + )} - + ); } diff --git a/apps/meteor/client/views/admin/import/PrepareChannels.tsx b/apps/meteor/client/views/admin/import/PrepareChannels.tsx index c07e76b2dd819..e7b5f4a6a6a34 100644 --- a/apps/meteor/client/views/admin/import/PrepareChannels.tsx +++ b/apps/meteor/client/views/admin/import/PrepareChannels.tsx @@ -1,4 +1,4 @@ -import { CheckBox, Table, Tag, Pagination } from '@rocket.chat/fuselage'; +import { CheckBox, Table, Tag, Pagination, TableHead, TableRow, TableCell, TableBody } from '@rocket.chat/fuselage'; import { useTranslation } from '@rocket.chat/ui-contexts'; import type { FC, Dispatch, SetStateAction, ChangeEvent } from 'react'; import React, { useState, useCallback } from 'react'; @@ -33,9 +33,9 @@ const PrepareChannels: FC = ({ channels, channelsCount, se return ( <> - - - + + + 0} indeterminate={channelsCount > 0 && channelsCount !== channels.length} @@ -56,15 +56,15 @@ const PrepareChannels: FC = ({ channels, channelsCount, se }); }} /> - - {t('Name')} - - - - + + {t('Name')} + + + + {channels.slice(current, current + itemsPerPage).map((channel) => ( - - + + ): void => { @@ -74,12 +74,12 @@ const PrepareChannels: FC = ({ channels, channelsCount, se ); }} /> - - {channel.name} - {channel.is_archived && {t('Importer_Archived')}} - + + {channel.name} + {channel.is_archived && {t('Importer_Archived')}} + ))} - +
= ({ usersCount, users, setUsers }) => return ( <> - - - + + + 0} indeterminate={usersCount > 0 && usersCount !== users.length} @@ -53,16 +53,16 @@ const PrepareUsers: FC = ({ usersCount, users, setUsers }) => }); }} /> - - {t('Username')} - {t('Email')} - - - - + + {t('Username')} + {t('Email')} + + + + {users.slice(current, current + itemsPerPage).map((user) => ( - - + + ): void => { @@ -70,13 +70,13 @@ const PrepareUsers: FC = ({ usersCount, users, setUsers }) => setUsers((users) => users.map((_user) => (_user === user ? { ..._user, do_import: checked } : _user))); }} /> - - {user.username} - {user.email} - {user.is_deleted && {t('Deleted')}} - + + {user.username} + {user.email} + {user.is_deleted && {t('Deleted')}} + ))} - +
onClick(_id)} onClick={(): void => onClick(_id)} tabIndex={0} role='link' action> - + onClick(_id)} onClick={(): void => onClick(_id)} tabIndex={0} role='link' action> + {username && ( @@ -49,22 +50,22 @@ const ModerationConsoleTableRow = ({ report, onClick, isDesktopOrLarger }: Moder - + {isDesktopOrLarger && ( - + {username} - + )} - {message} - {concatenatedRoomNames} - {formatDateAndTime(ts)} - {count} - e.stopPropagation()}> + {message} + {concatenatedRoomNames} + {formatDateAndTime(ts)} + {count} + e.stopPropagation()}> - - + + ); }; diff --git a/apps/meteor/client/views/admin/permissions/PermissionsTable/PermissionRow.tsx b/apps/meteor/client/views/admin/permissions/PermissionsTable/PermissionRow.tsx index 36d337a024c42..300d80f4f51cc 100644 --- a/apps/meteor/client/views/admin/permissions/PermissionsTable/PermissionRow.tsx +++ b/apps/meteor/client/views/admin/permissions/PermissionsTable/PermissionRow.tsx @@ -1,5 +1,4 @@ import type { IRole, IPermission } from '@rocket.chat/core-typings'; -import { TableRow, TableCell } from '@rocket.chat/fuselage'; import { useMutableCallback } from '@rocket.chat/fuselage-hooks'; import type { TranslationKey } from '@rocket.chat/ui-contexts'; import { useTranslation } from '@rocket.chat/ui-contexts'; @@ -7,6 +6,7 @@ import type { ReactElement } from 'react'; import React, { useState, memo } from 'react'; import { CONSTANTS } from '../../../../../app/authorization/lib'; +import { GenericTableRow, GenericTableCell } from '../../../../components/GenericTable'; import { useChangeRole } from '../hooks/useChangeRole'; import RoleCell from './RoleCell'; @@ -42,10 +42,10 @@ const PermissionRow = ({ permission, roleList, onGrant, onRemove }: PermissionRo const onMouseLeave = useMutableCallback(() => setHovered(false)); return ( - - + + {getName(t, permission)} - + {roleList.map(({ _id, name, description }) => ( ))} - + ); }; diff --git a/apps/meteor/client/views/admin/permissions/PermissionsTable/RoleCell.tsx b/apps/meteor/client/views/admin/permissions/PermissionsTable/RoleCell.tsx index f2ca908d95176..cb686584b2c04 100644 --- a/apps/meteor/client/views/admin/permissions/PermissionsTable/RoleCell.tsx +++ b/apps/meteor/client/views/admin/permissions/PermissionsTable/RoleCell.tsx @@ -1,10 +1,11 @@ import type { IRole } from '@rocket.chat/core-typings'; -import { TableCell, Margins, Box, CheckBox, Throbber } from '@rocket.chat/fuselage'; +import { Margins, Box, CheckBox, Throbber } from '@rocket.chat/fuselage'; import { useMutableCallback } from '@rocket.chat/fuselage-hooks'; import type { ReactElement } from 'react'; import React, { useState, memo } from 'react'; import { AuthorizationUtils } from '../../../../../app/authorization/lib'; +import { GenericTableCell } from '../../../../components/GenericTable'; type RoleCellProps = { _id: IRole['_id']; @@ -32,7 +33,7 @@ const RoleCell = ({ _id, name, description, onChange, lineHovered, permissionId, const isDisabled = !!loading || !!isRestrictedForRole; return ( - + {!loading && ( @@ -42,7 +43,7 @@ const RoleCell = ({ _id, name, description, onChange, lineHovered, permissionId, )} {loading && } - + ); }; diff --git a/apps/meteor/client/views/admin/permissions/UsersInRole/UsersInRoleTable/UsersInRoleTableRow.tsx b/apps/meteor/client/views/admin/permissions/UsersInRole/UsersInRoleTable/UsersInRoleTableRow.tsx index d12818a314478..b4a9dcebb8823 100644 --- a/apps/meteor/client/views/admin/permissions/UsersInRole/UsersInRoleTable/UsersInRoleTableRow.tsx +++ b/apps/meteor/client/views/admin/permissions/UsersInRole/UsersInRoleTable/UsersInRoleTableRow.tsx @@ -1,10 +1,11 @@ import type { IUserInRole } from '@rocket.chat/core-typings'; -import { Box, TableRow, TableCell, Button, Icon } from '@rocket.chat/fuselage'; +import { Box, Button, Icon } from '@rocket.chat/fuselage'; import { useMutableCallback } from '@rocket.chat/fuselage-hooks'; import type { ReactElement } from 'react'; import React, { memo } from 'react'; import { getUserEmailAddress } from '../../../../../../lib/getUserEmailAddress'; +import { GenericTableRow, GenericTableCell } from '../../../../../components/GenericTable'; import UserAvatar from '../../../../../components/avatar/UserAvatar'; type UsersInRoleTableRowProps = { @@ -21,8 +22,8 @@ const UsersInRoleTableRow = ({ user, onRemove }: UsersInRoleTableRowProps): Reac }); return ( - - + + @@ -39,14 +40,14 @@ const UsersInRoleTableRow = ({ user, onRemove }: UsersInRoleTableRowProps): Reac - - {email} - + + {email} + - - + + ); }; diff --git a/apps/meteor/client/views/admin/settings/groups/voip/AssignAgentButton.tsx b/apps/meteor/client/views/admin/settings/groups/voip/AssignAgentButton.tsx index 681c4aab54b44..86e7013f6f3a7 100644 --- a/apps/meteor/client/views/admin/settings/groups/voip/AssignAgentButton.tsx +++ b/apps/meteor/client/views/admin/settings/groups/voip/AssignAgentButton.tsx @@ -1,9 +1,10 @@ -import { Table, IconButton } from '@rocket.chat/fuselage'; +import { IconButton } from '@rocket.chat/fuselage'; import { useMutableCallback } from '@rocket.chat/fuselage-hooks'; import { useSetModal, useTranslation } from '@rocket.chat/ui-contexts'; import type { FC } from 'react'; import React from 'react'; +import { GenericTableCell } from '../../../../../components/GenericTable'; import AssignAgentModal from './AssignAgentModal'; const AssignAgentButton: FC<{ extension: string; reload: () => void }> = ({ extension, reload }) => { @@ -16,9 +17,9 @@ const AssignAgentButton: FC<{ extension: string; reload: () => void }> = ({ exte }); return ( - + - + ); }; diff --git a/apps/meteor/client/views/admin/settings/groups/voip/RemoveAgentButton.tsx b/apps/meteor/client/views/admin/settings/groups/voip/RemoveAgentButton.tsx index f1026086ba615..7ef6e0c3b7984 100644 --- a/apps/meteor/client/views/admin/settings/groups/voip/RemoveAgentButton.tsx +++ b/apps/meteor/client/views/admin/settings/groups/voip/RemoveAgentButton.tsx @@ -1,10 +1,11 @@ -import { Table, IconButton } from '@rocket.chat/fuselage'; +import { IconButton } from '@rocket.chat/fuselage'; import { useMutableCallback } from '@rocket.chat/fuselage-hooks'; import { useSetModal, useToastMessageDispatch, useEndpoint, useTranslation } from '@rocket.chat/ui-contexts'; import type { FC } from 'react'; import React from 'react'; import GenericModal from '../../../../../components/GenericModal'; +import { GenericTableCell } from '../../../../../components/GenericTable'; const RemoveAgentButton: FC<{ username: string; reload: () => void }> = ({ username, reload }) => { const removeAgent = useEndpoint('DELETE', '/v1/omnichannel/agent/extension/:username', { username }); @@ -45,9 +46,9 @@ const RemoveAgentButton: FC<{ username: string; reload: () => void }> = ({ usern }); return ( - + - + ); }; diff --git a/apps/meteor/client/views/admin/users/UsersTable/UsersTableRow.tsx b/apps/meteor/client/views/admin/users/UsersTable/UsersTableRow.tsx index 2f63539a3585c..e8df21e35b6a6 100644 --- a/apps/meteor/client/views/admin/users/UsersTable/UsersTableRow.tsx +++ b/apps/meteor/client/views/admin/users/UsersTable/UsersTableRow.tsx @@ -1,5 +1,5 @@ import type { IRole, IUser } from '@rocket.chat/core-typings'; -import { Box, TableRow, TableCell } from '@rocket.chat/fuselage'; +import { Box } from '@rocket.chat/fuselage'; import { capitalize } from '@rocket.chat/string-helpers'; import type { TranslationKey } from '@rocket.chat/ui-contexts'; import { useTranslation } from '@rocket.chat/ui-contexts'; @@ -7,6 +7,7 @@ import type { ReactElement } from 'react'; import React from 'react'; import { Roles } from '../../../../../app/models/client'; +import { GenericTableRow, GenericTableCell } from '../../../../components/GenericTable'; import UserAvatar from '../../../../components/avatar/UserAvatar'; type UsersTableRowProps = { @@ -26,8 +27,15 @@ const UsersTableRow = ({ user, onClick, mediaQuery }: UsersTableRowProps): React .join(', '); return ( - onClick(_id)} onClick={(): void => onClick(_id)} tabIndex={0} role='link' action qa-user-id={_id}> - + onClick(_id)} + onClick={(): void => onClick(_id)} + tabIndex={0} + role='link' + action + qa-user-id={_id} + > + {username && } @@ -44,21 +52,21 @@ const UsersTableRow = ({ user, onClick, mediaQuery }: UsersTableRowProps): React - + {mediaQuery && ( - + {username} {' '} - + )} - {emails?.length && emails[0].address} - {mediaQuery && {roleNames}} - + {emails?.length && emails[0].address} + {mediaQuery && {roleNames}} + {statusText} - - + + ); }; diff --git a/apps/meteor/client/views/directory/tabs/channels/ChannelsTable/ChannelsTableRow.tsx b/apps/meteor/client/views/directory/tabs/channels/ChannelsTable/ChannelsTableRow.tsx index df70a8040133b..0ab051ee5d203 100644 --- a/apps/meteor/client/views/directory/tabs/channels/ChannelsTable/ChannelsTableRow.tsx +++ b/apps/meteor/client/views/directory/tabs/channels/ChannelsTable/ChannelsTableRow.tsx @@ -1,7 +1,8 @@ import type { IRoom, ITeam } from '@rocket.chat/core-typings'; -import { Box, TableRow, TableCell, Avatar } from '@rocket.chat/fuselage'; +import { Box, Avatar } from '@rocket.chat/fuselage'; import React from 'react'; +import { GenericTableRow, GenericTableCell } from '../../../../../components/GenericTable'; import MarkdownText from '../../../../../components/MarkdownText'; import { RoomIcon } from '../../../../../components/RoomIcon'; import { useFormatDate } from '../../../../../hooks/useFormatDate'; @@ -20,8 +21,8 @@ const ChannelsTableRow = ({ onClick, room, mediaQuery }: ChannelsTableRowProps) const avatarUrl = roomCoordinator.getRoomDirectives(t).getAvatarPath(room); return ( - - + + {avatarUrl && } @@ -35,26 +36,26 @@ const ChannelsTableRow = ({ onClick, room, mediaQuery }: ChannelsTableRowProps) {topic && } - - + + {usersCount} - + {mediaQuery && ts && ( - + {formatDate(ts)} - + )} {mediaQuery && ( - + {lastMessage && formatDate(lastMessage.ts)} - + )} {mediaQuery && ( - + {belongsTo} - + )} - + ); }; diff --git a/apps/meteor/client/views/directory/tabs/teams/TeamsTable/TeamsTableRow.tsx b/apps/meteor/client/views/directory/tabs/teams/TeamsTable/TeamsTableRow.tsx index 9c1abb18e69b1..672309e351a23 100644 --- a/apps/meteor/client/views/directory/tabs/teams/TeamsTable/TeamsTableRow.tsx +++ b/apps/meteor/client/views/directory/tabs/teams/TeamsTable/TeamsTableRow.tsx @@ -1,7 +1,8 @@ import type { IRoom } from '@rocket.chat/core-typings'; -import { Box, TableRow, TableCell, Avatar } from '@rocket.chat/fuselage'; +import { Box, Avatar } from '@rocket.chat/fuselage'; import React from 'react'; +import { GenericTableRow, GenericTableCell } from '../../../../../components/GenericTable'; import MarkdownText from '../../../../../components/MarkdownText'; import { RoomIcon } from '../../../../../components/RoomIcon'; import { useFormatDate } from '../../../../../hooks/useFormatDate'; @@ -20,8 +21,8 @@ const TeamsTableRow = ({ onClick, team, mediaQuery }: TeamsTableRowProps) => { const avatarUrl = roomCoordinator.getRoomDirectives(t).getAvatarPath(team); return ( - - + + {avatarUrl && } @@ -35,16 +36,16 @@ const TeamsTableRow = ({ onClick, team, mediaQuery }: TeamsTableRowProps) => { {topic && } - - + + {roomsCount} - + {mediaQuery && ts && ( - + {formatDate(ts)} - + )} - + ); }; diff --git a/apps/meteor/client/views/directory/tabs/users/UsersTable/UsersTableRow.tsx b/apps/meteor/client/views/directory/tabs/users/UsersTable/UsersTableRow.tsx index 7d1e1b73229b3..b950a694192f4 100644 --- a/apps/meteor/client/views/directory/tabs/users/UsersTable/UsersTableRow.tsx +++ b/apps/meteor/client/views/directory/tabs/users/UsersTable/UsersTableRow.tsx @@ -1,7 +1,8 @@ import type { IUser, Serialized } from '@rocket.chat/core-typings'; -import { Box, Flex, TableRow, TableCell } from '@rocket.chat/fuselage'; +import { Box, Flex } from '@rocket.chat/fuselage'; import React from 'react'; +import { GenericTableRow, GenericTableCell } from '../../../../../components/GenericTable'; import MarkdownText from '../../../../../components/MarkdownText'; import UserAvatar from '../../../../../components/avatar/UserAvatar'; import { useFormatDate } from '../../../../../hooks/useFormatDate'; @@ -24,8 +25,8 @@ const UsersTableRow = ({ const formatDate = useFormatDate(); return ( - - + + {username && } @@ -44,15 +45,17 @@ const UsersTableRow = ({ - - {mediaQuery && canViewFullOtherUserInfo && {emails?.length && emails[0].address}} - {federation && {domain}} + + {mediaQuery && canViewFullOtherUserInfo && ( + {emails?.length && emails[0].address} + )} + {federation && {domain}} {mediaQuery && ( - + {formatDate(createdAt)} - + )} - + ); }; diff --git a/apps/meteor/client/views/omnichannel/analytics/AgentOverview.tsx b/apps/meteor/client/views/omnichannel/analytics/AgentOverview.tsx index 46ce28c9be199..a34b9af8bb723 100644 --- a/apps/meteor/client/views/omnichannel/analytics/AgentOverview.tsx +++ b/apps/meteor/client/views/omnichannel/analytics/AgentOverview.tsx @@ -1,4 +1,4 @@ -import { Table } from '@rocket.chat/fuselage'; +import { Table, TableBody, TableCell, TableHead, TableRow } from '@rocket.chat/fuselage'; import type { TranslationKey } from '@rocket.chat/ui-contexts'; import { useMethod, useTranslation } from '@rocket.chat/ui-contexts'; import React, { useMemo, useEffect, useState } from 'react'; @@ -46,21 +46,21 @@ const AgentOverview = ({ return ( - - + + {displayData.head?.map(({ name }, i) => ( - {t(name)} + {t(name)} ))} - - - + + + {displayData.data?.map(({ name, value }, i) => ( - - {name} - {value} - + + {name} + {value} + ))} - +
); }; diff --git a/apps/meteor/client/views/omnichannel/departments/DepartmentAgentsTable/AgentRow.tsx b/apps/meteor/client/views/omnichannel/departments/DepartmentAgentsTable/AgentRow.tsx index dfa14374dc012..27312b9e9fac4 100644 --- a/apps/meteor/client/views/omnichannel/departments/DepartmentAgentsTable/AgentRow.tsx +++ b/apps/meteor/client/views/omnichannel/departments/DepartmentAgentsTable/AgentRow.tsx @@ -1,8 +1,9 @@ -import { NumberInput, TableCell, TableRow } from '@rocket.chat/fuselage'; +import { NumberInput } from '@rocket.chat/fuselage'; import { useTranslation } from '@rocket.chat/ui-contexts'; import React, { memo } from 'react'; import type { UseFormRegister } from 'react-hook-form'; +import { GenericTableRow, GenericTableCell } from '../../../../components/GenericTable'; import type { FormValues, IDepartmentAgent } from '../EditDepartment'; import AgentAvatar from './AgentAvatar'; import RemoveAgentButton from './RemoveAgentButton'; @@ -18,20 +19,20 @@ const AgentRow = ({ index, agent, register, onRemove }: AgentRowProps) => { const t = useTranslation(); return ( - - + + - - + + - - + + - - + + - - + + ); }; export default memo(AgentRow); diff --git a/apps/meteor/client/views/omnichannel/directory/calls/CallTableRow.tsx b/apps/meteor/client/views/omnichannel/directory/calls/CallTableRow.tsx index 8ead7e104cc76..403f4312772ff 100644 --- a/apps/meteor/client/views/omnichannel/directory/calls/CallTableRow.tsx +++ b/apps/meteor/client/views/omnichannel/directory/calls/CallTableRow.tsx @@ -1,11 +1,11 @@ import type { IVoipRoom, Serialized } from '@rocket.chat/core-typings'; -import { Table } from '@rocket.chat/fuselage'; import { useTranslation } from '@rocket.chat/ui-contexts'; import moment from 'moment'; import type { ReactElement } from 'react'; import React, { useCallback } from 'react'; import { parseOutboundPhoneNumber } from '../../../../../ee/client/lib/voip/parseOutboundPhoneNumber'; +import { GenericTableRow, GenericTableCell } from '../../../../components/GenericTable'; import { useIsCallReady } from '../../../../contexts/CallContext'; import { CallDialpadButton } from '../components/CallDialpadButton'; @@ -34,7 +34,7 @@ export const CallTableRow = ({ room, onRowClick }: CallTableRowProps): ReactElem ); return ( - - {parseOutboundPhoneNumber(fname)} - {parseOutboundPhoneNumber(phoneNumber)} - {queue} - {moment(callStarted).format('L LTS')} - {duration.isValid() && duration.humanize()} - {resolveDirectionLabel(direction)} - {isCallReady && } - + {parseOutboundPhoneNumber(fname)} + {parseOutboundPhoneNumber(phoneNumber)} + {queue} + {moment(callStarted).format('L LTS')} + {duration.isValid() && duration.humanize()} + {resolveDirectionLabel(direction)} + {isCallReady && } + ); }; diff --git a/apps/meteor/client/views/omnichannel/managers/RemoveManagerButton.tsx b/apps/meteor/client/views/omnichannel/managers/RemoveManagerButton.tsx index 7b591446eb80d..8ce973b7b69fa 100644 --- a/apps/meteor/client/views/omnichannel/managers/RemoveManagerButton.tsx +++ b/apps/meteor/client/views/omnichannel/managers/RemoveManagerButton.tsx @@ -1,10 +1,11 @@ -import { Table, IconButton } from '@rocket.chat/fuselage'; +import { IconButton } from '@rocket.chat/fuselage'; import { useMutableCallback } from '@rocket.chat/fuselage-hooks'; import { useSetModal, useToastMessageDispatch, useTranslation } from '@rocket.chat/ui-contexts'; import type { ReactElement } from 'react'; import React from 'react'; import GenericModal from '../../../components/GenericModal'; +import { GenericTableCell } from '../../../components/GenericTable'; import { useEndpointAction } from '../../../hooks/useEndpointAction'; const RemoveManagerButton = ({ _id, reload }: { _id: string; reload: () => void }): ReactElement => { @@ -41,9 +42,9 @@ const RemoveManagerButton = ({ _id, reload }: { _id: string; reload: () => void }); return ( - + - + ); }; diff --git a/apps/meteor/client/views/teams/ChannelDesertionTable/ChannelDesertionTableRow.tsx b/apps/meteor/client/views/teams/ChannelDesertionTable/ChannelDesertionTableRow.tsx index f14f549c3bd06..864ea50d0ab03 100644 --- a/apps/meteor/client/views/teams/ChannelDesertionTable/ChannelDesertionTableRow.tsx +++ b/apps/meteor/client/views/teams/ChannelDesertionTable/ChannelDesertionTableRow.tsx @@ -1,9 +1,10 @@ import type { IRoom, Serialized } from '@rocket.chat/core-typings'; -import { CheckBox, TableRow, TableCell, Icon, Margins } from '@rocket.chat/fuselage'; +import { CheckBox, Icon, Margins } from '@rocket.chat/fuselage'; import { useMutableCallback } from '@rocket.chat/fuselage-hooks'; import type { ReactElement } from 'react'; import React from 'react'; +import { GenericTableRow, GenericTableCell } from '../../../components/GenericTable'; import { useFormatDateAndTime } from '../../../hooks/useFormatDateAndTime'; type ChannelDesertionTableRowProps = { @@ -19,19 +20,19 @@ const ChannelDesertionTableRow = ({ room, onChange, selected, lastOwnerWarning } const handleChange = useMutableCallback(() => onChange(room)); return ( - - + + {fname ?? name} {isLastOwner && } - - + + {formatDate(ts)} - - + + ); }; diff --git a/apps/meteor/ee/client/omnichannel/RemoveBusinessHourButton.js b/apps/meteor/ee/client/omnichannel/RemoveBusinessHourButton.js index 48706148ccb1d..4e7143b55de79 100644 --- a/apps/meteor/ee/client/omnichannel/RemoveBusinessHourButton.js +++ b/apps/meteor/ee/client/omnichannel/RemoveBusinessHourButton.js @@ -1,9 +1,10 @@ -import { Table, IconButton } from '@rocket.chat/fuselage'; +import { IconButton } from '@rocket.chat/fuselage'; import { useMutableCallback } from '@rocket.chat/fuselage-hooks'; import { useSetModal, useToastMessageDispatch, useMethod, useTranslation } from '@rocket.chat/ui-contexts'; import React from 'react'; import GenericModal from '../../../client/components/GenericModal'; +import { GenericTableCell } from '../../../client/components/GenericTable'; function RemoveBusinessHourButton({ _id, type, reload }) { const removeBusinessHour = useMethod('livechat:removeBusinessHour'); @@ -36,9 +37,9 @@ function RemoveBusinessHourButton({ _id, type, reload }) { }); return ( - + - + ); } diff --git a/apps/meteor/ee/client/views/account/deviceManagement/DeviceManagementAccountTable/DeviceManagementAccountRow.tsx b/apps/meteor/ee/client/views/account/deviceManagement/DeviceManagementAccountTable/DeviceManagementAccountRow.tsx index a581658f68cbc..7fc197ef06c29 100644 --- a/apps/meteor/ee/client/views/account/deviceManagement/DeviceManagementAccountTable/DeviceManagementAccountRow.tsx +++ b/apps/meteor/ee/client/views/account/deviceManagement/DeviceManagementAccountTable/DeviceManagementAccountRow.tsx @@ -1,9 +1,10 @@ -import { Box, Button, TableRow, TableCell } from '@rocket.chat/fuselage'; +import { Box, Button } from '@rocket.chat/fuselage'; import { useMediaQuery } from '@rocket.chat/fuselage-hooks'; import { useTranslation } from '@rocket.chat/ui-contexts'; import type { ReactElement } from 'react'; import React from 'react'; +import { GenericTableCell, GenericTableRow } from '../../../../../../client/components/GenericTable'; import { useFormatDateAndTime } from '../../../../../../client/hooks/useFormatDateAndTime'; import DeviceIcon from '../../../../deviceManagement/components/DeviceIcon'; import { useDeviceLogout } from '../../../../hooks/useDeviceLogout'; @@ -32,20 +33,20 @@ const DeviceManagementAccountRow = ({ const handleDeviceLogout = useDeviceLogout(_id, '/v1/sessions/logout.me'); return ( - - + + {deviceName && {deviceName}} - - {deviceOSName || ''} - {formatDateAndTime(loginAt)} - {mediaQuery && {_id}} - + + {deviceOSName || ''} + {formatDateAndTime(loginAt)} + {mediaQuery && {_id}} + - - + + ); }; diff --git a/apps/meteor/ee/client/views/admin/deviceManagement/DeviceManagementAdminTable/DeviceManagementAdminRow.tsx b/apps/meteor/ee/client/views/admin/deviceManagement/DeviceManagementAdminTable/DeviceManagementAdminRow.tsx index d68cf21315a91..cb7aae0ba80a4 100644 --- a/apps/meteor/ee/client/views/admin/deviceManagement/DeviceManagementAdminTable/DeviceManagementAdminRow.tsx +++ b/apps/meteor/ee/client/views/admin/deviceManagement/DeviceManagementAdminTable/DeviceManagementAdminRow.tsx @@ -1,9 +1,10 @@ -import { Box, TableRow, TableCell, Menu, Option } from '@rocket.chat/fuselage'; +import { Box, Menu, Option } from '@rocket.chat/fuselage'; import { useMediaQuery, useMutableCallback } from '@rocket.chat/fuselage-hooks'; import { useRoute, useTranslation } from '@rocket.chat/ui-contexts'; import type { KeyboardEvent, ReactElement } from 'react'; import React, { useCallback } from 'react'; +import { GenericTableRow, GenericTableCell } from '../../../../../../client/components/GenericTable'; import { useFormatDateAndTime } from '../../../../../../client/hooks/useFormatDateAndTime'; import DeviceIcon from '../../../../deviceManagement/components/DeviceIcon'; import { useDeviceLogout } from '../../../../hooks/useDeviceLogout'; @@ -61,26 +62,26 @@ const DeviceManagementAdminRow = ({ }; return ( - - + + {deviceName && {deviceName}} - - {deviceOSName} - {username} - {mediaQuery && {formatDateAndTime(loginAt)}} - {mediaQuery && {_id}} - {mediaQuery && {ip}} - e.stopPropagation()}> + + {deviceOSName} + {username} + {mediaQuery && {formatDateAndTime(loginAt)}} + {mediaQuery && {_id}} + {mediaQuery && {ip}} + e.stopPropagation()}>