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/.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/.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/.changeset/little-crews-end.md b/.changeset/little-crews-end.md new file mode 100644 index 0000000000000..62f6cb87032ea --- /dev/null +++ b/.changeset/little-crews-end.md @@ -0,0 +1,5 @@ +--- +'@rocket.chat/meteor': patch +--- + +fix show badge for thread direct mentions 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/.changeset/slimy-olives-march.md b/.changeset/slimy-olives-march.md new file mode 100644 index 0000000000000..3959ad46463f4 --- /dev/null +++ b/.changeset/slimy-olives-march.md @@ -0,0 +1,6 @@ +--- +'@rocket.chat/rest-typings': minor +'@rocket.chat/meteor': minor +--- + +Reintroduce an user preference to allow users to see all thread messages in the main channel 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/.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/.github/workflows/ci-code-check.yml b/.github/workflows/ci-code-check.yml index fbfd8b6e0f048..421c517b715a0 100644 --- a/.github/workflows/ci-code-check.yml +++ b/.github/workflows/ci-code-check.yml @@ -22,10 +22,10 @@ jobs: check: ['ts', 'lint'] steps: - # - name: Set Swap Space - # uses: pierotofy/set-swap-space@master - # with: - # swap-size-gb: 4 + - name: Set Swap Space + uses: pierotofy/set-swap-space@master + with: + swap-size-gb: 4 - uses: actions/checkout@v3 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/apps/meteor/app/api/server/v1/misc.ts b/apps/meteor/app/api/server/v1/misc.ts index 7f085a6eab7f4..5f52304da6142 100644 --- a/apps/meteor/app/api/server/v1/misc.ts +++ b/apps/meteor/app/api/server/v1/misc.ts @@ -30,6 +30,7 @@ import { getUserInfo } from '../helpers/getUserInfo'; import { getPaginationItems } from '../helpers/getPaginationItems'; import { getUserFromParams } from '../helpers/getUserFromParams'; import { i18n } from '../../../../server/lib/i18n'; +import { apiDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger'; /** * @openapi @@ -392,7 +393,7 @@ API.v1.addRoute( API.v1.addRoute( 'pw.getPolicy', { - authRequired: true, + authRequired: false, }, { get() { @@ -409,6 +410,7 @@ API.v1.addRoute( }, { async get() { + apiDeprecationLogger.endpoint(this.request.route, '7.0.0', this.response, ' Use pw.getPolicy instead.'); check( this.queryParams, Match.ObjectIncluding({ 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/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/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) { 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/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/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) => ({ 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/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/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/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/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/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/app/ui-message/client/ActionManager.js b/apps/meteor/app/ui-message/client/ActionManager.js index 0f3d356204ecd..6e2aadd1babed 100644 --- a/apps/meteor/app/ui-message/client/ActionManager.js +++ b/apps/meteor/app/ui-message/client/ActionManager.js @@ -160,7 +160,7 @@ const handlePayloadUserInteraction = (type, { /* appId,*/ triggerId, ...data }) return UIKitInteractionTypes.MODAL_ClOSE; }; -export const triggerAction = async ({ type, actionId, appId, rid, mid, viewId, container, ...rest }) => +export const triggerAction = async ({ type, actionId, appId, rid, mid, viewId, container, tmid, ...rest }) => new Promise(async (resolve, reject) => { const triggerId = generateTriggerId(appId); @@ -177,6 +177,7 @@ export const triggerAction = async ({ type, actionId, appId, rid, mid, viewId, c container, mid, rid, + tmid, triggerId, viewId, }); diff --git a/apps/meteor/app/ui-utils/client/lib/RoomHistoryManager.ts b/apps/meteor/app/ui-utils/client/lib/RoomHistoryManager.ts index ba4f8a436fed7..879977f7052d1 100644 --- a/apps/meteor/app/ui-utils/client/lib/RoomHistoryManager.ts +++ b/apps/meteor/app/ui-utils/client/lib/RoomHistoryManager.ts @@ -8,6 +8,7 @@ import type { MutableRefObject } from 'react'; import { waitForElement } from '../../../../client/lib/utils/waitForElement'; import { readMessage } from './readMessages'; +import { getUserPreference } from '../../../utils/client'; import { getConfig } from '../../../../client/lib/utils/getConfig'; import { ChatMessage, ChatSubscription } from '../../../models/client'; import { callWithErrorHandling } from '../../../../client/lib/utils/callWithErrorHandling'; @@ -140,7 +141,15 @@ class RoomHistoryManagerClass extends Emitter { ({ ls } = subscription); } - const result = await callWithErrorHandling('loadHistory', rid, room.oldestTs, limit, ls ? String(ls) : undefined, false); + const showThreadsInMainChannel = getUserPreference(Meteor.userId(), 'showThreadsInMainChannel', false); + const result = await callWithErrorHandling( + 'loadHistory', + rid, + room.oldestTs, + limit, + ls ? String(ls) : undefined, + showThreadsInMainChannel, + ); if (!result) { throw new Error('loadHistory returned nothing'); @@ -174,7 +183,7 @@ class RoomHistoryManagerClass extends Emitter { room.loaded = 0; } - const visibleMessages = messages.filter((msg) => !msg.tmid || msg.tshow); + const visibleMessages = messages.filter((msg) => !msg.tmid || showThreadsInMainChannel || msg.tshow); room.loaded += visibleMessages.length; 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; } } 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/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/components/message/variants/threadPreview/ThreadMessagePreviewBody.tsx b/apps/meteor/client/components/message/variants/threadPreview/ThreadMessagePreviewBody.tsx index 0327ee327acd4..33bce63745e26 100644 --- a/apps/meteor/client/components/message/variants/threadPreview/ThreadMessagePreviewBody.tsx +++ b/apps/meteor/client/components/message/variants/threadPreview/ThreadMessagePreviewBody.tsx @@ -26,6 +26,9 @@ const ThreadMessagePreviewBody = ({ message }: ThreadMessagePreviewBodyProps): R ) { mdTokens?.shift(); } + if (message.attachments && message.msg === '') { + return <>{t('Message_with_attachment')}; + } if (!isEncryptedMessage || message.e2e === 'done') { return mdTokens ? ( 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/sidebar/RoomList/SideBarItemTemplateWithData.tsx b/apps/meteor/client/sidebar/RoomList/SideBarItemTemplateWithData.tsx index a901e91bde351..29dc2f5b4c450 100644 --- a/apps/meteor/client/sidebar/RoomList/SideBarItemTemplateWithData.tsx +++ b/apps/meteor/client/sidebar/RoomList/SideBarItemTemplateWithData.tsx @@ -136,7 +136,7 @@ function SideBarItemTemplateWithData({ ((userMentions || tunreadUser.length) && 'danger') || (threadUnread && 'primary') || (groupMentions && 'warning') || 'secondary'; const isUnread = unread > 0 || threadUnread; - const showBadge = !hideUnreadStatus || (!hideMentionStatus && Boolean(userMentions)); + const showBadge = !hideUnreadStatus || (!hideMentionStatus && (Boolean(userMentions) || tunreadUser.length > 0)); const badges = ( 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; } diff --git a/apps/meteor/client/views/account/preferences/PreferencesMessagesSection.tsx b/apps/meteor/client/views/account/preferences/PreferencesMessagesSection.tsx index ebb0e17281310..25f143772be67 100644 --- a/apps/meteor/client/views/account/preferences/PreferencesMessagesSection.tsx +++ b/apps/meteor/client/views/account/preferences/PreferencesMessagesSection.tsx @@ -9,6 +9,7 @@ import type { FormSectionProps } from './AccountPreferencesPage'; type Values = { unreadAlert: boolean; + showThreadsInMainChannel: boolean; alsoSendThreadToChannel: 'default' | 'always' | 'never'; useEmojis: boolean; convertAsciiEmoji: boolean; @@ -30,6 +31,7 @@ const PreferencesMessagesSection = ({ onChange, commitRef, ...props }: FormSecti const settings = { unreadAlert: useUserPreference('unreadAlert'), + showThreadsInMainChannel: useUserPreference('showThreadsInMainChannel'), alsoSendThreadToChannel: useUserPreference('alsoSendThreadToChannel'), useEmojis: useUserPreference('useEmojis'), convertAsciiEmoji: useUserPreference('convertAsciiEmoji'), @@ -48,6 +50,7 @@ const PreferencesMessagesSection = ({ onChange, commitRef, ...props }: FormSecti const { unreadAlert, + showThreadsInMainChannel, alsoSendThreadToChannel, useEmojis, convertAsciiEmoji, @@ -64,6 +67,7 @@ const PreferencesMessagesSection = ({ onChange, commitRef, ...props }: FormSecti const { handleUnreadAlert, + handleShowThreadsInMainChannel, handleAlsoSendThreadToChannel, handleUseEmojis, handleConvertAsciiEmoji, @@ -121,6 +125,18 @@ const PreferencesMessagesSection = ({ onChange, commitRef, ...props }: FormSecti ), [handleUnreadAlert, t, unreadAlert], )} + {useMemo( + () => ( + + {t('Always_show_thread_replies_in_main_channel')} + + + + {t('Accounts_Default_User_Preferences_showThreadsInMainChannel_Description')} + + ), + [handleShowThreadsInMainChannel, showThreadsInMainChannel, t], + )} {useMemo( () => ( diff --git a/apps/meteor/client/views/account/profile/AccountProfileForm.tsx b/apps/meteor/client/views/account/profile/AccountProfileForm.tsx index ac289f92d9602..23381a6341247 100644 --- a/apps/meteor/client/views/account/profile/AccountProfileForm.tsx +++ b/apps/meteor/client/views/account/profile/AccountProfileForm.tsx @@ -1,27 +1,16 @@ /* eslint-disable @typescript-eslint/no-non-null-assertion */ import type { IUser } from '@rocket.chat/core-typings'; -import { - Field, - FieldGroup, - TextInput, - TextAreaInput, - Box, - Icon, - AnimatedVisibility, - PasswordInput, - Button, - Grid, - Margins, -} from '@rocket.chat/fuselage'; +import { Field, FieldGroup, TextInput, TextAreaInput, Box, Icon, PasswordInput, Button } from '@rocket.chat/fuselage'; import { useDebouncedCallback, useSafely } from '@rocket.chat/fuselage-hooks'; +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 { 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'; @@ -44,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<{ @@ -70,6 +61,8 @@ const AccountProfileForm = ({ values, handlers, user, settings, onSaveStateChang const { realname, email, username, password, confirmationPassword, statusText, bio, statusType, customFields, nickname } = values as AccountFormValues; + const passwordVerifications = useVerifyPassword(password); + const { handleRealname, handleEmail, @@ -80,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 () => { @@ -132,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(); @@ -175,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); @@ -295,93 +318,80 @@ const AccountProfileForm = ({ values, handlers, user, settings, onSaveStateChang ), [bio, handleBio, bioError, t], )} - - - - - {useMemo( - () => ( - - {t('Email')} - - } - disabled={!allowEmailChange} - /> - - {!allowEmailChange && {t('Email_Change_Disabled')}} - {t(emailError as TranslationKey)} - - ), - [t, email, handleEmail, verified, allowEmailChange, emailError], - )} - {useMemo( - () => - !verified && ( - - - - - - ), - [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, + ], + )} + + {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/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/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/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/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/admin/users/AddUser.js b/apps/meteor/client/views/admin/users/AddUser.js index b882ccdbc2949..e7d439317cb0b 100644 --- a/apps/meteor/client/views/admin/users/AddUser.js +++ b/apps/meteor/client/views/admin/users/AddUser.js @@ -125,7 +125,7 @@ const AddUser = ({ onReload, ...props }) => { - 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/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/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/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/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/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..403f4312772ff 100644 --- a/apps/meteor/client/views/omnichannel/directory/calls/CallTableRow.tsx +++ b/apps/meteor/client/views/omnichannel/directory/calls/CallTableRow.tsx @@ -1,16 +1,16 @@ -import type { IVoipRoom } from '@rocket.chat/core-typings'; -import { Table } from '@rocket.chat/fuselage'; +import type { IVoipRoom, Serialized } from '@rocket.chat/core-typings'; 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'; type CallTableRowProps = { - room: IVoipRoom; + room: Serialized; onRowClick(_id: string, token?: string): void; }; @@ -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/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/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/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/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/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/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/room/MessageList/hooks/useMessages.ts b/apps/meteor/client/views/room/MessageList/hooks/useMessages.ts index fbc987e68e638..a4a52fe84575d 100644 --- a/apps/meteor/client/views/room/MessageList/hooks/useMessages.ts +++ b/apps/meteor/client/views/room/MessageList/hooks/useMessages.ts @@ -1,6 +1,6 @@ import type { IRoom, IMessage, MessageTypesValues } from '@rocket.chat/core-typings'; import { useStableArray } from '@rocket.chat/fuselage-hooks'; -import { useSetting } from '@rocket.chat/ui-contexts'; +import { useSetting, useUserPreference } from '@rocket.chat/ui-contexts'; import type { Mongo } from 'meteor/mongo'; import { useCallback, useMemo } from 'react'; @@ -16,6 +16,7 @@ const mergeHideSysMessages = ( }; export const useMessages = ({ rid }: { rid: IRoom['_id'] }): IMessage[] => { + const showThreadsInMainChannel = useUserPreference('showThreadsInMainChannel', false); const hideSysMesSetting = useSetting('Hide_System_Messages') ?? []; const room = useRoom(); const hideRoomSysMes: Array = Array.isArray(room.sysMes) ? room.sysMes : []; @@ -27,9 +28,11 @@ export const useMessages = ({ rid }: { rid: IRoom['_id'] }): IMessage[] => { rid, _hidden: { $ne: true }, t: { $nin: hideSysMessages }, - $or: [{ tmid: { $exists: false } }, { tshow: { $eq: true } }], + ...(!showThreadsInMainChannel && { + $or: [{ tmid: { $exists: false } }, { tshow: { $eq: true } }], + }), }), - [rid, hideSysMessages], + [rid, hideSysMessages, showThreadsInMainChannel], ); return useReactiveValue( 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]); } 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/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/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/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 e300bbdb286fd..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); @@ -42,7 +43,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/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/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/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/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 ( - + - - + + ); }; 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()}>
- - - {'#'} - {t('Channel')} - {t('Created')} - {t('Last_active')} - {t('Messages_sent')} - - - + + + {'#'} + {t('Channel')} + {t('Created')} + {t('Last_active')} + {t('Messages_sent')} + + + {channels?.map(({ t, name, createdAt, updatedAt, messagesCount, messagesVariation }, i) => ( - - {i + 1}. - + + {i + 1}. + {(t === 'd' && ) || (t === 'p' && ) || (t === 'c' && )} {name} - - {moment(createdAt).format('L')} - {moment(updatedAt).format('L')} - + + {moment(createdAt).format('L')} + {moment(updatedAt).format('L')} + {messagesCount} {messagesVariation} - - + + ))} {!channels && Array.from({ length: 5 }, (_, i) => ( - - + + - - + + - - + + - - + + - - + + - - + + ))} - +
)} { )} {(!table || !!table.length) && ( - - - {'#'} - {t('Channel')} - {t('Number_of_messages')} - - - + + + {'#'} + {t('Channel')} + {t('Number_of_messages')} + + + {table?.map(({ i, t, name, messages }) => ( - - {i + 1}. - + + {i + 1}. + {(t === 'd' && ) || (t === 'p' && ) || (t === 'c' && )} {name} - - {messages} - + + {messages} + ))} {!table && Array.from({ length: 5 }, (_, i) => ( - - + + - - + + - - + + - - + + ))} - +
)} diff --git a/apps/meteor/ee/client/views/audit/components/AuditLogEntry.tsx b/apps/meteor/ee/client/views/audit/components/AuditLogEntry.tsx index 230ea852b89d9..14a85d806cc4d 100644 --- a/apps/meteor/ee/client/views/audit/components/AuditLogEntry.tsx +++ b/apps/meteor/ee/client/views/audit/components/AuditLogEntry.tsx @@ -1,9 +1,10 @@ import type { IAuditLog } from '@rocket.chat/core-typings'; -import { Box, TableCell, TableRow } from '@rocket.chat/fuselage'; +import { Box } from '@rocket.chat/fuselage'; import { useMediaQuery } from '@rocket.chat/fuselage-hooks'; import type { ReactElement } from 'react'; import React, { memo, useMemo } from 'react'; +import { GenericTableRow, GenericTableCell } from '../../../../../client/components/GenericTable'; import UserAvatar from '../../../../../client/components/avatar/UserAvatar'; import { useFormatDateAndTime } from '../../../../../client/hooks/useFormatDateAndTime'; import AuditFiltersDisplay from './AuditFiltersDisplay'; @@ -22,8 +23,8 @@ const AuditLogEntry = ({ value: { u, results, ts, _id, fields } }: AuditLogEntry const mediaQuery = useMediaQuery('(min-width: 1024px)'); return ( - - + + {username && } @@ -40,16 +41,16 @@ const AuditLogEntry = ({ value: { u, results, ts, _id, fields } }: AuditLogEntry - - + + {msg} - - {when} - {results} - + + {when} + {results} + - - + + ); }; 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/apps/meteor/ee/server/apps/communication/uikit.ts b/apps/meteor/ee/server/apps/communication/uikit.ts index 5b760c8423979..a3362e929427a 100644 --- a/apps/meteor/ee/server/apps/communication/uikit.ts +++ b/apps/meteor/ee/server/apps/communication/uikit.ts @@ -283,6 +283,7 @@ const appsRoutes = triggerId, rid, mid, + tmid, payload: { context, message: msgText }, } = req.body; @@ -298,6 +299,7 @@ const appsRoutes = user, room, message, + tmid, payload: { context, ...(msgText && { message: msgText }), 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/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/apps/meteor/package.json b/apps/meteor/package.json index b8d6391ad9e3a..726ddd56e1181 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", @@ -218,7 +219,7 @@ "@rocket.chat/account-utils": "workspace:^", "@rocket.chat/agenda": "workspace:^", "@rocket.chat/api-client": "workspace:^", - "@rocket.chat/apps-engine": "1.40.0-alpha.275", + "@rocket.chat/apps-engine": "1.40.0-alpha.280", "@rocket.chat/base64": "workspace:^", "@rocket.chat/cas-validate": "workspace:^", "@rocket.chat/core-services": "workspace:^", @@ -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/packages/rocketchat-i18n/i18n/en.i18n.json b/apps/meteor/packages/rocketchat-i18n/i18n/en.i18n.json index 0247cac57adbe..b2c18812828e7 100644 --- a/apps/meteor/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/apps/meteor/packages/rocketchat-i18n/i18n/en.i18n.json @@ -91,6 +91,7 @@ "Accounts_Default_User_Preferences_desktopNotifications": "Desktop Notifications Default Alert", "Accounts_Default_User_Preferences_pushNotifications": "Push Notifications Default Alert", "Accounts_Default_User_Preferences_not_available": "Failed to retrieve User Preferences because they haven't been set up by the user yet", + "Accounts_Default_User_Preferences_showThreadsInMainChannel_Description": "When enabled, all replies under a thread will also be displayed directly in the main room. When disabled, thread replies will be displayed based on the sender's choice.", "Accounts_DefaultUsernamePrefixSuggestion": "Default Username Prefix Suggestion", "Accounts_denyUnverifiedEmail": "Deny unverified email", "Accounts_Directory_DefaultView": "Default Directory Listing", @@ -395,6 +396,7 @@ "Also_send_thread_message_to_channel_behavior": "Also send thread message to channel behavior", "Also_send_to_channel": "Also send to channel", "Always_open_in_new_window": "Always Open in New Window", + "Always_show_thread_replies_in_main_channel": "Always show thread replies in main channel", "Analytics": "Analytics", "Analytics_Description": "See how users interact with your workspace.", "Analytics_features_enabled": "Features Enabled", @@ -1073,7 +1075,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 +2393,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", @@ -3327,6 +3337,7 @@ "Message_Attachments_Thumbnails_Enabled": "Enable image thumbnails to save bandwith", "Message_Attachments_Thumbnails_Width": "Thumbnail's max width (in pixels)", "Message_Attachments_Thumbnails_Height": "Thumbnail's max height (in pixels)", + "Message_with_attachment": "Message with attachment", "Report_sent": "Report sent", "Message_Attachments_Thumbnails_EnabledDesc": "Thumbnails will be served instead of the original image to reduce bandwith usage. Images at original resolution can be downloaded using the icon next to the attachment's name.", "Message_Attachments_Strip_Exif": "Remove EXIF metadata from supported files", @@ -3837,6 +3848,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", @@ -4573,7 +4585,6 @@ "Show_default_content": "Show default content", "Show_email_field": "Show email field", "Show_mentions": "Show badge for mentions", - "Show_Message_In_Main_Thread": "Show thread messages in the main thread", "Show_more": "Show more", "Show_name_field": "Show name field", "show_offline_users": "show offline users", @@ -5087,7 +5098,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 +5814,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/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/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/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); } 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/apps/meteor/server/settings/accounts.ts b/apps/meteor/server/settings/accounts.ts index a4db6512ed16e..76f1c344b94f8 100644 --- a/apps/meteor/server/settings/accounts.ts +++ b/apps/meteor/server/settings/accounts.ts @@ -572,6 +572,12 @@ export const createAccountSettings = () => i18nLabel: 'Sort_By', }); + await this.add('Accounts_Default_User_Preferences_showThreadsInMainChannel', false, { + type: 'boolean', + public: true, + i18nLabel: 'Always_show_thread_replies_in_main_channel', + }); + await this.add('Accounts_Default_User_Preferences_alsoSendThreadToChannel', 'default', { type: 'select', values: [ 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 92% rename from apps/meteor/tests/e2e/omnichannel-contact-center.spec.ts rename to apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center.spec.ts index 8cb47b0556a32..b9ac92d67a9a8 100644 --- a/apps/meteor/tests/e2e/omnichannel-contact-center.spec.ts +++ b/apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center.spec.ts @@ -1,10 +1,11 @@ import { faker } from '@faker-js/faker'; -import { createToken } from '../../client/lib/utils/createToken'; -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, @@ -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/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 { 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..971ed7d8e7b86 100644 --- a/apps/meteor/tests/end-to-end/api/00-miscellaneous.js +++ b/apps/meteor/tests/end-to-end/api/00-miscellaneous.js @@ -142,6 +142,7 @@ describe('miscellaneous', function () { // 'language', 'newRoomNotification', 'newMessageNotification', + 'showThreadsInMainChannel', // 'clockMode', 'useEmojis', 'convertAsciiEmoji', @@ -675,18 +676,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/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/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 bd081d6512d61..5603b95319d6f 100644 --- a/packages/core-services/package.json +++ b/packages/core-services/package.json @@ -3,16 +3,25 @@ "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:^", - "eslint": "~8.38.0", + "@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.0.4" + "typescript": "~5.1.3" }, "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/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/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/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/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/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; } 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/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(); 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/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, 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/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/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/rest-typings/src/v1/users/UsersSetPreferenceParamsPOST.ts b/packages/rest-typings/src/v1/users/UsersSetPreferenceParamsPOST.ts index 5a07797dc80a9..69ac5440189a0 100644 --- a/packages/rest-typings/src/v1/users/UsersSetPreferenceParamsPOST.ts +++ b/packages/rest-typings/src/v1/users/UsersSetPreferenceParamsPOST.ts @@ -24,6 +24,7 @@ export type UsersSetPreferencesParamsPOST = { highlights?: string[]; alsoSendThreadToChannel?: 'never' | 'always' | 'default'; desktopNotificationRequireInteraction?: boolean; + showThreadsInMainChannel?: boolean; hideUsernames?: boolean; hideRoles?: boolean; displayAvatars?: boolean; @@ -124,6 +125,10 @@ const UsersSetPreferencesParamsPostSchema = { }, nullable: true, }, + showThreadsInMainChannel: { + type: 'boolean', + nullable: true, + }, desktopNotificationRequireInteraction: { type: 'boolean', nullable: true, 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..8fbb4d6acd212 100644 --- a/packages/ui-client/package.json +++ b/packages/ui-client/package.json @@ -23,16 +23,17 @@ "@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", + "react-hook-form": "^7.30.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/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/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..5a0f1463be808 100644 --- a/packages/ui-client/src/components/index.ts +++ b/packages/ui-client/src/components/index.ts @@ -1,6 +1,8 @@ export * from './EmojiPicker'; export * from './ExternalLink'; export * from './DotLeader'; +export * from './CustomFieldsForm'; +export * from './PasswordVerifier'; export { default as TextSeparator } from './TextSeparator'; export * from './TooltipComponent'; export * as UserStatus from './UserStatus'; 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/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/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..7780e6fa7fa16 100644 --- a/packages/ui-contexts/src/index.ts +++ b/packages/ui-contexts/src/index.ts @@ -79,12 +79,15 @@ 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'; 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/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/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'] : [], }, diff --git a/packages/web-ui-registration/package.json b/packages/web-ui-registration/package.json index bba768ce6d8ab..2eadd13319c33 100644 --- a/packages/web-ui-registration/package.json +++ b/packages/web-ui-registration/package.json @@ -4,15 +4,16 @@ "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", "@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/packages/web-ui-registration/src/RegisterForm.tsx b/packages/web-ui-registration/src/RegisterForm.tsx index f2a880a7db6b7..5400dccce79f5 100644 --- a/packages/web-ui-registration/src/RegisterForm.tsx +++ b/packages/web-ui-registration/src/RegisterForm.tsx @@ -1,8 +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, useToastMessageDispatch } from '@rocket.chat/ui-contexts'; +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'; @@ -19,6 +21,7 @@ type LoginRegisterPayload = { reason: string; }; +// eslint-disable-next-line complexity export const RegisterForm = ({ setLoginRoute }: { setLoginRoute: DispatchLoginRouter }): ReactElement => { const { t } = useTranslation(); @@ -32,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(); @@ -42,9 +48,12 @@ export const RegisterForm = ({ setLoginRoute }: { setLoginRoute: DispatchLoginRo watch, getValues, clearErrors, + control, formState: { errors }, } = useForm(); + const passwordVerifications = useVerifyPassword(watch('password')); + const handleRegister = async ({ password, passwordConfirmation: _, ...formData }: LoginRegisterPayload) => { registerUser.mutate( { pass: password, ...formData }, @@ -71,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); + } }, }, ); @@ -98,6 +110,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 +162,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')}* @@ -194,6 +204,8 @@ export const RegisterForm = ({ setLoginRoute }: { setLoginRoute: DispatchLoginRo {errors.reason && {t('registration.component.form.requiredField')}} )} + {customFields.length > 0 && } + {serverError && {serverError}} 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 402cdc445bd80..ce4fd467ba94b 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: @@ -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 @@ -5054,23 +5107,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 +5124,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 +5254,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" @@ -5714,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" @@ -5748,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" @@ -9245,12 +9263,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 +9278,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 +9288,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 +9304,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 +9320,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 +9332,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 @@ -9336,9 +9354,9 @@ __metadata: languageName: node linkType: hard -"@rocket.chat/apps-engine@npm:1.40.0-alpha.275": - version: 1.40.0-alpha.275 - resolution: "@rocket.chat/apps-engine@npm:1.40.0-alpha.275" +"@rocket.chat/apps-engine@npm:1.40.0-alpha.280": + version: 1.40.0-alpha.280 + resolution: "@rocket.chat/apps-engine@npm:1.40.0-alpha.280" dependencies: adm-zip: ^0.5.9 cryptiles: ^4.1.3 @@ -9350,7 +9368,7 @@ __metadata: vm2: ^3.9.19 peerDependencies: "@rocket.chat/ui-kit": "*" - checksum: 77a4ad45c409397a7a8b1ef4ee2db67af75aa7a1f8a078cc59bc69681e8338ed90a110dfc279a46dc84d6bc93e4e43880ec1620a73837a6a9dcccbe055a51212 + checksum: e52495051a4f245ee04794a88df6f0c771f16367448290a8e83603ddc9341585d62699c84e829515ca43afe3e19135d38b205019a3ad611e7cbcbe45e5de978e languageName: node linkType: hard @@ -9366,11 +9384,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 +9398,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 +9409,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 +9424,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 @@ -9417,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:^" @@ -9425,12 +9446,17 @@ __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 - eslint: ~8.38.0 + "@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.0.4 + typescript: ~5.1.3 languageName: unknown linkType: soft @@ -9443,10 +9469,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,15 +9485,15 @@ __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 -"@rocket.chat/css-in-js@npm:^0.31.12, @rocket.chat/css-in-js@npm:^0.31.23, @rocket.chat/css-in-js@npm:~0.31.23-dev.103, @rocket.chat/css-in-js@npm:~0.31.23-dev.132": +"@rocket.chat/css-in-js@npm:^0.31.12, @rocket.chat/css-in-js@npm:^0.31.23, @rocket.chat/css-in-js@npm:~0.31.23-dev.103, @rocket.chat/css-in-js@npm:~0.31.23-dev.143": version: 0.31.23 resolution: "@rocket.chat/css-in-js@npm:0.31.23" dependencies: @@ -9493,7 +9519,7 @@ __metadata: languageName: node linkType: hard -"@rocket.chat/css-supports@npm:^0.31.23, @rocket.chat/css-supports@npm:~0.31.23-dev.103, @rocket.chat/css-supports@npm:~0.31.23-dev.132": +"@rocket.chat/css-supports@npm:^0.31.23, @rocket.chat/css-supports@npm:~0.31.23-dev.103, @rocket.chat/css-supports@npm:~0.31.23-dev.143": version: 0.31.23 resolution: "@rocket.chat/css-supports@npm:0.31.23" dependencies: @@ -9509,15 +9535,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 +9566,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 +9575,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 +9588,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 +9608,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 +9624,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 @@ -9722,10 +9748,10 @@ __metadata: languageName: node linkType: hard -"@rocket.chat/fuselage-tokens@npm:~0.32.0-dev.308": - version: 0.32.0-dev.308 - resolution: "@rocket.chat/fuselage-tokens@npm:0.32.0-dev.308" - checksum: 8199770d85b86990d33337e0a5b27e55fc48bd4ba7a36b62df233b04e3d70859bac5618d1658b1cf1d90700caa2e4bb1539ac298f11b83d7de0062516e36e813 +"@rocket.chat/fuselage-tokens@npm:~0.32.0-dev.319": + version: 0.32.0-dev.319 + resolution: "@rocket.chat/fuselage-tokens@npm:0.32.0-dev.319" + checksum: 2bc25081e2efd632130d3ae0aecb21744e354fa7299bf283a41aa8fd564e2238508f4aac0958ad33de810c4df328b77aa10755ad2c05692cdcb6c70f417146be languageName: node linkType: hard @@ -9757,7 +9783,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 +9791,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": "*" @@ -9784,21 +9810,15 @@ __metadata: languageName: unknown linkType: soft -"@rocket.chat/fuselage@link:../../../fuselage/packages/fuselage::locator=%40rocket.chat%2Fmeteor%40workspace%3Aapps%2Fmeteor": - version: 0.0.0-use.local - resolution: "@rocket.chat/fuselage@link:../../../fuselage/packages/fuselage::locator=%40rocket.chat%2Fmeteor%40workspace%3Aapps%2Fmeteor" - languageName: node - linkType: soft - "@rocket.chat/fuselage@npm:next": - version: 0.32.0-dev.358 - resolution: "@rocket.chat/fuselage@npm:0.32.0-dev.358" - dependencies: - "@rocket.chat/css-in-js": ~0.31.23-dev.132 - "@rocket.chat/css-supports": ~0.31.23-dev.132 - "@rocket.chat/fuselage-tokens": ~0.32.0-dev.308 - "@rocket.chat/memo": ~0.31.23-dev.132 - "@rocket.chat/styled": ~0.31.23-dev.132 + version: 0.32.0-dev.369 + resolution: "@rocket.chat/fuselage@npm:0.32.0-dev.369" + dependencies: + "@rocket.chat/css-in-js": ~0.31.23-dev.143 + "@rocket.chat/css-supports": ~0.31.23-dev.143 + "@rocket.chat/fuselage-tokens": ~0.32.0-dev.319 + "@rocket.chat/memo": ~0.31.23-dev.143 + "@rocket.chat/styled": ~0.31.23-dev.143 invariant: ^2.2.4 react-aria: ~3.23.1 react-keyed-flatten-children: ^1.3.0 @@ -9810,7 +9830,7 @@ __metadata: react: ^17.0.2 react-dom: ^17.0.2 react-virtuoso: 1.2.4 - checksum: 2850f7229bde95fbe5f7a1f283c66056e813db0a0df5a297ba03405cd5d1728fc7374609ad9f0523f97ebe24009b2986dfc9b42a49aa070c6de52af07bb0a46b + checksum: 109d05662debb9dbe38b218d8585953ed4c88b02f3ef7b9c529813e978a93c4af345602078ce237a03d8666d6ce09f91e7b72d2cea1cd4fc5101125b809e5a81 languageName: node linkType: hard @@ -9836,7 +9856,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 @@ -9845,10 +9865,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 @@ -9863,7 +9883,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": "*" @@ -9889,18 +9909,18 @@ __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 "@rocket.chat/icons@npm:next": - version: 0.32.0-dev.311 - resolution: "@rocket.chat/icons@npm:0.32.0-dev.311" - checksum: b967b3f788546e62906f87be5e5460a45d9cd2cf0bdc5df093b1e110f93908a8a596018aba2a170e4d37bb636b99b408f053980e20359dd2c1768a6b16d018c4 + version: 0.32.0-dev.349 + resolution: "@rocket.chat/icons@npm:0.32.0-dev.349" + checksum: 45553695c95ef0aa908b133e7347aff9b3845fe03486e145ed2e717efa1b2fc5044f8d7bd390031cc3e401ecfb89723ef4c158a136f164bf73b4a9653775963d languageName: node linkType: hard @@ -9910,10 +9930,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 @@ -9949,8 +9969,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 @@ -9962,7 +9982,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 @@ -10001,7 +10021,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 @@ -10022,10 +10042,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 @@ -10042,7 +10062,7 @@ __metadata: languageName: node linkType: hard -"@rocket.chat/memo@npm:^0.31.23, @rocket.chat/memo@npm:~0.31.23-dev.103, @rocket.chat/memo@npm:~0.31.23-dev.132": +"@rocket.chat/memo@npm:^0.31.23, @rocket.chat/memo@npm:~0.31.23-dev.103, @rocket.chat/memo@npm:~0.31.23-dev.143": version: 0.31.23 resolution: "@rocket.chat/memo@npm:0.31.23" checksum: 070debb940749a2e4463cf767dd65c6967cea664a5bd67c22a812d611f6c3c46d6fe4bb0bf329e43dcd927493413add37c45ae3b05ec08f0b24e9d7385caebdd @@ -10070,7 +10090,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 @@ -10093,7 +10113,7 @@ __metadata: "@rocket.chat/account-utils": "workspace:^" "@rocket.chat/agenda": "workspace:^" "@rocket.chat/api-client": "workspace:^" - "@rocket.chat/apps-engine": 1.40.0-alpha.275 + "@rocket.chat/apps-engine": 1.40.0-alpha.280 "@rocket.chat/base64": "workspace:^" "@rocket.chat/cas-validate": "workspace:^" "@rocket.chat/core-services": "workspace:^" @@ -10105,7 +10125,7 @@ __metadata: "@rocket.chat/favicon": "workspace:^" "@rocket.chat/forked-matrix-appservice-bridge": ^4.0.1 "@rocket.chat/forked-matrix-bot-sdk": ^0.6.0-beta.2 - "@rocket.chat/fuselage": "link:../../../fuselage/packages/fuselage" + "@rocket.chat/fuselage": next "@rocket.chat/fuselage-hooks": next "@rocket.chat/fuselage-polyfills": next "@rocket.chat/fuselage-toastbar": next @@ -10150,7 +10170,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 @@ -10229,8 +10249,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 @@ -10280,16 +10300,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 @@ -10416,7 +10436,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 @@ -10440,11 +10460,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 @@ -10454,10 +10474,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 @@ -10488,7 +10508,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 @@ -10498,7 +10518,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 @@ -10517,12 +10537,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 @@ -10534,7 +10554,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 @@ -10577,7 +10597,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 @@ -10585,7 +10605,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 @@ -10594,10 +10614,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 @@ -10613,11 +10633,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 @@ -10627,7 +10647,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 @@ -10646,10 +10666,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 @@ -10674,12 +10694,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 @@ -10691,7 +10711,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 @@ -10702,13 +10722,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 @@ -10723,7 +10743,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 @@ -10745,12 +10765,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 @@ -10773,14 +10793,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 @@ -10791,12 +10811,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 @@ -10813,11 +10833,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 @@ -10827,7 +10847,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 @@ -10847,7 +10867,7 @@ __metadata: languageName: node linkType: hard -"@rocket.chat/styled@npm:~0.31.23-dev.103, @rocket.chat/styled@npm:~0.31.23-dev.132": +"@rocket.chat/styled@npm:~0.31.23-dev.103, @rocket.chat/styled@npm:~0.31.23-dev.143": version: 0.31.23 resolution: "@rocket.chat/styled@npm:0.31.23" dependencies: @@ -10872,11 +10892,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 @@ -10904,16 +10924,17 @@ __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 + react-hook-form: ^7.30.0 ts-jest: ~29.0.5 - typescript: ~5.0.4 + typescript: ~5.1.3 peerDependencies: "@rocket.chat/css-in-js": "*" "@rocket.chat/fuselage": "*" @@ -10941,14 +10962,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": "*" @@ -10969,12 +10990,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:^" @@ -11014,16 +11035,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": "*" @@ -11055,14 +11076,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": "*" @@ -11097,13 +11118,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 @@ -11111,7 +11132,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 @@ -11122,15 +11143,16 @@ __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 "@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": "*" @@ -12617,90 +12639,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: @@ -12727,7 +12749,7 @@ __metadata: peerDependenciesMeta: "@swc/helpers": optional: true - checksum: ea77168089a34dcec088ab81aef99301eba003b5ed3dca4039803050ba9344e754687f7d4fb4b3e40d22509658bdbdbac2f94f99c6f94051970566c857774371 + checksum: e6029c648ba47c522bed51a9f2fee606f82de1f9233e2e89197e43b0a4867054174ca05e825e688cdc4de332221c0da2e12ba7ba875549e8b5432aa70fe19263 languageName: node linkType: hard @@ -12977,7 +12999,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: @@ -12990,6 +13012,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" @@ -13012,7 +13047,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 @@ -13277,7 +13312,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: @@ -13287,7 +13322,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: @@ -13544,7 +13579,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: @@ -14583,38 +14618,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" - 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 - 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: 10d28bac7a5af9e41767be0bb9c270ee3dcdfeaa38d1b036c6822e7260b88821c460699ba943664eb1ef272d00de6a81b99d7d955332044ea87b624e7ead84a1 - 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/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.58.0 - "@typescript-eslint/type-utils": 5.58.0 - "@typescript-eslint/utils": 5.58.0 + "@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 @@ -14627,41 +14638,24 @@ __metadata: 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 + checksum: 61dd70a1ea9787e69d0d4cd14f6a4c94ba786b535a3f519ade7926d965ee1d4f8fefa8bf0224ee57c5c6517eec3674c0fd06f9226536aa428c2bdddeed1e70f4 languageName: node linkType: hard -"@typescript-eslint/parser@npm:~5.58.0": - version: 5.58.0 - resolution: "@typescript-eslint/parser@npm:5.58.0" +"@typescript-eslint/parser@npm:~5.60.0": + version: 5.60.0 + resolution: "@typescript-eslint/parser@npm:5.60.0" dependencies: - "@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 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 @@ -14675,32 +14669,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: @@ -14708,14 +14692,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 @@ -14733,10 +14710,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 @@ -14775,12 +14752,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 @@ -14789,7 +14766,7 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: eefe82eedf9ee2e14463c3f2b5b18df084c1328a859b245ee897a9a7075acce7cca0216a21fd7968b75aa64189daa008bfde1e2f9afbcc336f3dfe856e7f342e + checksum: 0f4f342730ead42ba60b5fca4bf1950abebd83030010c38b5df98ff9fd95d0ce1cfc3974a44c90c65f381f4f172adcf1a540e018d7968cc845d937bf6c734dae languageName: node linkType: hard @@ -14811,49 +14788,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 @@ -14877,13 +14844,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 @@ -22139,20 +22106,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 @@ -22165,16 +22133,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 @@ -22202,12 +22170,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 @@ -22250,14 +22218,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 @@ -22290,16 +22258,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" @@ -22333,7 +22291,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 @@ -22404,57 +22362,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: @@ -22503,104 +22411,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" @@ -22612,17 +22422,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" @@ -28143,13 +27942,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" @@ -36411,7 +36203,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 @@ -40068,17 +39860,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: @@ -40088,17 +39870,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: