diff --git a/.changeset/friendly-ravens-teach.md b/.changeset/friendly-ravens-teach.md new file mode 100644 index 0000000000000..1c464a8679b64 --- /dev/null +++ b/.changeset/friendly-ravens-teach.md @@ -0,0 +1,5 @@ +--- +'@rocket.chat/meteor': minor +--- + +adds unread badge to sidebar collapser diff --git a/.changeset/green-papayas-thank.md b/.changeset/green-papayas-thank.md new file mode 100644 index 0000000000000..22547db942efa --- /dev/null +++ b/.changeset/green-papayas-thank.md @@ -0,0 +1,7 @@ +--- +'@rocket.chat/model-typings': patch +'@rocket.chat/core-typings': patch +'@rocket.chat/meteor': patch +--- + +Fixes an issue where updating custom emojis didn’t work as expected, ensuring that uploaded emojis now update correctly and display without any caching problems. diff --git a/.changeset/lemon-foxes-carry.md b/.changeset/lemon-foxes-carry.md new file mode 100644 index 0000000000000..7e14dda307474 --- /dev/null +++ b/.changeset/lemon-foxes-carry.md @@ -0,0 +1,6 @@ +--- +"@rocket.chat/meteor": patch +"@rocket.chat/i18n": patch +--- + +Fixes message character limit not being applied to file upload descriptions \ No newline at end of file diff --git a/.changeset/metal-avocados-serve.md b/.changeset/metal-avocados-serve.md new file mode 100644 index 0000000000000..478407fcb97b3 --- /dev/null +++ b/.changeset/metal-avocados-serve.md @@ -0,0 +1,5 @@ +--- +"@rocket.chat/livechat": patch +--- + +Fixes the 'Finish Chat' option in Livechat appearing before the conversation is started, which caused the action to fail. diff --git a/.changeset/neat-flies-drive.md b/.changeset/neat-flies-drive.md new file mode 100644 index 0000000000000..27b5270f81f95 --- /dev/null +++ b/.changeset/neat-flies-drive.md @@ -0,0 +1,5 @@ +--- +'@rocket.chat/meteor': patch +--- + +Adds a divider on Create team modal - advanced settings diff --git a/.changeset/seven-otters-fold.md b/.changeset/seven-otters-fold.md new file mode 100644 index 0000000000000..7f2af2075f734 --- /dev/null +++ b/.changeset/seven-otters-fold.md @@ -0,0 +1,5 @@ +--- +'@rocket.chat/meteor': patch +--- + +Sends server statistics only once a day despite multiple instance being started at different times. diff --git a/.changeset/silent-steaks-happen.md b/.changeset/silent-steaks-happen.md new file mode 100644 index 0000000000000..1ae791c68177a --- /dev/null +++ b/.changeset/silent-steaks-happen.md @@ -0,0 +1,6 @@ +--- +"@rocket.chat/meteor": minor +"@rocket.chat/i18n": minor +--- + +Improves the customizability of the naming of automatic Persistent video calls discussions, allowing the date of the call to be in different parts of the name, using the `[date]` keyword. diff --git a/.changeset/spotty-ads-knock.md b/.changeset/spotty-ads-knock.md new file mode 100644 index 0000000000000..b40e70b74a982 --- /dev/null +++ b/.changeset/spotty-ads-knock.md @@ -0,0 +1,5 @@ +--- +'@rocket.chat/meteor': patch +--- + +Fixes display of emoji aliases in custom emoji list by adding commas between aliases diff --git a/.changeset/sweet-needles-melt.md b/.changeset/sweet-needles-melt.md new file mode 100644 index 0000000000000..51cd6e03d8315 --- /dev/null +++ b/.changeset/sweet-needles-melt.md @@ -0,0 +1,5 @@ +--- +'@rocket.chat/meteor': patch +--- + +Fixes edge case of thread unread not being added to unread group diff --git a/.changeset/swift-suns-perform.md b/.changeset/swift-suns-perform.md new file mode 100644 index 0000000000000..2a52249d984cc --- /dev/null +++ b/.changeset/swift-suns-perform.md @@ -0,0 +1,5 @@ +--- +"@rocket.chat/livechat": patch +--- + +Fixes livechat popout mode not working correctly in cross domain situations diff --git a/.changeset/tricky-trees-destroy.md b/.changeset/tricky-trees-destroy.md new file mode 100644 index 0000000000000..3d43cc5b571ad --- /dev/null +++ b/.changeset/tricky-trees-destroy.md @@ -0,0 +1,4 @@ +--- +"@rocket.chat/meteor": patch +--- +Adds login and permission validation for resetIrcConnection method diff --git a/.changeset/twelve-horses-suffer.md b/.changeset/twelve-horses-suffer.md new file mode 100644 index 0000000000000..bc7f7d5b3ba4a --- /dev/null +++ b/.changeset/twelve-horses-suffer.md @@ -0,0 +1,6 @@ +--- +'@rocket.chat/i18n': minor +'@rocket.chat/meteor': minor +--- + +Adds a confirmation modal to the cancel subscription action diff --git a/.changeset/twenty-news-own.md b/.changeset/twenty-news-own.md new file mode 100644 index 0000000000000..c48d06e0a05e2 --- /dev/null +++ b/.changeset/twenty-news-own.md @@ -0,0 +1,6 @@ +--- +"@rocket.chat/meteor": minor +"@rocket.chat/i18n": minor +--- + +Disables the possiblity to upload exempted apps diff --git a/.changeset/unlucky-wasps-check.md b/.changeset/unlucky-wasps-check.md new file mode 100644 index 0000000000000..fd7e8af17824f --- /dev/null +++ b/.changeset/unlucky-wasps-check.md @@ -0,0 +1,5 @@ +--- +'@rocket.chat/meteor': patch +--- + +Fixes an issue where resizable handler renders over the expanded thread view while using contextualbarResizable feature preview diff --git a/.github/actions/setup-node/action.yml b/.github/actions/setup-node/action.yml index ea90fc57b07c2..b538d485535d1 100644 --- a/.github/actions/setup-node/action.yml +++ b/.github/actions/setup-node/action.yml @@ -53,7 +53,7 @@ runs: - name: Use Node.js ${{ inputs.node-version }} id: node-version - uses: actions/setup-node@v3.7.0 + uses: actions/setup-node@v4.1.0 with: node-version: ${{ inputs.node-version }} cache: 'yarn' diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c6f4e1116fc76..bc56fe6b309ad 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -364,6 +364,15 @@ jobs: run: | docker run --rm -w /app/bundle/programs/server/npm/node_modules/matrix-appservice-bridge ghcr.io/rocketchat/rocket.chat:$RC_DOCKER_TAG -e 'require(".")' + - name: Rename official Docker tag to GitHub Container Registry + if: matrix.platform == needs.release-versions.outputs.official-platform + run: | + IMAGE_NAME_BASE="ghcr.io/${LOWERCASE_REPOSITORY}/rocket.chat:${DOCKER_TAG}" + + echo "Push Docker image: ${IMAGE_NAME_BASE}.official" + docker tag ${IMAGE_NAME_BASE}.${{matrix.platform}} ${IMAGE_NAME_BASE}.official + docker push ${IMAGE_NAME_BASE}.official + build-gh-docker: name: 🚢 Build Docker Images for Production needs: [build-prod, release-versions] diff --git a/.github/workflows/release-candidate.yml b/.github/workflows/release-candidate.yml index d2d22a3fc6c55..506f4cc1e5ddf 100644 --- a/.github/workflows/release-candidate.yml +++ b/.github/workflows/release-candidate.yml @@ -1,7 +1,7 @@ name: Release candidate cut on: schedule: - - cron: '28 0 20 * *' # run at minute 28 to avoid the chance of delay due to high load on GH + - cron: '28 12 20 * *' # run at minute 28 to avoid the chance of delay due to high load on GH jobs: new-release: runs-on: ubuntu-latest diff --git a/.github/workflows/update-version-durability.yml b/.github/workflows/update-version-durability.yml index 410734f94e2b9..45fd4859502bb 100644 --- a/.github/workflows/update-version-durability.yml +++ b/.github/workflows/update-version-durability.yml @@ -17,7 +17,7 @@ jobs: - uses: actions/checkout@v4 - name: Use Node.js - uses: actions/setup-node@v4.0.4 + uses: actions/setup-node@v4.1.0 with: node-version: '20.18.0' diff --git a/.kodiak.toml b/.kodiak.toml index 496895b2c85ad..378f922d81e4a 100644 --- a/.kodiak.toml +++ b/.kodiak.toml @@ -16,7 +16,5 @@ include_coauthors=true [merge.automerge_dependencies] versions = ["minor", "patch"] usernames = ["dependabot"] -[update] -ignored_usernames = ["dependabot"] [approve] auto_approve_usernames = ["dependabot"] diff --git a/apps/meteor/.eslintignore b/apps/meteor/.eslintignore index 9f66dc806f8b4..f7051767d7727 100644 --- a/apps/meteor/.eslintignore +++ b/apps/meteor/.eslintignore @@ -13,3 +13,4 @@ !/client/.eslintrc.js !/ee/client/.eslintrc.js /storybook-static/ +/packages/ diff --git a/apps/meteor/.stylelintrc b/apps/meteor/.stylelintrc index 0b2488ab89f33..f0a8cfc1475e0 100644 --- a/apps/meteor/.stylelintrc +++ b/apps/meteor/.stylelintrc @@ -1,327 +1,59 @@ { - "plugins": [ - "stylelint-order" - ], - "rules": { - "at-rule-empty-line-before": [ "always", { - except: [ - "blockless-after-same-name-blockless", - "first-nested", - ], - ignore: ["after-comment"], - } ], - "at-rule-name-case": "lower", - "at-rule-name-space-after": "always", - "at-rule-semicolon-newline-after": "always", - "block-closing-brace-empty-line-before": "never", - "block-closing-brace-newline-after": "always", - "block-closing-brace-newline-before": "always", - "block-closing-brace-space-before": "never-single-line", + "extends": ["stylelint-config-standard"], + "plugins": ["stylelint-order", "stylelint-selector-bem-pattern"], + "rules": { + "at-rule-empty-line-before": [ + "always", + { + "except": ["blockless-after-same-name-blockless", "first-nested"], + "ignore": ["after-comment"] + } + ], "block-no-empty": true, - "block-opening-brace-newline-after": "always", - "block-opening-brace-space-after": "never-single-line", - "block-opening-brace-space-before": "always", - "color-hex-case": "lower", "color-hex-length": "long", "color-no-invalid-hex": true, - "comment-empty-line-before": [ "always", { - except: ["first-nested"], - ignore: ["stylelint-commands"], - } ], + "comment-empty-line-before": [ + "always", + { + "except": ["first-nested"], + "ignore": ["stylelint-commands"] + } + ], "comment-no-empty": true, "comment-whitespace-inside": "always", "custom-property-empty-line-before": "never", - "declaration-bang-space-after": "never", - "declaration-bang-space-before": "always", - "declaration-block-no-duplicate-properties": [ true, { - ignore: ["consecutive-duplicates-with-different-values"], - } ], + "declaration-block-no-duplicate-properties": [ + true, + { + "ignore": ["consecutive-duplicates-with-different-values"] + } + ], "declaration-block-no-redundant-longhand-properties": true, "declaration-block-no-shorthand-property-overrides": true, - "declaration-block-semicolon-newline-after": "always", - "declaration-block-semicolon-space-after": "always-single-line", - "declaration-block-semicolon-space-before": "never", "declaration-block-single-line-max-declarations": 1, - "declaration-block-trailing-semicolon": "always", - "declaration-colon-newline-after": "always-multi-line", - "declaration-colon-space-after": "always-single-line", - "declaration-colon-space-before": "never", "font-family-no-duplicate-names": true, - "function-comma-newline-after": "always-multi-line", - "function-comma-space-after": "always-single-line", - "function-comma-space-before": "never", "function-linear-gradient-no-nonstandard-direction": true, - "function-max-empty-lines": 0, "function-name-case": "lower", - "function-parentheses-newline-inside": "always-multi-line", - "function-parentheses-space-inside": "never-single-line", - "function-whitespace-after": "always", - "indentation": "tab", "keyframe-declaration-no-important": true, "length-zero-no-unit": true, - "max-empty-lines": 1, - "media-feature-colon-space-after": "always", - "media-feature-colon-space-before": "never", - "media-feature-name-case": "lower", "media-feature-name-no-unknown": true, - "media-feature-parentheses-space-inside": "never", - "media-feature-range-operator-space-after": "always", - "media-feature-range-operator-space-before": "always", - "media-query-list-comma-newline-after": "always-multi-line", - "media-query-list-comma-space-after": "always-single-line", - "media-query-list-comma-space-before": "never", "no-duplicate-selectors": true, "no-empty-source": true, - "no-eol-whitespace": true, - "no-extra-semicolons": true, - "no-missing-end-of-source-newline": true, - "number-leading-zero": "always", - "number-no-trailing-zeros": true, - "property-case": "lower", "property-no-unknown": true, - "rule-empty-line-before": [ "always", { - except: ["first-nested"], - ignore: ["after-comment"], - } ], - "selector-attribute-brackets-space-inside": "never", - "selector-attribute-operator-space-after": "never", - "selector-attribute-operator-space-before": "never", - "selector-combinator-space-after": "always", - "selector-combinator-space-before": "always", - "selector-descendant-combinator-no-non-space": true, - "selector-list-comma-newline-after": "always", - "selector-list-comma-space-before": "never", - "selector-max-empty-lines": 0, - "selector-pseudo-class-case": "lower", + "rule-empty-line-before": [ + "always", + { + "except": ["first-nested"], + "ignore": ["after-comment"] + } + ], "selector-pseudo-class-no-unknown": true, - "selector-pseudo-class-parentheses-space-inside": "never", - "selector-pseudo-element-case": "lower", "selector-pseudo-element-colon-notation": "double", "selector-pseudo-element-no-unknown": true, "selector-type-case": "lower", "selector-type-no-unknown": true, "shorthand-property-no-redundant-values": true, "string-no-newline": true, - "unit-case": "lower", - "unit-no-unknown": true, - "value-list-comma-newline-after": "always-multi-line", - "value-list-comma-space-after": "always-single-line", - "value-list-comma-space-before": "never", - "value-list-max-empty-lines": 0, - "order/properties-order": [ - [ - { - "emptyLineBefore": "always", - "order": "strict", - "properties": [ - "position", - "z-index", - "top", - "right", - "bottom", - "left" - ] - }, - { - "emptyLineBefore": "always", - "order": "strict", - "properties": [ - "display", - "visibility", - "float", - "clear", - "overflow", - "overflow-x", - "overflow-y", - "clip", - "zoom", - "flex-direction", - "flex-order", - "flex-pack", - "flex-align", - "flex" - ] - }, - { - "emptyLineBefore": "always", - "order": "strict", - "properties": [ - "box-sizing", - "width", - "min-width", - "max-width", - "height", - "min-height", - "max-height", - "margin", - "margin-top", - "margin-right", - "margin-bottom", - "margin-left", - "padding", - "padding-top", - "padding-right", - "padding-bottom", - "padding-left" - ] - }, - { - "emptyLineBefore": "always", - "order": "strict", - "properties": [ - "table-layout", - "empty-cells", - "caption-side", - "border-spacing", - "border-collapse", - "list-style", - "list-style-position", - "list-style-type", - "list-style-image" - ] - }, - { - "emptyLineBefore": "always", - "order": "strict", - "properties": [ - "content", - "quotes", - "counter-reset", - "counter-increment", - "resize", - "cursor", - "user-select", - "nav-index", - "nav-up", - "nav-right", - "nav-down", - "nav-left", - "transition", - "transition-delay", - "transition-timing-function", - "transition-duration", - "transition-property", - "transform", - "transform-origin", - "animation", - "animation-name", - "animation-duration", - "animation-play-state", - "animation-timing-function", - "animation-delay", - "animation-iteration-count", - "animation-direction", - "text-align", - "text-align-last", - "vertical-align", - "white-space", - "text-decoration", - "text-emphasis", - "text-emphasis-color", - "text-emphasis-style", - "text-emphasis-position", - "text-indent", - "text-justify", - "text-transform", - "letter-spacing", - "word-spacing", - "text-outline", - "text-transform", - "text-wrap", - "text-overflow", - "text-overflow-ellipsis", - "text-overflow-mode", - "word-wrap", - "word-break", - "tab-size", - "hyphens", - "pointer-events" - ] - }, - { - "emptyLineBefore": "always", - "order": "strict", - "properties": [ - "opacity", - "filter:progid:DXImageTransform.Microsoft.Alpha(Opacity", - "color", - "border", - "border-collapse", - "border-width", - "border-style", - "border-color", - "border-top", - "border-top-width", - "border-top-style", - "border-top-color", - "border-right", - "border-right-width", - "border-right-style", - "border-right-color", - "border-bottom", - "border-bottom-width", - "border-bottom-style", - "border-bottom-color", - "border-left", - "border-left-width", - "border-left-style", - "border-left-color", - "border-radius", - "border-top-left-radius", - "border-top-right-radius", - "border-bottom-right-radius", - "border-bottom-left-radius", - "border-image", - "border-image-source", - "border-image-slice", - "border-image-width", - "border-image-outset", - "border-image-repeat", - "outline", - "outline-width", - "outline-style", - "outline-color", - "outline-offset", - "background", - "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader", - "background-color", - "background-image", - "background-repeat", - "background-attachment", - "background-position", - "background-position-x", - "background-position-y", - "background-clip", - "background-origin", - "background-size", - "box-decoration-break", - "box-shadow", - "filter:progid:DXImageTransform.Microsoft.gradient", - "text-shadow" - ] - }, - { - "emptyLineBefore": "always", - "order": "strict", - "properties": [ - "font", - "font-family", - "font-size", - "font-weight", - "font-style", - "font-variant", - "font-size-adjust", - "font-stretch", - "font-effect", - "font-emphasize", - "font-emphasize-position", - "font-emphasize-style", - "font-smooth", - "line-height" - ] - } - ], - { unspecified: "bottomAlphabetical" } - ] + "unit-no-unknown": true } } diff --git a/apps/meteor/app/2fa/server/code/EmailCheck.ts b/apps/meteor/app/2fa/server/code/EmailCheck.ts index 5baf218a62bb2..8c9865c0b0042 100644 --- a/apps/meteor/app/2fa/server/code/EmailCheck.ts +++ b/apps/meteor/app/2fa/server/code/EmailCheck.ts @@ -4,10 +4,10 @@ import { Random } from '@rocket.chat/random'; import bcrypt from 'bcrypt'; import { Accounts } from 'meteor/accounts-base'; +import type { ICodeCheck, IProcessInvalidCodeResult } from './ICodeCheck'; import { i18n } from '../../../../server/lib/i18n'; import * as Mailer from '../../../mailer/server/api'; import { settings } from '../../../settings/server'; -import type { ICodeCheck, IProcessInvalidCodeResult } from './ICodeCheck'; export class EmailCheck implements ICodeCheck { public readonly name = 'email'; diff --git a/apps/meteor/app/2fa/server/code/PasswordCheckFallback.ts b/apps/meteor/app/2fa/server/code/PasswordCheckFallback.ts index 6c441127f79d5..ba462abc1f93c 100644 --- a/apps/meteor/app/2fa/server/code/PasswordCheckFallback.ts +++ b/apps/meteor/app/2fa/server/code/PasswordCheckFallback.ts @@ -1,8 +1,8 @@ import type { IUser } from '@rocket.chat/core-typings'; import { Accounts } from 'meteor/accounts-base'; -import { settings } from '../../../settings/server'; import type { ICodeCheck, IProcessInvalidCodeResult } from './ICodeCheck'; +import { settings } from '../../../settings/server'; export class PasswordCheckFallback implements ICodeCheck { public readonly name = 'password'; diff --git a/apps/meteor/app/2fa/server/code/TOTPCheck.ts b/apps/meteor/app/2fa/server/code/TOTPCheck.ts index 3aa2604c79656..236016883f89e 100644 --- a/apps/meteor/app/2fa/server/code/TOTPCheck.ts +++ b/apps/meteor/app/2fa/server/code/TOTPCheck.ts @@ -1,8 +1,8 @@ import type { IUser } from '@rocket.chat/core-typings'; +import type { ICodeCheck, IProcessInvalidCodeResult } from './ICodeCheck'; import { settings } from '../../../settings/server'; import { TOTP } from '../lib/totp'; -import type { ICodeCheck, IProcessInvalidCodeResult } from './ICodeCheck'; export class TOTPCheck implements ICodeCheck { public readonly name = 'totp'; diff --git a/apps/meteor/app/2fa/server/code/index.ts b/apps/meteor/app/2fa/server/code/index.ts index b05157416e313..d4be080259cf4 100644 --- a/apps/meteor/app/2fa/server/code/index.ts +++ b/apps/meteor/app/2fa/server/code/index.ts @@ -5,11 +5,11 @@ import { Users } from '@rocket.chat/models'; import { Accounts } from 'meteor/accounts-base'; import { Meteor } from 'meteor/meteor'; -import { settings } from '../../../settings/server'; import { EmailCheck } from './EmailCheck'; import type { ICodeCheck } from './ICodeCheck'; import { PasswordCheckFallback } from './PasswordCheckFallback'; import { TOTPCheck } from './TOTPCheck'; +import { settings } from '../../../settings/server'; export interface ITwoFactorOptions { disablePasswordFallback?: boolean; diff --git a/apps/meteor/app/2fa/server/loginHandler.ts b/apps/meteor/app/2fa/server/loginHandler.ts index a51ba72ec7fa6..b554330e140f4 100644 --- a/apps/meteor/app/2fa/server/loginHandler.ts +++ b/apps/meteor/app/2fa/server/loginHandler.ts @@ -3,8 +3,8 @@ import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; import { OAuth } from 'meteor/oauth'; -import { callbacks } from '../../../lib/callbacks'; import { checkCodeForUser } from './code/index'; +import { callbacks } from '../../../lib/callbacks'; const isMeteorError = (error: any): error is Meteor.Error => { return error?.meteorError !== undefined; diff --git a/apps/meteor/app/api/server/api.ts b/apps/meteor/app/api/server/api.ts index 57be4f294d9be..51930f1e9e50e 100644 --- a/apps/meteor/app/api/server/api.ts +++ b/apps/meteor/app/api/server/api.ts @@ -14,15 +14,6 @@ import type { Request, Response } from 'meteor/rocketchat:restivus'; import { Restivus } from 'meteor/rocketchat:restivus'; import _ from 'underscore'; -import { isObject } from '../../../lib/utils/isObject'; -import { getNestedProp } from '../../../server/lib/getNestedProp'; -import { getRestPayload } from '../../../server/lib/logger/logPayloads'; -import { checkCodeForUser } from '../../2fa/server/code'; -import { hasPermissionAsync } from '../../authorization/server/functions/hasPermission'; -import { notifyOnUserChangeAsync } from '../../lib/server/lib/notifyListener'; -import { metrics } from '../../metrics/server'; -import { settings } from '../../settings/server'; -import { getDefaultUserFields } from '../../utils/server/functions/getDefaultUserFields'; import type { PermissionsPayload } from './api.helpers'; import { checkPermissionsForInvocation, checkPermissions, parseDeprecation } from './api.helpers'; import type { @@ -37,6 +28,15 @@ import type { } from './definition'; import { getUserInfo } from './helpers/getUserInfo'; import { parseJsonQuery } from './helpers/parseJsonQuery'; +import { isObject } from '../../../lib/utils/isObject'; +import { getNestedProp } from '../../../server/lib/getNestedProp'; +import { getRestPayload } from '../../../server/lib/logger/logPayloads'; +import { checkCodeForUser } from '../../2fa/server/code'; +import { hasPermissionAsync } from '../../authorization/server/functions/hasPermission'; +import { notifyOnUserChangeAsync } from '../../lib/server/lib/notifyListener'; +import { metrics } from '../../metrics/server'; +import { settings } from '../../settings/server'; +import { getDefaultUserFields } from '../../utils/server/functions/getDefaultUserFields'; const logger = new Logger('API'); diff --git a/apps/meteor/app/api/server/lib/getUploadFormData.ts b/apps/meteor/app/api/server/lib/getUploadFormData.ts index 3136a6c16e130..1630afe8cae22 100644 --- a/apps/meteor/app/api/server/lib/getUploadFormData.ts +++ b/apps/meteor/app/api/server/lib/getUploadFormData.ts @@ -17,6 +17,14 @@ type UploadResult = { fields: K; }; +type UploadResultWithOptionalFile = + | UploadResult + | ({ + [P in keyof Omit, 'fields'>]: undefined; + } & { + fields: K; + }); + export async function getUploadFormData< T extends string, K extends Record = Record, @@ -27,8 +35,37 @@ export async function getUploadFormData< field?: T; validate?: V; sizeLimit?: number; + fileOptional: true; + }, +): Promise>; + +export async function getUploadFormData< + T extends string, + K extends Record = Record, + V extends ValidateFunction = ValidateFunction, +>( + { request }: { request: Request }, + options?: { + field?: T; + validate?: V; + sizeLimit?: number; + fileOptional?: false | undefined; + }, +): Promise>; + +export async function getUploadFormData< + T extends string, + K extends Record = Record, + V extends ValidateFunction = ValidateFunction, +>( + { request }: { request: Request }, + options: { + field?: T; + validate?: V; + sizeLimit?: number; + fileOptional?: boolean; } = {}, -): Promise> { +): Promise> { const limits = { files: 1, ...(options.sizeLimit && options.sizeLimit > -1 && { fileSize: options.sizeLimit }), @@ -37,9 +74,9 @@ export async function getUploadFormData< const bb = busboy({ headers: request.headers, defParamCharset: 'utf8', limits }); const fields = Object.create(null) as K; - let uploadedFile: UploadResult | undefined; + let uploadedFile: UploadResultWithOptionalFile | undefined; - let returnResult = (_value: UploadResult) => { + let returnResult = (_value: UploadResultWithOptionalFile) => { // noop }; let returnError = (_error?: Error | string | null | undefined) => { @@ -48,10 +85,22 @@ export async function getUploadFormData< function onField(fieldname: keyof K, value: K[keyof K]) { fields[fieldname] = value; + uploadedFile = { + fields, + encoding: undefined, + filename: undefined, + fieldname: undefined, + mimetype: undefined, + fileBuffer: undefined, + file: undefined, + }; } function onEnd() { if (!uploadedFile) { + return returnError(new MeteorError('No file or fields were uploaded')); + } + if (!('file' in uploadedFile) && !options.fileOptional) { return returnError(new MeteorError('No file uploaded')); } if (options.validate !== undefined && !options.validate(fields)) { @@ -121,7 +170,7 @@ export async function getUploadFormData< request.pipe(bb); - return new Promise((resolve, reject) => { + return new Promise>((resolve, reject) => { returnResult = resolve; returnError = reject; }); diff --git a/apps/meteor/app/api/server/v1/assets.ts b/apps/meteor/app/api/server/v1/assets.ts index 395bbd791afa8..939cb5f1469f6 100644 --- a/apps/meteor/app/api/server/v1/assets.ts +++ b/apps/meteor/app/api/server/v1/assets.ts @@ -1,13 +1,18 @@ +import { Settings } from '@rocket.chat/models'; import { isAssetsUnsetAssetProps } from '@rocket.chat/rest-typings'; -import { RocketChatAssets, setAsset, unsetAsset, refreshClients } from '../../../assets/server'; +import { RocketChatAssets, refreshClients } from '../../../assets/server'; +import { notifyOnSettingChangedById } from '../../../lib/server/lib/notifyListener'; import { settings } from '../../../settings/server'; import { API } from '../api'; import { getUploadFormData } from '../lib/getUploadFormData'; API.v1.addRoute( 'assets.setAsset', - { authRequired: true }, + { + authRequired: true, + permissionsRequired: ['manage-assets'], + }, { async post() { const asset = await getUploadFormData( @@ -29,7 +34,14 @@ API.v1.addRoute( throw new Error('Invalid asset'); } - await setAsset(this.userId, fileBuffer, mimetype, assetName); + const { key, value } = await RocketChatAssets.setAssetWithBuffer(fileBuffer, mimetype, assetName); + + const { modifiedCount } = await Settings.updateValueById(key, value); + + if (modifiedCount) { + void notifyOnSettingChangedById(key); + } + if (refreshAllClients) { await refreshClients(this.userId); } @@ -44,6 +56,7 @@ API.v1.addRoute( { authRequired: true, validateParams: isAssetsUnsetAssetProps, + permissionsRequired: ['manage-assets'], }, { async post() { @@ -52,7 +65,15 @@ API.v1.addRoute( if (!isValidAsset) { throw Error('Invalid asset'); } - await unsetAsset(this.userId, assetName); + + const { key, value } = await RocketChatAssets.unsetAsset(assetName); + + const { modifiedCount } = await Settings.updateValueById(key, value); + + if (modifiedCount) { + void notifyOnSettingChangedById(key); + } + if (refreshAllClients) { await refreshClients(this.userId); } diff --git a/apps/meteor/app/api/server/v1/chat.ts b/apps/meteor/app/api/server/v1/chat.ts index b5cfd9e46ce61..05eb7208c9b44 100644 --- a/apps/meteor/app/api/server/v1/chat.ts +++ b/apps/meteor/app/api/server/v1/chat.ts @@ -21,6 +21,7 @@ import { processWebhookMessage } from '../../../lib/server/functions/processWebh import { executeSendMessage } from '../../../lib/server/methods/sendMessage'; import { executeUpdateMessage } from '../../../lib/server/methods/updateMessage'; import { applyAirGappedRestrictionsValidation } from '../../../license/server/airGappedRestrictionsWrapper'; +import { pinMessage } from '../../../message-pin/server/pinMessage'; import { OEmbed } from '../../../oembed/server/server'; import { executeSetReaction } from '../../../reactions/server/setReaction'; import { settings } from '../../../settings/server'; @@ -145,7 +146,7 @@ API.v1.addRoute( throw new Meteor.Error('error-message-not-found', 'The provided "messageId" does not match any existing message.'); } - const pinnedMessage = await Meteor.callAsync('pinMessage', msg); + const pinnedMessage = await pinMessage(msg, this.userId); const [message] = await normalizeMessagesForUser([pinnedMessage], this.userId); @@ -161,6 +162,21 @@ API.v1.addRoute( { authRequired: true }, { async post() { + const { text, attachments } = this.bodyParams; + const maxAllowedSize = settings.get('Message_MaxAllowedSize') ?? 0; + + if (text && text.length > maxAllowedSize) { + return API.v1.failure('error-message-size-exceeded'); + } + + if (attachments && attachments.length > 0) { + for (const attachment of attachments) { + if (attachment.text && attachment.text.length > maxAllowedSize) { + return API.v1.failure('error-message-size-exceeded'); + } + } + } + const messageReturn = (await applyAirGappedRestrictionsValidation(() => processWebhookMessage(this.bodyParams, this.user)))[0]; if (!messageReturn) { diff --git a/apps/meteor/app/api/server/v1/emoji-custom.ts b/apps/meteor/app/api/server/v1/emoji-custom.ts index 261743e6c0a9a..5b255b6ef0c18 100644 --- a/apps/meteor/app/api/server/v1/emoji-custom.ts +++ b/apps/meteor/app/api/server/v1/emoji-custom.ts @@ -1,9 +1,11 @@ import { Media } from '@rocket.chat/core-services'; +import type { IEmojiCustom } from '@rocket.chat/core-typings'; import { EmojiCustom } from '@rocket.chat/models'; import { isEmojiCustomList } from '@rocket.chat/rest-typings'; import { Meteor } from 'meteor/meteor'; import { SystemLogger } from '../../../../server/lib/logger/system'; +import type { EmojiData } from '../../../emoji-custom/server/lib/insertOrUpdateEmoji'; import { insertOrUpdateEmoji } from '../../../emoji-custom/server/lib/insertOrUpdateEmoji'; import { uploadEmojiCustomWithBuffer } from '../../../emoji-custom/server/lib/uploadEmojiCustom'; import { settings } from '../../../settings/server'; @@ -114,16 +116,15 @@ API.v1.addRoute( fields.extension = extension; try { - await Meteor.callAsync('insertOrUpdateEmoji', { - ...fields, - newFile: true, - aliases: fields.aliases || '', - }); - await Meteor.callAsync('uploadEmojiCustom', fileBuffer, mimetype, { + const emojiData = await insertOrUpdateEmoji(this.userId, { ...fields, newFile: true, aliases: fields.aliases || '', + name: fields.name, + extension: fields.extension, }); + + await uploadEmojiCustomWithBuffer(this.userId, fileBuffer, mimetype, emojiData); } catch (e) { SystemLogger.error(e); return API.v1.failure(); @@ -143,7 +144,7 @@ API.v1.addRoute( { request: this.request, }, - { field: 'emoji', sizeLimit: settings.get('FileUpload_MaxFileSize') }, + { field: 'emoji', sizeLimit: settings.get('FileUpload_MaxFileSize'), fileOptional: true }, ); const { fields, fileBuffer, mimetype } = emoji; @@ -152,41 +153,40 @@ API.v1.addRoute( throw new Meteor.Error('The required "_id" query param is missing.'); } - const emojiToUpdate = await EmojiCustom.findOneById(fields._id); + const emojiToUpdate = await EmojiCustom.findOneById>(fields._id, { + projection: { name: 1, extension: 1 }, + }); if (!emojiToUpdate) { throw new Meteor.Error('Emoji not found.'); } - fields.previousName = emojiToUpdate.name; - fields.previousExtension = emojiToUpdate.extension; - fields.aliases = fields.aliases || ''; - const newFile = Boolean(emoji && fileBuffer.length); + const emojiData: EmojiData = { + previousName: emojiToUpdate.name, + previousExtension: emojiToUpdate.extension, + aliases: fields.aliases || '', + name: fields.name, + extension: fields.extension, + _id: fields._id, + newFile: false, + }; - if (fields.newFile) { + const isNewFile = fileBuffer?.length && !!mimetype; + if (isNewFile) { + emojiData.newFile = isNewFile; const isUploadable = await Media.isImage(fileBuffer); if (!isUploadable) { throw new Meteor.Error('emoji-is-not-image', "Emoji file provided cannot be uploaded since it's not an image"); } const [, extension] = mimetype.split('/'); - fields.extension = extension; + emojiData.extension = extension; } else { - fields.extension = emojiToUpdate.extension; + emojiData.extension = emojiToUpdate.extension; } - const emojiData = { - name: fields.name, - _id: fields._id, - aliases: fields.aliases, - extension: fields.extension, - previousName: fields.previousName, - previousExtension: fields.previousExtension, - newFile, - }; - - await insertOrUpdateEmoji(this.userId, emojiData); - if (fields.newFile) { - await uploadEmojiCustomWithBuffer(this.userId, fileBuffer, mimetype, emojiData); + const updatedEmojiData = await insertOrUpdateEmoji(this.userId, emojiData); + if (isNewFile) { + await uploadEmojiCustomWithBuffer(this.userId, fileBuffer, mimetype, updatedEmojiData); } return API.v1.success(); }, diff --git a/apps/meteor/app/api/server/v1/import.ts b/apps/meteor/app/api/server/v1/import.ts index 54dbce4d82d18..6104076c4fb46 100644 --- a/apps/meteor/app/api/server/v1/import.ts +++ b/apps/meteor/app/api/server/v1/import.ts @@ -15,8 +15,6 @@ import { } from '@rocket.chat/rest-typings'; import { Meteor } from 'meteor/meteor'; -import { PendingAvatarImporter } from '../../../importer-pending-avatars/server/PendingAvatarImporter'; -import { PendingFileImporter } from '../../../importer-pending-files/server/PendingFileImporter'; import { Importers } from '../../../importer/server'; import { executeUploadImportFile, @@ -26,6 +24,8 @@ import { executeStartImport, executeGetLatestImportOperations, } from '../../../importer/server/methods'; +import { PendingAvatarImporter } from '../../../importer-pending-avatars/server/PendingAvatarImporter'; +import { PendingFileImporter } from '../../../importer-pending-files/server/PendingFileImporter'; import { API } from '../api'; API.v1.addRoute( @@ -33,6 +33,7 @@ API.v1.addRoute( { authRequired: true, validateParams: isUploadImportFileParamsPOST, + permissionsRequired: ['run-import'], }, { async post() { diff --git a/apps/meteor/app/api/server/v1/invites.ts b/apps/meteor/app/api/server/v1/invites.ts index ac053f21f288b..ac916befc4fd0 100644 --- a/apps/meteor/app/api/server/v1/invites.ts +++ b/apps/meteor/app/api/server/v1/invites.ts @@ -63,8 +63,6 @@ API.v1.addRoute( { async post() { const { token } = this.bodyParams; - // eslint-disable-next-line react-hooks/rules-of-hooks - // eslint-disable-next-line react-hooks/rules-of-hooks return API.v1.success(await useInviteToken(this.userId, token)); }, diff --git a/apps/meteor/app/api/server/v1/rooms.ts b/apps/meteor/app/api/server/v1/rooms.ts index 355cce24d40b7..aaa3cff4e9931 100644 --- a/apps/meteor/app/api/server/v1/rooms.ts +++ b/apps/meteor/app/api/server/v1/rooms.ts @@ -196,6 +196,10 @@ API.v1.addRoute( const fileStore = FileUpload.getStore('Uploads'); const uploadedFile = await fileStore.insert(details, fileBuffer); + if ((fields.description?.length ?? 0) > settings.get('Message_MaxAllowedSize')) { + throw new Meteor.Error('error-message-size-exceeded'); + } + uploadedFile.description = fields.description; delete fields.description; @@ -299,6 +303,10 @@ API.v1.addRoute( throw new Meteor.Error('invalid-file'); } + if ((this.bodyParams.description?.length ?? 0) > settings.get('Message_MaxAllowedSize')) { + throw new Meteor.Error('error-message-size-exceeded'); + } + file.description = this.bodyParams.description; delete this.bodyParams.description; @@ -459,9 +467,14 @@ API.v1.addRoute( }, ); +/* +TO-DO: 8.0.0 should use the ajv validation +which will change this endpoint's +response errors. +*/ API.v1.addRoute( 'rooms.createDiscussion', - { authRequired: true }, + { authRequired: true /* , validateParams: isRoomsCreateDiscussionProps */ }, { async post() { // eslint-disable-next-line @typescript-eslint/naming-convention diff --git a/apps/meteor/app/api/server/v1/voip/extensions.ts b/apps/meteor/app/api/server/v1/voip/extensions.ts index 1a0fecf7cfc5f..91b0466626b62 100644 --- a/apps/meteor/app/api/server/v1/voip/extensions.ts +++ b/apps/meteor/app/api/server/v1/voip/extensions.ts @@ -3,10 +3,10 @@ import type { IVoipExtensionBase } from '@rocket.chat/core-typings'; import { Users } from '@rocket.chat/models'; import { Match, check } from 'meteor/check'; +import { logger } from './logger'; import { settings } from '../../../../settings/server'; import { generateJWT } from '../../../../utils/server/lib/JWTHelper'; import { API } from '../../api'; -import { logger } from './logger'; // Get the connector version and type API.v1.addRoute( diff --git a/apps/meteor/app/api/server/v1/voip/omnichannel.ts b/apps/meteor/app/api/server/v1/voip/omnichannel.ts index e2128375ea42b..abd92b9fa5899 100644 --- a/apps/meteor/app/api/server/v1/voip/omnichannel.ts +++ b/apps/meteor/app/api/server/v1/voip/omnichannel.ts @@ -3,10 +3,10 @@ import type { IUser, IVoipExtensionWithAgentInfo } from '@rocket.chat/core-typin import { Users } from '@rocket.chat/models'; import { Match, check } from 'meteor/check'; +import { logger } from './logger'; import { notifyOnUserChange } from '../../../../lib/server/lib/notifyListener'; import { API } from '../../api'; import { getPaginationItems } from '../../helpers/getPaginationItems'; -import { logger } from './logger'; function filter( array: IVoipExtensionWithAgentInfo[], diff --git a/apps/meteor/app/apple/server/appleOauthRegisterService.ts b/apps/meteor/app/apple/server/appleOauthRegisterService.ts index b9558fa701f77..7cb748c7ab917 100644 --- a/apps/meteor/app/apple/server/appleOauthRegisterService.ts +++ b/apps/meteor/app/apple/server/appleOauthRegisterService.ts @@ -1,9 +1,9 @@ import { KJUR } from 'jsrsasign'; import { ServiceConfiguration } from 'meteor/service-configuration'; +import { AppleCustomOAuth } from './AppleCustomOAuth'; import { settings } from '../../settings/server'; import { config } from '../lib/config'; -import { AppleCustomOAuth } from './AppleCustomOAuth'; new AppleCustomOAuth('apple', config); diff --git a/apps/meteor/app/apps/server/converters/threads.ts b/apps/meteor/app/apps/server/converters/threads.ts index e31ee094b4d73..d6284688b984a 100644 --- a/apps/meteor/app/apps/server/converters/threads.ts +++ b/apps/meteor/app/apps/server/converters/threads.ts @@ -1,8 +1,8 @@ import type { IAppRoomsConverter, IAppThreadsConverter, IAppUsersConverter, IAppsMessage, IAppsUser } from '@rocket.chat/apps'; import type { IMessage as AppsEngineMessage, IMessageAttachment } from '@rocket.chat/apps-engine/definition/messages'; import type { IRoom } from '@rocket.chat/apps-engine/definition/rooms'; -import type { IUser } from '@rocket.chat/core-typings'; -import { isEditedMessage, type IMessage } from '@rocket.chat/core-typings'; +import { isEditedMessage } from '@rocket.chat/core-typings'; +import type { IUser, IMessage } from '@rocket.chat/core-typings'; import { Messages } from '@rocket.chat/models'; import { cachedFunction } from './cachedFunction'; diff --git a/apps/meteor/app/apps/server/converters/transformMappedData.ts b/apps/meteor/app/apps/server/converters/transformMappedData.ts index 3fcd4db482a7f..85c54fc103b91 100644 --- a/apps/meteor/app/apps/server/converters/transformMappedData.ts +++ b/apps/meteor/app/apps/server/converters/transformMappedData.ts @@ -1,5 +1,3 @@ -import cloneDeep from 'lodash.clonedeep'; - /** * Transforms a `data` source object to another object, * essentially applying a to -> from mapping provided by @@ -79,7 +77,7 @@ export const transformMappedData = async < data: DataType, map: MapType, ): Promise => { - const originalData: DataType = cloneDeep(data); + const originalData: DataType = structuredClone(data); const transformedData: Record = {}; for await (const [to, from] of Object.entries(map)) { diff --git a/apps/meteor/app/assets/server/assets.ts b/apps/meteor/app/assets/server/assets.ts index 8bb2e8277a9f4..e9160b0ece61a 100644 --- a/apps/meteor/app/assets/server/assets.ts +++ b/apps/meteor/app/assets/server/assets.ts @@ -220,16 +220,14 @@ class RocketChatAssetsClass { return assets; } - public async setAsset(binaryContent: string, contentType: string, asset: string): Promise { - const file = Buffer.from(binaryContent, 'binary'); - await this.setAssetWithBuffer(file, contentType, asset); - } - - public async setAssetWithBuffer(binaryContent: Buffer, contentType: string, asset: string): Promise { - await this._setAsset(binaryContent, contentType, asset); - } - - private async _setAsset(file: Buffer, contentType: string, asset: string): Promise { + public async setAssetWithBuffer( + file: Buffer, + contentType: string, + asset: string, + ): Promise<{ + key: string; + value: IRocketChatAsset; + }> { const assetInstance = getAssetByKey(asset); if (!assetInstance) { throw new Meteor.Error('error-invalid-asset', 'Invalid asset', { @@ -260,29 +258,29 @@ class RocketChatAssetsClass { await RocketChatAssetsInstance.deleteFile(asset); const ws = RocketChatAssetsInstance.createWriteStream(asset, contentType); - ws.on('end', () => { - return setTimeout(async () => { - const key = `Assets_${asset}`; - const value = { - url: `assets/${asset}.${extension}`, - defaultUrl: assetInstance.defaultUrl, - }; - - void (async () => { - const { modifiedCount } = await Settings.updateValueById(key, value); - if (modifiedCount) { - void notifyOnSettingChangedById(key); - } - })(); - - return RocketChatAssets.processAsset(key, value); - }, 200); - }); - rs.pipe(ws); + return new Promise((resolve) => { + ws.on('end', () => { + return setTimeout(async () => { + const key = `Assets_${asset}`; + const value = { + url: `assets/${asset}.${extension}`, + defaultUrl: assetInstance.defaultUrl, + } as IRocketChatAsset; + + await RocketChatAssets.processAsset(key, value); + resolve({ + key, + value, + }); + }, 200); + }); + + rs.pipe(ws); + }); } - public async unsetAsset(asset: string): Promise { + public async unsetAsset(asset: string) { if (!getAssetByKey(asset)) { throw new Meteor.Error('error-invalid-asset', 'Invalid asset', { function: 'RocketChat.Assets.unsetAsset', @@ -295,14 +293,12 @@ class RocketChatAssetsClass { defaultUrl: getAssetByKey(asset).defaultUrl, }; - void (async () => { - const { modifiedCount } = await Settings.updateValueById(key, value); - if (modifiedCount) { - void notifyOnSettingChangedById(key); - } - })(); - await RocketChatAssets.processAsset(key, value); + + return { + key, + value, + }; } public refreshClients(): boolean { @@ -423,32 +419,6 @@ export const refreshClients = async (userId: string) => { return RocketChatAssets.refreshClients(); }; -export const unsetAsset = async (userId: string, asset: string) => { - if (!userId) { - throw new Error('Invalid user'); - } - - const _hasPermission = await hasPermissionAsync(userId, 'manage-assets'); - if (!_hasPermission) { - throw new Error('Managing assets not allowed'); - } - - return RocketChatAssets.unsetAsset(asset); -}; - -export const setAsset = async (userId: string, binaryContent: Buffer, contentType: string, asset: string) => { - if (!userId) { - throw new Error('Invalid user'); - } - - const _hasPermission = await hasPermissionAsync(userId, 'manage-assets'); - if (!_hasPermission) { - throw new Error('Managing assets not allowed'); - } - - await RocketChatAssets.setAssetWithBuffer(binaryContent, contentType, asset); -}; - const listener = (req: IncomingMessage, res: ServerResponse, next: NextHandleFunction) => { if (!req.url) { return; diff --git a/apps/meteor/app/assets/server/index.ts b/apps/meteor/app/assets/server/index.ts index 8aa8c123f9283..6802fadf6d20d 100644 --- a/apps/meteor/app/assets/server/index.ts +++ b/apps/meteor/app/assets/server/index.ts @@ -1 +1 @@ -export { RocketChatAssets, setAsset, unsetAsset, refreshClients } from './assets'; +export { RocketChatAssets, refreshClients } from './assets'; diff --git a/apps/meteor/app/authorization/client/hasPermission.ts b/apps/meteor/app/authorization/client/hasPermission.ts index 66171aeadd280..3495da05556cf 100644 --- a/apps/meteor/app/authorization/client/hasPermission.ts +++ b/apps/meteor/app/authorization/client/hasPermission.ts @@ -26,7 +26,7 @@ const createPermissionValidator = } } - const permission = Models.ChatPermissions.findOne(permissionId, { + const permission = Models.Permissions.findOne(permissionId, { fields: { roles: 1 }, }); const roles = permission?.roles ?? []; @@ -99,18 +99,3 @@ export const userHasAllPermission = ( ): boolean => validatePermissions(permissions, scope, all, userId); export const hasPermission = hasAllPermission; - -/** - * This function is used to check if the user will have the permission after something happens. - * For example, The user is creating a new channel and he wants to set read-only config to true. - * This is a problem, set-readonly is a permission related with the scoped permissions `owner` - * so the user cannot set this permission to true during the channel creation, because there is no room yet to be owned and used as scope, but is possible - * during the channel update, which is weird. - * - * @param permissions The permissions to check - * @param scopedRoles The scoped roles to check to be included in the user roles - * @returns If the user will have the permission - */ - -export const willHavePermission = (permissions: IPermission['_id'] | IPermission['_id'][], scopedRoles: IPermission['_id'][]): boolean => - validatePermissions(permissions, undefined, all, undefined, scopedRoles); diff --git a/apps/meteor/app/authorization/server/functions/canDeleteMessage.ts b/apps/meteor/app/authorization/server/functions/canDeleteMessage.ts index fea37fd1c2a58..1651affba0deb 100644 --- a/apps/meteor/app/authorization/server/functions/canDeleteMessage.ts +++ b/apps/meteor/app/authorization/server/functions/canDeleteMessage.ts @@ -1,9 +1,9 @@ import type { IUser, IRoom } from '@rocket.chat/core-typings'; import { Rooms } from '@rocket.chat/models'; -import { getValue } from '../../../settings/server/raw'; import { canAccessRoomAsync } from './canAccessRoom'; import { hasPermissionAsync } from './hasPermission'; +import { getValue } from '../../../settings/server/raw'; const elapsedTime = (ts: Date): number => { const dif = Date.now() - ts.getTime(); diff --git a/apps/meteor/app/authorization/server/functions/canSendMessage.ts b/apps/meteor/app/authorization/server/functions/canSendMessage.ts index 9cf5c5ec78d22..97767ee001b00 100644 --- a/apps/meteor/app/authorization/server/functions/canSendMessage.ts +++ b/apps/meteor/app/authorization/server/functions/canSendMessage.ts @@ -1,10 +1,10 @@ import type { IRoom, IUser } from '@rocket.chat/core-typings'; import { Subscriptions, Rooms } from '@rocket.chat/models'; -import { RoomMemberActions } from '../../../../definition/IRoomTypeConfig'; -import { roomCoordinator } from '../../../../server/lib/rooms/roomCoordinator'; import { canAccessRoomAsync } from './canAccessRoom'; import { hasPermissionAsync } from './hasPermission'; +import { RoomMemberActions } from '../../../../definition/IRoomTypeConfig'; +import { roomCoordinator } from '../../../../server/lib/rooms/roomCoordinator'; const subscriptionOptions = { projection: { diff --git a/apps/meteor/app/autotranslate/client/lib/actionButton.ts b/apps/meteor/app/autotranslate/client/lib/actionButton.ts index a720917ce175e..3901ef2df8e77 100644 --- a/apps/meteor/app/autotranslate/client/lib/actionButton.ts +++ b/apps/meteor/app/autotranslate/client/lib/actionButton.ts @@ -1,6 +1,7 @@ import { Meteor } from 'meteor/meteor'; import { Tracker } from 'meteor/tracker'; +import { AutoTranslate } from './autotranslate'; import { roomCoordinator } from '../../../../client/lib/rooms/roomCoordinator'; import { hasTranslationLanguageInAttachments, @@ -11,7 +12,6 @@ import { Messages } from '../../../models/client'; import { settings } from '../../../settings/client'; import { MessageAction } from '../../../ui-utils/client/lib/MessageAction'; import { sdk } from '../../../utils/client/lib/SDKClient'; -import { AutoTranslate } from './autotranslate'; Meteor.startup(() => { AutoTranslate.init(); diff --git a/apps/meteor/app/autotranslate/server/deeplTranslate.ts b/apps/meteor/app/autotranslate/server/deeplTranslate.ts index 349133f7fd4cb..caa4cf97c9a8c 100644 --- a/apps/meteor/app/autotranslate/server/deeplTranslate.ts +++ b/apps/meteor/app/autotranslate/server/deeplTranslate.ts @@ -13,10 +13,10 @@ import type { import { serverFetch as fetch } from '@rocket.chat/server-fetch'; import _ from 'underscore'; +import { TranslationProviderRegistry, AutoTranslate } from './autotranslate'; import { i18n } from '../../../server/lib/i18n'; import { SystemLogger } from '../../../server/lib/logger/system'; import { settings } from '../../settings/server'; -import { TranslationProviderRegistry, AutoTranslate } from './autotranslate'; const proApiEndpoint = 'https://api.deepl.com/v2/translate'; const freeApiEndpoint = 'https://api-free.deepl.com/v2/translate'; diff --git a/apps/meteor/app/autotranslate/server/googleTranslate.ts b/apps/meteor/app/autotranslate/server/googleTranslate.ts index 0e0b7a2057654..da5e156458dcb 100644 --- a/apps/meteor/app/autotranslate/server/googleTranslate.ts +++ b/apps/meteor/app/autotranslate/server/googleTranslate.ts @@ -13,10 +13,10 @@ import type { import { serverFetch as fetch } from '@rocket.chat/server-fetch'; import _ from 'underscore'; +import { AutoTranslate, TranslationProviderRegistry } from './autotranslate'; import { i18n } from '../../../server/lib/i18n'; import { SystemLogger } from '../../../server/lib/logger/system'; import { settings } from '../../settings/server'; -import { AutoTranslate, TranslationProviderRegistry } from './autotranslate'; /** * Represents google translate class diff --git a/apps/meteor/app/autotranslate/server/msTranslate.ts b/apps/meteor/app/autotranslate/server/msTranslate.ts index f885a23b8e6b1..ad36ff0b8b771 100644 --- a/apps/meteor/app/autotranslate/server/msTranslate.ts +++ b/apps/meteor/app/autotranslate/server/msTranslate.ts @@ -6,10 +6,10 @@ import type { IMessage, IProviderMetadata, ISupportedLanguage, ITranslationResul import { serverFetch as fetch } from '@rocket.chat/server-fetch'; import _ from 'underscore'; -import { i18n } from '../../../server/lib/i18n'; -import { settings } from '../../settings/server'; import { TranslationProviderRegistry, AutoTranslate } from './autotranslate'; import { msLogger } from './logger'; +import { i18n } from '../../../server/lib/i18n'; +import { settings } from '../../settings/server'; /** * Microsoft translation service provider class representation. diff --git a/apps/meteor/app/cloud/server/functions/connectWorkspace.ts b/apps/meteor/app/cloud/server/functions/connectWorkspace.ts index b7dc1d8b21b08..9d29fb7eb399e 100644 --- a/apps/meteor/app/cloud/server/functions/connectWorkspace.ts +++ b/apps/meteor/app/cloud/server/functions/connectWorkspace.ts @@ -1,10 +1,10 @@ import { serverFetch as fetch } from '@rocket.chat/server-fetch'; +import { getRedirectUri } from './getRedirectUri'; +import { saveRegistrationData } from './saveRegistrationData'; import { CloudWorkspaceConnectionError } from '../../../../lib/errors/CloudWorkspaceConnectionError'; import { SystemLogger } from '../../../../server/lib/logger/system'; import { settings } from '../../../settings/server'; -import { getRedirectUri } from './getRedirectUri'; -import { saveRegistrationData } from './saveRegistrationData'; const fetchRegistrationDataPayload = async ({ token, diff --git a/apps/meteor/app/cloud/server/functions/getCheckoutUrl.ts b/apps/meteor/app/cloud/server/functions/getCheckoutUrl.ts index 2665f31c84988..914020e96471a 100644 --- a/apps/meteor/app/cloud/server/functions/getCheckoutUrl.ts +++ b/apps/meteor/app/cloud/server/functions/getCheckoutUrl.ts @@ -1,10 +1,10 @@ import { serverFetch as fetch } from '@rocket.chat/server-fetch'; +import { getWorkspaceAccessTokenOrThrow } from './getWorkspaceAccessToken'; +import { syncWorkspace } from './syncWorkspace'; import { SystemLogger } from '../../../../server/lib/logger/system'; import { settings } from '../../../settings/server'; import { getURL } from '../../../utils/server/getURL'; -import { getWorkspaceAccessTokenOrThrow } from './getWorkspaceAccessToken'; -import { syncWorkspace } from './syncWorkspace'; export const fallback = `https://go.rocket.chat/i/contact-sales`; diff --git a/apps/meteor/app/cloud/server/functions/getWorkspaceKey.ts b/apps/meteor/app/cloud/server/functions/getWorkspaceKey.ts index 639f29402fe9d..2a2b8e8858fd5 100644 --- a/apps/meteor/app/cloud/server/functions/getWorkspaceKey.ts +++ b/apps/meteor/app/cloud/server/functions/getWorkspaceKey.ts @@ -1,5 +1,5 @@ -import { settings } from '../../../settings/server'; import { retrieveRegistrationStatus } from './retrieveRegistrationStatus'; +import { settings } from '../../../settings/server'; export async function getWorkspaceKey() { const { workspaceRegistered } = await retrieveRegistrationStatus(); diff --git a/apps/meteor/app/cloud/server/functions/registerPreIntentWorkspaceWizard.ts b/apps/meteor/app/cloud/server/functions/registerPreIntentWorkspaceWizard.ts index e0865c24156ac..a102ed3590536 100644 --- a/apps/meteor/app/cloud/server/functions/registerPreIntentWorkspaceWizard.ts +++ b/apps/meteor/app/cloud/server/functions/registerPreIntentWorkspaceWizard.ts @@ -2,9 +2,9 @@ import type { IUser } from '@rocket.chat/core-typings'; import { Users } from '@rocket.chat/models'; import { serverFetch as fetch } from '@rocket.chat/server-fetch'; +import { buildWorkspaceRegistrationData } from './buildRegistrationData'; import { SystemLogger } from '../../../../server/lib/logger/system'; import { settings } from '../../../settings/server'; -import { buildWorkspaceRegistrationData } from './buildRegistrationData'; export async function registerPreIntentWorkspaceWizard(): Promise { const firstUser = (await Users.getOldest({ projection: { name: 1, emails: 1 } })) as IUser | undefined; diff --git a/apps/meteor/app/cloud/server/functions/removeLicense.ts b/apps/meteor/app/cloud/server/functions/removeLicense.ts index b9afe2ddf09a0..88f1d68251777 100644 --- a/apps/meteor/app/cloud/server/functions/removeLicense.ts +++ b/apps/meteor/app/cloud/server/functions/removeLicense.ts @@ -1,12 +1,12 @@ import { serverFetch as fetch } from '@rocket.chat/server-fetch'; +import { CloudWorkspaceAccessTokenEmptyError, getWorkspaceAccessToken } from './getWorkspaceAccessToken'; +import { retrieveRegistrationStatus } from './retrieveRegistrationStatus'; +import { syncWorkspace } from './syncWorkspace'; import { callbacks } from '../../../../lib/callbacks'; import { CloudWorkspaceConnectionError } from '../../../../lib/errors/CloudWorkspaceConnectionError'; import { CloudWorkspaceRegistrationError } from '../../../../lib/errors/CloudWorkspaceRegistrationError'; import { settings } from '../../../settings/server'; -import { CloudWorkspaceAccessTokenEmptyError, getWorkspaceAccessToken } from './getWorkspaceAccessToken'; -import { retrieveRegistrationStatus } from './retrieveRegistrationStatus'; -import { syncWorkspace } from './syncWorkspace'; export async function removeLicense() { try { diff --git a/apps/meteor/app/cloud/server/functions/removeWorkspaceRegistrationInfo.ts b/apps/meteor/app/cloud/server/functions/removeWorkspaceRegistrationInfo.ts index bf2b5d0859459..b77a89128ef41 100644 --- a/apps/meteor/app/cloud/server/functions/removeWorkspaceRegistrationInfo.ts +++ b/apps/meteor/app/cloud/server/functions/removeWorkspaceRegistrationInfo.ts @@ -1,7 +1,7 @@ import { Settings, WorkspaceCredentials } from '@rocket.chat/models'; -import { notifyOnSettingChangedById } from '../../../lib/server/lib/notifyListener'; import { retrieveRegistrationStatus } from './retrieveRegistrationStatus'; +import { notifyOnSettingChangedById } from '../../../lib/server/lib/notifyListener'; export async function removeWorkspaceRegistrationInfo() { const { workspaceRegistered } = await retrieveRegistrationStatus(); diff --git a/apps/meteor/app/cloud/server/functions/saveRegistrationData.ts b/apps/meteor/app/cloud/server/functions/saveRegistrationData.ts index 63633c567845e..e86a34fb76a2a 100644 --- a/apps/meteor/app/cloud/server/functions/saveRegistrationData.ts +++ b/apps/meteor/app/cloud/server/functions/saveRegistrationData.ts @@ -1,9 +1,9 @@ import { applyLicense } from '@rocket.chat/license'; import { Settings } from '@rocket.chat/models'; +import { syncCloudData } from './syncWorkspace/syncCloudData'; import { notifyOnSettingChangedById } from '../../../lib/server/lib/notifyListener'; import { settings } from '../../../settings/server'; -import { syncCloudData } from './syncWorkspace/syncCloudData'; type SaveRegistrationDataDTO = { workspaceId: string; diff --git a/apps/meteor/app/cloud/server/functions/startRegisterWorkspace.ts b/apps/meteor/app/cloud/server/functions/startRegisterWorkspace.ts index 1fb2dcc064493..1455ed2329a5c 100644 --- a/apps/meteor/app/cloud/server/functions/startRegisterWorkspace.ts +++ b/apps/meteor/app/cloud/server/functions/startRegisterWorkspace.ts @@ -1,12 +1,12 @@ import { Settings } from '@rocket.chat/models'; import { serverFetch as fetch } from '@rocket.chat/server-fetch'; -import { SystemLogger } from '../../../../server/lib/logger/system'; -import { notifyOnSettingChangedById } from '../../../lib/server/lib/notifyListener'; -import { settings } from '../../../settings/server'; import { buildWorkspaceRegistrationData } from './buildRegistrationData'; import { retrieveRegistrationStatus } from './retrieveRegistrationStatus'; import { syncWorkspace } from './syncWorkspace'; +import { SystemLogger } from '../../../../server/lib/logger/system'; +import { notifyOnSettingChangedById } from '../../../lib/server/lib/notifyListener'; +import { settings } from '../../../settings/server'; export async function startRegisterWorkspace(resend = false) { const { workspaceRegistered } = await retrieveRegistrationStatus(); diff --git a/apps/meteor/app/cloud/server/functions/startRegisterWorkspaceSetupWizard.ts b/apps/meteor/app/cloud/server/functions/startRegisterWorkspaceSetupWizard.ts index 382478db61c7c..36b858d932c89 100644 --- a/apps/meteor/app/cloud/server/functions/startRegisterWorkspaceSetupWizard.ts +++ b/apps/meteor/app/cloud/server/functions/startRegisterWorkspaceSetupWizard.ts @@ -1,9 +1,9 @@ import type { CloudRegistrationIntentData } from '@rocket.chat/core-typings'; import { serverFetch as fetch } from '@rocket.chat/server-fetch'; +import { buildWorkspaceRegistrationData } from './buildRegistrationData'; import { SystemLogger } from '../../../../server/lib/logger/system'; import { settings } from '../../../settings/server'; -import { buildWorkspaceRegistrationData } from './buildRegistrationData'; export async function startRegisterWorkspaceSetupWizard(resend = false, email: string): Promise { const regInfo = await buildWorkspaceRegistrationData(email); diff --git a/apps/meteor/app/cloud/server/functions/syncWorkspace/index.ts b/apps/meteor/app/cloud/server/functions/syncWorkspace/index.ts index a410ea274c07c..2ae63939e9d93 100644 --- a/apps/meteor/app/cloud/server/functions/syncWorkspace/index.ts +++ b/apps/meteor/app/cloud/server/functions/syncWorkspace/index.ts @@ -1,10 +1,10 @@ import { CloudWorkspaceRegistrationError } from '../../../../../lib/errors/CloudWorkspaceRegistrationError'; import { SystemLogger } from '../../../../../server/lib/logger/system'; import { CloudWorkspaceAccessTokenEmptyError, CloudWorkspaceAccessTokenError, isAbortError } from '../getWorkspaceAccessToken'; -import { getCachedSupportedVersionsToken } from '../supportedVersionsToken/supportedVersionsToken'; import { announcementSync } from './announcementSync'; import { legacySyncWorkspace } from './legacySyncWorkspace'; import { syncCloudData } from './syncCloudData'; +import { getCachedSupportedVersionsToken } from '../supportedVersionsToken/supportedVersionsToken'; /** * Syncs the workspace with the cloud diff --git a/apps/meteor/app/cloud/server/functions/userLogout.ts b/apps/meteor/app/cloud/server/functions/userLogout.ts index 386137ced6040..590a581ed4f01 100644 --- a/apps/meteor/app/cloud/server/functions/userLogout.ts +++ b/apps/meteor/app/cloud/server/functions/userLogout.ts @@ -1,10 +1,10 @@ import { Users } from '@rocket.chat/models'; import { serverFetch as fetch } from '@rocket.chat/server-fetch'; -import { SystemLogger } from '../../../../server/lib/logger/system'; -import { settings } from '../../../settings/server'; import { retrieveRegistrationStatus } from './retrieveRegistrationStatus'; import { userLoggedOut } from './userLoggedOut'; +import { SystemLogger } from '../../../../server/lib/logger/system'; +import { settings } from '../../../settings/server'; export async function userLogout(userId: string): Promise { const { workspaceRegistered } = await retrieveRegistrationStatus(); diff --git a/apps/meteor/app/cloud/server/index.ts b/apps/meteor/app/cloud/server/index.ts index 6a82c16331c03..95c987610351f 100644 --- a/apps/meteor/app/cloud/server/index.ts +++ b/apps/meteor/app/cloud/server/index.ts @@ -1,12 +1,12 @@ import { cronJobs } from '@rocket.chat/cron'; import { Meteor } from 'meteor/meteor'; -import { SystemLogger } from '../../../server/lib/logger/system'; import { connectWorkspace } from './functions/connectWorkspace'; import { CloudWorkspaceAccessTokenEmptyError, getWorkspaceAccessToken } from './functions/getWorkspaceAccessToken'; import { getWorkspaceAccessTokenWithScope } from './functions/getWorkspaceAccessTokenWithScope'; import { retrieveRegistrationStatus } from './functions/retrieveRegistrationStatus'; import { syncWorkspace } from './functions/syncWorkspace'; +import { SystemLogger } from '../../../server/lib/logger/system'; import './methods'; const licenseCronName = 'Cloud Workspace Sync'; diff --git a/apps/meteor/app/cloud/server/methods.ts b/apps/meteor/app/cloud/server/methods.ts index 29daefe0d58ca..c132dbb1a48c2 100644 --- a/apps/meteor/app/cloud/server/methods.ts +++ b/apps/meteor/app/cloud/server/methods.ts @@ -2,7 +2,6 @@ import type { ServerMethods } from '@rocket.chat/ddp-client'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; -import { hasPermissionAsync } from '../../authorization/server/functions/hasPermission'; import { buildWorkspaceRegistrationData } from './functions/buildRegistrationData'; import { checkUserHasCloudLogin } from './functions/checkUserHasCloudLogin'; import { connectWorkspace } from './functions/connectWorkspace'; @@ -12,6 +11,7 @@ import { retrieveRegistrationStatus } from './functions/retrieveRegistrationStat import { startRegisterWorkspace } from './functions/startRegisterWorkspace'; import { syncWorkspace } from './functions/syncWorkspace'; import { userLogout } from './functions/userLogout'; +import { hasPermissionAsync } from '../../authorization/server/functions/hasPermission'; declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention diff --git a/apps/meteor/app/crowd/server/crowd.ts b/apps/meteor/app/crowd/server/crowd.ts index 70f54dd7b7261..3219a851c8c42 100644 --- a/apps/meteor/app/crowd/server/crowd.ts +++ b/apps/meteor/app/crowd/server/crowd.ts @@ -6,13 +6,13 @@ import AtlassianCrowd from 'atlassian-crowd-patched'; import { Accounts } from 'meteor/accounts-base'; import { Meteor } from 'meteor/meteor'; +import { logger } from './logger'; import { crowdIntervalValuesToCronMap } from '../../../server/settings/crowd'; import { deleteUser } from '../../lib/server/functions/deleteUser'; import { _setRealName } from '../../lib/server/functions/setRealName'; import { setUserActiveStatus } from '../../lib/server/functions/setUserActiveStatus'; import { notifyOnUserChange, notifyOnUserChangeById, notifyOnUserChangeAsync } from '../../lib/server/lib/notifyListener'; import { settings } from '../../settings/server'; -import { logger } from './logger'; type CrowdUser = Pick & { crowd: Record; crowd_username: string }; diff --git a/apps/meteor/app/crowd/server/methods.ts b/apps/meteor/app/crowd/server/methods.ts index 48faa2fcbcabc..c659afc4fbf36 100644 --- a/apps/meteor/app/crowd/server/methods.ts +++ b/apps/meteor/app/crowd/server/methods.ts @@ -2,10 +2,10 @@ import type { ServerMethods } from '@rocket.chat/ddp-client'; import type { TranslationKey } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; -import { hasPermissionAsync } from '../../authorization/server/functions/hasPermission'; -import { settings } from '../../settings/server'; import { CROWD } from './crowd'; import { logger } from './logger'; +import { hasPermissionAsync } from '../../authorization/server/functions/hasPermission'; +import { settings } from '../../settings/server'; declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention diff --git a/apps/meteor/app/custom-oauth/server/custom_oauth_server.js b/apps/meteor/app/custom-oauth/server/custom_oauth_server.js index a546a7c527eb0..c45f3619c8aac 100644 --- a/apps/meteor/app/custom-oauth/server/custom_oauth_server.js +++ b/apps/meteor/app/custom-oauth/server/custom_oauth_server.js @@ -9,12 +9,12 @@ import { OAuth } from 'meteor/oauth'; import { ServiceConfiguration } from 'meteor/service-configuration'; import _ from 'underscore'; +import { normalizers, fromTemplate, renameInvalidProperties } from './transform_helpers'; import { callbacks } from '../../../lib/callbacks'; import { isURL } from '../../../lib/utils/isURL'; import { notifyOnUserChange } from '../../lib/server/lib/notifyListener'; import { registerAccessTokenService } from '../../lib/server/oauth/oauth'; import { settings } from '../../settings/server'; -import { normalizers, fromTemplate, renameInvalidProperties } from './transform_helpers'; const logger = new Logger('CustomOAuth'); diff --git a/apps/meteor/app/custom-sounds/server/methods/uploadCustomSound.ts b/apps/meteor/app/custom-sounds/server/methods/uploadCustomSound.ts index f955f373ed4d4..64286bb71d86a 100644 --- a/apps/meteor/app/custom-sounds/server/methods/uploadCustomSound.ts +++ b/apps/meteor/app/custom-sounds/server/methods/uploadCustomSound.ts @@ -3,10 +3,10 @@ import type { RequiredField } from '@rocket.chat/core-typings'; import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; +import type { ICustomSoundData } from './insertOrUpdateSound'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; import { RocketChatFile } from '../../../file/server'; import { RocketChatFileCustomSoundsInstance } from '../startup/custom-sounds'; -import type { ICustomSoundData } from './insertOrUpdateSound'; declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention diff --git a/apps/meteor/app/discussion/server/methods/createDiscussion.ts b/apps/meteor/app/discussion/server/methods/createDiscussion.ts index f2b4533489d89..c4b8fb8e9a2ed 100644 --- a/apps/meteor/app/discussion/server/methods/createDiscussion.ts +++ b/apps/meteor/app/discussion/server/methods/createDiscussion.ts @@ -3,6 +3,7 @@ import type { IMessage, IRoom, IUser, MessageAttachmentDefault } from '@rocket.c import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Messages, Rooms, Users } from '@rocket.chat/models'; import { Random } from '@rocket.chat/random'; +import { check, Match } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; import { i18n } from '../../../../server/lib/i18n'; @@ -246,6 +247,13 @@ Meteor.methods({ * @param {boolean} encrypted - if the discussion's e2e encryption should be enabled. */ async createDiscussion({ prid, pmid, t_name: discussionName, reply, users, encrypted }: CreateDiscussionProperties) { + check(prid, Match.Maybe(String)); + check(pmid, Match.Maybe(String)); + check(reply, Match.Maybe(String)); + check(discussionName, String); + check(users, [String]); + check(encrypted, Match.Maybe(Boolean)); + const uid = Meteor.userId(); if (!uid) { throw new Meteor.Error('error-invalid-user', 'Invalid user', { diff --git a/apps/meteor/app/dolphin/client/index.ts b/apps/meteor/app/dolphin/client/index.ts index 0cc16f78319de..cf327e4971bb2 100644 --- a/apps/meteor/app/dolphin/client/index.ts +++ b/apps/meteor/app/dolphin/client/index.ts @@ -1,2 +1 @@ import './lib'; -import './login-button.css'; diff --git a/apps/meteor/app/dolphin/client/login-button.css b/apps/meteor/app/dolphin/client/login-button.css deleted file mode 100644 index b511270b27f1f..0000000000000 --- a/apps/meteor/app/dolphin/client/login-button.css +++ /dev/null @@ -1,16 +0,0 @@ -.icon-dolphin { - display: inline-block; - - width: 30px; - height: 20px; - - vertical-align: middle; - - background-image: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNDMwIDQzMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4NCjxnIGlkPSJzaWduLWluIiB0cmFuc2Zvcm09Im1hdHJpeCgwLjUgMCAwIDAuNSAwIDApIj4NCjxwYXRoIGZpbGw9IiNmZmZmZmYiIGQ9Ik02NjAuNjcyIDUwMC4wMzJxMCAxNC41MDggLTEwLjYwMiAyNS4xMWwtMzAzLjU1MiAzMDMuNTUycS0xMC42MDIgMTAuNjAyIC0yNS4xMSAxMC42MDJ0LTI1LjExIC0xMC42MDIgLTEwLjYwMiAtMjUuMTF2LTE2MC43MDRoLTI0OS45ODRxLTE0LjUwOCAwIC0yNS4xMSAtMTAuNjAydC0xMC42MDIgLTI1LjExdi0yMTQuMjcycTAgLTE0LjUwOCAxMC42MDIgLTI1LjExdDI1LjExIC0xMC42MDJoMjQ5Ljk4NHYtMTYwLjcwNHEwIC0xNC41MDggMTAuNjAyIC0yNS4xMXQyNS4xMSAtMTAuNjAyIDI1LjExIDEwLjYwMmwzMDMuNTUyIDMwMy41NTJxMTAuNjAyIDEwLjYwMiAxMC42MDIgMjUuMTF6bTE5Ni40MTYgLTE5Ni40MTZ2MzkyLjgzMnEwIDY2LjQwMiAtNDcuMTUxIDExMy41NTN0LTExMy41NTMgNDcuMTUxaC0xNzguNTZxLTcuMjU0IDAgLTEyLjU1NSAtNS4zMDF0LTUuMzAxIC0xMi41NTVxMCAtMi4yMzIgLS41NTggLTExLjE2dC0uMjc5IC0xNC43ODcgMS42NzQgLTEzLjExMyA1LjU4IC0xMC44ODEgMTEuNDM5IC0zLjYyN2gxNzguNTZxMzYuODI4IDAgNjMuMDU0IC0yNi4yMjZ0MjYuMjI2IC02My4wNTR2LTM5Mi44MzJxMCAtMzYuODI4IC0yNi4yMjYgLTYzLjA1NHQtNjMuMDU0IC0yNi4yMjZoLTE3NC4wOTZ0LTYuNDE3IC0uNTU4IC02LjQxNyAtMS42NzQgLTQuNDY0IC0zLjA2OSAtMy45MDYgLTUuMDIyIC0xLjExNiAtNy41MzNxMCAtMi4yMzIgLS41NTggLTExLjE2dC0uMjc5IC0xNC43ODcgMS42NzQgLTEzLjExMyA1LjU4IC0xMC44ODEgMTEuNDM5IC0zLjYyN2gxNzguNTZxNjYuNDAyIDAgMTEzLjU1MyA0Ny4xNTF0NDcuMTUxIDExMy41NTN6Ii8+DQo8L2c+DQo8L3N2Zz4=); - background-repeat: no-repeat; -} - -.icon-dolphin ~ .icon-spin, -.icon-dolphin ~ span { - vertical-align: middle; -} diff --git a/apps/meteor/app/drupal/client/index.ts b/apps/meteor/app/drupal/client/index.ts index 0cc16f78319de..cf327e4971bb2 100644 --- a/apps/meteor/app/drupal/client/index.ts +++ b/apps/meteor/app/drupal/client/index.ts @@ -1,2 +1 @@ import './lib'; -import './login-button.css'; diff --git a/apps/meteor/app/drupal/client/login-button.css b/apps/meteor/app/drupal/client/login-button.css deleted file mode 100644 index 2cda29b8c62e5..0000000000000 --- a/apps/meteor/app/drupal/client/login-button.css +++ /dev/null @@ -1,13 +0,0 @@ -.icon-drupal.service-icon { - display: inline-block; - - width: 21px; - height: 28px; - - background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAcCAYAAACOGPReAAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAP8A/wD/oL2nkwAAAcNJREFUSMetlbFrFFEQh7/dJnhpDHcx6SyiRLhLkUKDsRZB8S9IWi2Syj8iVooQ0FLBNlqJRpNO8Br7FLkoRDBooQHhNCr6WTjB48zd7d7uNI+d+c333pt9bx5kNPVGVm1WYF39rTbKhD7zr62XBVwI4MsYF4sCZ9S2uq6mMbbVmWGBx9WW+kGdCN+J+G6pY3mBo2pT/ape6IrNx2qb6mhW4Ii6qf5Ur/TQXI74pjoyCJioa3F8FgdoF0K3pib9hLfiDy9l3NVS6G/3EiyH4GbO+q9E3nJ3oKF+Vx/33Urvkj2K/EZn4JW6l/uY/MsfU9+rzUPHXCz/+jDADvC14Myhrqpf1EpB6LHgrCbqa+BzkiSXikAD/ByopcAUsFUUGLYFTKVABWiXBG0DlRTYB8ZLgo4D+ynQAuolQevAdgq8AM6rk0Vo0R7ngQ3UU+qvvNfzCOhKcE4fOu6r39TpIYHT0XsfdDon45puq7WcwFrk7f1XQvVsdPS3Wd+geMPeRN65XqJZdVf9od5Tz/TZ7t3Q7aqzg2avqnfUg2gQO+pT9WGMO+E/CF21m5H0gU8AV4GLwEmgCnwC3gEbwJMkST4elfsHJbIReGbv9uUAAAAASUVORK5CYII=); - background-repeat: no-repeat; -} - -.button.external-login.drupal { - background-color: #0f85b6; -} diff --git a/apps/meteor/app/e2e/client/rocketchat.e2e.room.ts b/apps/meteor/app/e2e/client/rocketchat.e2e.room.ts index ff1841a7ef86e..dc7efb60dc144 100644 --- a/apps/meteor/app/e2e/client/rocketchat.e2e.room.ts +++ b/apps/meteor/app/e2e/client/rocketchat.e2e.room.ts @@ -2,12 +2,6 @@ import { Base64 } from '@rocket.chat/base64'; import { Emitter } from '@rocket.chat/emitter'; import EJSON from 'ejson'; -import { RoomManager } from '../../../client/lib/RoomManager'; -import { roomCoordinator } from '../../../client/lib/rooms/roomCoordinator'; -import { RoomSettingsEnum } from '../../../definition/IRoomTypeConfig'; -import { ChatRoom, Subscriptions, Messages } from '../../models/client'; -import { sdk } from '../../utils/client/lib/SDKClient'; -import { t } from '../../utils/lib/i18n'; import { E2ERoomState } from './E2ERoomState'; import { toString, @@ -30,6 +24,12 @@ import { } from './helper'; import { log, logError } from './logger'; import { e2e } from './rocketchat.e2e'; +import { RoomManager } from '../../../client/lib/RoomManager'; +import { roomCoordinator } from '../../../client/lib/rooms/roomCoordinator'; +import { RoomSettingsEnum } from '../../../definition/IRoomTypeConfig'; +import { Rooms, Subscriptions, Messages } from '../../models/client'; +import { sdk } from '../../utils/client/lib/SDKClient'; +import { t } from '../../utils/lib/i18n'; const KEY_ID = Symbol('keyID'); const PAUSED = Symbol('PAUSED'); @@ -325,7 +325,7 @@ export class E2ERoom extends Emitter { } try { - const room = ChatRoom.findOne({ _id: this.roomId })!; + const room = Rooms.findOne({ _id: this.roomId })!; // Only room creator can set keys for room if (!room.e2eKeyId && this.userShouldCreateKeys(room)) { this.setState(E2ERoomState.CREATING_KEYS); diff --git a/apps/meteor/app/e2e/client/rocketchat.e2e.ts b/apps/meteor/app/e2e/client/rocketchat.e2e.ts index 824afc3aa2d5c..38df2ba1bc34a 100644 --- a/apps/meteor/app/e2e/client/rocketchat.e2e.ts +++ b/apps/meteor/app/e2e/client/rocketchat.e2e.ts @@ -10,22 +10,6 @@ import { Accounts } from 'meteor/accounts-base'; import { Meteor } from 'meteor/meteor'; import { Tracker } from 'meteor/tracker'; -import * as banners from '../../../client/lib/banners'; -import type { LegacyBannerPayload } from '../../../client/lib/banners'; -import { imperativeModal } from '../../../client/lib/imperativeModal'; -import { dispatchToastMessage } from '../../../client/lib/toast'; -import { mapMessageFromApi } from '../../../client/lib/utils/mapMessageFromApi'; -import { waitUntilFind } from '../../../client/lib/utils/waitUntilFind'; -import EnterE2EPasswordModal from '../../../client/views/e2e/EnterE2EPasswordModal'; -import SaveE2EPasswordModal from '../../../client/views/e2e/SaveE2EPasswordModal'; -import { createQuoteAttachment } from '../../../lib/createQuoteAttachment'; -import { getMessageUrlRegex } from '../../../lib/getMessageUrlRegex'; -import { isTruthy } from '../../../lib/isTruthy'; -import { ChatRoom, Subscriptions, Messages } from '../../models/client'; -import { settings } from '../../settings/client'; -import { getUserAvatarURL } from '../../utils/client'; -import { sdk } from '../../utils/client/lib/SDKClient'; -import { t } from '../../utils/lib/i18n'; import { E2EEState } from './E2EEState'; import { toString, @@ -43,6 +27,22 @@ import { } from './helper'; import { log, logError } from './logger'; import { E2ERoom } from './rocketchat.e2e.room'; +import * as banners from '../../../client/lib/banners'; +import type { LegacyBannerPayload } from '../../../client/lib/banners'; +import { imperativeModal } from '../../../client/lib/imperativeModal'; +import { dispatchToastMessage } from '../../../client/lib/toast'; +import { mapMessageFromApi } from '../../../client/lib/utils/mapMessageFromApi'; +import { waitUntilFind } from '../../../client/lib/utils/waitUntilFind'; +import EnterE2EPasswordModal from '../../../client/views/e2e/EnterE2EPasswordModal'; +import SaveE2EPasswordModal from '../../../client/views/e2e/SaveE2EPasswordModal'; +import { createQuoteAttachment } from '../../../lib/createQuoteAttachment'; +import { getMessageUrlRegex } from '../../../lib/getMessageUrlRegex'; +import { isTruthy } from '../../../lib/isTruthy'; +import { Rooms, Subscriptions, Messages } from '../../models/client'; +import { settings } from '../../settings/client'; +import { getUserAvatarURL } from '../../utils/client'; +import { sdk } from '../../utils/client/lib/SDKClient'; +import { t } from '../../utils/lib/i18n'; import './events'; @@ -254,7 +254,7 @@ class E2E extends Emitter { } async getInstanceByRoomId(rid: IRoom['_id']): Promise { - const room = await waitUntilFind(() => ChatRoom.findOne({ _id: rid })); + const room = await waitUntilFind(() => Rooms.findOne({ _id: rid })); if (room.t !== 'd' && room.t !== 'p') { return null; @@ -835,7 +835,7 @@ class E2E extends Emitter { } const keyDistribution = async () => { - const roomIds = ChatRoom.find({ + const roomIds = Rooms.find({ 'usersWaitingForE2EKeys': { $exists: true }, 'usersWaitingForE2EKeys.userId': { $ne: Meteor.userId() }, }).map((room) => room._id); diff --git a/apps/meteor/app/emoji-custom/client/lib/emojiCustom.ts b/apps/meteor/app/emoji-custom/client/lib/emojiCustom.ts index 11b5359731b1c..8b24cd0c29c76 100644 --- a/apps/meteor/app/emoji-custom/client/lib/emojiCustom.ts +++ b/apps/meteor/app/emoji-custom/client/lib/emojiCustom.ts @@ -1,7 +1,6 @@ import type { IEmoji } from '@rocket.chat/core-typings'; import { escapeRegExp } from '@rocket.chat/string-helpers'; import { Meteor } from 'meteor/meteor'; -import { Session } from 'meteor/session'; import { onLoggedIn } from '../../../../client/lib/loggedIn'; import { emoji, removeFromRecent, replaceEmojiInRecent } from '../../../emoji/client'; @@ -18,16 +17,12 @@ const isSetNotNull = (fn: () => unknown) => { return value !== null && value !== undefined; }; -const getEmojiUrlFromName = (name: string, extension: string) => { - if (name == null) { +const getEmojiUrlFromName = (name: string, extension: string, etag?: string) => { + if (!name) { return; } - const key = `emoji_random_${name}` as const; - - const random = (Session as unknown as { keys: Record }).keys[key] ?? 0; - - return getURL(`/emoji-custom/${encodeURIComponent(name)}.${extension}?_dc=${random}`); + return getURL(`/emoji-custom/${encodeURIComponent(name)}.${extension}${etag ? `?etag=${etag}` : ''}`); }; export const deleteEmojiCustom = (emojiData: IEmoji) => { @@ -126,6 +121,7 @@ const customRender = (html: string) => { return `${shortname}`; }); diff --git a/apps/meteor/app/emoji-custom/server/lib/insertOrUpdateEmoji.ts b/apps/meteor/app/emoji-custom/server/lib/insertOrUpdateEmoji.ts index 7e838baee9b03..85a9648cf6d98 100644 --- a/apps/meteor/app/emoji-custom/server/lib/insertOrUpdateEmoji.ts +++ b/apps/meteor/app/emoji-custom/server/lib/insertOrUpdateEmoji.ts @@ -2,16 +2,15 @@ import { api } from '@rocket.chat/core-services'; import { EmojiCustom } from '@rocket.chat/models'; import limax from 'limax'; import { Meteor } from 'meteor/meteor'; -import _ from 'underscore'; import { trim } from '../../../../lib/utils/stringUtils'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; import { RocketChatFileEmojiCustomInstance } from '../startup/emoji-custom'; -type EmojiData = { +export type EmojiData = { _id?: string; name: string; - aliases: string; + aliases?: string; extension: string; previousName?: string; previousExtension?: string; @@ -33,7 +32,6 @@ export async function insertOrUpdateEmoji(userId: string | null, emojiData: Emoj } emojiData.name = limax(emojiData.name, { replacement: '_' }); - emojiData.aliases = limax(emojiData.aliases, { replacement: '_' }); // allow all characters except colon, whitespace, comma, >, <, &, ", ', /, \, (, ) // more practical than allowing specific sets of characters; also allows foreign languages @@ -42,7 +40,7 @@ export async function insertOrUpdateEmoji(userId: string | null, emojiData: Emoj // silently strip colon; this allows for uploading :emojiname: as emojiname emojiData.name = emojiData.name.replace(/:/g, ''); - emojiData.aliases = emojiData.aliases.replace(/:/g, ''); + emojiData.aliases = emojiData.aliases?.replace(/:/g, ''); if (nameValidation.test(emojiData.name)) { throw new Meteor.Error('error-input-is-not-a-valid-field', `${emojiData.name} is not a valid name`, { @@ -61,7 +59,11 @@ export async function insertOrUpdateEmoji(userId: string | null, emojiData: Emoj field: 'Alias_Set', }); } - aliases = _.without(emojiData.aliases.split(/[\s,]/).filter(Boolean), emojiData.name); + aliases = emojiData.aliases + .split(/\s*,\s*/) + .filter(Boolean) + .map((alias) => limax(alias, { replacement: '_' })) + .filter((alias) => alias !== emojiData.name); } emojiData.extension = emojiData.extension === 'svg+xml' ? 'png' : emojiData.extension; @@ -119,7 +121,8 @@ export async function insertOrUpdateEmoji(userId: string | null, emojiData: Emoj const rs = await RocketChatFileEmojiCustomInstance.getFileWithReadStream( encodeURIComponent(`${emojiData.previousName}.${emojiData.previousExtension}`), ); - if (rs !== null) { + + if (rs) { await RocketChatFileEmojiCustomInstance.deleteFile(encodeURIComponent(`${emojiData.name}.${emojiData.extension}`)); const ws = RocketChatFileEmojiCustomInstance.createWriteStream( encodeURIComponent(`${emojiData.name}.${emojiData.previousExtension}`), diff --git a/apps/meteor/app/emoji-custom/server/lib/uploadEmojiCustom.ts b/apps/meteor/app/emoji-custom/server/lib/uploadEmojiCustom.ts index 07633eaa1a7da..cfa887c4a4415 100644 --- a/apps/meteor/app/emoji-custom/server/lib/uploadEmojiCustom.ts +++ b/apps/meteor/app/emoji-custom/server/lib/uploadEmojiCustom.ts @@ -1,8 +1,11 @@ import { api, Media } from '@rocket.chat/core-services'; +import { EmojiCustom } from '@rocket.chat/models'; +import { Random } from '@rocket.chat/random'; import limax from 'limax'; import { Meteor } from 'meteor/meteor'; import sharp from 'sharp'; +import type { EmojiData } from './insertOrUpdateEmoji'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; import { RocketChatFile } from '../../../file/server'; import { RocketChatFileEmojiCustomInstance } from '../startup/emoji-custom'; @@ -15,17 +18,14 @@ const getFile = async (file: Buffer, extension: string) => { return sharp(file).png().toBuffer(); }; -type EmojiData = { - _id?: string; - name: string; - aliases?: string | string[]; - extension: string; - previousName?: string; - previousExtension?: string; - newFile?: boolean; -}; +export type EmojiDataWithAliases = Omit & { aliases?: string | string[] }; -export async function uploadEmojiCustom(userId: string | null, binaryContent: string, contentType: string, emojiData: EmojiData) { +export async function uploadEmojiCustom( + userId: string | null, + binaryContent: string, + contentType: string, + emojiData: EmojiDataWithAliases, +) { return uploadEmojiCustomWithBuffer(userId, Buffer.from(binaryContent, 'binary'), contentType, emojiData); } @@ -33,7 +33,7 @@ export async function uploadEmojiCustomWithBuffer( userId: string | null, buffer: Buffer, contentType: string, - emojiData: EmojiData, + emojiData: EmojiDataWithAliases, ): Promise { // technically, since this method doesnt have any datatype validations, users can // upload videos as emojis. The FE won't play them, but they will waste space for sure. @@ -41,9 +41,12 @@ export async function uploadEmojiCustomWithBuffer( throw new Meteor.Error('not_authorized'); } + if (!Array.isArray(emojiData.aliases)) { + // delete aliases for notification purposes. here, it is a string or undefined rather than an array + delete emojiData.aliases; + } + emojiData.name = limax(emojiData.name, { replacement: '_' }); - // delete aliases for notification purposes. here, it is a string rather than an array - delete emojiData.aliases; const file = await getFile(buffer, emojiData.extension); emojiData.extension = emojiData.extension === 'svg+xml' ? 'png' : emojiData.extension; @@ -67,8 +70,10 @@ export async function uploadEmojiCustomWithBuffer( encodeURIComponent(`${emojiData.name}.${emojiData.extension}`), contentType, ); - ws.on('end', () => { - setTimeout(() => api.broadcast('emoji.updateCustom', emojiData), 500); + ws.on('end', async () => { + const etag = Random.hexString(6); + await EmojiCustom.setETagByName(emojiData.name, etag); + setTimeout(() => api.broadcast('emoji.updateCustom', { ...emojiData, etag }), 500); resolve(); }); diff --git a/apps/meteor/app/emoji/client/emojiParser.ts b/apps/meteor/app/emoji/client/emojiParser.ts index 08ec99b069586..ff4a010bed5ce 100644 --- a/apps/meteor/app/emoji/client/emojiParser.ts +++ b/apps/meteor/app/emoji/client/emojiParser.ts @@ -1,5 +1,5 @@ -import { isIE11 } from '../../../client/lib/utils/isIE11'; import { emoji } from './lib'; +import { isIE11 } from '../../../client/lib/utils/isIE11'; /** * emojiParser is a function that will replace emojis diff --git a/apps/meteor/app/emoji/lib/rocketchat.ts b/apps/meteor/app/emoji/lib/rocketchat.ts index f5d33cce3de08..1c5b515407ed8 100644 --- a/apps/meteor/app/emoji/lib/rocketchat.ts +++ b/apps/meteor/app/emoji/lib/rocketchat.ts @@ -31,6 +31,7 @@ export type EmojiPackages = { aliases?: string[]; aliasOf?: undefined; extension?: string; + etag?: string; } | { emojiPackage: string; @@ -38,6 +39,7 @@ export type EmojiPackages = { extension?: undefined; aliases?: undefined; shortnames?: undefined; + etag?: string; }; }; }; diff --git a/apps/meteor/app/federation/server/endpoints/dispatch.js b/apps/meteor/app/federation/server/endpoints/dispatch.js index 4f2a197b25ee8..d80f74bf18d35 100644 --- a/apps/meteor/app/federation/server/endpoints/dispatch.js +++ b/apps/meteor/app/federation/server/endpoints/dispatch.js @@ -6,6 +6,7 @@ import EJSON from 'ejson'; import { API } from '../../../api/server'; import { FileUpload } from '../../../file-upload/server'; import { deleteRoom } from '../../../lib/server/functions/deleteRoom'; +import { apiDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger'; import { notifyOnMessageChange, notifyOnRoomChanged, @@ -551,6 +552,18 @@ API.v1.addRoute( { authRequired: false, rateLimiterOptions: { numRequestsAllowed: 30, intervalTimeInMS: 1000 } }, { async post() { + /* + The legacy federation has been deprecated for over a year + and no longer receives any updates. This feature also has + relevant security issues that weren't addressed. + Workspaces should migrate to the newer matrix federation. + */ + apiDeprecationLogger.endpoint(this.request.route, '8.0.0', this.response, 'Use Matrix Federation instead.'); + + if (!process.env.ENABLE_INSECURE_LEGACY_FEDERATION) { + return API.v1.failure('Deprecated. ENABLE_INSECURE_LEGACY_FEDERATION environment variable is needed to enable it.'); + } + if (!isFederationEnabled()) { return API.v1.failure('Federation not enabled'); } diff --git a/apps/meteor/app/federation/server/endpoints/requestFromLatest.js b/apps/meteor/app/federation/server/endpoints/requestFromLatest.js index b45e8944e466b..8dca41d3f4426 100644 --- a/apps/meteor/app/federation/server/endpoints/requestFromLatest.js +++ b/apps/meteor/app/federation/server/endpoints/requestFromLatest.js @@ -2,6 +2,7 @@ import { FederationRoomEvents } from '@rocket.chat/models'; import EJSON from 'ejson'; import { API } from '../../../api/server'; +import { apiDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger'; import { dispatchEvents } from '../handler'; import { decryptIfNeeded } from '../lib/crypt'; import { isFederationEnabled } from '../lib/isFederationEnabled'; @@ -12,6 +13,18 @@ API.v1.addRoute( { authRequired: false }, { async post() { + /* + The legacy federation has been deprecated for over a year + and no longer receives any updates. This feature also has + relevant security issues that weren't addressed. + Workspaces should migrate to the newer matrix federation. + */ + apiDeprecationLogger.endpoint(this.request.route, '8.0.0', this.response, 'Use Matrix Federation instead.'); + + if (!process.env.ENABLE_INSECURE_LEGACY_FEDERATION) { + return API.v1.failure('Deprecated. ENABLE_INSECURE_LEGACY_FEDERATION environment variable is needed to enable it.'); + } + if (!isFederationEnabled()) { return API.v1.failure('Federation not enabled'); } diff --git a/apps/meteor/app/federation/server/endpoints/uploads.js b/apps/meteor/app/federation/server/endpoints/uploads.js index da5740f95f16b..10c513b3741ca 100644 --- a/apps/meteor/app/federation/server/endpoints/uploads.js +++ b/apps/meteor/app/federation/server/endpoints/uploads.js @@ -2,6 +2,7 @@ import { Uploads } from '@rocket.chat/models'; import { API } from '../../../api/server'; import { FileUpload } from '../../../file-upload/server'; +import { apiDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger'; import { isFederationEnabled } from '../lib/isFederationEnabled'; API.v1.addRoute( @@ -9,6 +10,18 @@ API.v1.addRoute( { authRequired: false }, { async get() { + /* + The legacy federation has been deprecated for over a year + and no longer receives any updates. This feature also has + relevant security issues that weren't addressed. + Workspaces should migrate to the newer matrix federation. + */ + apiDeprecationLogger.endpoint(this.request.route, '8.0.0', this.response, 'Use Matrix Federation instead.'); + + if (!process.env.ENABLE_INSECURE_LEGACY_FEDERATION) { + return API.v1.failure('Deprecated. ENABLE_INSECURE_LEGACY_FEDERATION environment variable is needed to enable it.'); + } + if (!isFederationEnabled()) { return API.v1.failure('Federation not enabled'); } diff --git a/apps/meteor/app/federation/server/endpoints/users.js b/apps/meteor/app/federation/server/endpoints/users.js index 0d9a4ff4b0ced..fba9b1642e8f6 100644 --- a/apps/meteor/app/federation/server/endpoints/users.js +++ b/apps/meteor/app/federation/server/endpoints/users.js @@ -1,6 +1,7 @@ import { Users } from '@rocket.chat/models'; import { API } from '../../../api/server'; +import { apiDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger'; import { isFederationEnabled } from '../lib/isFederationEnabled'; import { serverLogger } from '../lib/logger'; import { normalizers } from '../normalizers'; @@ -12,6 +13,18 @@ API.v1.addRoute( { authRequired: false }, { async get() { + /* + The legacy federation has been deprecated for over a year + and no longer receives any updates. This feature also has + relevant security issues that weren't addressed. + Workspaces should migrate to the newer matrix federation. + */ + apiDeprecationLogger.endpoint(this.request.route, '8.0.0', this.response, 'Use Matrix Federation instead.'); + + if (!process.env.ENABLE_INSECURE_LEGACY_FEDERATION) { + return API.v1.failure('Deprecated. ENABLE_INSECURE_LEGACY_FEDERATION environment variable is needed to enable it.'); + } + if (!isFederationEnabled()) { return API.v1.failure('Federation not enabled'); } @@ -39,6 +52,18 @@ API.v1.addRoute( { authRequired: false }, { async get() { + /* + The legacy federation has been deprecated for over a year + and no longer receives any updates. This feature also has + relevant security issues that weren't addressed. + Workspaces should migrate to the newer matrix federation. + */ + apiDeprecationLogger.endpoint(this.request.route, '8.0.0', this.response, 'Use Matrix Federation instead.'); + + if (!process.env.ENABLE_INSECURE_LEGACY_FEDERATION) { + return API.v1.failure('Deprecated. ENABLE_INSECURE_LEGACY_FEDERATION environment variable is needed to enable it.'); + } + if (!isFederationEnabled()) { return API.v1.failure('Federation not enabled'); } diff --git a/apps/meteor/app/federation/server/lib/dns.js b/apps/meteor/app/federation/server/lib/dns.js index f8ef27e1dcf67..83ce0cc70349f 100644 --- a/apps/meteor/app/federation/server/lib/dns.js +++ b/apps/meteor/app/federation/server/lib/dns.js @@ -3,10 +3,10 @@ import util from 'util'; import mem from 'mem'; -import * as federationErrors from '../functions/errors'; import { federationRequest } from './http'; import { isFederationEnabled } from './isFederationEnabled'; import { dnsLogger } from './logger'; +import * as federationErrors from '../functions/errors'; const dnsResolveSRV = util.promisify(dnsResolver.resolveSrv); const dnsResolveTXT = util.promisify(dnsResolver.resolveTxt); diff --git a/apps/meteor/app/file-upload/server/config/AmazonS3.ts b/apps/meteor/app/file-upload/server/config/AmazonS3.ts index 0f551d3b90d1c..48b7a9b850a99 100644 --- a/apps/meteor/app/file-upload/server/config/AmazonS3.ts +++ b/apps/meteor/app/file-upload/server/config/AmazonS3.ts @@ -3,11 +3,11 @@ import https from 'https'; import _ from 'underscore'; +import { forceDownload } from './helper'; import { settings } from '../../../settings/server'; import type { S3Options } from '../../ufs/AmazonS3/server'; import { FileUploadClass, FileUpload } from '../lib/FileUpload'; import '../../ufs/AmazonS3/server'; -import { forceDownload } from './helper'; const get: FileUploadClass['get'] = async function (this: FileUploadClass, file, req, res) { const forcedDownload = forceDownload(req); diff --git a/apps/meteor/app/file-upload/server/config/FileSystem.ts b/apps/meteor/app/file-upload/server/config/FileSystem.ts index 75fdb5afc8aeb..c39cf5807d602 100644 --- a/apps/meteor/app/file-upload/server/config/FileSystem.ts +++ b/apps/meteor/app/file-upload/server/config/FileSystem.ts @@ -1,10 +1,10 @@ import fsp from 'fs/promises'; +import { getContentDisposition } from './helper'; import { UploadFS } from '../../../../server/ufs'; import { settings } from '../../../settings/server'; import { FileUploadClass, FileUpload } from '../lib/FileUpload'; import { getFileRange, setRangeHeaders } from '../lib/ranges'; -import { getContentDisposition } from './helper'; const FileSystemUploads = new FileUploadClass({ name: 'FileSystem:Uploads', diff --git a/apps/meteor/app/file-upload/server/config/GoogleStorage.ts b/apps/meteor/app/file-upload/server/config/GoogleStorage.ts index 8fb901b5a1235..ccd94d533b62c 100644 --- a/apps/meteor/app/file-upload/server/config/GoogleStorage.ts +++ b/apps/meteor/app/file-upload/server/config/GoogleStorage.ts @@ -3,10 +3,10 @@ import https from 'https'; import _ from 'underscore'; +import { forceDownload } from './helper'; import { settings } from '../../../settings/server'; import { FileUploadClass, FileUpload } from '../lib/FileUpload'; import '../../ufs/GoogleStorage/server'; -import { forceDownload } from './helper'; const get: FileUploadClass['get'] = async function (this: FileUploadClass, file, req, res) { const forcedDownload = forceDownload(req); diff --git a/apps/meteor/app/file-upload/server/config/GridFS.ts b/apps/meteor/app/file-upload/server/config/GridFS.ts index 3bb5f806f3a75..551569d4c58c4 100644 --- a/apps/meteor/app/file-upload/server/config/GridFS.ts +++ b/apps/meteor/app/file-upload/server/config/GridFS.ts @@ -6,10 +6,10 @@ import zlib from 'zlib'; import type { IUpload } from '@rocket.chat/core-typings'; import { Logger } from '@rocket.chat/logger'; +import { getContentDisposition } from './helper'; import { UploadFS } from '../../../../server/ufs'; import { FileUploadClass, FileUpload } from '../lib/FileUpload'; import { getFileRange, setRangeHeaders } from '../lib/ranges'; -import { getContentDisposition } from './helper'; const logger = new Logger('FileUpload'); diff --git a/apps/meteor/app/file-upload/server/lib/FileUpload.ts b/apps/meteor/app/file-upload/server/lib/FileUpload.ts index c7b82fe3e02c3..cffdfe6288f28 100644 --- a/apps/meteor/app/file-upload/server/lib/FileUpload.ts +++ b/apps/meteor/app/file-upload/server/lib/FileUpload.ts @@ -22,6 +22,7 @@ import sharp from 'sharp'; import type { WritableStreamBuffer } from 'stream-buffers'; import streamBuffers from 'stream-buffers'; +import { streamToBuffer } from './streamToBuffer'; import { i18n } from '../../../../server/lib/i18n'; import { SystemLogger } from '../../../../server/lib/logger/system'; import { roomCoordinator } from '../../../../server/lib/rooms/roomCoordinator'; @@ -33,7 +34,6 @@ import { settings } from '../../../settings/server'; import { mime } from '../../../utils/lib/mimeTypes'; import { isValidJWT, generateJWT } from '../../../utils/server/lib/JWTHelper'; import { fileUploadIsValidContentType } from '../../../utils/server/restrictions'; -import { streamToBuffer } from './streamToBuffer'; const cookie = new Cookies(); let maxFileSize = 0; diff --git a/apps/meteor/app/github-enterprise/client/github-enterprise-login-button.css b/apps/meteor/app/github-enterprise/client/github-enterprise-login-button.css deleted file mode 100644 index e7ba61d7be385..0000000000000 --- a/apps/meteor/app/github-enterprise/client/github-enterprise-login-button.css +++ /dev/null @@ -1,9 +0,0 @@ -.icon-github_enterprise::before { - height: 1em; - - content: ""; - - background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9wJGBYxHYxl31wAAAHpSURBVDjLpZI/aFNRFMZ/973bJqGRPopV4qNq/+SpTYnWRhCKilShg9BGcHOM+GfQoZuLk4iLgw4qZNBaHLuIdBNHl7Ta1qdNFI3SihnaNG1MpH3vuiQYQnwZvHCG893zffc751z4z6PX5T5gA1DAKnAaOAQEgAfAVeCpl+CeCrlRuEC6maO4h0A1wl4tPAHMqNUthvrDdHYY7A3t4rDVjeO6rBU2FaABM1WCrBNoi48Mi+nH9yj+KtPibAKwJXfQ5vcRG7soUnYmWEuQgAEIYBv4cGpoILI0Z4tyYYPegS6UguyijZQ6J45GSNmZHzUcJYD2ii2Ajv7efZ8WZ6ZwXFj79hXpayW4O0SL1Nl/8jzZlZ9dQLFS70pgvZKIyGD0yvu5eRmMnrk1PjI81ir1qBACTdPevXj95mVuNX8XKDQc/+T334bZZ104cvzYw2s3J3qAL5WXSsDbf61NNMBu+wOBs+VSyQ84Nfhg028ZGx3/qyy0lC7lgi7lghBitoon03lvB8l0/k7Wnk+8mny0cyXzEcfZxgwfZPTyRMHsOzAFXE9YhtNQIJnOx4FpJXT1eSkn2g0frqMoFrfoCXcqlCOAGwnLuO/l4JymcWl5uRxzXUKghBAiZ5r+WaV4lrCM555zqO+x2d0ftGmpiA/0k70AAAAASUVORK5CYII=); - background-repeat: no-repeat; - background-position: center center; -} diff --git a/apps/meteor/app/github-enterprise/client/index.ts b/apps/meteor/app/github-enterprise/client/index.ts index 7a032388cc0c8..cf327e4971bb2 100644 --- a/apps/meteor/app/github-enterprise/client/index.ts +++ b/apps/meteor/app/github-enterprise/client/index.ts @@ -1,2 +1 @@ import './lib'; -import './github-enterprise-login-button.css'; diff --git a/apps/meteor/app/gitlab/client/gitlab-login-button.css b/apps/meteor/app/gitlab/client/gitlab-login-button.css index c73a1ee23c91f..fa9d41b34e74e 100644 --- a/apps/meteor/app/gitlab/client/gitlab-login-button.css +++ b/apps/meteor/app/gitlab/client/gitlab-login-button.css @@ -1,3 +1,3 @@ #login-buttons-image-gitlab { - background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9wJGBYxHYxl31wAAAHpSURBVDjLpZI/aFNRFMZ/973bJqGRPopV4qNq/+SpTYnWRhCKilShg9BGcHOM+GfQoZuLk4iLgw4qZNBaHLuIdBNHl7Ta1qdNFI3SihnaNG1MpH3vuiQYQnwZvHCG893zffc751z4z6PX5T5gA1DAKnAaOAQEgAfAVeCpl+CeCrlRuEC6maO4h0A1wl4tPAHMqNUthvrDdHYY7A3t4rDVjeO6rBU2FaABM1WCrBNoi48Mi+nH9yj+KtPibAKwJXfQ5vcRG7soUnYmWEuQgAEIYBv4cGpoILI0Z4tyYYPegS6UguyijZQ6J45GSNmZHzUcJYD2ii2Ajv7efZ8WZ6ZwXFj79hXpayW4O0SL1Nl/8jzZlZ9dQLFS70pgvZKIyGD0yvu5eRmMnrk1PjI81ir1qBACTdPevXj95mVuNX8XKDQc/+T334bZZ104cvzYw2s3J3qAL5WXSsDbf61NNMBu+wOBs+VSyQ84Nfhg028ZGx3/qyy0lC7lgi7lghBitoon03lvB8l0/k7Wnk+8mny0cyXzEcfZxgwfZPTyRMHsOzAFXE9YhtNQIJnOx4FpJXT1eSkn2g0frqMoFrfoCXcqlCOAGwnLuO/l4JymcWl5uRxzXUKghBAiZ5r+WaV4lrCM555zqO+x2d0ftGmpiA/0k70AAAAASUVORK5CYII=); + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9wJGBYxHYxl31wAAAHpSURBVDjLpZI/aFNRFMZ/973bJqGRPopV4qNq/+SpTYnWRhCKilShg9BGcHOM+GfQoZuLk4iLgw4qZNBaHLuIdBNHl7Ta1qdNFI3SihnaNG1MpH3vuiQYQnwZvHCG893zffc751z4z6PX5T5gA1DAKnAaOAQEgAfAVeCpl+CeCrlRuEC6maO4h0A1wl4tPAHMqNUthvrDdHYY7A3t4rDVjeO6rBU2FaABM1WCrBNoi48Mi+nH9yj+KtPibAKwJXfQ5vcRG7soUnYmWEuQgAEIYBv4cGpoILI0Z4tyYYPegS6UguyijZQ6J45GSNmZHzUcJYD2ii2Ajv7efZ8WZ6ZwXFj79hXpayW4O0SL1Nl/8jzZlZ9dQLFS70pgvZKIyGD0yvu5eRmMnrk1PjI81ir1qBACTdPevXj95mVuNX8XKDQc/+T334bZZ104cvzYw2s3J3qAL5WXSsDbf61NNMBu+wOBs+VSyQ84Nfhg028ZGx3/qyy0lC7lgi7lghBitoon03lvB8l0/k7Wnk+8mny0cyXzEcfZxgwfZPTyRMHsOzAFXE9YhtNQIJnOx4FpJXT1eSkn2g0frqMoFrfoCXcqlCOAGwnLuO/l4JymcWl5uRxzXUKghBAiZ5r+WaV4lrCM555zqO+x2d0ftGmpiA/0k70AAAAASUVORK5CYII="); } diff --git a/apps/meteor/app/importer-csv/server/index.ts b/apps/meteor/app/importer-csv/server/index.ts index 2d913f740955c..f20c375ae9435 100644 --- a/apps/meteor/app/importer-csv/server/index.ts +++ b/apps/meteor/app/importer-csv/server/index.ts @@ -1,5 +1,5 @@ -import { Importers } from '../../importer/server'; import { CsvImporter } from './CsvImporter'; +import { Importers } from '../../importer/server'; Importers.add({ key: 'csv', diff --git a/apps/meteor/app/importer-pending-avatars/server/index.ts b/apps/meteor/app/importer-pending-avatars/server/index.ts index b69c6de8e7457..2710c06b9d15b 100644 --- a/apps/meteor/app/importer-pending-avatars/server/index.ts +++ b/apps/meteor/app/importer-pending-avatars/server/index.ts @@ -1,5 +1,5 @@ -import { Importers } from '../../importer/server'; import { PendingAvatarImporter } from './PendingAvatarImporter'; +import { Importers } from '../../importer/server'; Importers.add({ key: 'pending-avatars', diff --git a/apps/meteor/app/importer-pending-files/server/index.ts b/apps/meteor/app/importer-pending-files/server/index.ts index 24961551cdb52..e18b0de0a29e4 100644 --- a/apps/meteor/app/importer-pending-files/server/index.ts +++ b/apps/meteor/app/importer-pending-files/server/index.ts @@ -1,5 +1,5 @@ -import { Importers } from '../../importer/server'; import { PendingFileImporter } from './PendingFileImporter'; +import { Importers } from '../../importer/server'; Importers.add({ key: 'pending-files', diff --git a/apps/meteor/app/importer-slack-users/server/index.ts b/apps/meteor/app/importer-slack-users/server/index.ts index ab99ede8f9121..67b2dbdb319a2 100644 --- a/apps/meteor/app/importer-slack-users/server/index.ts +++ b/apps/meteor/app/importer-slack-users/server/index.ts @@ -1,5 +1,5 @@ -import { Importers } from '../../importer/server'; import { SlackUsersImporter } from './SlackUsersImporter'; +import { Importers } from '../../importer/server'; Importers.add({ key: 'slack-users', diff --git a/apps/meteor/app/importer-slack/server/index.ts b/apps/meteor/app/importer-slack/server/index.ts index b8040d77538a5..d32edde7271fb 100644 --- a/apps/meteor/app/importer-slack/server/index.ts +++ b/apps/meteor/app/importer-slack/server/index.ts @@ -1,5 +1,5 @@ -import { Importers } from '../../importer/server'; import { SlackImporter } from './SlackImporter'; +import { Importers } from '../../importer/server'; Importers.add({ key: 'slack', diff --git a/apps/meteor/app/importer/server/classes/Importer.ts b/apps/meteor/app/importer/server/classes/Importer.ts index 5f40ead0e1eaa..0eae9fd240400 100644 --- a/apps/meteor/app/importer/server/classes/Importer.ts +++ b/apps/meteor/app/importer/server/classes/Importer.ts @@ -13,14 +13,14 @@ import AdmZip from 'adm-zip'; import type { MatchKeysAndValues, MongoServerError } from 'mongodb'; import { Selection, SelectionChannel, SelectionUser } from '..'; -import { notifyOnSettingChangedById } from '../../../lib/server/lib/notifyListener'; -import { t } from '../../../utils/lib/i18n'; -import { ProgressStep, ImportPreparingStartedStates } from '../../lib/ImporterProgressStep'; -import type { ImporterInfo } from '../definitions/ImporterInfo'; import { ImportDataConverter } from './ImportDataConverter'; import type { ConverterOptions } from './ImportDataConverter'; import { ImporterProgress } from './ImporterProgress'; import { ImporterWebsocket } from './ImporterWebsocket'; +import { notifyOnSettingChangedById } from '../../../lib/server/lib/notifyListener'; +import { t } from '../../../utils/lib/i18n'; +import { ProgressStep, ImportPreparingStartedStates } from '../../lib/ImporterProgressStep'; +import type { ImporterInfo } from '../definitions/ImporterInfo'; type OldSettings = { allowedDomainList?: string | null; diff --git a/apps/meteor/app/importer/server/classes/converters/MessageConverter.ts b/apps/meteor/app/importer/server/classes/converters/MessageConverter.ts index b4540ed6182f3..732e46b4398bc 100644 --- a/apps/meteor/app/importer/server/classes/converters/MessageConverter.ts +++ b/apps/meteor/app/importer/server/classes/converters/MessageConverter.ts @@ -2,10 +2,10 @@ import type { IImportMessageRecord, IMessage as IDBMessage, IImportMessage, IImp import { Rooms } from '@rocket.chat/models'; import limax from 'limax'; -import { insertMessage } from '../../../../lib/server/functions/insertMessage'; -import type { IConversionCallbacks } from '../../definitions/IConversionCallbacks'; import type { UserIdentification, MentionedChannel } from './ConverterCache'; import { RecordConverter } from './RecordConverter'; +import { insertMessage } from '../../../../lib/server/functions/insertMessage'; +import type { IConversionCallbacks } from '../../definitions/IConversionCallbacks'; export type MessageConversionCallbacks = IConversionCallbacks & { afterImportAllMessagesFn?: (roomIds: string[]) => Promise }; diff --git a/apps/meteor/app/importer/server/classes/converters/RecordConverter.ts b/apps/meteor/app/importer/server/classes/converters/RecordConverter.ts index d0a6d60fa7235..9003fe4bd416f 100644 --- a/apps/meteor/app/importer/server/classes/converters/RecordConverter.ts +++ b/apps/meteor/app/importer/server/classes/converters/RecordConverter.ts @@ -4,8 +4,8 @@ import { ImportData } from '@rocket.chat/models'; import { Random } from '@rocket.chat/random'; import { type FindCursor, ObjectId } from 'mongodb'; -import type { IConversionCallbacks } from '../../definitions/IConversionCallbacks'; import { ConverterCache } from './ConverterCache'; +import type { IConversionCallbacks } from '../../definitions/IConversionCallbacks'; export type RecordConverterOptions = { workInMemory?: boolean; diff --git a/apps/meteor/app/importer/server/classes/converters/RoomConverter.ts b/apps/meteor/app/importer/server/classes/converters/RoomConverter.ts index f57fa1a7cb883..e9a14fed6a038 100644 --- a/apps/meteor/app/importer/server/classes/converters/RoomConverter.ts +++ b/apps/meteor/app/importer/server/classes/converters/RoomConverter.ts @@ -2,13 +2,13 @@ import type { IImportChannel, IImportChannelRecord, IRoom } from '@rocket.chat/c import { Subscriptions, Rooms, Users } from '@rocket.chat/models'; import limax from 'limax'; +import { RecordConverter } from './RecordConverter'; import { createDirectMessage } from '../../../../../server/methods/createDirectMessage'; import { saveRoomSettings } from '../../../../channel-settings/server/methods/saveRoomSettings'; import { notifyOnSubscriptionChangedByRoomId } from '../../../../lib/server/lib/notifyListener'; import { createChannelMethod } from '../../../../lib/server/methods/createChannel'; import { createPrivateGroupMethod } from '../../../../lib/server/methods/createPrivateGroup'; import type { IConversionCallbacks } from '../../definitions/IConversionCallbacks'; -import { RecordConverter } from './RecordConverter'; export class RoomConverter extends RecordConverter { public startedByUserId: string; diff --git a/apps/meteor/app/importer/server/classes/converters/UserConverter.ts b/apps/meteor/app/importer/server/classes/converters/UserConverter.ts index 52716dabef5a3..454989a89ec80 100644 --- a/apps/meteor/app/importer/server/classes/converters/UserConverter.ts +++ b/apps/meteor/app/importer/server/classes/converters/UserConverter.ts @@ -5,6 +5,7 @@ import { SHA256 } from '@rocket.chat/sha256'; import { hash as bcryptHash } from 'bcrypt'; import { Accounts } from 'meteor/accounts-base'; +import { RecordConverter, type RecordConverterOptions } from './RecordConverter'; import { callbacks as systemCallbacks } from '../../../../../lib/callbacks'; import { addUserToDefaultChannels } from '../../../../lib/server/functions/addUserToDefaultChannels'; import { generateUsernameSuggestion } from '../../../../lib/server/functions/getUsernameSuggestion'; @@ -12,7 +13,6 @@ import { saveUserIdentity } from '../../../../lib/server/functions/saveUserIdent import { setUserActiveStatus } from '../../../../lib/server/functions/setUserActiveStatus'; import { notifyOnUserChange } from '../../../../lib/server/lib/notifyListener'; import type { IConversionCallbacks } from '../../definitions/IConversionCallbacks'; -import { RecordConverter, type RecordConverterOptions } from './RecordConverter'; export type UserConverterOptions = { flagEmailsAsVerified?: boolean; diff --git a/apps/meteor/app/integrations/server/lib/validateOutgoingIntegration.ts b/apps/meteor/app/integrations/server/lib/validateOutgoingIntegration.ts index 398f811612795..e86b982d2cf20 100644 --- a/apps/meteor/app/integrations/server/lib/validateOutgoingIntegration.ts +++ b/apps/meteor/app/integrations/server/lib/validateOutgoingIntegration.ts @@ -5,10 +5,10 @@ import { Babel } from 'meteor/babel-compiler'; import { Match } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; +import { isScriptEngineFrozen } from './validateScriptEngine'; import { parseCSV } from '../../../../lib/utils/parseCSV'; import { hasPermissionAsync, hasAllPermissionAsync } from '../../../authorization/server/functions/hasPermission'; import { outgoingEvents } from '../../lib/outgoingEvents'; -import { isScriptEngineFrozen } from './validateScriptEngine'; const scopedChannels = ['all_public_channels', 'all_private_groups', 'all_direct_messages']; const validChannelChars = ['@', '#']; diff --git a/apps/meteor/app/integrations/server/triggers.ts b/apps/meteor/app/integrations/server/triggers.ts index 64b95827645fa..06fc9b0a9e1af 100644 --- a/apps/meteor/app/integrations/server/triggers.ts +++ b/apps/meteor/app/integrations/server/triggers.ts @@ -1,6 +1,6 @@ +import { triggerHandler } from './lib/triggerHandler'; import { callbacks } from '../../../lib/callbacks'; import { afterLeaveRoomCallback } from '../../../lib/callbacks/afterLeaveRoomCallback'; -import { triggerHandler } from './lib/triggerHandler'; const callbackHandler = function _callbackHandler(eventType: string) { return function _wrapperFunction(...args: any[]) { diff --git a/apps/meteor/app/invites/server/functions/useInviteToken.ts b/apps/meteor/app/invites/server/functions/useInviteToken.ts index 21e89bd22fbcf..f514736da590c 100644 --- a/apps/meteor/app/invites/server/functions/useInviteToken.ts +++ b/apps/meteor/app/invites/server/functions/useInviteToken.ts @@ -1,10 +1,10 @@ import { Invites, Subscriptions, Users } from '@rocket.chat/models'; import { Meteor } from 'meteor/meteor'; +import { validateInviteToken } from './validateInviteToken'; import { RoomMemberActions } from '../../../../definition/IRoomTypeConfig'; import { roomCoordinator } from '../../../../server/lib/rooms/roomCoordinator'; import { addUserToRoom } from '../../../lib/server/functions/addUserToRoom'; -import { validateInviteToken } from './validateInviteToken'; export const useInviteToken = async (userId: string, token: string) => { if (!userId) { diff --git a/apps/meteor/app/irc/server/irc.js b/apps/meteor/app/irc/server/irc.js index 2f6efcb99e414..7012e28291343 100644 --- a/apps/meteor/app/irc/server/irc.js +++ b/apps/meteor/app/irc/server/irc.js @@ -1,7 +1,7 @@ import { Meteor } from 'meteor/meteor'; -import { settings } from '../../settings/server'; import Bridge from './irc-bridge'; +import { settings } from '../../settings/server'; if (!!settings.get('IRC_Enabled') === true) { // Normalize the config values diff --git a/apps/meteor/app/irc/server/methods/resetIrcConnection.ts b/apps/meteor/app/irc/server/methods/resetIrcConnection.ts index aaaeef1c06b8c..a42cd80667b43 100644 --- a/apps/meteor/app/irc/server/methods/resetIrcConnection.ts +++ b/apps/meteor/app/irc/server/methods/resetIrcConnection.ts @@ -2,6 +2,7 @@ import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Settings } from '@rocket.chat/models'; import { Meteor } from 'meteor/meteor'; +import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; import { notifyOnSettingChangedById } from '../../../lib/server/lib/notifyListener'; import { settings } from '../../../settings/server'; import Bridge from '../irc-bridge'; @@ -16,8 +17,18 @@ declare module '@rocket.chat/ddp-client' { Meteor.methods({ async resetIrcConnection() { const ircEnabled = Boolean(settings.get('IRC_Enabled')); + const uid = Meteor.userId(); + + if (!uid) { + throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'resetIrcConnection' }); + } + + if (!(await hasPermissionAsync(uid, 'edit-privileged-setting'))) { + throw new Meteor.Error('error-not-allowed', 'Not allowed', { method: 'resetIrcConnection' }); + } const updatedLastPingValue = await Settings.updateValueById('IRC_Bridge_Last_Ping', new Date(0), { upsert: true }); + if (updatedLastPingValue.modifiedCount || updatedLastPingValue.upsertedCount) { void notifyOnSettingChangedById('IRC_Bridge_Last_Ping'); } diff --git a/apps/meteor/app/lib/client/methods/sendMessage.ts b/apps/meteor/app/lib/client/methods/sendMessage.ts index 19220f9014582..f87684eb978e0 100644 --- a/apps/meteor/app/lib/client/methods/sendMessage.ts +++ b/apps/meteor/app/lib/client/methods/sendMessage.ts @@ -6,7 +6,7 @@ import { onClientMessageReceived } from '../../../../client/lib/onClientMessageR import { dispatchToastMessage } from '../../../../client/lib/toast'; import { callbacks } from '../../../../lib/callbacks'; import { trim } from '../../../../lib/utils/stringUtils'; -import { ChatMessage, ChatRoom } from '../../../models/client'; +import { Messages, Rooms } from '../../../models/client'; import { settings } from '../../../settings/client'; import { t } from '../../../utils/lib/i18n'; @@ -16,7 +16,7 @@ Meteor.methods({ if (!uid || trim(message.msg) === '') { return false; } - const messageAlreadyExists = message._id && ChatMessage.findOne({ _id: message._id }); + const messageAlreadyExists = message._id && Messages.findOne({ _id: message._id }); if (messageAlreadyExists) { return dispatchToastMessage({ type: 'error', message: t('Message_Already_Sent') }); } @@ -36,13 +36,13 @@ Meteor.methods({ } // If the room is federated, send the message to matrix only - const room = ChatRoom.findOne({ _id: message.rid }, { fields: { federated: 1, name: 1 } }); + const room = Rooms.findOne({ _id: message.rid }, { fields: { federated: 1, name: 1 } }); if (room?.federated) { return; } await onClientMessageReceived(message as IMessage).then((message) => { - ChatMessage.insert(message); + Messages.insert(message); return callbacks.run('afterSaveMessage', message, { room }); }); }, diff --git a/apps/meteor/app/lib/server/functions/addUserToDefaultChannels.ts b/apps/meteor/app/lib/server/functions/addUserToDefaultChannels.ts index 3fb9c419aa5fa..f5317a7b0e3b3 100644 --- a/apps/meteor/app/lib/server/functions/addUserToDefaultChannels.ts +++ b/apps/meteor/app/lib/server/functions/addUserToDefaultChannels.ts @@ -2,11 +2,11 @@ import { Message } from '@rocket.chat/core-services'; import type { IUser } from '@rocket.chat/core-typings'; import { Subscriptions } from '@rocket.chat/models'; +import { getDefaultChannels } from './getDefaultChannels'; import { callbacks } from '../../../../lib/callbacks'; import { getSubscriptionAutotranslateDefaultConfig } from '../../../../server/lib/getSubscriptionAutotranslateDefaultConfig'; import { getDefaultSubscriptionPref } from '../../../utils/lib/getDefaultSubscriptionPref'; import { notifyOnSubscriptionChangedById } from '../lib/notifyListener'; -import { getDefaultChannels } from './getDefaultChannels'; export const addUserToDefaultChannels = async function (user: IUser, silenced?: boolean): Promise { await callbacks.run('beforeJoinDefaultChannels', user); diff --git a/apps/meteor/app/lib/server/functions/checkUsernameAvailability.ts b/apps/meteor/app/lib/server/functions/checkUsernameAvailability.ts index 316a3b8779a0a..498828444e4b2 100644 --- a/apps/meteor/app/lib/server/functions/checkUsernameAvailability.ts +++ b/apps/meteor/app/lib/server/functions/checkUsernameAvailability.ts @@ -4,8 +4,8 @@ import { escapeRegExp } from '@rocket.chat/string-helpers'; import { Meteor } from 'meteor/meteor'; import _ from 'underscore'; -import { settings } from '../../../settings/server'; import { validateName } from './validateName'; +import { settings } from '../../../settings/server'; let usernameBlackList: RegExp[] = []; diff --git a/apps/meteor/app/lib/server/functions/cleanRoomHistory.ts b/apps/meteor/app/lib/server/functions/cleanRoomHistory.ts index 765a03cad87b9..8fc449cdc615b 100644 --- a/apps/meteor/app/lib/server/functions/cleanRoomHistory.ts +++ b/apps/meteor/app/lib/server/functions/cleanRoomHistory.ts @@ -2,10 +2,10 @@ import { api } from '@rocket.chat/core-services'; import type { IRoom } from '@rocket.chat/core-typings'; import { Messages, Rooms, Subscriptions, ReadReceipts, Users } from '@rocket.chat/models'; +import { deleteRoom } from './deleteRoom'; import { i18n } from '../../../../server/lib/i18n'; import { FileUpload } from '../../../file-upload/server'; import { notifyOnRoomChangedById, notifyOnSubscriptionChangedById } from '../lib/notifyListener'; -import { deleteRoom } from './deleteRoom'; export async function cleanRoomHistory({ rid = '', diff --git a/apps/meteor/app/lib/server/functions/createRoom.ts b/apps/meteor/app/lib/server/functions/createRoom.ts index 769155b66b60a..fda2314d3f2ee 100644 --- a/apps/meteor/app/lib/server/functions/createRoom.ts +++ b/apps/meteor/app/lib/server/functions/createRoom.ts @@ -7,13 +7,13 @@ import type { ICreatedRoom, IUser, IRoom, RoomType } from '@rocket.chat/core-typ import { Rooms, Subscriptions, Users } from '@rocket.chat/models'; import { Meteor } from 'meteor/meteor'; +import { createDirectRoom } from './createDirectRoom'; import { callbacks } from '../../../../lib/callbacks'; import { beforeCreateRoomCallback } from '../../../../lib/callbacks/beforeCreateRoomCallback'; import { getSubscriptionAutotranslateDefaultConfig } from '../../../../server/lib/getSubscriptionAutotranslateDefaultConfig'; import { getDefaultSubscriptionPref } from '../../../utils/lib/getDefaultSubscriptionPref'; import { getValidRoomName } from '../../../utils/server/lib/getValidRoomName'; import { notifyOnRoomChanged, notifyOnSubscriptionChangedById } from '../lib/notifyListener'; -import { createDirectRoom } from './createDirectRoom'; const isValidName = (name: unknown): name is string => { return typeof name === 'string' && name.trim().length > 0; diff --git a/apps/meteor/app/lib/server/functions/deleteUser.ts b/apps/meteor/app/lib/server/functions/deleteUser.ts index 483085d40811b..e0a217a0d39b3 100644 --- a/apps/meteor/app/lib/server/functions/deleteUser.ts +++ b/apps/meteor/app/lib/server/functions/deleteUser.ts @@ -16,6 +16,10 @@ import { } from '@rocket.chat/models'; import { Meteor } from 'meteor/meteor'; +import { getSubscribedRoomsForUserWithDetails, shouldRemoveOrChangeOwner } from './getRoomsWithSingleOwner'; +import { getUserSingleOwnedRooms } from './getUserSingleOwnedRooms'; +import { relinquishRoomOwnerships } from './relinquishRoomOwnerships'; +import { updateGroupDMsName } from './updateGroupDMsName'; import { callbacks } from '../../../../lib/callbacks'; import { i18n } from '../../../../server/lib/i18n'; import { FileUpload } from '../../../file-upload/server'; @@ -26,10 +30,6 @@ import { notifyOnLivechatDepartmentAgentChanged, notifyOnUserChange, } from '../lib/notifyListener'; -import { getSubscribedRoomsForUserWithDetails, shouldRemoveOrChangeOwner } from './getRoomsWithSingleOwner'; -import { getUserSingleOwnedRooms } from './getUserSingleOwnedRooms'; -import { relinquishRoomOwnerships } from './relinquishRoomOwnerships'; -import { updateGroupDMsName } from './updateGroupDMsName'; export async function deleteUser(userId: string, confirmRelinquish = false, deletedBy?: IUser['_id']): Promise { if (userId === 'rocket.cat') { diff --git a/apps/meteor/app/lib/server/functions/getRoomByNameOrIdWithOptionToJoin.ts b/apps/meteor/app/lib/server/functions/getRoomByNameOrIdWithOptionToJoin.ts index 113f8f59a5578..1dd803f8b13c5 100644 --- a/apps/meteor/app/lib/server/functions/getRoomByNameOrIdWithOptionToJoin.ts +++ b/apps/meteor/app/lib/server/functions/getRoomByNameOrIdWithOptionToJoin.ts @@ -2,9 +2,9 @@ import type { IRoom, IUser, RoomType } from '@rocket.chat/core-typings'; import { Rooms, Users } from '@rocket.chat/models'; import { Meteor } from 'meteor/meteor'; +import { addUserToRoom } from './addUserToRoom'; import { isObject } from '../../../../lib/utils/isObject'; import { createDirectMessage } from '../../../../server/methods/createDirectMessage'; -import { addUserToRoom } from './addUserToRoom'; export const getRoomByNameOrIdWithOptionToJoin = async ({ user, diff --git a/apps/meteor/app/lib/server/functions/processWebhookMessage.ts b/apps/meteor/app/lib/server/functions/processWebhookMessage.ts index 2a4303a82ddcb..ae304b2af01d3 100644 --- a/apps/meteor/app/lib/server/functions/processWebhookMessage.ts +++ b/apps/meteor/app/lib/server/functions/processWebhookMessage.ts @@ -2,12 +2,12 @@ import type { IMessage, IUser, RequiredField, MessageAttachment } from '@rocket. import { Meteor } from 'meteor/meteor'; import _ from 'underscore'; +import { getRoomByNameOrIdWithOptionToJoin } from './getRoomByNameOrIdWithOptionToJoin'; +import { sendMessage } from './sendMessage'; import { ensureArray } from '../../../../lib/utils/arrayUtils'; import { trim } from '../../../../lib/utils/stringUtils'; import { SystemLogger } from '../../../../server/lib/logger/system'; import { validateRoomMessagePermissionsAsync } from '../../../authorization/server/functions/canSendMessage'; -import { getRoomByNameOrIdWithOptionToJoin } from './getRoomByNameOrIdWithOptionToJoin'; -import { sendMessage } from './sendMessage'; type Payload = { channel?: string | string[]; diff --git a/apps/meteor/app/lib/server/functions/relinquishRoomOwnerships.ts b/apps/meteor/app/lib/server/functions/relinquishRoomOwnerships.ts index 8f1981ca386dc..2d53b9b55c7c7 100644 --- a/apps/meteor/app/lib/server/functions/relinquishRoomOwnerships.ts +++ b/apps/meteor/app/lib/server/functions/relinquishRoomOwnerships.ts @@ -1,8 +1,8 @@ import { Messages, Roles, Rooms, Subscriptions, ReadReceipts } from '@rocket.chat/models'; +import type { SubscribedRoomsForUserWithDetails } from './getRoomsWithSingleOwner'; import { FileUpload } from '../../../file-upload/server'; import { notifyOnSubscriptionChanged } from '../lib/notifyListener'; -import type { SubscribedRoomsForUserWithDetails } from './getRoomsWithSingleOwner'; const bulkRoomCleanUp = async (rids: string[]): Promise => { // no bulk deletion for files diff --git a/apps/meteor/app/lib/server/functions/saveCustomFields.ts b/apps/meteor/app/lib/server/functions/saveCustomFields.ts index 0657ca4bbf2bc..a67304d5c5a4b 100644 --- a/apps/meteor/app/lib/server/functions/saveCustomFields.ts +++ b/apps/meteor/app/lib/server/functions/saveCustomFields.ts @@ -1,7 +1,7 @@ -import { trim } from '../../../../lib/utils/stringUtils'; -import { settings } from '../../../settings/server'; import { saveCustomFieldsWithoutValidation } from './saveCustomFieldsWithoutValidation'; import { validateCustomFields } from './validateCustomFields'; +import { trim } from '../../../../lib/utils/stringUtils'; +import { settings } from '../../../settings/server'; export const saveCustomFields = async function (userId: string, formData: Record): Promise { if (trim(settings.get('Accounts_CustomFields')) !== '') { diff --git a/apps/meteor/app/lib/server/functions/saveUser/saveUser.ts b/apps/meteor/app/lib/server/functions/saveUser/saveUser.ts index 047a417e94a12..ce9624c604446 100644 --- a/apps/meteor/app/lib/server/functions/saveUser/saveUser.ts +++ b/apps/meteor/app/lib/server/functions/saveUser/saveUser.ts @@ -1,6 +1,6 @@ import { Apps, AppEvents } from '@rocket.chat/apps'; -import type { DeepWritable, DeepPartial } from '@rocket.chat/core-typings'; -import { isUserFederated, type IUser, type IRole, type IUserSettings, type RequiredField } from '@rocket.chat/core-typings'; +import { isUserFederated } from '@rocket.chat/core-typings'; +import type { DeepWritable, DeepPartial, IUser, IRole, IUserSettings, RequiredField } from '@rocket.chat/core-typings'; import { Users } from '@rocket.chat/models'; import { Accounts } from 'meteor/accounts-base'; import { Meteor } from 'meteor/meteor'; diff --git a/apps/meteor/app/lib/server/functions/saveUser/sendUserEmail.ts b/apps/meteor/app/lib/server/functions/saveUser/sendUserEmail.ts index babe985dbd4b8..cba836cdbf9cb 100644 --- a/apps/meteor/app/lib/server/functions/saveUser/sendUserEmail.ts +++ b/apps/meteor/app/lib/server/functions/saveUser/sendUserEmail.ts @@ -1,8 +1,8 @@ import { MeteorError } from '@rocket.chat/core-services'; +import type { SaveUserData } from './saveUser'; import * as Mailer from '../../../../mailer/server/api'; import { settings } from '../../../../settings/server'; -import type { SaveUserData } from './saveUser'; let html = ''; let passwordChangedHtml = ''; diff --git a/apps/meteor/app/lib/server/functions/saveUser/validateUserEditing.ts b/apps/meteor/app/lib/server/functions/saveUser/validateUserEditing.ts index 78b8910361cdd..fc151204fba11 100644 --- a/apps/meteor/app/lib/server/functions/saveUser/validateUserEditing.ts +++ b/apps/meteor/app/lib/server/functions/saveUser/validateUserEditing.ts @@ -2,9 +2,9 @@ import { MeteorError } from '@rocket.chat/core-services'; import type { IUser, RequiredField } from '@rocket.chat/core-typings'; import { Users } from '@rocket.chat/models'; +import type { SaveUserData } from './saveUser'; import { hasPermissionAsync } from '../../../../authorization/server/functions/hasPermission'; import { settings } from '../../../../settings/server'; -import type { SaveUserData } from './saveUser'; const isEditingUserRoles = (previousRoles: IUser['roles'], newRoles?: IUser['roles']) => newRoles !== undefined && diff --git a/apps/meteor/app/lib/server/functions/saveUserIdentity.ts b/apps/meteor/app/lib/server/functions/saveUserIdentity.ts index 1729a1ba8abd5..7a200a0297256 100644 --- a/apps/meteor/app/lib/server/functions/saveUserIdentity.ts +++ b/apps/meteor/app/lib/server/functions/saveUserIdentity.ts @@ -1,6 +1,10 @@ import type { IUser } from '@rocket.chat/core-typings'; import { Messages, VideoConference, LivechatDepartmentAgents, Rooms, Subscriptions, Users } from '@rocket.chat/models'; +import { _setRealName } from './setRealName'; +import { _setUsername } from './setUsername'; +import { updateGroupDMsName } from './updateGroupDMsName'; +import { validateName } from './validateName'; import { SystemLogger } from '../../../../server/lib/logger/system'; import { FileUpload } from '../../../file-upload/server'; import { @@ -8,10 +12,6 @@ import { notifyOnSubscriptionChangedByUserId, notifyOnSubscriptionChangedByNameAndRoomType, } from '../lib/notifyListener'; -import { _setRealName } from './setRealName'; -import { _setUsername } from './setUsername'; -import { updateGroupDMsName } from './updateGroupDMsName'; -import { validateName } from './validateName'; /** * diff --git a/apps/meteor/app/lib/server/functions/sendMessage.ts b/apps/meteor/app/lib/server/functions/sendMessage.ts index aba5ddb7264ce..828de8451a217 100644 --- a/apps/meteor/app/lib/server/functions/sendMessage.ts +++ b/apps/meteor/app/lib/server/functions/sendMessage.ts @@ -4,6 +4,7 @@ import type { IMessage, IRoom } from '@rocket.chat/core-typings'; import { Messages } from '@rocket.chat/models'; import { Match, check } from 'meteor/check'; +import { parseUrlsInMessage } from './parseUrlsInMessage'; import { isRelativeURL } from '../../../../lib/utils/isRelativeURL'; import { isURL } from '../../../../lib/utils/isURL'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; @@ -12,7 +13,6 @@ import { settings } from '../../../settings/server'; import { afterSaveMessage } from '../lib/afterSaveMessage'; import { notifyOnRoomChangedById, notifyOnMessageChange } from '../lib/notifyListener'; import { validateCustomMessageFields } from '../lib/validateCustomMessageFields'; -import { parseUrlsInMessage } from './parseUrlsInMessage'; // TODO: most of the types here are wrong, but I don't want to change them now diff --git a/apps/meteor/app/lib/server/functions/setRoomAvatar.ts b/apps/meteor/app/lib/server/functions/setRoomAvatar.ts index 42fc615f09dbe..8a3467bdc4dca 100644 --- a/apps/meteor/app/lib/server/functions/setRoomAvatar.ts +++ b/apps/meteor/app/lib/server/functions/setRoomAvatar.ts @@ -4,8 +4,8 @@ import { isRegisterUser } from '@rocket.chat/core-typings'; import { Avatars, Rooms } from '@rocket.chat/models'; import { Meteor } from 'meteor/meteor'; -import { FileUpload } from '../../../file-upload/server'; import { RocketChatFile } from '../../../file/server'; +import { FileUpload } from '../../../file-upload/server'; export const setRoomAvatar = async function (rid: string, dataURI: string, user: IUser): Promise { if (!isRegisterUser(user)) { diff --git a/apps/meteor/app/lib/server/functions/setUserActiveStatus.ts b/apps/meteor/app/lib/server/functions/setUserActiveStatus.ts index 929c24210d2d7..466a5862853df 100644 --- a/apps/meteor/app/lib/server/functions/setUserActiveStatus.ts +++ b/apps/meteor/app/lib/server/functions/setUserActiveStatus.ts @@ -6,6 +6,10 @@ import { Accounts } from 'meteor/accounts-base'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; +import { closeOmnichannelConversations } from './closeOmnichannelConversations'; +import { shouldRemoveOrChangeOwner, getSubscribedRoomsForUserWithDetails } from './getRoomsWithSingleOwner'; +import { getUserSingleOwnedRooms } from './getUserSingleOwnedRooms'; +import { relinquishRoomOwnerships } from './relinquishRoomOwnerships'; import { callbacks } from '../../../../lib/callbacks'; import * as Mailer from '../../../mailer/server/api'; import { settings } from '../../../settings/server'; @@ -15,10 +19,6 @@ import { notifyOnSubscriptionChangedByNameAndRoomType, notifyOnUserChange, } from '../lib/notifyListener'; -import { closeOmnichannelConversations } from './closeOmnichannelConversations'; -import { shouldRemoveOrChangeOwner, getSubscribedRoomsForUserWithDetails } from './getRoomsWithSingleOwner'; -import { getUserSingleOwnedRooms } from './getUserSingleOwnedRooms'; -import { relinquishRoomOwnerships } from './relinquishRoomOwnerships'; async function reactivateDirectConversations(userId: string) { // since both users can be deactivated at the same time, we should just reactivate rooms if both users are active diff --git a/apps/meteor/app/lib/server/functions/setUserAvatar.ts b/apps/meteor/app/lib/server/functions/setUserAvatar.ts index 13ccd2de69546..c678b8a07e22c 100644 --- a/apps/meteor/app/lib/server/functions/setUserAvatar.ts +++ b/apps/meteor/app/lib/server/functions/setUserAvatar.ts @@ -5,12 +5,12 @@ import type { Response } from '@rocket.chat/server-fetch'; import { serverFetch as fetch } from '@rocket.chat/server-fetch'; import { Meteor } from 'meteor/meteor'; +import { checkUrlForSsrf } from './checkUrlForSsrf'; import { SystemLogger } from '../../../../server/lib/logger/system'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; -import { FileUpload } from '../../../file-upload/server'; import { RocketChatFile } from '../../../file/server'; +import { FileUpload } from '../../../file-upload/server'; import { settings } from '../../../settings/server'; -import { checkUrlForSsrf } from './checkUrlForSsrf'; export const setAvatarFromServiceWithValidation = async ( userId: string, diff --git a/apps/meteor/app/lib/server/functions/setUsername.ts b/apps/meteor/app/lib/server/functions/setUsername.ts index c4d2c47c6d9da..57591d2ed2c9f 100644 --- a/apps/meteor/app/lib/server/functions/setUsername.ts +++ b/apps/meteor/app/lib/server/functions/setUsername.ts @@ -5,12 +5,9 @@ import { Accounts } from 'meteor/accounts-base'; import { Meteor } from 'meteor/meteor'; import _ from 'underscore'; -import { callbacks } from '../../../../lib/callbacks'; -import { SystemLogger } from '../../../../server/lib/logger/system'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; import { settings } from '../../../settings/server'; import { RateLimiter } from '../lib'; -import { notifyOnUserChange } from '../lib/notifyListener'; import { addUserToRoom } from './addUserToRoom'; import { checkUsernameAvailability } from './checkUsernameAvailability'; import { getAvatarSuggestionForUser } from './getAvatarSuggestionForUser'; @@ -18,6 +15,9 @@ import { joinDefaultChannels } from './joinDefaultChannels'; import { saveUserIdentity } from './saveUserIdentity'; import { setUserAvatar } from './setUserAvatar'; import { validateUsername } from './validateUsername'; +import { callbacks } from '../../../../lib/callbacks'; +import { SystemLogger } from '../../../../server/lib/logger/system'; +import { notifyOnUserChange } from '../lib/notifyListener'; export const setUsernameWithValidation = async (userId: string, username: string, joinDefaultChannelsSilenced?: boolean): Promise => { if (!username) { diff --git a/apps/meteor/app/lib/server/functions/updateMessage.ts b/apps/meteor/app/lib/server/functions/updateMessage.ts index 96683d40348f4..d480a21bd7131 100644 --- a/apps/meteor/app/lib/server/functions/updateMessage.ts +++ b/apps/meteor/app/lib/server/functions/updateMessage.ts @@ -4,11 +4,11 @@ import type { IMessage, IUser, AtLeast } from '@rocket.chat/core-typings'; import { Messages, Rooms } from '@rocket.chat/models'; import { Meteor } from 'meteor/meteor'; +import { parseUrlsInMessage } from './parseUrlsInMessage'; import { settings } from '../../../settings/server'; import { afterSaveMessage } from '../lib/afterSaveMessage'; import { notifyOnRoomChangedById, notifyOnMessageChange } from '../lib/notifyListener'; import { validateCustomMessageFields } from '../lib/validateCustomMessageFields'; -import { parseUrlsInMessage } from './parseUrlsInMessage'; export const updateMessage = async function ( message: AtLeast, diff --git a/apps/meteor/app/lib/server/lib/interceptDirectReplyEmails.js b/apps/meteor/app/lib/server/lib/interceptDirectReplyEmails.js index 075dd055cad04..77aaa03887c54 100644 --- a/apps/meteor/app/lib/server/lib/interceptDirectReplyEmails.js +++ b/apps/meteor/app/lib/server/lib/interceptDirectReplyEmails.js @@ -1,9 +1,9 @@ import POP3Lib from '@rocket.chat/poplib'; import { simpleParser } from 'mailparser'; +import { processDirectEmail } from './processDirectEmail'; import { IMAPInterceptor } from '../../../../server/email/IMAPInterceptor'; import { settings } from '../../../settings/server'; -import { processDirectEmail } from './processDirectEmail'; export class DirectReplyIMAPInterceptor extends IMAPInterceptor { constructor(imapConfig, options = {}) { diff --git a/apps/meteor/app/lib/server/lib/notifyUsersOnMessage.ts b/apps/meteor/app/lib/server/lib/notifyUsersOnMessage.ts index e729b9652cb67..ac8587c0717a2 100644 --- a/apps/meteor/app/lib/server/lib/notifyUsersOnMessage.ts +++ b/apps/meteor/app/lib/server/lib/notifyUsersOnMessage.ts @@ -4,14 +4,14 @@ import type { Updater } from '@rocket.chat/models'; import { Subscriptions, Rooms } from '@rocket.chat/models'; import moment from 'moment'; -import { callbacks } from '../../../../lib/callbacks'; -import { settings } from '../../../settings/server'; -import { messageContainsHighlight } from '../functions/notifications/messageContainsHighlight'; import { notifyOnSubscriptionChanged, notifyOnSubscriptionChangedByRoomIdAndUserId, notifyOnSubscriptionChangedByRoomIdAndUserIds, } from './notifyListener'; +import { callbacks } from '../../../../lib/callbacks'; +import { settings } from '../../../settings/server'; +import { messageContainsHighlight } from '../functions/notifications/messageContainsHighlight'; export async function getMentions(message: IMessage): Promise<{ toAll: boolean; toHere: boolean; mentionIds: string[] }> { const { diff --git a/apps/meteor/app/lib/server/lib/sendNotificationsOnMessage.ts b/apps/meteor/app/lib/server/lib/sendNotificationsOnMessage.ts index fe65ebe5a5d24..25330d912aafd 100644 --- a/apps/meteor/app/lib/server/lib/sendNotificationsOnMessage.ts +++ b/apps/meteor/app/lib/server/lib/sendNotificationsOnMessage.ts @@ -12,6 +12,7 @@ import emojione from 'emojione'; import moment from 'moment'; import type { RootFilterOperators } from 'mongodb'; +import { getMentions } from './notifyUsersOnMessage'; import { callbacks } from '../../../../lib/callbacks'; import { roomCoordinator } from '../../../../server/lib/rooms/roomCoordinator'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; @@ -22,7 +23,6 @@ import { notifyDesktopUser, shouldNotifyDesktop } from '../functions/notificatio import { getEmailData, shouldNotifyEmail } from '../functions/notifications/email'; import { messageContainsHighlight } from '../functions/notifications/messageContainsHighlight'; import { getPushData, shouldNotifyMobile } from '../functions/notifications/mobile'; -import { getMentions } from './notifyUsersOnMessage'; type SubscriptionAggregation = { receiver: [Pick | null]; diff --git a/apps/meteor/app/lib/server/lib/validateEmailDomain.js b/apps/meteor/app/lib/server/lib/validateEmailDomain.js index 3862dad83fef1..898a3e6b8942e 100644 --- a/apps/meteor/app/lib/server/lib/validateEmailDomain.js +++ b/apps/meteor/app/lib/server/lib/validateEmailDomain.js @@ -3,9 +3,9 @@ import util from 'util'; import { Meteor } from 'meteor/meteor'; +import { emailDomainDefaultBlackList } from './defaultBlockedDomainsList'; import { validateEmail } from '../../../../lib/emailValidator'; import { settings } from '../../../settings/server'; -import { emailDomainDefaultBlackList } from './defaultBlockedDomainsList'; const dnsResolveMx = util.promisify(dns.resolveMx); diff --git a/apps/meteor/app/lib/server/methods/getChannelHistory.ts b/apps/meteor/app/lib/server/methods/getChannelHistory.ts index 5fcdc09e0eeba..8fe5812dd62a1 100644 --- a/apps/meteor/app/lib/server/methods/getChannelHistory.ts +++ b/apps/meteor/app/lib/server/methods/getChannelHistory.ts @@ -3,7 +3,6 @@ import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Messages, Subscriptions, Rooms } from '@rocket.chat/models'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; -import _ from 'underscore'; import { canAccessRoomAsync } from '../../../authorization/server'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; @@ -64,7 +63,8 @@ Meteor.methods({ } // Verify oldest is a date if it exists - if (oldest !== undefined && !_.isDate(oldest)) { + + if (oldest !== undefined && {}.toString.call(oldest) !== '[object Date]') { throw new Meteor.Error('error-invalid-date', 'Invalid date', { method: 'getChannelHistory' }); } diff --git a/apps/meteor/app/lib/server/methods/sendMessage.ts b/apps/meteor/app/lib/server/methods/sendMessage.ts index 76134c81d0b3a..6ab03df337ef6 100644 --- a/apps/meteor/app/lib/server/methods/sendMessage.ts +++ b/apps/meteor/app/lib/server/methods/sendMessage.ts @@ -4,7 +4,7 @@ import type { ServerMethods } from '@rocket.chat/ddp-client'; import type { RocketchatI18nKeys } from '@rocket.chat/i18n'; import { Messages, Users } from '@rocket.chat/models'; import type { TOptions } from 'i18next'; -import { check } from 'meteor/check'; +import { check, Match } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; import moment from 'moment'; @@ -123,7 +123,24 @@ declare module '@rocket.chat/ddp-client' { Meteor.methods({ async sendMessage(message, previewUrls) { - check(message, Object); + check(message, { + _id: Match.Maybe(String), + rid: Match.Maybe(String), + msg: Match.Maybe(String), + tmid: Match.Maybe(String), + tshow: Match.Maybe(Boolean), + ts: Match.Maybe(Date), + t: Match.Maybe(String), + otrAck: Match.Maybe(String), + bot: Match.Maybe(Boolean), + content: Match.Maybe(Object), + e2e: Match.Maybe(String), + e2eMentions: Match.Maybe(Object), + customFields: Match.Maybe(Object), + federation: Match.Maybe(Object), + groupable: Match.Maybe(Boolean), + sentByEmail: Match.Maybe(Boolean), + }); const uid = Meteor.userId(); if (!uid) { diff --git a/apps/meteor/app/livechat/client/index.ts b/apps/meteor/app/livechat/client/index.ts index c6884923db308..8346d2ddb978e 100644 --- a/apps/meteor/app/livechat/client/index.ts +++ b/apps/meteor/app/livechat/client/index.ts @@ -1,4 +1,3 @@ import '../lib/messageTypes'; import './voip'; import './ui'; -import './stylesheets/livechat.css'; diff --git a/apps/meteor/app/livechat/client/stylesheets/livechat.css b/apps/meteor/app/livechat/client/stylesheets/livechat.css deleted file mode 100644 index b6e8bf366940b..0000000000000 --- a/apps/meteor/app/livechat/client/stylesheets/livechat.css +++ /dev/null @@ -1,42 +0,0 @@ -:root { - --header-min-height: 30px; - --footer-min-height: 55px; - --link-font-color: #008ce3; - --primary-font-color: #444444; - --secondary-font-color: #7f7f7f; - --info-font-color: #aaaaaa; - --color-gray: #9ea2a8; -} - -.external-frame { - width: 100%; - height: 100%; -} - -.open { - padding-left: 4% !important; -} - -.closing-message-body-wrapper { - margin-top: 3%; -} - -.closing-message-title { - color: var(--color-dark-light); - - font-family: Inter; - font-size: 12px; - font-weight: bold; - font-style: normal; - line-height: 16px; -} - -.closing-message-text { - color: var(--color-gray); - - font-family: Inter; - font-size: 12px; - font-weight: 500; - font-style: italic; - line-height: 16px; -} diff --git a/apps/meteor/app/livechat/server/business-hour/BusinessHourManager.ts b/apps/meteor/app/livechat/server/business-hour/BusinessHourManager.ts index ec21ff2de0677..0f125910b9a4f 100644 --- a/apps/meteor/app/livechat/server/business-hour/BusinessHourManager.ts +++ b/apps/meteor/app/livechat/server/business-hour/BusinessHourManager.ts @@ -4,12 +4,12 @@ import type { AgendaCronJobs } from '@rocket.chat/cron'; import { LivechatBusinessHours, LivechatDepartment, Users } from '@rocket.chat/models'; import moment from 'moment'; +import type { IBusinessHourBehavior, IBusinessHourType } from './AbstractBusinessHour'; +import { closeBusinessHour } from './closeBusinessHour'; import { callbacks } from '../../../../lib/callbacks'; import { notifyOnUserChange } from '../../../lib/server/lib/notifyListener'; import { settings } from '../../../settings/server'; import { businessHourLogger } from '../lib/logger'; -import type { IBusinessHourBehavior, IBusinessHourType } from './AbstractBusinessHour'; -import { closeBusinessHour } from './closeBusinessHour'; const CRON_EVERY_MIDNIGHT_EXPRESSION = '0 0 * * *'; const CRON_DAYLIGHT_JOB_NAME = 'livechat-business-hour-daylight-saving-time-verifier'; diff --git a/apps/meteor/app/livechat/server/business-hour/Helper.ts b/apps/meteor/app/livechat/server/business-hour/Helper.ts index e19300691660a..2f535ad190afa 100644 --- a/apps/meteor/app/livechat/server/business-hour/Helper.ts +++ b/apps/meteor/app/livechat/server/business-hour/Helper.ts @@ -3,10 +3,10 @@ import { ILivechatAgentStatus, LivechatBusinessHourTypes } from '@rocket.chat/co import { LivechatBusinessHours, Users } from '@rocket.chat/models'; import moment from 'moment'; -import { notifyOnUserChangeAsync } from '../../../lib/server/lib/notifyListener'; -import { businessHourLogger } from '../lib/logger'; import { createDefaultBusinessHourRow } from './LivechatBusinessHours'; import { filterBusinessHoursThatMustBeOpened } from './filterBusinessHoursThatMustBeOpened'; +import { notifyOnUserChangeAsync } from '../../../lib/server/lib/notifyListener'; +import { businessHourLogger } from '../lib/logger'; export { filterBusinessHoursThatMustBeOpened }; diff --git a/apps/meteor/app/livechat/server/business-hour/Single.ts b/apps/meteor/app/livechat/server/business-hour/Single.ts index ea8166c75fa98..13a8673ad7fab 100644 --- a/apps/meteor/app/livechat/server/business-hour/Single.ts +++ b/apps/meteor/app/livechat/server/business-hour/Single.ts @@ -1,11 +1,11 @@ import { ILivechatAgentStatus, LivechatBusinessHourTypes } from '@rocket.chat/core-typings'; import { LivechatBusinessHours, Users } from '@rocket.chat/models'; -import { notifyOnUserChange } from '../../../lib/server/lib/notifyListener'; -import { businessHourLogger } from '../lib/logger'; import type { IBusinessHourBehavior } from './AbstractBusinessHour'; import { AbstractBusinessHourBehavior } from './AbstractBusinessHour'; import { filterBusinessHoursThatMustBeOpened, makeAgentsUnavailableBasedOnBusinessHour, openBusinessHourDefault } from './Helper'; +import { notifyOnUserChange } from '../../../lib/server/lib/notifyListener'; +import { businessHourLogger } from '../lib/logger'; export class SingleBusinessHourBehavior extends AbstractBusinessHourBehavior implements IBusinessHourBehavior { async openBusinessHoursByDayAndHour(): Promise { diff --git a/apps/meteor/app/livechat/server/business-hour/closeBusinessHour.ts b/apps/meteor/app/livechat/server/business-hour/closeBusinessHour.ts index 976d8ec1705ea..c18784adb5ea4 100644 --- a/apps/meteor/app/livechat/server/business-hour/closeBusinessHour.ts +++ b/apps/meteor/app/livechat/server/business-hour/closeBusinessHour.ts @@ -2,9 +2,9 @@ import type { ILivechatBusinessHour, IUser } from '@rocket.chat/core-typings'; import { Users } from '@rocket.chat/models'; import { makeFunction } from '@rocket.chat/patch-injection'; -import { businessHourLogger } from '../lib/logger'; import { makeAgentsUnavailableBasedOnBusinessHour } from './Helper'; import { getAgentIdsForBusinessHour } from './getAgentIdsForBusinessHour'; +import { businessHourLogger } from '../lib/logger'; export const closeBusinessHourByAgentIds = async ( businessHourId: ILivechatBusinessHour['_id'], diff --git a/apps/meteor/app/livechat/server/business-hour/index.ts b/apps/meteor/app/livechat/server/business-hour/index.ts index 8b5f10b938ff6..8df93c5cbaeeb 100644 --- a/apps/meteor/app/livechat/server/business-hour/index.ts +++ b/apps/meteor/app/livechat/server/business-hour/index.ts @@ -3,10 +3,10 @@ import { cronJobs } from '@rocket.chat/cron'; import { Accounts } from 'meteor/accounts-base'; import { Meteor } from 'meteor/meteor'; -import { callbacks } from '../../../../lib/callbacks'; import { BusinessHourManager } from './BusinessHourManager'; import { DefaultBusinessHour } from './Default'; import { SingleBusinessHourBehavior } from './Single'; +import { callbacks } from '../../../../lib/callbacks'; export const businessHourManager = new BusinessHourManager(cronJobs); diff --git a/apps/meteor/app/livechat/server/lib/Helper.ts b/apps/meteor/app/livechat/server/lib/Helper.ts index cf11c8d12b2a8..faa33a640fc43 100644 --- a/apps/meteor/app/livechat/server/lib/Helper.ts +++ b/apps/meteor/app/livechat/server/lib/Helper.ts @@ -34,6 +34,10 @@ import { Match, check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; import { ObjectId } from 'mongodb'; +import { Livechat as LivechatTyped } from './LivechatTyped'; +import { queueInquiry, saveQueueInquiry } from './QueueManager'; +import { RoutingManager } from './RoutingManager'; +import { getOnlineAgents } from './getOnlineAgents'; import { callbacks } from '../../../../lib/callbacks'; import { validateEmail as validatorFunc } from '../../../../lib/emailValidator'; import { i18n } from '../../../../server/lib/i18n'; @@ -47,10 +51,6 @@ import { notifyOnSubscriptionChanged, } from '../../../lib/server/lib/notifyListener'; import { settings } from '../../../settings/server'; -import { Livechat as LivechatTyped } from './LivechatTyped'; -import { queueInquiry, saveQueueInquiry } from './QueueManager'; -import { RoutingManager } from './RoutingManager'; -import { getOnlineAgents } from './getOnlineAgents'; const logger = new Logger('LivechatHelper'); export const allowAgentSkipQueue = (agent: SelectedAgent) => { diff --git a/apps/meteor/app/livechat/server/lib/QueueManager.ts b/apps/meteor/app/livechat/server/lib/QueueManager.ts index a467b6e0b360f..0a02b8b253513 100644 --- a/apps/meteor/app/livechat/server/lib/QueueManager.ts +++ b/apps/meteor/app/livechat/server/lib/QueueManager.ts @@ -1,12 +1,14 @@ import { Apps, AppEvents } from '@rocket.chat/apps'; import { Omnichannel } from '@rocket.chat/core-services'; -import type { ILivechatDepartment, IOmnichannelRoomInfo, IOmnichannelRoomExtraData } from '@rocket.chat/core-typings'; -import { - LivechatInquiryStatus, - type ILivechatInquiryRecord, - type ILivechatVisitor, - type IOmnichannelRoom, - type SelectedAgent, +import { LivechatInquiryStatus } from '@rocket.chat/core-typings'; +import type { + ILivechatDepartment, + IOmnichannelRoomInfo, + IOmnichannelRoomExtraData, + ILivechatInquiryRecord, + ILivechatVisitor, + IOmnichannelRoom, + SelectedAgent, } from '@rocket.chat/core-typings'; import { Logger } from '@rocket.chat/logger'; import { LivechatDepartment, LivechatDepartmentAgents, LivechatInquiry, LivechatRooms, Users } from '@rocket.chat/models'; @@ -14,6 +16,11 @@ import { Random } from '@rocket.chat/random'; import { Match, check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; +import { createLivechatRoom, createLivechatInquiry, allowAgentSkipQueue } from './Helper'; +import { Livechat } from './LivechatTyped'; +import { RoutingManager } from './RoutingManager'; +import { getOnlineAgents } from './getOnlineAgents'; +import { getInquirySortMechanismSetting } from './settings'; import { dispatchInquiryPosition } from '../../../../ee/app/livechat-enterprise/server/lib/Helper'; import { callbacks } from '../../../../lib/callbacks'; import { sendNotification } from '../../../lib/server'; @@ -24,11 +31,6 @@ import { } from '../../../lib/server/lib/notifyListener'; import { settings } from '../../../settings/server'; import { i18n } from '../../../utils/lib/i18n'; -import { createLivechatRoom, createLivechatInquiry, allowAgentSkipQueue } from './Helper'; -import { Livechat } from './LivechatTyped'; -import { RoutingManager } from './RoutingManager'; -import { getOnlineAgents } from './getOnlineAgents'; -import { getInquirySortMechanismSetting } from './settings'; const logger = new Logger('QueueManager'); diff --git a/apps/meteor/app/livechat/server/lib/RoutingManager.ts b/apps/meteor/app/livechat/server/lib/RoutingManager.ts index 8781f675ebf98..123c56f4d31fa 100644 --- a/apps/meteor/app/livechat/server/lib/RoutingManager.ts +++ b/apps/meteor/app/livechat/server/lib/RoutingManager.ts @@ -17,9 +17,6 @@ import { LivechatInquiry, LivechatRooms, Subscriptions, Rooms, Users } from '@ro import { Match, check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; -import { callbacks } from '../../../../lib/callbacks'; -import { notifyOnLivechatInquiryChangedById, notifyOnLivechatInquiryChanged } from '../../../lib/server/lib/notifyListener'; -import { settings } from '../../../settings/server'; import { createLivechatSubscription, dispatchAgentDelegated, @@ -30,6 +27,9 @@ import { updateChatDepartment, allowAgentSkipQueue, } from './Helper'; +import { callbacks } from '../../../../lib/callbacks'; +import { notifyOnLivechatInquiryChangedById, notifyOnLivechatInquiryChanged } from '../../../lib/server/lib/notifyListener'; +import { settings } from '../../../settings/server'; const logger = new Logger('RoutingManager'); diff --git a/apps/meteor/app/livechat/server/lib/departmentsLib.ts b/apps/meteor/app/livechat/server/lib/departmentsLib.ts index fa66fdbfe5735..76c70cba49ba0 100644 --- a/apps/meteor/app/livechat/server/lib/departmentsLib.ts +++ b/apps/meteor/app/livechat/server/lib/departmentsLib.ts @@ -2,14 +2,14 @@ import type { LivechatDepartmentDTO, ILivechatDepartment, ILivechatDepartmentAge import { LivechatDepartment, LivechatDepartmentAgents, LivechatVisitors, LivechatRooms } from '@rocket.chat/models'; import { Meteor } from 'meteor/meteor'; +import { updateDepartmentAgents } from './Helper'; +import { isDepartmentCreationAvailable } from './isDepartmentCreationAvailable'; +import { livechatLogger } from './logger'; import { callbacks } from '../../../../lib/callbacks'; import { notifyOnLivechatDepartmentAgentChangedByDepartmentId, notifyOnLivechatDepartmentAgentChanged, } from '../../../lib/server/lib/notifyListener'; -import { updateDepartmentAgents } from './Helper'; -import { isDepartmentCreationAvailable } from './isDepartmentCreationAvailable'; -import { livechatLogger } from './logger'; /** * @param {string|null} _id - The department id * @param {Partial} departmentData diff --git a/apps/meteor/app/livechat/server/lib/parseTranscriptRequest.ts b/apps/meteor/app/livechat/server/lib/parseTranscriptRequest.ts index 76595a7ff6402..1a9b27b50151e 100644 --- a/apps/meteor/app/livechat/server/lib/parseTranscriptRequest.ts +++ b/apps/meteor/app/livechat/server/lib/parseTranscriptRequest.ts @@ -1,8 +1,8 @@ import type { ILivechatVisitor, IOmnichannelRoom, IUser } from '@rocket.chat/core-typings'; import { LivechatVisitors, Users } from '@rocket.chat/models'; -import { settings } from '../../../settings/server'; import type { CloseRoomParams } from './localTypes'; +import { settings } from '../../../settings/server'; export const parseTranscriptRequest = async ( room: IOmnichannelRoom, diff --git a/apps/meteor/app/livechat/server/lib/tracking.ts b/apps/meteor/app/livechat/server/lib/tracking.ts index fb0e91a336681..bfbcf9912212e 100644 --- a/apps/meteor/app/livechat/server/lib/tracking.ts +++ b/apps/meteor/app/livechat/server/lib/tracking.ts @@ -1,8 +1,8 @@ import { Message } from '@rocket.chat/core-services'; import { Users } from '@rocket.chat/models'; -import { settings } from '../../../settings/server'; import { livechatLogger } from './logger'; +import { settings } from '../../../settings/server'; type PageInfo = { title: string; location: { href: string }; change: string }; diff --git a/apps/meteor/app/livechat/server/methods/sendFileLivechatMessage.ts b/apps/meteor/app/livechat/server/methods/sendFileLivechatMessage.ts index 0268207b2f6c5..ef12cf728c733 100644 --- a/apps/meteor/app/livechat/server/methods/sendFileLivechatMessage.ts +++ b/apps/meteor/app/livechat/server/methods/sendFileLivechatMessage.ts @@ -11,8 +11,8 @@ import { Random } from '@rocket.chat/random'; import { Match, check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; -import { FileUpload } from '../../../file-upload/server'; import { sendMessageLivechat } from './sendMessageLivechat'; +import { FileUpload } from '../../../file-upload/server'; interface ISendFileLivechatMessage { roomId: string; diff --git a/apps/meteor/app/livechat/server/roomAccessValidator.compatibility.ts b/apps/meteor/app/livechat/server/roomAccessValidator.compatibility.ts index d5ef83272550b..d772b0cb7f212 100644 --- a/apps/meteor/app/livechat/server/roomAccessValidator.compatibility.ts +++ b/apps/meteor/app/livechat/server/roomAccessValidator.compatibility.ts @@ -1,9 +1,9 @@ import type { IUser, IOmnichannelRoom } from '@rocket.chat/core-typings'; import { LivechatDepartmentAgents, LivechatInquiry, LivechatRooms, LivechatDepartment } from '@rocket.chat/models'; +import { RoutingManager } from './lib/RoutingManager'; import { hasPermissionAsync } from '../../authorization/server/functions/hasPermission'; import { hasRoleAsync } from '../../authorization/server/functions/hasRole'; -import { RoutingManager } from './lib/RoutingManager'; type OmnichannelRoomAccessValidator = ( room: IOmnichannelRoom, diff --git a/apps/meteor/app/livechat/server/sendMessageBySMS.ts b/apps/meteor/app/livechat/server/sendMessageBySMS.ts index c7f88646158b9..cd14bcaa88567 100644 --- a/apps/meteor/app/livechat/server/sendMessageBySMS.ts +++ b/apps/meteor/app/livechat/server/sendMessageBySMS.ts @@ -2,10 +2,10 @@ import { OmnichannelIntegration } from '@rocket.chat/core-services'; import { isEditedMessage } from '@rocket.chat/core-typings'; import { LivechatVisitors } from '@rocket.chat/models'; +import { callbackLogger } from './lib/logger'; import { callbacks } from '../../../lib/callbacks'; import { settings } from '../../settings/server'; import { normalizeMessageFileUpload } from '../../utils/server/functions/normalizeMessageFileUpload'; -import { callbackLogger } from './lib/logger'; callbacks.add( 'afterOmnichannelSaveMessage', diff --git a/apps/meteor/app/livechat/server/startup.ts b/apps/meteor/app/livechat/server/startup.ts index e546e6967569a..5c02587f17e6e 100644 --- a/apps/meteor/app/livechat/server/startup.ts +++ b/apps/meteor/app/livechat/server/startup.ts @@ -5,6 +5,10 @@ import { LivechatRooms } from '@rocket.chat/models'; import { Accounts } from 'meteor/accounts-base'; import { Meteor } from 'meteor/meteor'; +import { businessHourManager } from './business-hour'; +import { createDefaultBusinessHourIfNotExists } from './business-hour/Helper'; +import { Livechat as LivechatTyped } from './lib/LivechatTyped'; +import { LivechatAgentActivityMonitor } from './statistics/LivechatAgentActivityMonitor'; import { callbacks } from '../../../lib/callbacks'; import { beforeLeaveRoomCallback } from '../../../lib/callbacks/beforeLeaveRoomCallback'; import { i18n } from '../../../server/lib/i18n'; @@ -12,10 +16,6 @@ import { roomCoordinator } from '../../../server/lib/rooms/roomCoordinator'; import { hasPermissionAsync } from '../../authorization/server/functions/hasPermission'; import { notifyOnUserChange } from '../../lib/server/lib/notifyListener'; import { settings } from '../../settings/server'; -import { businessHourManager } from './business-hour'; -import { createDefaultBusinessHourIfNotExists } from './business-hour/Helper'; -import { Livechat as LivechatTyped } from './lib/LivechatTyped'; -import { LivechatAgentActivityMonitor } from './statistics/LivechatAgentActivityMonitor'; import './roomAccessValidator.internalService'; const logger = new Logger('LivechatStartup'); diff --git a/apps/meteor/app/mailer/server/api.ts b/apps/meteor/app/mailer/server/api.ts index a7577af5843f3..a32461d16a92e 100644 --- a/apps/meteor/app/mailer/server/api.ts +++ b/apps/meteor/app/mailer/server/api.ts @@ -8,12 +8,12 @@ import { Meteor } from 'meteor/meteor'; import stripHtml from 'string-strip-html'; import _ from 'underscore'; +import { replaceVariables } from './replaceVariables'; import { validateEmail } from '../../../lib/emailValidator'; import { strLeft, strRightBack } from '../../../lib/utils/stringUtils'; import { i18n } from '../../../server/lib/i18n'; import { notifyOnSettingChanged } from '../../lib/server/lib/notifyListener'; import { settings } from '../../settings/server'; -import { replaceVariables } from './replaceVariables'; let contentHeader: string | undefined; let contentFooter: string | undefined; diff --git a/apps/meteor/app/markdown/lib/parser/original/code.js b/apps/meteor/app/markdown/lib/parser/original/code.js index 61059d24a06d6..2bb2ef603b965 100644 --- a/apps/meteor/app/markdown/lib/parser/original/code.js +++ b/apps/meteor/app/markdown/lib/parser/original/code.js @@ -4,8 +4,8 @@ */ import { unescapeHTML } from '@rocket.chat/string-helpers'; -import hljs, { register } from '../../hljs'; import { addAsToken } from './token'; +import hljs, { register } from '../../hljs'; const inlinecode = (message) => { // Support `text` diff --git a/apps/meteor/app/message-mark-as-unread/client/actionButton.ts b/apps/meteor/app/message-mark-as-unread/client/actionButton.ts index 97cdf8a7a1ac0..fc052eaf63d3a 100644 --- a/apps/meteor/app/message-mark-as-unread/client/actionButton.ts +++ b/apps/meteor/app/message-mark-as-unread/client/actionButton.ts @@ -3,7 +3,7 @@ import { Meteor } from 'meteor/meteor'; import { roomCoordinator } from '../../../client/lib/rooms/roomCoordinator'; import { dispatchToastMessage } from '../../../client/lib/toast'; import { router } from '../../../client/providers/RouterProvider'; -import { ChatSubscription } from '../../models/client'; +import { Subscriptions } from '../../models/client'; import { LegacyRoomManager, MessageAction } from '../../ui-utils/client'; import { sdk } from '../../utils/client/lib/SDKClient'; @@ -16,7 +16,7 @@ Meteor.startup(() => { type: 'interaction', async action(_, { message }) { try { - const subscription = ChatSubscription.findOne({ + const subscription = Subscriptions.findOne({ rid: message.rid, }); diff --git a/apps/meteor/app/message-mark-as-unread/server/unreadMessages.ts b/apps/meteor/app/message-mark-as-unread/server/unreadMessages.ts index f213ae4b72435..69a4444e8394e 100644 --- a/apps/meteor/app/message-mark-as-unread/server/unreadMessages.ts +++ b/apps/meteor/app/message-mark-as-unread/server/unreadMessages.ts @@ -3,8 +3,8 @@ import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Messages, Subscriptions } from '@rocket.chat/models'; import { Meteor } from 'meteor/meteor'; -import { notifyOnSubscriptionChangedByRoomIdAndUserId } from '../../lib/server/lib/notifyListener'; import logger from './logger'; +import { notifyOnSubscriptionChangedByRoomIdAndUserId } from '../../lib/server/lib/notifyListener'; declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention diff --git a/apps/meteor/app/message-pin/server/pinMessage.ts b/apps/meteor/app/message-pin/server/pinMessage.ts index 9f3dd44cc16d6..f3622ff7bcadd 100644 --- a/apps/meteor/app/message-pin/server/pinMessage.ts +++ b/apps/meteor/app/message-pin/server/pinMessage.ts @@ -43,108 +43,101 @@ declare module '@rocket.chat/ddp-client' { } } -Meteor.methods({ - async pinMessage(message, pinnedAt) { - check(message._id, String); - - const userId = Meteor.userId(); - if (!userId) { - throw new Meteor.Error('error-invalid-user', 'Invalid user', { - method: 'pinMessage', - }); - } +export async function pinMessage(originalMessage: IMessage, userId: string, pinnedAt?: Date) { + if (!settings.get('Message_AllowPinning')) { + throw new Meteor.Error('error-action-not-allowed', 'Message pinning not allowed', { + method: 'pinMessage', + action: 'Message_pinning', + }); + } - if (!settings.get('Message_AllowPinning')) { - throw new Meteor.Error('error-action-not-allowed', 'Message pinning not allowed', { - method: 'pinMessage', - action: 'Message_pinning', - }); - } + if (!(await hasPermissionAsync(userId, 'pin-message', originalMessage.rid))) { + throw new Meteor.Error('not-authorized', 'Not Authorized', { method: 'pinMessage' }); + } - let originalMessage = await Messages.findOneById(message._id); - if (originalMessage == null || originalMessage._id == null) { - throw new Meteor.Error('error-invalid-message', 'Message you are pinning was not found', { - method: 'pinMessage', - action: 'Message_pinning', - }); - } + const room = await Rooms.findOneById(originalMessage.rid); + if (!room) { + throw new Meteor.Error('not-authorized', 'Not Authorized', { method: 'pinMessage' }); + } - const subscription = await Subscriptions.findOneByRoomIdAndUserId(originalMessage.rid, userId, { projection: { _id: 1 } }); - if (!subscription) { - // If it's a valid message but on a room that the user is not subscribed to, report that the message was not found. - throw new Meteor.Error('error-invalid-message', 'Message you are pinning was not found', { - method: 'pinMessage', - action: 'Message_pinning', - }); - } + if (!(await canAccessRoomAsync(room, { _id: userId }))) { + throw new Meteor.Error('not-authorized', 'Not Authorized', { method: 'pinMessage' }); + } - if (!(await hasPermissionAsync(userId, 'pin-message', originalMessage.rid))) { - throw new Meteor.Error('not-authorized', 'Not Authorized', { method: 'pinMessage' }); - } + if (originalMessage.pinned) { + return originalMessage; + } - const me = await Users.findOneById(userId); - if (!me) { - throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'pinMessage' }); - } + const me = await Users.findOneById(userId); + if (!me) { + throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'pinMessage' }); + } - // If we keep history of edits, insert a new message to store history information - if (settings.get('Message_KeepHistory') && isRegisterUser(me)) { - await Messages.cloneAndSaveAsHistoryById(message._id, me); - } + originalMessage.pinned = true; + originalMessage.pinnedAt = pinnedAt || new Date(); + originalMessage.pinnedBy = { + _id: userId, + username: me.username, + }; - const room = await Rooms.findOneById(originalMessage.rid); - if (!room) { - throw new Meteor.Error('not-authorized', 'Not Authorized', { method: 'pinMessage' }); - } + originalMessage = await Message.beforeSave({ message: originalMessage, room, user: me }); - if (!(await canAccessRoomAsync(room, { _id: userId }))) { - throw new Meteor.Error('not-authorized', 'Not Authorized', { method: 'pinMessage' }); - } + await Messages.setPinnedByIdAndUserId(originalMessage._id, originalMessage.pinnedBy, originalMessage.pinned); + if (settings.get('Message_Read_Receipt_Store_Users')) { + await ReadReceipts.setPinnedByMessageId(originalMessage._id, originalMessage.pinned); + } + if (isTheLastMessage(room, originalMessage)) { + await Rooms.setLastMessagePinned(room._id, originalMessage.pinnedBy, originalMessage.pinned); + } - originalMessage.pinned = true; - originalMessage.pinnedAt = pinnedAt || new Date(); - originalMessage.pinnedBy = { - _id: userId, - username: me.username, - }; + const attachments: MessageAttachment[] = []; - originalMessage = await Message.beforeSave({ message: originalMessage, room, user: me }); + if (Array.isArray(originalMessage.attachments)) { + originalMessage.attachments.forEach((attachment) => { + if (!isQuoteAttachment(attachment) || shouldAdd(attachments, attachment)) { + attachments.push(attachment); + } + }); + } - await Messages.setPinnedByIdAndUserId(originalMessage._id, originalMessage.pinnedBy, originalMessage.pinned); - if (settings.get('Message_Read_Receipt_Store_Users')) { - await ReadReceipts.setPinnedByMessageId(message._id, originalMessage.pinned); - } - if (isTheLastMessage(room, message)) { - await Rooms.setLastMessagePinned(room._id, originalMessage.pinnedBy, originalMessage.pinned); - void notifyOnRoomChangedById(room._id); - } + // App IPostMessagePinned event hook + await Apps.self?.triggerEvent(AppEvents.IPostMessagePinned, originalMessage, await Meteor.userAsync(), originalMessage.pinned); + + const pinMessageType = originalMessage.t === 'e2e' ? 'message_pinned_e2e' : 'message_pinned'; + + return Message.saveSystemMessage(pinMessageType, originalMessage.rid, '', me, { + attachments: [ + { + text: originalMessage.msg, + author_name: originalMessage.u.username, + author_icon: getUserAvatarURL(originalMessage.u.username), + ts: originalMessage.ts, + attachments: attachments.map(recursiveRemove), + }, + ], + }); +} - const attachments: MessageAttachment[] = []; +Meteor.methods({ + async pinMessage(message, pinnedAt) { + check(message._id, String); - if (Array.isArray(originalMessage.attachments)) { - originalMessage.attachments.forEach((attachment) => { - if (!isQuoteAttachment(attachment) || shouldAdd(attachments, attachment)) { - attachments.push(attachment); - } + const userId = Meteor.userId(); + if (!userId) { + throw new Meteor.Error('error-invalid-user', 'Invalid user', { + method: 'pinMessage', }); } - // App IPostMessagePinned event hook - await Apps.self?.triggerEvent(AppEvents.IPostMessagePinned, originalMessage, await Meteor.userAsync(), originalMessage.pinned); + const originalMessage = await Messages.findOneById(message._id); + if (!originalMessage?.rid) { + throw new Meteor.Error('error-invalid-message', 'Message you are pinning was not found', { + method: 'pinMessage', + action: 'Message_pinning', + }); + } - const pinMessageType = originalMessage.t === 'e2e' ? 'message_pinned_e2e' : 'message_pinned'; - - return Message.saveSystemMessage(pinMessageType, originalMessage.rid, '', me, { - attachments: [ - { - text: originalMessage.msg, - author_name: originalMessage.u.username, - author_icon: getUserAvatarURL(originalMessage.u.username), - ts: originalMessage.ts, - attachments: attachments.map(recursiveRemove), - }, - ], - }); + return pinMessage(originalMessage, userId, pinnedAt); }, async unpinMessage(message) { check(message._id, String); diff --git a/apps/meteor/app/meteor-accounts-saml/server/lib/SAML.ts b/apps/meteor/app/meteor-accounts-saml/server/lib/SAML.ts index 03642cab1eda7..e3b12ca15aa79 100644 --- a/apps/meteor/app/meteor-accounts-saml/server/lib/SAML.ts +++ b/apps/meteor/app/meteor-accounts-saml/server/lib/SAML.ts @@ -7,6 +7,8 @@ import { escapeRegExp, escapeHTML } from '@rocket.chat/string-helpers'; import { Accounts } from 'meteor/accounts-base'; import { Meteor } from 'meteor/meteor'; +import { SAMLServiceProvider } from './ServiceProvider'; +import { SAMLUtils } from './Utils'; import { ensureArray } from '../../../../lib/utils/arrayUtils'; import { SystemLogger } from '../../../../server/lib/logger/system'; import { addUserToRoom } from '../../../lib/server/functions/addUserToRoom'; @@ -18,8 +20,6 @@ import { i18n } from '../../../utils/lib/i18n'; import type { ISAMLAction } from '../definition/ISAMLAction'; import type { ISAMLUser } from '../definition/ISAMLUser'; import type { IServiceProviderOptions } from '../definition/IServiceProviderOptions'; -import { SAMLServiceProvider } from './ServiceProvider'; -import { SAMLUtils } from './Utils'; const showErrorMessage = function (res: ServerResponse, err: string): void { res.writeHead(200, { diff --git a/apps/meteor/app/meteor-accounts-saml/server/lib/ServiceProvider.ts b/apps/meteor/app/meteor-accounts-saml/server/lib/ServiceProvider.ts index bf3d2151ce0d5..0ffb5fe50fdfa 100644 --- a/apps/meteor/app/meteor-accounts-saml/server/lib/ServiceProvider.ts +++ b/apps/meteor/app/meteor-accounts-saml/server/lib/ServiceProvider.ts @@ -5,11 +5,11 @@ import zlib from 'zlib'; import { Meteor } from 'meteor/meteor'; +import { SAMLUtils } from './Utils'; import type { ILogoutResponse } from '../definition/ILogoutResponse'; import type { ISAMLRequest } from '../definition/ISAMLRequest'; import type { IServiceProviderOptions } from '../definition/IServiceProviderOptions'; import type { ILogoutRequestValidateCallback, ILogoutResponseValidateCallback, IResponseValidateCallback } from '../definition/callbacks'; -import { SAMLUtils } from './Utils'; import { AuthorizeRequest } from './generators/AuthorizeRequest'; import { LogoutRequest } from './generators/LogoutRequest'; import { LogoutResponse } from './generators/LogoutResponse'; diff --git a/apps/meteor/app/meteor-accounts-saml/server/lib/Utils.ts b/apps/meteor/app/meteor-accounts-saml/server/lib/Utils.ts index 984c7bc458a30..c2e8e8b000502 100644 --- a/apps/meteor/app/meteor-accounts-saml/server/lib/Utils.ts +++ b/apps/meteor/app/meteor-accounts-saml/server/lib/Utils.ts @@ -3,12 +3,12 @@ import zlib from 'zlib'; import type { Logger } from '@rocket.chat/logger'; +import { StatusCode } from './constants'; import { ensureArray } from '../../../../lib/utils/arrayUtils'; import type { IUserDataMap, IAttributeMapping } from '../definition/IAttributeMapping'; import type { ISAMLGlobalSettings } from '../definition/ISAMLGlobalSettings'; import type { ISAMLUser } from '../definition/ISAMLUser'; import type { IServiceProviderOptions } from '../definition/IServiceProviderOptions'; -import { StatusCode } from './constants'; let providerList: Array = []; let debug = false; diff --git a/apps/meteor/app/meteor-accounts-saml/server/lib/settings.ts b/apps/meteor/app/meteor-accounts-saml/server/lib/settings.ts index 5c16716720b04..f2b15c9af16ea 100644 --- a/apps/meteor/app/meteor-accounts-saml/server/lib/settings.ts +++ b/apps/meteor/app/meteor-accounts-saml/server/lib/settings.ts @@ -2,13 +2,6 @@ import type { SAMLConfiguration } from '@rocket.chat/core-typings'; import { LoginServiceConfiguration } from '@rocket.chat/models'; import { Meteor } from 'meteor/meteor'; -import { SystemLogger } from '../../../../server/lib/logger/system'; -import { - notifyOnLoginServiceConfigurationChanged, - notifyOnLoginServiceConfigurationChangedByService, -} from '../../../lib/server/lib/notifyListener'; -import { settings, settingsRegistry } from '../../../settings/server'; -import type { IServiceProviderOptions } from '../definition/IServiceProviderOptions'; import { SAMLUtils } from './Utils'; import { defaultAuthnContextTemplate, @@ -21,6 +14,13 @@ import { defaultMetadataTemplate, defaultMetadataCertificateTemplate, } from './constants'; +import { SystemLogger } from '../../../../server/lib/logger/system'; +import { + notifyOnLoginServiceConfigurationChanged, + notifyOnLoginServiceConfigurationChangedByService, +} from '../../../lib/server/lib/notifyListener'; +import { settings, settingsRegistry } from '../../../settings/server'; +import type { IServiceProviderOptions } from '../definition/IServiceProviderOptions'; const getSamlConfigs = function (service: string): SAMLConfiguration { const configs: SAMLConfiguration = { diff --git a/apps/meteor/app/meteor-accounts-saml/server/listener.ts b/apps/meteor/app/meteor-accounts-saml/server/listener.ts index 8dd4495976810..92a0c520ab651 100644 --- a/apps/meteor/app/meteor-accounts-saml/server/listener.ts +++ b/apps/meteor/app/meteor-accounts-saml/server/listener.ts @@ -6,10 +6,10 @@ import { Meteor } from 'meteor/meteor'; import { RoutePolicy } from 'meteor/routepolicy'; import { WebApp } from 'meteor/webapp'; -import { SystemLogger } from '../../../server/lib/logger/system'; import type { ISAMLAction } from './definition/ISAMLAction'; import { SAML } from './lib/SAML'; import { SAMLUtils } from './lib/Utils'; +import { SystemLogger } from '../../../server/lib/logger/system'; RoutePolicy.declare('/_saml/', 'network'); diff --git a/apps/meteor/app/meteor-accounts-saml/server/loginHandler.ts b/apps/meteor/app/meteor-accounts-saml/server/loginHandler.ts index 4adbfc7e06747..b95513fef0366 100644 --- a/apps/meteor/app/meteor-accounts-saml/server/loginHandler.ts +++ b/apps/meteor/app/meteor-accounts-saml/server/loginHandler.ts @@ -1,10 +1,10 @@ import { Accounts } from 'meteor/accounts-base'; import { Meteor } from 'meteor/meteor'; -import { i18n } from '../../../server/lib/i18n'; -import { SystemLogger } from '../../../server/lib/logger/system'; import { SAML } from './lib/SAML'; import { SAMLUtils } from './lib/Utils'; +import { i18n } from '../../../server/lib/i18n'; +import { SystemLogger } from '../../../server/lib/logger/system'; const makeError = (message: string): Record => ({ type: 'saml', diff --git a/apps/meteor/app/meteor-accounts-saml/server/startup.ts b/apps/meteor/app/meteor-accounts-saml/server/startup.ts index 556ab7df13e7d..721edce08d463 100644 --- a/apps/meteor/app/meteor-accounts-saml/server/startup.ts +++ b/apps/meteor/app/meteor-accounts-saml/server/startup.ts @@ -2,9 +2,9 @@ import { Logger } from '@rocket.chat/logger'; import debounce from 'lodash.debounce'; import { Meteor } from 'meteor/meteor'; -import { settings } from '../../settings/server'; import { SAMLUtils } from './lib/Utils'; import { loadSamlServiceProviders, addSettings } from './lib/settings'; +import { settings } from '../../settings/server'; const logger = new Logger('steffo:meteor-accounts-saml'); SAMLUtils.setLoggerInstance(logger); diff --git a/apps/meteor/app/metrics/server/lib/collectMetrics.ts b/apps/meteor/app/metrics/server/lib/collectMetrics.ts index 8f2b256f6759b..a1ad41c9a95cf 100644 --- a/apps/meteor/app/metrics/server/lib/collectMetrics.ts +++ b/apps/meteor/app/metrics/server/lib/collectMetrics.ts @@ -10,12 +10,12 @@ import client from 'prom-client'; import gcStats from 'prometheus-gc-stats'; import _ from 'underscore'; +import { metrics } from './metrics'; import { SystemLogger } from '../../../../server/lib/logger/system'; import { getControl } from '../../../../server/lib/migrations'; import { settings } from '../../../settings/server'; import { getAppsStatistics } from '../../../statistics/server/lib/getAppsStatistics'; import { Info } from '../../../utils/rocketchat.info'; -import { metrics } from './metrics'; const { mongo } = MongoInternals.defaultRemoteCollectionDriver(); diff --git a/apps/meteor/app/models/client/index.ts b/apps/meteor/app/models/client/index.ts index 397a1e45bb184..e719791066154 100644 --- a/apps/meteor/app/models/client/index.ts +++ b/apps/meteor/app/models/client/index.ts @@ -1,42 +1,28 @@ -import { Base } from './models/Base'; -import { CachedChannelList } from './models/CachedChannelList'; import { CachedChatRoom } from './models/CachedChatRoom'; import { CachedChatSubscription } from './models/CachedChatSubscription'; -import { CachedUserList } from './models/CachedUserList'; -import { ChatMessage } from './models/ChatMessage'; -import { AuthzCachedCollection, ChatPermissions } from './models/ChatPermissions'; -import { ChatRoom } from './models/ChatRoom'; -import { ChatSubscription } from './models/ChatSubscription'; -import CustomSounds from './models/CustomSounds'; -import EmojiCustom from './models/EmojiCustom'; +import { Messages } from './models/Messages'; +import { AuthzCachedCollection, Permissions } from './models/Permissions'; import { Roles } from './models/Roles'; import { RoomRoles } from './models/RoomRoles'; +import { Rooms } from './models/Rooms'; +import { Subscriptions } from './models/Subscriptions'; import { UserRoles } from './models/UserRoles'; import { Users } from './models/Users'; export { - Base, Roles, - CachedChannelList, CachedChatRoom, CachedChatSubscription, - CachedUserList, RoomRoles, UserRoles, AuthzCachedCollection, - ChatPermissions, - CustomSounds, - EmojiCustom, + Permissions, /** @deprecated new code refer to Minimongo collections like this one; prefer fetching data from the REST API, listening to changes via streamer events, and storing the state in a Tanstack Query */ Users, /** @deprecated new code refer to Minimongo collections like this one; prefer fetching data from the REST API, listening to changes via streamer events, and storing the state in a Tanstack Query */ - ChatRoom, + Rooms, /** @deprecated new code refer to Minimongo collections like this one; prefer fetching data from the REST API, listening to changes via streamer events, and storing the state in a Tanstack Query */ - ChatSubscription, + Subscriptions, /** @deprecated new code refer to Minimongo collections like this one; prefer fetching data from the REST API, listening to changes via streamer events, and storing the state in a Tanstack Query */ - ChatSubscription as Subscriptions, - /** @deprecated new code refer to Minimongo collections like this one; prefer fetching data from the REST API, listening to changes via streamer events, and storing the state in a Tanstack Query */ - ChatMessage, - /** @deprecated new code refer to Minimongo collections like this one; prefer fetching data from the REST API, listening to changes via streamer events, and storing the state in a Tanstack Query */ - ChatMessage as Messages, + Messages, }; diff --git a/apps/meteor/app/models/client/models/CachedChannelList.ts b/apps/meteor/app/models/client/models/CachedChannelList.ts deleted file mode 100644 index 2ec0979e6c5ee..0000000000000 --- a/apps/meteor/app/models/client/models/CachedChannelList.ts +++ /dev/null @@ -1,4 +0,0 @@ -import type { IRoom } from '@rocket.chat/core-typings'; -import { Mongo } from 'meteor/mongo'; - -export const CachedChannelList = new Mongo.Collection(null); diff --git a/apps/meteor/app/models/client/models/CachedChatRoom.ts b/apps/meteor/app/models/client/models/CachedChatRoom.ts index 0ebf3e64bcd43..784503a1b0afc 100644 --- a/apps/meteor/app/models/client/models/CachedChatRoom.ts +++ b/apps/meteor/app/models/client/models/CachedChatRoom.ts @@ -1,8 +1,8 @@ import type { IOmnichannelRoom, IRoom, IRoomWithRetentionPolicy } from '@rocket.chat/core-typings'; import { DEFAULT_SLA_CONFIG, LivechatPriorityWeight } from '@rocket.chat/core-typings'; -import { CachedCollection } from '../../../../client/lib/cachedCollections/CachedCollection'; import { CachedChatSubscription } from './CachedChatSubscription'; +import { CachedCollection } from '../../../../client/lib/cachedCollections/CachedCollection'; class CachedChatRoom extends CachedCollection { constructor() { diff --git a/apps/meteor/app/models/client/models/CachedChatSubscription.ts b/apps/meteor/app/models/client/models/CachedChatSubscription.ts index 171d3f0edda10..6ea6ea6917e99 100644 --- a/apps/meteor/app/models/client/models/CachedChatSubscription.ts +++ b/apps/meteor/app/models/client/models/CachedChatSubscription.ts @@ -2,8 +2,8 @@ import type { IOmnichannelRoom, IRoomWithRetentionPolicy, ISubscription } from ' import { DEFAULT_SLA_CONFIG, LivechatPriorityWeight } from '@rocket.chat/core-typings'; import type { SubscriptionWithRoom } from '@rocket.chat/ui-contexts'; -import { CachedCollection } from '../../../../client/lib/cachedCollections/CachedCollection'; import { CachedChatRoom } from './CachedChatRoom'; +import { CachedCollection } from '../../../../client/lib/cachedCollections/CachedCollection'; declare module '@rocket.chat/core-typings' { interface ISubscription { diff --git a/apps/meteor/app/models/client/models/CachedUserList.ts b/apps/meteor/app/models/client/models/CachedUserList.ts deleted file mode 100644 index 0233659b47d51..0000000000000 --- a/apps/meteor/app/models/client/models/CachedUserList.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { Mongo } from 'meteor/mongo'; - -export const CachedUserList = new Mongo.Collection(null); diff --git a/apps/meteor/app/models/client/models/ChatRoom.ts b/apps/meteor/app/models/client/models/ChatRoom.ts deleted file mode 100644 index f23f20e8048eb..0000000000000 --- a/apps/meteor/app/models/client/models/ChatRoom.ts +++ /dev/null @@ -1,13 +0,0 @@ -import type { IMessage, IRoom } from '@rocket.chat/core-typings'; - -import { CachedChatRoom } from './CachedChatRoom'; - -/** @deprecated new code refer to Minimongo collections like this one; prefer fetching data from the REST API, listening to changes via streamer events, and storing the state in a Tanstack Query */ -export const ChatRoom = Object.assign(CachedChatRoom.collection, { - setReactionsInLastMessage(this: typeof CachedChatRoom.collection, roomId: IRoom['_id'], lastMessage: IMessage) { - return this.update({ _id: roomId }, { $set: { lastMessage } }); - }, - unsetReactionsInLastMessage(this: typeof CachedChatRoom.collection, roomId: IRoom['_id']) { - return this.update({ _id: roomId }, { $unset: { 'lastMessage.reactions': 1 as const } }); - }, -}); diff --git a/apps/meteor/app/models/client/models/CustomSounds.ts b/apps/meteor/app/models/client/models/CustomSounds.ts deleted file mode 100644 index ccbf8c4b50eb5..0000000000000 --- a/apps/meteor/app/models/client/models/CustomSounds.ts +++ /dev/null @@ -1,12 +0,0 @@ -import type { ICustomSound } from '@rocket.chat/core-typings'; - -import { Base } from './Base'; - -class CustomSounds extends Base { - constructor() { - super(); - this._initModel('custom_sounds'); - } -} - -export default new CustomSounds(); diff --git a/apps/meteor/app/models/client/models/EmojiCustom.ts b/apps/meteor/app/models/client/models/EmojiCustom.ts deleted file mode 100644 index 48bf83e659b32..0000000000000 --- a/apps/meteor/app/models/client/models/EmojiCustom.ts +++ /dev/null @@ -1,22 +0,0 @@ -import type { ICustomEmojiDescriptor } from '@rocket.chat/core-typings'; -import type { Mongo } from 'meteor/mongo'; - -import { Base } from './Base'; - -class EmojiCustom extends Base { - constructor() { - super(); - this._initModel('custom_emoji'); - } - - // find - findByNameOrAlias(name: ICustomEmojiDescriptor['name'], options?: Mongo.Options) { - const query = { - $or: [{ name }, { aliases: name }], - }; - - return this.find(query, options); - } -} - -export default new EmojiCustom(); diff --git a/apps/meteor/app/models/client/models/ChatMessage.ts b/apps/meteor/app/models/client/models/Messages.ts similarity index 68% rename from apps/meteor/app/models/client/models/ChatMessage.ts rename to apps/meteor/app/models/client/models/Messages.ts index 1e9b066bdaaa4..94a9ff65f2f04 100644 --- a/apps/meteor/app/models/client/models/ChatMessage.ts +++ b/apps/meteor/app/models/client/models/Messages.ts @@ -1,4 +1,4 @@ -import type { IMessage, IRoom } from '@rocket.chat/core-typings'; +import type { IMessage } from '@rocket.chat/core-typings'; import { Mongo } from 'meteor/mongo'; import type { MinimongoCollection } from '../../../../client/definitions/MinimongoCollection'; @@ -11,19 +11,10 @@ class ChatMessageCollection super(null); } - findOneByRoomIdAndMessageId(rid: IRoom['_id'], messageId: IMessage['_id'], options?: Mongo.Options) { - const query = { - rid, - _id: messageId, - }; - - return this.findOne(query, options); - } - public declare _collection: MinimongoCollection['_collection']; public declare queries: MinimongoCollection['queries']; } /** @deprecated new code refer to Minimongo collections like this one; prefer fetching data from the REST API, listening to changes via streamer events, and storing the state in a Tanstack Query */ -export const ChatMessage = new ChatMessageCollection(); +export const Messages = new ChatMessageCollection(); diff --git a/apps/meteor/app/models/client/models/ChatPermissions.ts b/apps/meteor/app/models/client/models/Permissions.ts similarity index 80% rename from apps/meteor/app/models/client/models/ChatPermissions.ts rename to apps/meteor/app/models/client/models/Permissions.ts index fcf6ccef0e83a..5793ab3e897de 100644 --- a/apps/meteor/app/models/client/models/ChatPermissions.ts +++ b/apps/meteor/app/models/client/models/Permissions.ts @@ -7,4 +7,4 @@ export const AuthzCachedCollection = new CachedCollection({ eventType: 'notify-logged', }); -export const ChatPermissions = AuthzCachedCollection.collection; +export const Permissions = AuthzCachedCollection.collection; diff --git a/apps/meteor/app/models/client/models/Roles.ts b/apps/meteor/app/models/client/models/Roles.ts index a048905cd2b46..62dec04f32626 100644 --- a/apps/meteor/app/models/client/models/Roles.ts +++ b/apps/meteor/app/models/client/models/Roles.ts @@ -1,10 +1,10 @@ -import type { IRole, IRoom, IUser } from '@rocket.chat/core-typings'; +import type { IRole, IUser } from '@rocket.chat/core-typings'; import { Mongo } from 'meteor/mongo'; import { ReactiveVar } from 'meteor/reactive-var'; -import type { MinimongoCollection } from '../../../../client/definitions/MinimongoCollection'; -import { ChatSubscription } from './ChatSubscription'; +import { Subscriptions } from './Subscriptions'; import { Users } from './Users'; +import type { MinimongoCollection } from '../../../../client/definitions/MinimongoCollection'; class RolesCollection extends Mongo.Collection implements MinimongoCollection { ready = new ReactiveVar(false); @@ -13,22 +13,6 @@ class RolesCollection extends Mongo.Collection implements MinimongoCollec super(null); } - findUsersInRole(roleId: IRole['_id'], scope: IRoom['_id'], options: any) { - const role = this.findOne(roleId); - const roleScope = role?.scope || 'Users'; - - switch (roleScope) { - case 'Subscriptions': - return ChatSubscription.findUsersInRoles(roleId, scope, options); - - case 'Users': - return Users.findUsersInRoles(roleId, scope, options); - - default: - return undefined; - } - } - isUserInRoles(userId: IUser['_id'], roles: IRole['_id'][] | IRole['_id'], scope?: string, ignoreSubscriptions = false) { roles = Array.isArray(roles) ? roles : [roles]; return roles.some((roleId) => { @@ -37,7 +21,7 @@ class RolesCollection extends Mongo.Collection implements MinimongoCollec switch (roleScope) { case 'Subscriptions': - return ChatSubscription.isUserInRole(userId, roleId, scope); + return Subscriptions.isUserInRole(userId, roleId, scope); case 'Users': return Users.isUserInRole(userId, roleId); diff --git a/apps/meteor/app/models/client/models/Rooms.ts b/apps/meteor/app/models/client/models/Rooms.ts new file mode 100644 index 0000000000000..91328881c432e --- /dev/null +++ b/apps/meteor/app/models/client/models/Rooms.ts @@ -0,0 +1,4 @@ +import { CachedChatRoom } from './CachedChatRoom'; + +/** @deprecated new code refer to Minimongo collections like this one; prefer fetching data from the REST API, listening to changes via streamer events, and storing the state in a Tanstack Query */ +export const Rooms = CachedChatRoom.collection; diff --git a/apps/meteor/app/models/client/models/ChatSubscription.ts b/apps/meteor/app/models/client/models/Subscriptions.ts similarity index 95% rename from apps/meteor/app/models/client/models/ChatSubscription.ts rename to apps/meteor/app/models/client/models/Subscriptions.ts index aa7892fe50313..ab33f79b1050a 100644 --- a/apps/meteor/app/models/client/models/ChatSubscription.ts +++ b/apps/meteor/app/models/client/models/Subscriptions.ts @@ -3,11 +3,11 @@ import mem from 'mem'; import { Meteor } from 'meteor/meteor'; import type { Filter } from 'mongodb'; -import { isTruthy } from '../../../../lib/isTruthy'; import { CachedChatSubscription } from './CachedChatSubscription'; +import { isTruthy } from '../../../../lib/isTruthy'; /** @deprecated new code refer to Minimongo collections like this one; prefer fetching data from the REST API, listening to changes via streamer events, and storing the state in a Tanstack Query */ -export const ChatSubscription = Object.assign(CachedChatSubscription.collection, { +export const Subscriptions = Object.assign(CachedChatSubscription.collection, { isUserInRole: mem( function (this: typeof CachedChatSubscription.collection, _uid: IUser['_id'], roleId: IRole['_id'], rid?: IRoom['_id']) { if (!rid) { diff --git a/apps/meteor/app/oauth2-server-config/server/admin/functions/addOAuthApp.ts b/apps/meteor/app/oauth2-server-config/server/admin/functions/addOAuthApp.ts index 8e828f5c11d9d..43bcd0ce14bd5 100644 --- a/apps/meteor/app/oauth2-server-config/server/admin/functions/addOAuthApp.ts +++ b/apps/meteor/app/oauth2-server-config/server/admin/functions/addOAuthApp.ts @@ -4,8 +4,8 @@ import { Random } from '@rocket.chat/random'; import type { OauthAppsAddParams } from '@rocket.chat/rest-typings'; import { Meteor } from 'meteor/meteor'; -import { hasPermissionAsync } from '../../../../authorization/server/functions/hasPermission'; import { parseUriList } from './parseUriList'; +import { hasPermissionAsync } from '../../../../authorization/server/functions/hasPermission'; export async function addOAuthApp(applicationParams: OauthAppsAddParams, uid: IUser['_id'] | undefined): Promise { if (!uid) { diff --git a/apps/meteor/app/otr/client/OTR.ts b/apps/meteor/app/otr/client/OTR.ts index 9f3eea155384a..6237b73e25459 100644 --- a/apps/meteor/app/otr/client/OTR.ts +++ b/apps/meteor/app/otr/client/OTR.ts @@ -1,7 +1,7 @@ import type { IRoom, IUser } from '@rocket.chat/core-typings'; -import type { IOTR } from '../lib/IOTR'; import { OTRRoom } from './OTRRoom'; +import type { IOTR } from '../lib/IOTR'; class OTR implements IOTR { private instancesByRoomId: { [rid: string]: OTRRoom }; diff --git a/apps/meteor/app/otr/lib/IOTR.ts b/apps/meteor/app/otr/lib/IOTR.ts index 9e7cd4ca6b8e2..c7aeb0a3777ac 100644 --- a/apps/meteor/app/otr/lib/IOTR.ts +++ b/apps/meteor/app/otr/lib/IOTR.ts @@ -1,7 +1,7 @@ import type { IMessage, IRoom, IUser } from '@rocket.chat/core-typings'; -import type { OTRRoom } from '../client/OTRRoom'; import type { OtrRoomState } from './OtrRoomState'; +import type { OTRRoom } from '../client/OTRRoom'; export interface IOnUserStreamData { roomId: IRoom['_id']; diff --git a/apps/meteor/app/push/server/push.ts b/apps/meteor/app/push/server/push.ts index 6c724b45282fa..77092051eee24 100644 --- a/apps/meteor/app/push/server/push.ts +++ b/apps/meteor/app/push/server/push.ts @@ -7,12 +7,12 @@ import { JWT } from 'google-auth-library'; import { Match, check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; -import { settings } from '../../settings/server'; import { initAPN, sendAPN } from './apn'; import type { PushOptions, PendingPushNotification } from './definition'; import { sendFCM } from './fcm'; import { sendGCM } from './gcm'; import { logger } from './logger'; +import { settings } from '../../settings/server'; export const _matchToken = Match.OneOf({ apn: String }, { gcm: String }); diff --git a/apps/meteor/app/reactions/client/methods/setReaction.ts b/apps/meteor/app/reactions/client/methods/setReaction.ts index 1744d49c0cebe..2e3a03b248c20 100644 --- a/apps/meteor/app/reactions/client/methods/setReaction.ts +++ b/apps/meteor/app/reactions/client/methods/setReaction.ts @@ -4,7 +4,7 @@ import { Meteor } from 'meteor/meteor'; import { roomCoordinator } from '../../../../client/lib/rooms/roomCoordinator'; import { emoji } from '../../../emoji/client'; -import { Messages, ChatRoom, Subscriptions } from '../../../models/client'; +import { Messages, Rooms, Subscriptions } from '../../../models/client'; Meteor.methods({ async setReaction(reaction, messageId) { @@ -23,7 +23,7 @@ Meteor.methods({ return false; } - const room: IRoom | undefined = ChatRoom.findOne({ _id: message.rid }); + const room: IRoom | undefined = Rooms.findOne({ _id: message.rid }); if (!room) { return false; } diff --git a/apps/meteor/app/search/server/model/SearchProvider.ts b/apps/meteor/app/search/server/model/SearchProvider.ts index 89428e4a7dc62..88388262b95d7 100644 --- a/apps/meteor/app/search/server/model/SearchProvider.ts +++ b/apps/meteor/app/search/server/model/SearchProvider.ts @@ -1,9 +1,9 @@ import type { IMessageSearchSuggestion, IRoom, IUser } from '@rocket.chat/core-typings'; import type { TranslationKey } from '@rocket.chat/ui-contexts'; -import { SearchLogger } from '../logger/logger'; import type { IRawSearchResult } from './ISearchResult'; import { Settings } from './Settings'; +import { SearchLogger } from '../logger/logger'; export abstract class SearchProvider { private _key: string; diff --git a/apps/meteor/app/search/server/search.internalService.ts b/apps/meteor/app/search/server/search.internalService.ts index 2fbaa2e1da312..bf4a0c484ddc0 100644 --- a/apps/meteor/app/search/server/search.internalService.ts +++ b/apps/meteor/app/search/server/search.internalService.ts @@ -1,9 +1,9 @@ import { api, ServiceClassInternal } from '@rocket.chat/core-services'; import { Users } from '@rocket.chat/models'; -import { settings } from '../../settings/server'; import { searchEventService } from './events'; import { searchProviderService } from './service'; +import { settings } from '../../settings/server'; class Search extends ServiceClassInternal { protected name = 'search'; diff --git a/apps/meteor/app/settings/server/SettingsRegistry.ts b/apps/meteor/app/settings/server/SettingsRegistry.ts index d7d2fa0a79f80..ec9cf6b902f57 100644 --- a/apps/meteor/app/settings/server/SettingsRegistry.ts +++ b/apps/meteor/app/settings/server/SettingsRegistry.ts @@ -4,12 +4,12 @@ import { Emitter } from '@rocket.chat/emitter'; import type { ISettingsModel } from '@rocket.chat/model-typings'; import { isEqual } from 'underscore'; -import { SystemLogger } from '../../../server/lib/logger/system'; import type { ICachedSettings } from './CachedSettings'; import { getSettingDefaults } from './functions/getSettingDefaults'; import { overrideSetting } from './functions/overrideSetting'; import { overwriteSetting } from './functions/overwriteSetting'; import { validateSetting } from './functions/validateSetting'; +import { SystemLogger } from '../../../server/lib/logger/system'; const blockedSettings = new Set(); const hiddenSettings = new Set(); diff --git a/apps/meteor/app/settings/server/applyMiddlewares.ts b/apps/meteor/app/settings/server/applyMiddlewares.ts index 93f6efc8a9b11..d707757f0defe 100644 --- a/apps/meteor/app/settings/server/applyMiddlewares.ts +++ b/apps/meteor/app/settings/server/applyMiddlewares.ts @@ -1,3 +1,4 @@ +/* eslint-disable react-hooks/rules-of-hooks */ import { use } from './Middleware'; import { settings } from './cached'; diff --git a/apps/meteor/app/settings/server/index.ts b/apps/meteor/app/settings/server/index.ts index c358a174d69c8..30a8c9fd6ba27 100644 --- a/apps/meteor/app/settings/server/index.ts +++ b/apps/meteor/app/settings/server/index.ts @@ -1,3 +1,4 @@ +/* eslint-disable react-hooks/rules-of-hooks */ import { Settings } from '@rocket.chat/models'; import { use } from './Middleware'; diff --git a/apps/meteor/app/slackbridge/server/RocketAdapter.js b/apps/meteor/app/slackbridge/server/RocketAdapter.js index 8ba2a76dcbc21..245e28c722037 100644 --- a/apps/meteor/app/slackbridge/server/RocketAdapter.js +++ b/apps/meteor/app/slackbridge/server/RocketAdapter.js @@ -6,13 +6,13 @@ import { Accounts } from 'meteor/accounts-base'; import { Meteor } from 'meteor/meteor'; import _ from 'underscore'; +import { rocketLogger } from './logger'; import { callbacks } from '../../../lib/callbacks'; import { sleep } from '../../../lib/utils/sleep'; import { createRoom } from '../../lib/server/functions/createRoom'; import { sendMessage } from '../../lib/server/functions/sendMessage'; import { setUserAvatar } from '../../lib/server/functions/setUserAvatar'; import { settings } from '../../settings/server'; -import { rocketLogger } from './logger'; export default class RocketAdapter { constructor(slackBridge) { diff --git a/apps/meteor/app/slackbridge/server/SlackAdapter.js b/apps/meteor/app/slackbridge/server/SlackAdapter.js index 31cbff69463de..46a5ab6d35b5e 100644 --- a/apps/meteor/app/slackbridge/server/SlackAdapter.js +++ b/apps/meteor/app/slackbridge/server/SlackAdapter.js @@ -8,6 +8,8 @@ import { App as SlackApp } from '@slack/bolt'; import { RTMClient } from '@slack/rtm-api'; import { Meteor } from 'meteor/meteor'; +import { SlackAPI } from './SlackAPI'; +import { slackLogger } from './logger'; import { saveRoomName, saveRoomTopic } from '../../channel-settings/server'; import { FileUpload } from '../../file-upload/server'; import { addUserToRoom } from '../../lib/server/functions/addUserToRoom'; @@ -20,8 +22,6 @@ import { updateMessage } from '../../lib/server/functions/updateMessage'; import { executeSetReaction } from '../../reactions/server/setReaction'; import { settings } from '../../settings/server'; import { getUserAvatarURL } from '../../utils/server/getUserAvatarURL'; -import { SlackAPI } from './SlackAPI'; -import { slackLogger } from './logger'; export default class SlackAdapter { constructor(slackBridge) { diff --git a/apps/meteor/app/slackbridge/server/slackbridge.js b/apps/meteor/app/slackbridge/server/slackbridge.js index b5983e7fff584..89ff66a13397e 100644 --- a/apps/meteor/app/slackbridge/server/slackbridge.js +++ b/apps/meteor/app/slackbridge/server/slackbridge.js @@ -1,9 +1,9 @@ import { debounce } from 'lodash'; -import { settings } from '../../settings/server'; import RocketAdapter from './RocketAdapter.js'; import SlackAdapter from './SlackAdapter.js'; import { classLogger, connLogger } from './logger'; +import { settings } from '../../settings/server'; /** * SlackBridge interfaces between this Rocket installation and a remote Slack installation. diff --git a/apps/meteor/app/slackbridge/server/slackbridge_import.server.js b/apps/meteor/app/slackbridge/server/slackbridge_import.server.js index 2cac64433cb57..6e7117af976a2 100644 --- a/apps/meteor/app/slackbridge/server/slackbridge_import.server.js +++ b/apps/meteor/app/slackbridge/server/slackbridge_import.server.js @@ -2,10 +2,10 @@ import { Rooms, Users } from '@rocket.chat/models'; import { Random } from '@rocket.chat/random'; import { Match } from 'meteor/check'; +import { SlackBridge } from './slackbridge'; import { i18n } from '../../../server/lib/i18n'; import { msgStream } from '../../lib/server'; import { slashCommands } from '../../utils/server/slashCommand'; -import { SlackBridge } from './slackbridge'; async function SlackBridgeImport({ command, params, message, userId }) { if (command !== 'slackbridge-import' || !Match.test(params, String)) { diff --git a/apps/meteor/app/slashcommands-open/client/client.ts b/apps/meteor/app/slashcommands-open/client/client.ts index 99438a24eeb0e..b0d4d45c22bbd 100644 --- a/apps/meteor/app/slashcommands-open/client/client.ts +++ b/apps/meteor/app/slashcommands-open/client/client.ts @@ -3,7 +3,7 @@ import type { Mongo } from 'meteor/mongo'; import { roomCoordinator } from '../../../client/lib/rooms/roomCoordinator'; import { router } from '../../../client/providers/RouterProvider'; -import { Subscriptions, ChatSubscription } from '../../models/client'; +import { Subscriptions } from '../../models/client'; import { sdk } from '../../utils/client/lib/SDKClient'; import { slashCommands } from '../../utils/client/slashCommand'; @@ -23,7 +23,7 @@ slashCommands.add({ ...(type && { t: { $in: type } }), }; - const subscription = ChatSubscription.findOne(query); + const subscription = Subscriptions.findOne(query); if (subscription) { roomCoordinator.openRouteLink(subscription.t, subscription, router.getSearchParameters()); diff --git a/apps/meteor/app/slashcommands-topic/client/topic.ts b/apps/meteor/app/slashcommands-topic/client/topic.ts index f7e47c334b5a1..bc32cacd65bd8 100644 --- a/apps/meteor/app/slashcommands-topic/client/topic.ts +++ b/apps/meteor/app/slashcommands-topic/client/topic.ts @@ -3,7 +3,7 @@ import type { SlashCommandCallbackParams } from '@rocket.chat/core-typings'; import { dispatchToastMessage } from '../../../client/lib/toast'; import { callbacks } from '../../../lib/callbacks'; import { hasPermission } from '../../authorization/client'; -import { ChatRoom } from '../../models/client/models/ChatRoom'; +import { Rooms } from '../../models/client/models/Rooms'; import { sdk } from '../../utils/client/lib/SDKClient'; import { slashCommands } from '../../utils/client/slashCommand'; @@ -13,7 +13,7 @@ slashCommands.add({ if (hasPermission('edit-room', message.rid)) { try { await sdk.call('saveRoomSettings', message.rid, 'roomTopic', params); - await callbacks.run('roomTopicChanged', ChatRoom.findOne(message.rid)); + await callbacks.run('roomTopicChanged', Rooms.findOne(message.rid)); } catch (error: unknown) { dispatchToastMessage({ type: 'error', message: error }); throw error; diff --git a/apps/meteor/app/smarsh-connector/server/functions/generateEml.ts b/apps/meteor/app/smarsh-connector/server/functions/generateEml.ts index ce110cbff4302..cf0b7deab5db8 100644 --- a/apps/meteor/app/smarsh-connector/server/functions/generateEml.ts +++ b/apps/meteor/app/smarsh-connector/server/functions/generateEml.ts @@ -3,10 +3,10 @@ import { Meteor } from 'meteor/meteor'; import moment from 'moment'; import 'moment-timezone'; +import { sendEmail } from './sendEmail'; import { i18n } from '../../../../server/lib/i18n'; import { settings } from '../../../settings/server'; import { MessageTypes } from '../../../ui-utils/server'; -import { sendEmail } from './sendEmail'; const start = ''; diff --git a/apps/meteor/app/smarsh-connector/server/startup.ts b/apps/meteor/app/smarsh-connector/server/startup.ts index f757dea7510b6..edd4be4570824 100644 --- a/apps/meteor/app/smarsh-connector/server/startup.ts +++ b/apps/meteor/app/smarsh-connector/server/startup.ts @@ -1,8 +1,8 @@ import { cronJobs } from '@rocket.chat/cron'; +import { generateEml } from './functions/generateEml'; import { smarshIntervalValuesToCronMap } from '../../../server/settings/smarsh'; import { settings } from '../../settings/server'; -import { generateEml } from './functions/generateEml'; const smarshJobName = 'Smarsh EML Connector'; diff --git a/apps/meteor/app/statistics/server/functions/otrStats.ts b/apps/meteor/app/statistics/server/functions/otrStats.ts index f936f8d213f7c..6553cae42c054 100644 --- a/apps/meteor/app/statistics/server/functions/otrStats.ts +++ b/apps/meteor/app/statistics/server/functions/otrStats.ts @@ -1,7 +1,7 @@ import { Rooms } from '@rocket.chat/models'; -import telemetryEvent from '../lib/telemetryEvents'; import { updateCounter } from './updateStatsCounter'; +import telemetryEvent from '../lib/telemetryEvents'; type otrDataType = { rid: string }; diff --git a/apps/meteor/app/statistics/server/functions/sendUsageReport.ts b/apps/meteor/app/statistics/server/functions/sendUsageReport.ts index a4b1e6182c964..c39276be6f357 100644 --- a/apps/meteor/app/statistics/server/functions/sendUsageReport.ts +++ b/apps/meteor/app/statistics/server/functions/sendUsageReport.ts @@ -1,3 +1,4 @@ +import type { IStats } from '@rocket.chat/core-typings'; import type { Logger } from '@rocket.chat/logger'; import { Statistics } from '@rocket.chat/models'; import { serverFetch as fetch } from '@rocket.chat/server-fetch'; @@ -7,32 +8,53 @@ import { Meteor } from 'meteor/meteor'; import { statistics } from '..'; import { getWorkspaceAccessToken } from '../../../cloud/server'; -export async function sendUsageReport(logger: Logger): Promise { - return tracerSpan('generateStatistics', {}, async () => { - const cronStatistics = await statistics.save(); +async function sendStats(logger: Logger, cronStatistics: IStats): Promise { + try { + const token = await getWorkspaceAccessToken(); + const headers = { ...(token && { Authorization: `Bearer ${token}` }) }; - try { - const token = await getWorkspaceAccessToken(); - const headers = { ...(token && { Authorization: `Bearer ${token}` }) }; + const response = await fetch('https://collector.rocket.chat/', { + method: 'POST', + body: { + ...cronStatistics, + host: Meteor.absoluteUrl(), + }, + headers, + }); + + const { statsToken } = await response.json(); + + if (statsToken != null) { + await Statistics.updateOne({ _id: cronStatistics._id }, { $set: { statsToken } }); + return statsToken; + } + } catch (err) { + logger.error({ msg: 'Failed to send usage report', err }); + } +} - const response = await fetch('https://collector.rocket.chat/', { - method: 'POST', - body: { - ...cronStatistics, - host: Meteor.absoluteUrl(), - }, - headers, - }); +export async function sendUsageReport(logger: Logger): Promise { + return tracerSpan('generateStatistics', {}, async () => { + const last = await Statistics.findLast(); + if (last) { + const yesterday = new Date(); + yesterday.setDate(yesterday.getDate() - 1); - const { statsToken } = await response.json(); + // if the last data we have has less than 24h and was not sent to yet, send it + if (last.createdAt > yesterday) { + // but if it has the confirmation token, we can skip + if (last.statsToken) { + return last.statsToken; + } - if (statsToken != null) { - await Statistics.updateOne({ _id: cronStatistics._id }, { $set: { statsToken } }); - return statsToken; + // if it doesn't it means the request failed, so we try sending again with the same data + return sendStats(logger, last); } - } catch (error) { - /* error*/ - logger.warn('Failed to send usage report'); } + + // if our latest stats has more than 24h, it is time to generate a new one and send it + const cronStatistics = await statistics.save(); + + return sendStats(logger, cronStatistics); }); } diff --git a/apps/meteor/app/statistics/server/functions/slashCommandsStats.ts b/apps/meteor/app/statistics/server/functions/slashCommandsStats.ts index 6d973a64c6be8..5cb9e26d6d57f 100644 --- a/apps/meteor/app/statistics/server/functions/slashCommandsStats.ts +++ b/apps/meteor/app/statistics/server/functions/slashCommandsStats.ts @@ -1,5 +1,5 @@ -import telemetryEvent from '../lib/telemetryEvents'; import { updateCounter } from './updateStatsCounter'; +import telemetryEvent from '../lib/telemetryEvents'; type slashCommandsDataType = { command: string }; diff --git a/apps/meteor/app/statistics/server/lib/SAUMonitor.ts b/apps/meteor/app/statistics/server/lib/SAUMonitor.ts index 0db63a9294914..e1cdab7f07738 100644 --- a/apps/meteor/app/statistics/server/lib/SAUMonitor.ts +++ b/apps/meteor/app/statistics/server/lib/SAUMonitor.ts @@ -6,11 +6,11 @@ import mem from 'mem'; import { Meteor } from 'meteor/meteor'; import UAParser from 'ua-parser-js'; +import { UAParserMobile, UAParserDesktop } from './UAParserCustom'; import { getMostImportantRole } from '../../../../lib/roles/getMostImportantRole'; import { getClientAddress } from '../../../../server/lib/getClientAddress'; import { aggregates } from '../../../../server/models/raw/Sessions'; import { sauEvents } from '../../../../server/services/sauMonitor/events'; -import { UAParserMobile, UAParserDesktop } from './UAParserCustom'; type DateObj = { day: number; month: number; year: number }; diff --git a/apps/meteor/app/statistics/server/lib/statistics.ts b/apps/meteor/app/statistics/server/lib/statistics.ts index 65b363cad1252..25d93a6985c35 100644 --- a/apps/meteor/app/statistics/server/lib/statistics.ts +++ b/apps/meteor/app/statistics/server/lib/statistics.ts @@ -29,6 +29,10 @@ import { import { MongoInternals } from 'meteor/mongo'; import moment from 'moment'; +import { getAppsStatistics } from './getAppsStatistics'; +import { getStatistics as getEnterpriseStatistics } from './getEEStatistics'; +import { getImporterStatistics } from './getImporterStatistics'; +import { getServicesStatistics } from './getServicesStatistics'; import { readSecondaryPreferred } from '../../../../server/database/readSecondaryPreferred'; import { isRunningMs } from '../../../../server/lib/isRunningMs'; import { getControl } from '../../../../server/lib/migrations'; @@ -38,10 +42,6 @@ import { getStatistics as federationGetStatistics } from '../../../federation/se import { settings } from '../../../settings/server'; import { Info } from '../../../utils/rocketchat.info'; import { getMongoInfo } from '../../../utils/server/functions/getMongoInfo'; -import { getAppsStatistics } from './getAppsStatistics'; -import { getStatistics as getEnterpriseStatistics } from './getEEStatistics'; -import { getImporterStatistics } from './getImporterStatistics'; -import { getServicesStatistics } from './getServicesStatistics'; const getUserLanguages = async (totalUsers: number): Promise<{ [key: string]: number }> => { const result = await Users.getUserLanguages(); diff --git a/apps/meteor/app/theme/client/imports/components/emoji.css b/apps/meteor/app/theme/client/imports/components/emoji.css index 5180c05c5f5c0..58668075584d0 100644 --- a/apps/meteor/app/theme/client/imports/components/emoji.css +++ b/apps/meteor/app/theme/client/imports/components/emoji.css @@ -1,21 +1,16 @@ .emoji { position: relative; - display: inline-block; overflow: hidden; - width: 1.375rem; height: 1.375rem; margin: 0 0.15em; - vertical-align: middle; white-space: nowrap; text-indent: 100%; - background-repeat: no-repeat; background-position: center; background-size: contain; - font-size: inherit; line-height: normal; image-rendering: auto; diff --git a/apps/meteor/app/theme/client/imports/components/flex-nav.css b/apps/meteor/app/theme/client/imports/components/flex-nav.css index c521fc6a49b2b..6db8bf21ee945 100644 --- a/apps/meteor/app/theme/client/imports/components/flex-nav.css +++ b/apps/meteor/app/theme/client/imports/components/flex-nav.css @@ -3,12 +3,9 @@ z-index: 3; top: 0; left: 0; - width: 100%; height: 100%; - transition: transform 0.15s cubic-bezier(0.5, 0, 0.1, 1); - background-color: var(--flex-nav-background); will-change: transform; diff --git a/apps/meteor/app/theme/client/imports/components/loading.css b/apps/meteor/app/theme/client/imports/components/loading.css index a6ff93cc4fb75..d3212475d3932 100644 --- a/apps/meteor/app/theme/client/imports/components/loading.css +++ b/apps/meteor/app/theme/client/imports/components/loading.css @@ -1,51 +1,44 @@ -.loading__animation { - display: flex; - align-items: center; - justify-content: center; -} - -.loading__animation__bounce { - display: inline-block; - - width: 1rem; - height: 1rem; - margin: 2px; - - animation: loading-bouncedelay 1.4s infinite ease-in-out both; - - -webkit-animation-delay: -0.32s; - animation-delay: -0.32s; - - border-radius: 100%; - background-color: var(--loading-bounce-color-light); - - @media (prefers-color-scheme: dark) { - background: var(--loading-bounce-color-dark); +.loading { + &__animation { + display: flex; + align-items: center; + justify-content: center; } -} - -.loading__animation__bounce--medium { - display: inline-block; - width: 1.25rem; - height: 1.25rem; -} + &__animation__bounce { + display: inline-block; + width: 1rem; + height: 1rem; + margin: 2px; + animation: loading-bouncedelay 1.4s infinite ease-in-out both; + animation-delay: -0.32s; + border-radius: 100%; + background-color: var(--loading-bounce-color-light); + + @media (prefers-color-scheme: dark) { + background: var(--loading-bounce-color-dark); + } + } -.loading__animation__bounce--large { - display: inline-block; + &__animation__bounce--medium { + display: inline-block; + width: 1.25rem; + height: 1.25rem; + } - width: 1.5rem; - height: 1.5rem; -} + &__animation__bounce--large { + display: inline-block; + width: 1.5rem; + height: 1.5rem; + } -.loading__animation__bounce + .loading__animation__bounce { - -webkit-animation-delay: -0.16s; - animation-delay: -0.16s; -} + &__animation__bounce + &__animation__bounce { + animation-delay: -0.16s; + } -.loading__animation__bounce + .loading__animation__bounce + .loading__animation__bounce { - -webkit-animation-delay: 0s; - animation-delay: 0s; + &__animation__bounce + &__animation__bounce + &__animation__bounce { + animation-delay: 0s; + } } @keyframes loading-bouncedelay { diff --git a/apps/meteor/app/theme/client/imports/components/main-content.css b/apps/meteor/app/theme/client/imports/components/main-content.css index 4c01f982ee363..3fd983bff8f45 100644 --- a/apps/meteor/app/theme/client/imports/components/main-content.css +++ b/apps/meteor/app/theme/client/imports/components/main-content.css @@ -1,14 +1,10 @@ .main-content { position: relative; - z-index: 0; - display: flex; flex-direction: column; flex: 1 1 100%; - width: 1vw; - height: 100%; } diff --git a/apps/meteor/app/theme/client/imports/components/message-box.css b/apps/meteor/app/theme/client/imports/components/message-box.css index 877a643e114f4..f55a49f4ec37d 100644 --- a/apps/meteor/app/theme/client/imports/components/message-box.css +++ b/apps/meteor/app/theme/client/imports/components/message-box.css @@ -1,114 +1,6 @@ .rc-message-box { position: relative; - width: 100%; padding: 0 24px; - font-size: var(--message-box-text-size); - - &__toolbar-formatting-item { - display: flex; - - min-width: 16px; - margin: 0 4px; - - transition: color 0.1s; - - color: var(--message-box-markdown-color); - align-items: center; - justify-content: center; - - &:hover, - &:focus, - &.active { - color: var(--message-box-markdown-hover-color); - } - } - - &__toolbar-formatting-link { - color: currentColor; - - font-size: 0.75rem; - } - - &__audio-message { - display: flex; - - &-mic { - display: flex; - } - - &-done, - &-cancel, - &-timer { - display: none; - } - - &-done { - color: var(--rc-color-success); - } - - &-cancel { - color: var(--rc-color-error); - } - - &-timer { - margin: 0 -0.25rem; - align-items: center; - justify-content: center; - - &-dot, - &-text { - margin: 0 0.25rem; - } - - &-text { - min-width: 3em; - } - - &-dot { - flex: 0 0 auto; - - width: 0.5rem; - height: 0.5rem; - - border-radius: 50%; - background-color: red; - } - } - - &--recording { - .rc-message-box__audio-message-mic, - .rc-message-box__audio-message-loading { - display: none; - } - - .rc-message-box__audio-message-done, - .rc-message-box__audio-message-cancel, - .rc-message-box__audio-message-timer { - display: flex; - } - } - - &--loading { - .rc-message-box__audio-message-mic, - .rc-message-box__audio-message-done, - .rc-message-box__audio-message-cancel, - .rc-message-box__audio-message-timer { - display: none; - } - - .rc-message-box__audio-message-loading { - display: flex; - } - } - - &--busy { - .rc-message-box__audio-message-mic { - cursor: not-allowed; - - opacity: 0.5; - } - } - } } diff --git a/apps/meteor/app/theme/client/imports/components/messages.css b/apps/meteor/app/theme/client/imports/components/messages.css deleted file mode 100644 index 34ae60609df07..0000000000000 --- a/apps/meteor/app/theme/client/imports/components/messages.css +++ /dev/null @@ -1,67 +0,0 @@ -.messages-container-wrapper { - position: relative; -} - -.message-actions { - position: absolute; - z-index: 2; - top: -28px; - right: 0.4rem; - - display: none; - - box-sizing: border-box; - - padding: 2px; - - user-select: none; - - color: var(--color-darkest); - - border: 1px solid #f2f3f7; - border-radius: 4px; - - background: var(rcx-surface, #ffffff); - - font-size: 1.25rem; - - &__buttons { - display: flex; - } - - &__button, - &__menu { - padding: 2px; - - cursor: pointer; - - &:hover { - border-radius: 2px; - background: #eeeff1; - } - - &-icon { - fill: currentColor; - } - } -} - -.rc-ui-kit { - display: inline-block; - - width: 100%; - - max-width: 400px; -} - -.rtl .message-actions { - right: auto; - left: 2px; -} - -.message-popup .rcx-message-attachment { - overflow-y: auto !important; - - max-width: 100% !important; - max-height: 200px !important; -} diff --git a/apps/meteor/app/theme/client/imports/components/modal.css b/apps/meteor/app/theme/client/imports/components/modal.css deleted file mode 100644 index 50cdb198b0723..0000000000000 --- a/apps/meteor/app/theme/client/imports/components/modal.css +++ /dev/null @@ -1,168 +0,0 @@ -.rc-modal { - display: flex; - flex-direction: column; - - min-width: 400px; - max-width: 500px; - height: auto; - max-height: 90%; - - padding: 1rem; - - animation: dropdown-show 0.3s cubic-bezier(0.45, 0.05, 0.55, 0.95); - - border: none; - - background: white; - - box-shadow: 0 0 2px 0 rgba(47, 52, 61, 0.08), 0 0 12px 0 rgba(47, 52, 61, 0.12); - - &-wrapper { - position: fixed; - z-index: 10; - top: 0; - right: 0; - bottom: 0; - left: 0; - - display: flex; - - padding: 10px; - - background: rgba(47, 52, 61, 0.8); - align-items: center; - justify-content: center; - } - - &--modal { - width: 640px; - max-width: 100%; - } - - &--modal &__title { - font-size: 1.375rem; - font-weight: 500; - } - - &__description { - font-size: 0.874rem; - margin-block-end: 1.5rem; - margin-block-start: 0.5rem; - } - - &__title { - flex: 1 1 auto; - - font-size: 1rem; - } - - &__close { - cursor: pointer; - transform: rotate(45deg); - - font-size: 20px; - } - - &__header { - display: flex; - flex-direction: row; - flex: 0 0 auto; - - margin-bottom: -16px; - padding: 16px; - - font-size: 21px; - justify-content: flex-end; - } - - &__content { - position: relative; - - display: flex; - - overflow: hidden auto; - - flex-direction: column; - - min-height: 72px; - max-height: 90%; - - padding: 16px; - - animation: dropdown-show 0.1s cubic-bezier(0.45, 0.05, 0.55, 0.95); - align-items: stretch; - } - - &__content-icon { - margin: 1.2rem auto; - - font-size: 6rem; - - &--modal-warning { - color: var(--rc-color-alert); - } - - &--modal-success { - color: var(--rc-color-success-light); - } - - &--modal-info { - color: var(--rc-color-alert); - } - - &--modal-error { - color: var(--rc-color-error-light); - } - } - - &__content-text { - text-align: center; - word-break: break-word; - - font-size: 1rem; - line-height: 1.5; - } - - &__content-error { - display: none; - - width: 100%; - margin: 0.5rem 0; - - text-align: center; - word-break: break-word; - - color: var(--color-white); - background: var(--rc-color-error); - - line-height: 2; - } - - &__footer { - display: flex; - - flex: 0 0 auto; - - padding: 1rem; - - justify-content: space-between; - - & > .rc-button { - margin: 0; - } - } -} - -@media (width <= 400px) { - .rc-modal { - top: 0 !important; - bottom: 0; - left: 0 !important; - - width: 100%; - min-width: 100%; - max-width: 100%; - - animation: dropup-show 0.3s cubic-bezier(0.45, 0.05, 0.55, 0.95); - } -} diff --git a/apps/meteor/app/theme/client/imports/forms/button.css b/apps/meteor/app/theme/client/imports/forms/button.css deleted file mode 100644 index 463ed17346cad..0000000000000 --- a/apps/meteor/app/theme/client/imports/forms/button.css +++ /dev/null @@ -1,219 +0,0 @@ -.rc-button { - &:not([disabled]):hover { - opacity: 0.6; - } - - &--icon > svg { - margin: 0 5px 0 -5px; - - font-size: 20px; - fill: currentColor; - - .rtl & { - margin: 0 -5px 0 5px; - } - } - - position: relative; - - display: flex; - - height: 40px; - - min-height: 40px; - - padding: 0 1.5rem; - - cursor: pointer; - transition: opacity 0.3s, background-color 0.3s, color 0.3s; - text-align: center; - - color: #000000; - - border-width: var(--button-border-width); - border-style: solid; - border-color: #000000; - - border-radius: var(--button-border-radius); - background-color: transparent; - - font-size: var(--button-text-size); - font-weight: 600; - - align-items: center; - justify-content: center; - - &:active, - &:focus:hover { - outline: none; - } - - &:active { - transform: translateY(2px); - - opacity: 0.9; - } - - &:active::before { - top: -2px; - } - - &:disabled { - cursor: default; - - color: var(--button-disabled-text-color); - border: 0; - border-color: var(--button-disabled-background); - background-color: var(--button-disabled-background); - } - - &--invisible { - visibility: hidden; - } - - &--primary { - color: var(--button-primary-text-color); - border: 0; - background-color: var(--button-primary-background); - } - - &--nude { - border: none; - background-color: inherit; - - font-weight: 400; - } - - &--primary.rc-button--nude { - color: var(--button-primary-background); - } - - &--primary.rc-button--outline { - color: var(--button-primary-background); - border-color: var(--button-primary-background); - } - - &--secondary { - color: var(--button-secondary-text-color); - border: 0; - border-color: var(--button-secondary-background); - background-color: var(--button-secondary-background); - } - - &--secondary.rc-button--outline { - color: var(--button-secondary-background); - border-color: var(--button-secondary-background); - } - - &--cancel { - color: var(--button-primary-text-color); - border: 0; - border-color: var(--button-cancel-color); - background-color: var(--button-cancel-color); - } - - &--cancel.rc-button--outline { - color: var(--button-cancel-color); - border-color: var(--button-cancel-color); - } - - &--small { - height: var(--button-height-small); - min-height: var(--button-height-small); - padding: var(--button-padding-small); - - font-size: var(--button-text-size-small); - } - - &--square { - display: flex; - flex: 0 0 var(--button-square-size); - - margin: 0; - padding: 0; - align-items: center; - justify-content: center; - } - - &--outline { - border-width: 2px; - border-style: solid; - background: transparent; - } - - &--stack { - width: 100%; - } - - &--no-padding { - padding-right: 0; - padding-left: 0; - } - - &.loading { - position: relative; - - padding-right: calc(3 * 0.782rem); - - transition: padding-right 0.3s; - - &::before { - position: absolute; - top: 25%; - right: 0.782rem; - - display: block; - - width: 20px; - height: 20px; - - content: ""; - animation: spin 1s infinite cubic-bezier(0.14, 0.48, 0.45, 0.63); - - border: 0.15rem solid rgba(127, 127, 127, 0.5); - border-top-color: white; - border-radius: 50%; - } - } - - &__group { - display: flex; - - flex-direction: row; - - margin: 10px -5px; - - justify-content: flex-end; - - & > .rc-button { - margin: 0 5px; - } - - &--wrap { - margin: 5px -5px; - flex-wrap: wrap; - - & > .rc-button { - margin: 5px; - } - } - - &--stretch { - justify-content: stretch; - - & > .rc-button { - flex: 1 1; - } - } - - &--vertical { - flex-direction: column; - } - } -} - -@media (width < 780px) { - .rc-button--full { - width: 100%; - } -} diff --git a/apps/meteor/app/theme/client/imports/forms/input.css b/apps/meteor/app/theme/client/imports/forms/input.css deleted file mode 100644 index 21ef11f574fab..0000000000000 --- a/apps/meteor/app/theme/client/imports/forms/input.css +++ /dev/null @@ -1,245 +0,0 @@ -textarea.rc-input__element { - height: auto; - padding: 0.5rem 1rem; - - font-family: inherit; -} - -.rc-input { - position: relative; - - width: 100%; - - &__label { - display: block; - - cursor: pointer; - } - - &__title { - font-size: var(--input-font-size); - } - - &__wrapper { - position: relative; - - padding: 0.5rem 0; - - color: var(--input-icon-color); - } - - &__icon { - position: absolute; - top: 0; - left: 1rem; - - display: flex; - - width: 20px; - height: 100%; - - cursor: default; - align-items: center; - justify-content: center; - - & + .rc-input__element { - padding: 0 1rem 0 2.75rem; - } - - &--right { - right: 1rem; - left: auto; - } - - &--clickable { - cursor: pointer; - } - - &--right + .rc-input__element { - padding: 0 2.75rem 0 1rem; - } - } - - &__element { - width: 100%; - height: 2.5rem; - padding: 0 1rem; - - text-align: start; - - text-overflow: ellipsis; - - color: var(--input-text-color); - - border-width: var(--input-border-width); - border-color: var(--input-border-color); - border-radius: var(--input-border-radius); - background-color: transparent; - - font-size: var(--input-font-size); - line-height: normal; - - &--small { - height: 2rem; - } - - &::placeholder { - text-align: start; - text-overflow: ellipsis; - - color: var(--input-placeholder-color); - } - - &[type=color] { - height: 45px; - } - } - - &__description { - margin-bottom: 0.25rem; - - color: var(--input-description-text-color); - - font-size: var(--input-description-text-size); - } - - &__error { - display: flex; - - color: var(--input-error-color); - align-items: center; - - &-icon { - width: 20px; - - &--warning { - width: 20px; - height: 20px; - stroke: currentColor; - } - } - - &-message { - margin-left: 0.5rem; - } - } - - &--small { - font-size: 14px; - - & .rc-input__element { - padding-top: 8px; - padding-bottom: 8px; - } - } - - &--error { - .rc-tags { - border-color: var(--input-error-color); - } - - & .rc-input { - &__element { - border-color: var(--input-error-color); - } - } - } -} - -.rc-input-file { - position: relative; - - width: 100%; - - &__label { - display: block; - - cursor: pointer; - } - - &__title { - font-size: var(--input-font-size); - } - - &__wrapper { - display: flex; - flex-direction: row; - - width: 100%; - margin: 0.5rem 0; - padding: 0.3rem; - - color: var(--input-text-color); - - border-width: var(--input-border-width); - border-color: var(--input-border-color); - border-radius: var(--input-border-radius); - background-color: transparent; - - font-size: var(--input-font-size); - align-items: center; - justify-content: flex-end; - - &::placeholder { - color: var(--input-placeholder-color); - } - - & > .rc-button { - flex: 0 0 auto; - - height: 10px; - min-height: 31px; - margin: 0; - padding: 8px; - - border-color: #e1e5e8; - border-radius: 2px; - background: #f1f1f1; - } - } - - &__name { - overflow: hidden; - - flex: 0 1 auto; - - width: 100%; - - padding: 0 5px; - - white-space: nowrap; - - text-overflow: ellipsis; - - line-height: 16px; - } - - &__element { - display: none; - } - - &__description { - color: var(--color-gray); - - font-size: 0.875rem; - } -} - -select.rc-input { - width: 100%; - padding: 0.782rem; - - color: var(--input-text-color); - - border-width: var(--input-border-width); - border-color: var(--input-border-color); - border-radius: var(--input-border-radius); - background-color: transparent; - - font-size: var(--input-font-size); - appearance: none; - - &--small { - padding: 0.5rem 1rem; - } -} diff --git a/apps/meteor/app/theme/client/imports/general/base.css b/apps/meteor/app/theme/client/imports/general/base.css index 9aa9b6c5ea9f9..0f1f90c913558 100644 --- a/apps/meteor/app/theme/client/imports/general/base.css +++ b/apps/meteor/app/theme/client/imports/general/base.css @@ -6,7 +6,6 @@ html { overflow-y: auto; - height: 100%; &.noscroll { @@ -16,17 +15,12 @@ html { body { position: relative; - display: flex; - overflow: visible; - flex-direction: column; - width: 100%; height: 100%; padding: 0; - font-family: var(--body-font-family); font-size: var(--text-small-size); -webkit-font-smoothing: antialiased; @@ -45,43 +39,32 @@ body { &::after { display: table; clear: both; - content: ''; } } button { padding: 0; - cursor: pointer; text-align: left; text-transform: inherit; - color: inherit; border-width: 0; background: none; - font-style: inherit; } #rocket-chat { position: relative; - display: flex; - overflow: hidden; - flex: 1 1 auto; - height: 100%; - max-height: 100%; - align-items: stretch; &.animated-hidden { visibility: hidden; - opacity: 0; } } @@ -96,37 +79,25 @@ button { @media print { #rocket-chat.menu-nav, - .simplebar-content-wrapper, - section.rcx-box.rcx-box--full, - .rc-old.main-content { + .main-content { overflow: visible !important; /* 1 */ - height: auto !important; /* 1 */ max-height: none !important; /* 1 */ flex-shrink: 0 !important; /* 1 */ } - div.simplebar-offset, - .simplebar-mask, - .rc-old .messages-container .wrapper { + .messages-container .wrapper { position: relative !important; /* 1 */ } - .simplebar-placeholder { - height: 0 !important; /* 1 */ - } - body { height: auto !important; /* 1 */ } - .rc-old .room-container, - .rc-old .room-container:first-child, - .rc-old .messages-container-main, - .rc-old .messages-container-wrapper, - .rc-old .main-content-flex { + .messages-container-main, + .messages-container-wrapper, + .main-content-flex { flex: 1 0 auto !important; /* 1 */ - height: auto !important; /* 1 */ } @@ -134,15 +105,15 @@ button { display: none !important; /* 1 */ } - .rcx-box.rcx-box--full { - overflow: visible !important /* 1 */; - - height: auto !important /* 1 */; + .rcx-box { + &--full.rcx-box { + overflow: visible !important /* 1 */; + height: auto !important /* 1 */; + } } .rc-scrollbars-container { overflow: visible !important; /* 1 */ - height: auto !important; /* 1 */ } @@ -153,6 +124,5 @@ button { .gallery-item { max-width: 100%; - cursor: pointer; } diff --git a/apps/meteor/app/theme/client/imports/general/base_old.css b/apps/meteor/app/theme/client/imports/general/base_old.css index 3120d9c05ff01..5b924491b54ec 100644 --- a/apps/meteor/app/theme/client/imports/general/base_old.css +++ b/apps/meteor/app/theme/client/imports/general/base_old.css @@ -1,730 +1,37 @@ -.rc-old .no-scroll { - overflow: hidden !important; -} - -.rc-old code { - margin: 5px 0; - padding: 0.5em; - - text-align: left; - vertical-align: middle; - white-space: pre-wrap; - word-wrap: break-word; - - border-width: 1px; - border-radius: var(--border-radius); - - font-family: Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace; - font-size: 13px; - font-weight: 600; - direction: ltr; - unicode-bidi: embed; - - &.inline { - display: inline; - - padding: 0.05rem 0.2rem; - - line-height: 1.25rem; - } -} - -.rc-old code.hljs { - overflow-y: hidden; -} - -.rc-old pre { - display: inline-block; - - width: 100%; -} - -.rc-old blockquote { - position: relative; - - display: block; - - clear: both; - - min-height: 20px; - - padding-left: 10px; - - &::after { - display: table; - clear: both; - - content: ''; - } - - &:first-child::before { - border-radius: 2px 2px 0 0; - } - - &:last-child::before { - border-radius: 0 0 2px 2px; - } - - &::before { - position: absolute; - top: 0; - bottom: 0; - left: 0; - - width: 2px; - - content: ' '; - } -} - -.rc-old .login-terms { - width: 520px; - max-width: 100%; - margin: auto; - padding: 10px; - - font-size: smaller; - - & a { - font-weight: bold !important; - } -} - -.upload-preview { - & .upload-preview-file { - height: 200px; - - background-repeat: no-repeat; - background-position: center center; - background-size: contain; - } -} - -.upload-preview-title { - padding: 3px; - - border-radius: 0 0 5px 5px; -} - -.copyonly { - display: none; - - width: 0; - height: 0; - - user-select: none; - vertical-align: baseline; - - font-size: 0; - -moz-box-orient: vertical; - - code & { - float: left; - } -} - -.rc-old .full-page .hidden { - display: none !important; - visibility: hidden !important; -} - -.rc-old .hidden { - display: none !important; -} - -.rc-old .page-container { - position: absolute; - top: 0; - left: 0; - - display: flex; - - overflow-y: hidden; - flex-direction: column; - - width: 100%; - height: 100%; - - padding: 1.25rem; - - & .content { - display: flex; - overflow-y: auto; - flex-direction: column; - flex: 1 1 auto; - - margin: 0 -1.25rem; - padding: 1.25rem 1.25rem 0; - - line-height: 1.3em; - -webkit-overflow-scrolling: touch; - - & fieldset { - margin-bottom: 1em; - } - - & .rocket-form { - & fieldset { - display: block; - - margin: 1em 0 1.5em; - - & small { - font-size: 11px; - } - } - - & legend { - position: relative; - - display: block; - - width: 100%; - margin: 12px 0; - - font-weight: bold; - - & h3 { - margin-bottom: 5px !important; - } - } - - & .submit { - margin-top: 20px; - - text-align: right; - } - } - } -} - -.rc-old .input-line { - display: block; - clear: both; - - margin-bottom: 12px; - - &::after { - display: table; - clear: both; - - content: ''; - } - - &:nth-last-child(1) { - margin-bottom: 0; - } - - &.search { - & i { - position: absolute; - top: 10px; - left: 7px; - } - - & .icon-spin { - right: 5px; - left: auto; - - animation-name: spin; - animation-duration: 2000ms; - animation-timing-function: linear; - animation-iteration-count: infinite; - - font-weight: 400; - } - - & input { - padding-left: 30px; - } - } - - & > label { - display: block; - - margin-bottom: 4px; - } - - & > div { - position: relative; - - & .right { - position: absolute; - z-index: 10; - top: 10px; - right: 10px; - } - } - - & > div.-autocomplete-container { - position: absolute; - } - - & input[type='text'] { - display: block; - } -} - -.rc-old form.inline { - & input[type='text'], - & input[type='number'], - & input[type='email'], - & input[type='url'], - & input[type='password'], - & select { - width: auto; - } -} - -.rc-old .-autocomplete-container { - top: auto; - - width: 100%; - - border-width: 0; - border-radius: 0; - box-shadow: 1px 1px 0 rgba(0, 0, 0, 0.2); - - & p { - padding: 8px; - - font-size: 14px; - } - - & .loading-animation { - position: relative; - - min-height: 60px; - } -} - -.rc-old .-autocomplete-item { - padding: 8px 5px; - - cursor: pointer; - - font-size: 12px; -} - -.rc-old label.required::after { - content: ' *'; -} - -.rc-old.flex-nav { - position: fixed; - z-index: 3; - top: 0; - left: 0; - - overflow-x: hidden; - overflow-y: auto; - - width: var(--rooms-box-width); - height: 100%; - - transition: transform 0.15s cubic-bezier(0.5, 0, 0.1, 1); - - &.animated-hidden { - transform: translateX(-100%); - - & header, - & footer, - & .content { - transform: translateX(-100%); - } - } - - & header, - & footer, - & .content { - transition: transform 0.425s cubic-bezier(0, 0.8, 0.05, 1); - } - - & > section { - position: absolute; - top: 0; - left: 0; - - width: 100%; - height: 100%; - } - - & header { - position: absolute; - z-index: 110; - top: 0; - left: 0; - - display: table; - - width: 100%; - height: var(--header-min-height); - min-height: var(--header-min-height); - padding-left: 15px; - - cursor: pointer; - - & > div { - display: table-cell; - - text-align: left; - vertical-align: middle; - } - - & h4 { - position: relative; - - overflow: hidden; - - margin-top: 2px; - - text-overflow: ellipsis; - - font-size: 20px; - font-weight: 300; - line-height: 24px; - } - - & p { - margin-top: 4px; - - font-size: 13px; - font-weight: 400; - line-height: 18px; - } - } - - & footer { - position: absolute; - z-index: 120; - bottom: 0; - left: 0; - - display: table; - - width: 100%; - height: var(--footer-min-height); - padding: 0 10px; - - text-align: left; - - & > div { - display: table-cell; - - text-align: left; - vertical-align: middle; - } - } - - & .content { - position: absolute; - top: var(--header-min-height); - - display: block; - overflow-x: hidden; - overflow-y: auto; - - width: 100%; - height: calc(100% - calc(var(--header-min-height) + var(--footer-min-height))); - padding: 20px 10px; - direction: rtl; - -webkit-overflow-scrolling: touch; - - & > .wrapper { - direction: ltr; - } - - & h4 { - margin-bottom: 30px; - - text-transform: uppercase; - - font-size: 13px; - font-weight: 400; - } - } - - & .input-line { - margin-bottom: 25px; - - &:nth-last-child(1) { - margin-bottom: 0; - } - - & label { - margin-bottom: 0; - - font-weight: 400; - } - - & input[type='text'], - & input[type='password'], - & select { - padding: 0 8px 0 30px; - - border-width: 1px; - border-radius: var(--border-radius); - box-shadow: 0 0 0; - appearance: none; - } - - & .inline-fields { - & input, - & label, - & select { - display: inline-block; - } - } - - &.toggle { - font-size: 0; - - & > label { - display: inline-block; - - width: calc(100% - 40px); - - vertical-align: top; - - font-size: 14px; - } - - & > div { - display: inline-block; - - width: 40px; - } - } - - &.no-icon input { - padding: 0 8px; - } - } - - & .selected-users { - padding: 20px 0 0; - - & li { - display: inline-block; - - margin-right: 2px; - margin-bottom: 2px; - padding: 5px; - } - - & i { - cursor: pointer; - } - } -} - -.rc-old .new-room-highlight a { - animation: highlight 6s infinite; -} - -/* MAIN CONTENT + MAIN PAGES */ - -.rc-old .page-settings { - & .settings-file-preview { - display: flex; - align-items: center; - - & input[type='file'] { - position: absolute !important; - z-index: 10000; - top: 0; - left: 0; - - width: 100%; - height: 100%; - - cursor: pointer; - - opacity: 0; - - & * { - cursor: pointer; - } - } - - & .preview { - overflow: hidden; - - width: 100px; - height: 40px; - - margin-right: 0.75rem; - - border-width: var(--input-border-width); - border-color: var(--input-border-color); - border-radius: var(--input-border-radius); - - background-repeat: no-repeat; - background-position: center center; - background-size: contain; - - &.no-file { - display: flex; - - align-items: center; - justify-content: center; - } - } - } -} - -.rc-old .room-not-found { - display: flex; - flex-direction: column; - - font-size: 30px; - align-items: center; - justify-content: center; - - & div { - text-align: center; - - line-height: 40px; - } - - & i { - padding-bottom: 30px; - - font-size: 100px; - } -} - -.rc-old .container-bars { - position: relative; - z-index: 2; - +.copyonly { display: none; - visibility: hidden; - overflow: hidden; - flex-direction: column; - - margin: 8px 10px 0; - - transition: transform 0.4s ease, visibility 0.3s ease, opacity 0.3s ease; - transform: translateY(-10px); - - opacity: 0; - border-radius: var(--border-radius); - box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.2), 0 2px 10px 0 rgba(0, 0, 0, 0.16); - - font-size: 1em; - font-weight: bold; - - &.show { - display: flex; - visibility: visible; - - transform: translateY(0); - - opacity: 1; - } - - & > div { - padding: 0 10px; - - line-height: 28px; - } - - & .upload-progress { - position: relative; - - display: flex; - - height: 28px; - - & .upload-progress-progress { - position: absolute; - z-index: 1; - left: 0; - - width: 0%; - height: 100%; - - transition: width, 1s, ease-out; - } - - & .upload-progress-text { - z-index: 2; - right: 0; - left: 0; - - overflow: hidden; - - width: 50%; - - height: 100%; - padding: 0 10px; - - white-space: nowrap; - text-overflow: ellipsis; - flex-grow: 1; - - & > a { - float: right; - - cursor: pointer; - text-transform: uppercase; - } - } - - & .upload-progress-close { - position: relative; - z-index: 3; - - float: right; - - height: 100%; - - text-transform: uppercase; + width: 0; + height: 0; + user-select: none; + vertical-align: baseline; + font-size: 0; + -moz-box-orient: vertical; - font-weight: bold; - } + code & { + float: left; } } -.rc-old .flex-tab-main-content { - position: relative; - z-index: 1; - - overflow: auto; - flex-grow: 1; -} - -.rc-old .room-container { - height: 100%; -} - /* change to page-messages */ -.rc-old .messages-container { +.messages-container { position: relative; - display: flex; flex-direction: column; flex: 1; - width: 100%; &-wrapper { display: flex; - flex: 1 1 auto; - height: 1%; } &-main { position: relative; - display: flex; flex-direction: column; flex: 1 1 auto; - width: 50%; } @@ -732,13 +39,9 @@ position: absolute; top: 0; left: 0; - - overflow-x: hidden; - overflow-y: auto; - + overflow: hidden auto; width: 100%; height: 100%; - word-wrap: break-word; -webkit-overflow-scrolling: touch; } @@ -748,23 +51,8 @@ } } -.rc-old .preview-items .popup-item { - margin: 2px; - - padding: 0; - - cursor: pointer; - - user-select: none; - - border: solid 1px transparent; - - line-height: initial; -} - .messages-box { position: relative; - overflow: hidden; flex-grow: 1; @@ -775,392 +63,289 @@ & ul.messages-list { padding: 21px 0 10px; } - - & .editing .body { - border-radius: var(--border-radius); - } -} - -.rcx-message { - &.highlight { - animation: highlight 6s; - } -} - -.rc-old .attachment-description { - margin: 6px; - - line-height: 1; -} - -/* FLEX-TAB and FLEX-TAB views */ -.rc-old .main-content-flex { - display: flex; - - height: 100%; - flex-grow: 1; } -.page-loading { - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - - display: flex; - - text-align: center; - - background-color: var(--page-loading-background-light); - - align-items: center; - justify-content: center; - - @media (prefers-color-scheme: dark) { - background: var(--page-loading-background-dark); - } +.highlight-text { + padding: 0 2px 2px; + color: var(--rcx-color-font-pure-white, #ffffff); + border-radius: var(--border-radius); + background-color: var(--rcx-color-badge-background-level-4, #f5455c); } -.rc-old.full-page { - display: flex; - overflow: auto; - +.inline-video { width: 100%; - min-height: 100%; - margin: auto; - - text-align: center; - - background-repeat: no-repeat; - background-attachment: fixed; - - background-position: center; - background-size: cover; - align-items: flex-start; - flex-flow: row nowrap; - - & .wrapper { - position: relative; - z-index: 10; - - width: 100%; - margin: auto; - padding: 20px; - - text-align: center; - } - - & .logo { - display: block; - - width: 100%; - max-width: 520px; - margin: 0 auto; - padding: 0 20px; - - & > img { - position: relative; - z-index: 20; - top: 0; - right: 0; - - display: inline-block; - - max-width: 100%; - max-height: 150px; - } - } - - & a:not(.rcx-box) { - font-weight: 300; - } - - & .cell { - display: table-cell; - - text-align: center; - vertical-align: middle; - } - - & header:not(.rcx-box) { - position: relative; - z-index: 1; - - display: block; - - max-width: 520px; - margin: auto; - padding: 0 20px; - } - - & .text { - position: relative; - z-index: 1; - - max-width: 580px; - margin: 0 auto 25px; - - font-weight: 300; - - & .button { - margin-top: 20px; - padding: 16px 20px; - - font-weight: 400; - } - - & h1 { - display: none; - - margin-bottom: 20px; - - letter-spacing: -0.5px; - text-transform: uppercase; - - font-size: 24px; - font-weight: 600; - } - - & h2 { - margin: 18px 0; - - letter-spacing: -0.5px; - text-transform: uppercase; - - font-size: 20px; - font-weight: 300; - } - - & h3 { - margin: 18px 0; - - letter-spacing: -0.5px; - text-transform: uppercase; - - font-size: 16px; - font-weight: 300; - } - - & p { - margin: 18px 0; - - font-size: 16px; - font-weight: 400; - line-height: 24px; - } - } - - & footer { - position: relative; - z-index: 1; - - padding: 20px 0 0; - - & h4 { - margin-bottom: 8px; - - text-transform: uppercase; - - font-size: 12px; - font-weight: 300; - } - } - - & .share { - min-height: 40px; + max-width: 480px; + height: auto; + max-height: 270px; +} - border-radius: 50%; +.load-more { + position: relative; + height: 2rem; +} - line-height: 20px; +.rcx-message { + &.highlight { + animation: highlight 6s; + } +} - &::before { - border-radius: 50%; - } +.page-loading { + position: absolute; + inset: 0; + display: flex; + text-align: center; + background-color: var(--page-loading-background-light); + align-items: center; + justify-content: center; - & span { - display: none; - } + @media (prefers-color-scheme: dark) { + background: var(--page-loading-background-dark); } } -.rc-old .highlight-text { - padding: 0 2px 2px; - - color: var(--rcx-color-font-pure-white, #ffffff); +/* FLEX-TAB and FLEX-TAB views */ +.main-content-flex { + display: flex; + height: 100%; + flex-grow: 1; +} - border-radius: var(--border-radius); - background-color: var(--rcx-color-badge-background-level-4, #f5455c); +.no-scroll { + overflow: hidden !important; } -@keyframes zoomIn { - 0% { - transform: scale3d(0.9, 0.9, 0.9); +code { + margin: 5px 0; + padding: 0.5em; + text-align: left; + vertical-align: middle; + white-space: pre-wrap; + word-wrap: break-word; + border-width: 1px; + border-radius: var(--border-radius); + font-family: Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace; + font-size: 13px; + font-weight: 600; + direction: ltr; + unicode-bidi: embed; - opacity: 0; + &.inline { + display: inline; + padding: 0.05rem 0.2rem; + line-height: 1.25rem; } - 50% { - opacity: 1; + &.hljs { + overflow-y: hidden; } } -.rc-old .touch .footer { - padding-right: 10px; - padding-left: 10px; +pre { + display: inline-block; + width: 100%; } -.rc-old .alert-icon { +blockquote { + position: relative; display: block; + clear: both; + min-height: 20px; + padding-left: 10px; + + &::after { + display: table; + clear: both; + content: ''; + } - margin-bottom: 20px; + &::before { + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 2px; + content: ' '; + } - font-size: 80px; + &:first-child::before { + border-radius: 2px 2px 0 0; + } + + &:last-child::before { + border-radius: 0 0 2px 2px; + } } -.rc-old .inline-video { - width: 100%; - max-width: 480px; - height: auto; - max-height: 270px; +.new-room-highlight a { + animation: highlight 6s infinite; } -.rc-old .attention-message { - padding-top: 50px; +.page-settings { + & .settings-file-preview { + display: flex; + align-items: center; - font-size: 24px; + & input[type='file'] { + position: absolute !important; + z-index: 10000; + top: 0; + left: 0; + width: 100%; + height: 100%; + cursor: pointer; + opacity: 0; - & i { - display: block; + & * { + cursor: pointer; + } + } + + & .preview { + overflow: hidden; + width: 100px; + height: 40px; + margin-right: 0.75rem; + border-width: var(--input-border-width); + border-color: var(--input-border-color); + border-radius: var(--input-border-radius); + background-repeat: no-repeat; + background-position: center center; + background-size: contain; - margin-bottom: 20px; + &.no-file { + display: flex; + align-items: center; + justify-content: center; + } + } + } +} - font-size: 40px; +.room-not-found { + display: flex; + flex-direction: column; + font-size: 30px; + align-items: center; + justify-content: center; + + & div { + text-align: center; + line-height: 40px; } - & span { - display: block; + & i { + padding-bottom: 30px; + font-size: 100px; } } -.rc-old .load-more { +.container-bars { position: relative; + z-index: 2; + display: none; + visibility: hidden; + overflow: hidden; + flex-direction: column; + margin: 8px 10px 0; + transition: transform 0.4s ease, visibility 0.3s ease, opacity 0.3s ease; + transform: translateY(-10px); + opacity: 0; + border-radius: var(--border-radius); + box-shadow: 0 1px 1px 0 rgb(0 0 0 / 20%), 0 2px 10px 0 rgb(0 0 0 / 16%); + font-size: 1em; + font-weight: bold; - height: 2rem; -} + &.show { + display: flex; + visibility: visible; + transform: translateY(0); + opacity: 1; + } -.flex-tab.discussions > .flex-tab__content { - padding: 0; -} + & > div { + padding: 0 10px; + line-height: 28px; + } -.rc-old .flex-tab { - &__content { + & .upload-progress { + position: relative; display: flex; - flex-direction: column; + height: 28px; - height: 100%; - } + & .upload-progress-progress { + position: absolute; + z-index: 1; + left: 0; + width: 0%; + height: 100%; + transition: width, 1s, ease-out; + } - &__header { - flex: 0 0 auto; + & .upload-progress-text { + z-index: 2; + right: 0; + left: 0; + overflow: hidden; + width: 50%; + height: 100%; + padding: 0 10px; + white-space: nowrap; + text-overflow: ellipsis; + flex-grow: 1; - padding-bottom: 10px; - } + & > a { + float: right; + cursor: pointer; + text-transform: uppercase; + } + } - &__result { - overflow-x: hidden; - overflow-y: auto; - flex: 1 1 auto; + & .upload-progress-close { + position: relative; + z-index: 3; + float: right; + height: 100%; + text-transform: uppercase; + font-weight: bold; + } } +} - & .no-results { - text-align: center; - } +.flex-tab-main-content { + position: relative; + z-index: 1; + overflow: auto; + flex-grow: 1; } -.rc-old .code-colors { +.code-colors { color: var(--rcx-color-font-default, #1f2329); border-color: var(--rcx-color-stroke-extra-light, #ebecef); background-color: var(--rcx-color-surface-neutral, #e4e7ea); } -.rc-old .powered-by { - margin-top: 1em; -} - -.rc-old .code-error-box { - & .title { - margin-top: 5px; - padding: 5px; - - font-size: 16px; - font-weight: bold; - } - - & .script-error { - padding: 6px; - - border-left: 3px solid; - - font-size: 12px; - font-weight: bold; - } -} - -.rc-old .code-mirror-box { - & .CodeMirror { +.code-mirror-box { + & .CodeMirror { /* stylelint-disable-line */ border-width: var(--input-border-width); border-color: var(--input-border-color); border-radius: var(--input-border-radius); } &.code-mirror-box-fullscreen { - & .CodeMirror { + & .CodeMirror { /* stylelint-disable-line */ display: flex; flex-direction: column; flex-grow: 1; - & .CodeMirror-scroll { + & .CodeMirror-scroll { /* stylelint-disable-line */ flex-grow: 1; } } } } -.rc-old .collapse-switch { - cursor: pointer; -} - -.toggle-hidden { - cursor: pointer; - - font-style: italic; -} - -.rc-old .form-inline { - & input, - & select { - display: inline-block; - - width: auto; - - vertical-align: middle; - } - - & label { - display: inline-block; - - max-width: 100%; - } - - & .form-group { - display: inline-block; - - vertical-align: middle; - } -} - -.rc-old .embedded-view { +.embedded-view { & .messages-container { border-width: 0; @@ -1183,52 +368,20 @@ } } -.rc-old .user-info.deactivated { - text-decoration: line-through; - - opacity: 0.8; -} - -/* MEDIA QUERIES */ - -@media (width <= 1100px) { - .rc-old .flex-tab-container.opened .flex-tab { - position: absolute; - z-index: 100; - - right: 40px; - - height: 100%; - } -} - -@media (max-width: 767px) { - .rc-old.main-content { +@media (width <= 767px) { + .main-content { transition: right 0.25s cubic-bezier(0.5, 0, 0.1, 1), transform 0.1s linear; will-change: transform; } } -@media (height <= 480px) { - .rc-old .oauth-login { - margin-bottom: 6px; - } -} - -@media (width <= 440px) { - .rc-old .flex-tab-container.opened .flex-tab { - left: 0; - - width: auto; - } - - .flex-tab-container.opened { - left: 0; +@keyframes zoom-in { + 0% { + transform: scale3d(0.9, 0.9, 0.9); + opacity: 0; } -} -@media (height <= 400px) { - .upload-preview .upload-preview-file { - height: 100px; + 50% { + opacity: 1; } } diff --git a/apps/meteor/app/theme/client/imports/general/forms.css b/apps/meteor/app/theme/client/imports/general/forms.css deleted file mode 100644 index e02c81b5b089f..0000000000000 --- a/apps/meteor/app/theme/client/imports/general/forms.css +++ /dev/null @@ -1,204 +0,0 @@ -.input { - &.checkbox.toggle { - position: relative; - - min-height: 20px; - - & input { - position: absolute; - z-index: -1; - top: 0; - left: 0; - - width: 0; - height: 0; - - opacity: 0; - outline: 0; - - &:checked + label::after { - left: 25px; - } - } - - & label { - display: block; - - min-height: 20px; - - cursor: pointer; - user-select: none; - vertical-align: top; - - &::before { - position: absolute; - z-index: 0; - top: 0; - left: 0; - - display: block; - - width: 40px; - height: 16px; - - content: ''; - transition: background-color 0.2s ease-out; - - border-radius: 50px; - box-shadow: none; - } - - &::after { - position: absolute; - z-index: 1; - top: 1px; - left: 1px; - - width: 14px; - height: 14px; - - content: ''; - transition: left 0.2s ease-out; - - border-radius: 50%; - } - } - } -} - -.rc-form-group { - margin-bottom: var(--gap-between-elements); - - &--small { - margin-bottom: var(--default-small-padding); - } - - &--inline { - display: flex; - flex-direction: row; - - margin-right: -0.5rem; - - margin-left: -0.5rem; - - white-space: nowrap; - align-items: flex-end; - } - - & > .rc-form-item-inline { - flex: 1 1 auto; - - margin-right: 0.5rem; - - margin-left: 0.5rem; - - &--full { - flex: 0 0 100%; - } - } -} - -.rc-form-label { - display: block; - - margin-bottom: var(--label-margin-bottom); - - cursor: pointer; - - color: #2d343d; - - font-size: var(--input-font-size); -} - -.rc-form-fieldset { - padding: var(--default-padding); - - border-width: var(--input-border-width); - border-color: var(--input-border-color); - border-radius: var(--input-border-radius); - background-color: transparent; - - &--error { - color: var(--input-error-color); - border-color: var(--input-error-color); - } -} - -.rc-form-legend { - margin: 0 -5px; - - padding: 0 5px; - - color: #2d343d; - - font-size: 1rem; - font-weight: 500; -} - -.rc-button-group { - display: flex; - - margin: 0 calc(var(--default-small-padding) / -2); - - & .rc-button { - margin: 0 calc(var(--default-small-padding) / 2); - } -} - -.rc-grid { - display: flex; - align-items: flex-start; - flex-flow: row wrap; -} - -.rc-w50 { - flex: 0 0 50%; - - &.padded { - &:nth-child(odd) { - padding-right: 15px; - } - - &:nth-child(even) { - padding-left: 15px; - } - } -} - -@media (width <= 500px) { - .rc-grid { - display: flex; - flex-direction: column; - align-items: flex-start; - } - - .rc-w50 { - flex: 0 0 100%; - - &.padded { - &:nth-child(odd) { - padding-right: 0; - } - - &:nth-child(even) { - padding-left: 0; - } - } - } -} - -@keyframes spin { - 0% { - transform: rotate(0deg); - } - - 100% { - transform: rotate(360deg); - } -} - -@keyframes ellipsis { - to { - width: 1.25em; - } -} diff --git a/apps/meteor/app/theme/client/imports/general/react-root.css b/apps/meteor/app/theme/client/imports/general/react-root.css index 8930a8bf05edc..4cca0ea5d52c0 100644 --- a/apps/meteor/app/theme/client/imports/general/react-root.css +++ b/apps/meteor/app/theme/client/imports/general/react-root.css @@ -1,13 +1,10 @@ #react-root { position: relative; - display: flex; overflow: visible; flex-direction: column; - width: 100vw; height: 100vh; padding: 0; - block-size: -webkit-fill-available; } diff --git a/apps/meteor/app/theme/client/imports/general/reset.css b/apps/meteor/app/theme/client/imports/general/reset.css index 425d9ff983192..3ab7367d23f2a 100644 --- a/apps/meteor/app/theme/client/imports/general/reset.css +++ b/apps/meteor/app/theme/client/imports/general/reset.css @@ -87,9 +87,7 @@ audio, video { margin: 0; padding: 0; - vertical-align: baseline; - border: 0 solid; &::after, @@ -134,6 +132,5 @@ q::after { table { border-spacing: 0; - border-collapse: collapse; } diff --git a/apps/meteor/app/theme/client/imports/general/theme_old.css b/apps/meteor/app/theme/client/imports/general/theme_old.css index b054e601451b5..9fe426b3df07f 100644 --- a/apps/meteor/app/theme/client/imports/general/theme_old.css +++ b/apps/meteor/app/theme/client/imports/general/theme_old.css @@ -4,7 +4,6 @@ &::-webkit-scrollbar { width: 6px; height: 6px; - background: var(--transparent-dark); } @@ -22,15 +21,6 @@ background-color: var(--content-background-color); } -:root { - --rcx-color-surface-light: var(--content-background-color); - --rcx-color-background-light: var(--content-background-color); -} - -.primary-background-color { - background-color: var(--primary-background-color); -} - .color-primary-font-color { color: var(--primary-font-color); } @@ -39,127 +29,21 @@ color: var(--primary-action-color); } -.secondary-background-color { - background-color: var(--secondary-background-color); -} - -.border-secondary-background-color { - border-color: var(--secondary-background-color); -} - .secondary-font-color { color: var(--secondary-font-color); } -.border-component-color { - border-color: var(--component-color); -} - .background-component-color { background-color: var(--component-color); } -.color-component-color { - color: var(--component-color); -} - -.filter-item { - &:hover { - border-color: var(--info-font-color); - } - - &.active { - border-color: var(--primary-background-color); - } -} - -input:-webkit-autofill { - color: var(--primary-font-color) !important; - background-color: transparent !important; +.upload-progress-progress { + background-color: var(--success-background); } input, select, textarea { - color: var(--primary-font-color); border-style: solid; - border-color: var(--input-border-color); background-color: transparent; - - &::placeholder { - color: var(--input-placeholder-color); - } - - &[disabled]:not(.rcx-box--full) { - background-color: var(--button-disabled-background); - } -} - -.disabled label, -[disabled] label { - color: var(--input-placeholder-color); -} - -.-autocomplete-container { - background-color: var(--popup-list-background); -} - -.-autocomplete-item.selected { - background-color: var(--popup-list-selected-background); -} - -.rc-old input[type='button'], -.rc-old input[type='submit'] { - color: var(--button-secondary-text-color); - border-color: var(--button-secondary-background); - background: var(--button-secondary-background); -} - -.flex-tab { - a i, - a[class^='icon-'] { - color: var(--primary-font-color); - - &:hover { - opacity: 0.6; - } - } -} - -.error { - border-color: var(--error-color); -} - -.upload-progress-progress { - background-color: var(--success-background); -} - -.popup-user-status-online, -.status-online::after { - background-color: var(--rc-status-online); -} - -label.required::after { - color: var(--error-color); -} - -.main-content, -.flex-tab { - .loading-animation > .bounce { - background-color: var(--primary-font-color); - } -} - -.loading-animation.loading-animation--primary > .bounce { - background-color: var(--primary-font-color); -} - -@keyframes blink { - from { - color: var(--selection-color); - } - - to { - opacity: inherit; - } } diff --git a/apps/meteor/app/theme/client/imports/general/variables.css b/apps/meteor/app/theme/client/imports/general/variables.css index e8e06ac68f423..60f2a558be80e 100644 --- a/apps/meteor/app/theme/client/imports/general/variables.css +++ b/apps/meteor/app/theme/client/imports/general/variables.css @@ -2,205 +2,45 @@ /* * Color palette */ - --color-dark-blue: #175cc4; - --color-blue: #1d74f5; - --color-light-blue: #4eb2f5; - --color-lighter-blue: #e8f2ff; - --color-purple: #861da8; --color-red: #f5455c; - --color-dark-red: #e0364d; - --color-orange: #f38c39; --color-yellow: #ffd21f; - --color-dark-yellow: #f6c502; --color-green: #2de0a5; /* * General Colors */ - --color-darkest: #1f2329; - --color-dark: #2f343d; - --color-dark-medium: #414852; - --color-dark-light: #6c727a; --color-gray: #9ea2a8; --color-gray-medium: #cbced1; - --color-gray-light: #e1e5e8; --color-gray-lightest: #f2f3f5; - --color-black: #000000; - --color-white: #ffffff; - /* #region colors Colors */ + /* Colors */ --rc-color-error: var(--color-red); - --rc-color-error-light: #e1364c; --rc-color-alert: var(--color-yellow); - --rc-color-alert-light: var(--color-dark-yellow); --rc-color-success: var(--color-green); - --rc-color-success-light: #25d198; - --rc-color-button-primary: var(--color-blue); - --rc-color-button-primary-light: var(--color-dark-blue); - --rc-color-alert-message-primary: var(--color-blue); - --rc-color-alert-message-primary-background: #f1f6ff; - --rc-color-alert-message-secondary: #7ca52b; - --rc-color-alert-message-secondary-background: #fafff1; - --rc-color-alert-message-warning: #d52d24; - --rc-color-alert-message-warning-background: #fff3f3; - --rc-color-primary: var(--color-dark); - --rc-color-primary-background: var(--color-dark); - --rc-color-primary-darkest: var(--color-darkest); - --rc-color-primary-dark: var(--color-dark-medium); --rc-color-primary-light: var(--color-gray); - --rc-color-primary-light-medium: var(--color-gray-medium); - --rc-color-primary-lightest: var(--color-gray-lightest); - --rc-color-content: var(--color-white); - --rc-color-link-active: var(--rc-color-button-primary); - --rc-color-announcement-text: #095ad2; - --rc-color-announcement-background: #d1ebfe; - --rc-color-announcement-text-hover: #01336b; - --rc-color-announcement-background-hover: #76b7fc; - /* #endregion */ - - /* #region colors Old Colors */ + /* Old Colors */ --content-background-color: #ffffff; - --primary-background-color: #04436a; --primary-font-color: #444444; --primary-action-color: #1d74f5; - --secondary-background-color: #f4f4f4; --secondary-font-color: #a0a0a0; - --secondary-action-color: #dddddd; --component-color: #f2f3f5; - --pending-color: #fcb316; - --error-color: #bc2031; - --success-color: #2de0a5; - --selection-color: #02acec; - --attention-color: #9c27b0; - --transparent-darker: rgba(0, 0, 0, 0.5); - - /* #endregion */ - - /* #region less-colors Old Colors (minor) */ - --tertiary-font-color: var(--transparent-lightest); - --link-font-color: var(--primary-action-color); - --info-font-color: var(--secondary-font-color); - --custom-scrollbar-color: var(--transparent-darker); - - /* #endregion */ - /* #region fonts Fonts */ - --body-font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Helvetica Neue', 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Meiryo UI', Arial, sans-serif; - - /* #endregion */ + /* Fonts */ + --body-font-family: -apple-system, blinkmacsystemfont, 'Segoe UI', roboto, oxygen, ubuntu, cantarell, 'Helvetica Neue', 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Meiryo UI', arial, sans-serif; /* * General */ - --text-size: 0.875rem; - --header-min-height: 60px; - --toolbar-height: 55px; - --footer-min-height: 70px; - --rooms-box-width: 280px; - --flex-tab-width: 380px; - --flex-tab-webrtc-width: 400px; - --flex-tab-webrtc-2-width: 850px; - --border: 1px; - --border-radius: 4px; --rc-status-online: var(--rc-color-success); --rc-status-away: var(--rc-color-alert); --rc-status-busy: var(--rc-color-error); --rc-status-invisible: var(--color-gray-medium); - --rc-status-offline: var(--transparent-darker); - --rc-status-invisible-sidebar: var(--rc-color-primary-darkest); - --default-padding: 1.5rem; - --default-small-padding: 1rem; - --status-bullet-size: 10px; - --status-bullet-radius: 50%; - --account-username-weight: 700; - --status-name-weight: 400; - --default-font-weight-header: 500; /* * General Typography */ - --text-default-size: 1rem; - --text-default-weight: 500; --text-small-size: 0.875rem; - --text-small-weight: 500; - --text-heading-size: 1.375rem; - --text-heading-weight: 700; - --text-label-size: 075rem; - --text-label-weight: 600; - --text-tiny-size: 075rem; - --text-tiny-weight: 400; - --text-micro-size: 0.625rem; - --text-micro-weight: 700; - - /* - * Forms - */ - --gap-between-elements: 2.5rem; - --label-margin-bottom: 1rem; - - /* - * Forms - Button - */ - --button-square-size: 36px; - --button-padding: 0.782rem; - --button-padding-small: 0 0.5rem; - --button-height-small: 28px; - --button-text-size-small: 13px; - --button-text-size: var(--input-font-size); - --button-border-width: var(--border); - --button-border-radius: var(--border-radius); - --button-disabled-background: var(--color-gray-light); - --button-disabled-text-color: var(--color-white); - --button-primary-background: var(--rc-color-button-primary); - --button-primary-text-color: var(--color-white); - --button-cancel-color: var(--rc-color-error); - --button-secondary-background: var(--color-gray-medium); - --button-secondary-text-color: var(--color-dark-medium); - - /* - * Forms - Input - */ - --input-font-size: 0.875rem; - --input-title-text-size: var(--input-font-size); - --input-title-color: var(--rcx-color-font-default, var(--rcx-color-neutral-800, #2f343d)); - --input-text-color: var(--rcx-color-font-default, var(--rcx-color-neutral-800, #2f343d)); - --input-placeholder-color: var(--rc-input-colors-placeholder-color, var(--rcx-color-font-annotation, var(--rcx-color-neutral-600, #9ea2a8))); - --input-icon-color: var(--rcx-color-font-default, var(--rcx-color-neutral-800, var(--color-dark))); - --input-border-color: var(--rcx-input-colors-border-color, var(--rcx-color-stroke-light, var(--rcx-color-neutral-500, var(--color-gray-light)))); - --input-border-width: var(--border); - --input-border-radius: var(--border-radius); - --input-description-text-color: var(--rcx-color-font-annotation, var(--rcx-color-neutral-600, var(--color-gray))); - --input-description-text-size: var(--input-font-size); - --input-error-color: var(--rc-color-error); - - /* - * Forms - popup list - */ - --popup-list-border-radius: var(--border-radius); - --popup-list-background: var(--color-white); - --popup-list-background-hover: var(--color-gray-lightest); - --popup-list-selected-background: var(--color-gray-lightest); - --popup-list-name-color: #2d343d; - --popup-list-name-size: 1rem; - - /* - * Forms - tags - */ - --tags-border-width: var(--border); - --tags-border-radius: var(--border-radius); - --tags-border-color: var(--color-gray-light); - --tags-text-color: var(--rc-color-primary); - --tags-background: #f2f3f5; - --tags-avatar-size: 20px; - - /* - * Forms - select avatar - */ - --select-avatar-size: 48px; - --select-avatar-preview-size: 150px; - --select-avatar-upload-background: var(--color-gray-light); - --select-avatar-upload-color: #2d343d; /* * Sidebar @@ -208,60 +48,8 @@ --sidebar-width: 17.5rem; --sidebar-md-width: 20rem; --sidebar-lg-width: 21rem; - --sidebar-small-width: 90%; - --sidebar-background-hover: var(--rc-color-primary-dark); - --sidebar-background-light: var(--rc-color-primary-lightest); - --sidebar-background-light-hover: var(--rc-color-primary-light); - --sidebar-background-light-active: var(--rc-color-primary-light-medium); --sidebar-default-padding: 24px; --sidebar-small-default-padding: 16px; - --sidebar-extra-small-default-padding: 12px; - --sidebar-footer-height: 48px; - --sidebar-small-header-padding: var(--sidebar-small-default-padding); - - /* - * Sidebar flex - */ - --sidebar-flex-search-background: var(--color-white); - --sidebar-flex-search-placeholder-color: var(--color-gray); - - /* - * Sidebar Account - */ - --sidebar-account-thumb-size: 23px; - --sidebar-small-account-thumb-size: 40px; - --sidebar-account-status-bullet-size: 10px; - --sidebar-small-account-status-bullet-size: 8px; - --sidebar-account-status-bullet-radius: 50%; - --sidebar-account-username-size: 1rem; - --sidebar-account-username-weight: 700; - --sidebar-small-account-username-weight: 400; - --sidebar-account-username-color: var(--color-white); - --sidebar-account-username-color-darker: var(--color-dark); - --sidebar-account-status-font-size: 0.875rem; - --sidebar-account-status-color: var(--color-gray); - - /* - * Sidebar Item - */ - --sidebar-item-radius: 2px; - --sidebar-item-height: 24px; - --sidebar-item-height-medium: 34px; - --sidebar-item-height-extended: 52px; - --sidebar-item-thumb-size: 18px; - --sidebar-item-thumb-size-medium: 27px; - --sidebar-item-thumb-size-extended: 36px; - --sidebar-item-text-color: var(--rc-color-primary-light); - --sidebar-item-background: inherit; - --sidebar-item-hover-background: var(--rc-color-primary-darkest); - --sidebar-item-active-background: var(--rc-color-primary-dark); - --sidebar-item-active-color: var(--sidebar-item-text-color); - --sidebar-item-unread-color: var(--rc-color-content); - --sidebar-item-unread-font-weight: 600; - --sidebar-item-popup-background: var(--rc-color-primary-dark); - --sidebar-item-user-status-size: 6px; - --sidebar-item-user-status-radius: 50%; - --sidebar-item-text-size: 0.875rem; /* * Rooms list @@ -270,89 +58,17 @@ --rooms-list-title-text-size: 0.75rem; --rooms-list-empty-text-color: var(--color-gray); --rooms-list-empty-text-size: 0.75rem; - --rooms-list-padding: var(--sidebar-default-padding); - --rooms-list-small-padding: var(--sidebar-small-default-padding); - - /* - * Chip - */ - --chip-background: #dddddd; - - /* - * Avatar - */ - --avatar-radius: var(--border-radius); - --avatar-initials-text-size: 22px; - --avatar-initials-text-weight: 700; - - /* - * Badge - */ - --badge-text-color: var(--color-white); - --badge-radius: 12px; - --badge-text-size: 0.75rem; - --badge-background: var(--rc-color-primary-dark); - --badge-unread-background: var(--color-blue); - --badge-user-mentions-background: var(--color-red); - --badge-group-mentions-background: var(--color-orange); - - /* - * Mention link - */ - --mention-link-radius: 4px; - --mention-link-background: #fff6d6; - --mention-link-text-color: #b68d00; - --mention-link-me-background: #ffe9ec; - --mention-link-me-text-color: var(--color-red); - --mention-link-group-background: #fde8d7; - --mention-link-group-text-color: var(--color-orange); /* * Message box */ --message-box-text-size: var(--input-font-size); - --message-box-placeholder-color: var(--rc-input-colors-placeholder-color, var(--rcx-color-font-annotation, var(--rcx-color-neutral-600, #9ea2a8))); - --message-box-markdown-color: var(--rcx-color-font-annotation, var(--rcx-color-neutral-600, var(--color-gray))); - --message-box-markdown-hover-color: var(--rcx-color-font-default, var(--rcx-color-neutral-800, var(--color-dark))); - --message-box-user-activity-color: var(--rcx-color-font-annotation, var(--rcx-color-neutral-600, var(--color-gray))); - --message-box-user-activity-text-size: 0.75rem; - --message-box-user-activity-user-color: var(--rcx-color-font-default, var(--rcx-color-neutral-800, var(--color-dark))); - --message-box-container-border-color: var(--rcx-input-colors-border-color, var(--rcx-color-stroke-light, var(--rcx-color-neutral-500, var(--color-gray-medium)))); - --message-box-container-border-width: var(--border); - --message-box-container-border-radius: var(--border-radius); - --message-box-editing-color: var(--rcx-color-status-background-warning-2, #fff6d6); - --message-box-popover-title-text-color: var(--rcx-color-font-annotation, var(--rcx-color-neutral-600, var(--color-gray))); - --message-box-popover-title-text-size: 0.75rem; - --message-box-color: var(--rcx-color-font-default, var(--rcx-color-neutral-800, #2f343d)); /* * Flex nav */ --flex-nav-background: var(--color-gray-lightest); - /* - * Popover - */ - --popover-padding: 1rem; - --popover-radius: var(--border-radius); - --popover-background: var(--color-white); - --popover-column-min-width: 130px; - --popover-column-padding: 1rem; - --popover-title-color: var(--color-dark); - --popover-title-text-size: 0.75rem; - --popover-item-color: var(--color-dark); - --popover-item-text-size: 0.875rem; - --popover-divider-height: 2px; - --popover-divider-color: var(--color-gray-light); - - /* - * Tooltip - */ - --tooltip-background: var(--color-darkest); - --tooltip-text-color: var(--color-white); - --tooltip-text-size: 0.75rem; - --tooltip-radius: var(--border-radius); - /* * Loading */ @@ -362,10 +78,8 @@ --loading-bounce-color-dark: var(--rcx-color-font-default, #e4e7ea); } -.rcx-sidebar--main { - --sidebar-background: var(--rcx-color-surface-tint, #262931); - --sidebar-item-text-color: var(--rcx-color-font-default, #9ea2a8); - --sidebar-border-color: var(--rcx-color-stroke-extra-light, #2f343d); +.rcx-sidebar { + &--main { + --sidebar-background: var(--rcx-color-surface-tint, #262931); + } } - -/* #endregion */ diff --git a/apps/meteor/app/theme/client/main.css b/apps/meteor/app/theme/client/main.css index 33b7a8f0d2906..7fc8ddbfe6438 100644 --- a/apps/meteor/app/theme/client/main.css +++ b/apps/meteor/app/theme/client/main.css @@ -1,27 +1,19 @@ /* General */ -@import 'imports/general/variables.css'; -@import 'imports/general/reset.css'; -@import 'imports/general/base_old.css'; -@import 'imports/general/base.css'; -@import 'imports/general/react-root.css'; - -/* Forms */ -@import 'imports/general/forms.css'; -@import 'imports/forms/button.css'; -@import 'imports/forms/input.css'; +@import url('imports/general/variables.css'); +@import url('imports/general/reset.css'); +@import url('imports/general/base_old.css'); +@import url('imports/general/base.css'); +@import url('imports/general/react-root.css'); /* Main */ -@import 'imports/components/flex-nav.css'; -@import 'imports/components/main-content.css'; -@import 'imports/components/message-box.css'; -@import 'imports/components/modal.css'; -@import 'imports/components/messages.css'; -@import 'imports/components/emoji.css'; -@import 'imports/components/loading.css'; +@import url('imports/components/flex-nav.css'); +@import url('imports/components/main-content.css'); +@import url('imports/components/message-box.css'); +@import url('imports/components/emoji.css'); +@import url('imports/components/loading.css'); /* Legacy theming */ -@import 'imports/general/theme_old.css'; -@import './vendor/fontello/css/fontello.css'; -@import './rocketchat.font.css'; -@import './mentionLink.css'; -@import '../../../node_modules/@rocket.chat/fuselage/dist/fuselage.css'; +@import url('imports/general/theme_old.css'); +@import url('./vendor/fontello/css/fontello.css'); +@import url('./rocketchat.font.css'); +@import url('../../../node_modules/@rocket.chat/fuselage/dist/fuselage.css'); diff --git a/apps/meteor/app/theme/client/mentionLink.css b/apps/meteor/app/theme/client/mentionLink.css deleted file mode 100644 index 5deed00646c95..0000000000000 --- a/apps/meteor/app/theme/client/mentionLink.css +++ /dev/null @@ -1,37 +0,0 @@ -.mention-link { - padding: 0 2px 2px; - - cursor: pointer; - - transition: opacity 0.3s, background-color 0.3s, color 0.3s; - - color: var(--mention-link-text-color); - - border-radius: var(--mention-link-radius); - - background-color: var(--mention-link-background); - - font-weight: 700; - - &:hover { - opacity: 0.6; - } - - &--me { - color: var(--mention-link-me-text-color); - background-color: var(--mention-link-me-background); - - &:hover { - color: var(--mention-link-me-text-color); - } - } - - &--group { - color: var(--mention-link-group-text-color); - background-color: var(--mention-link-group-background); - - &:hover { - color: var(--mention-link-group-text-color); - } - } -} diff --git a/apps/meteor/app/theme/client/rocketchat.font.css b/apps/meteor/app/theme/client/rocketchat.font.css index 571c679fa6978..4db1230558f54 100644 --- a/apps/meteor/app/theme/client/rocketchat.font.css +++ b/apps/meteor/app/theme/client/rocketchat.font.css @@ -1,9 +1,8 @@ @font-face { - font-family: 'RocketChat'; + font-family: RocketChat; font-weight: 400; font-style: normal; font-display: block; - src: url('/fonts/rocketchat.eot'); src: url('/fonts/rocketchat.eot?#iefix') format('embedded-opentype'), diff --git a/apps/meteor/app/threads/client/threads.css b/apps/meteor/app/threads/client/threads.css index a9a9ade825d47..9ec4365bd68b5 100644 --- a/apps/meteor/app/threads/client/threads.css +++ b/apps/meteor/app/threads/client/threads.css @@ -1,20 +1,6 @@ -.thread-empty { - padding: calc(2 * var(--default-padding)); -} - .thread-list { - overflow-x: hidden; - overflow-y: auto; - + overflow: hidden auto; word-wrap: break-word; flex-grow: 1; flex-shrink: 1; } - -.contextual-bar__content.thread, -.contextual-bar__content.discussions, -.contextual-bar__content.channel-settings, -.contextual-bar__content.keyboard-shortcut-list, -.contextual-bar__content.threads { - padding: 0; -} diff --git a/apps/meteor/app/ui-master/server/index.ts b/apps/meteor/app/ui-master/server/index.ts index b4f15f211abc2..7e095b80b5f5e 100644 --- a/apps/meteor/app/ui-master/server/index.ts +++ b/apps/meteor/app/ui-master/server/index.ts @@ -5,10 +5,10 @@ import { Meteor } from 'meteor/meteor'; import { Inject } from 'meteor/meteorhacks:inject-initial'; import { Tracker } from 'meteor/tracker'; +import { applyHeadInjections, headInjections, injectIntoBody, injectIntoHead } from './inject'; import { withDebouncing } from '../../../lib/utils/highOrderFunctions'; import { settings } from '../../settings/server'; import { getURL } from '../../utils/server/getURL'; -import { applyHeadInjections, headInjections, injectIntoBody, injectIntoHead } from './inject'; import './scripts'; diff --git a/apps/meteor/app/ui-master/server/scripts.ts b/apps/meteor/app/ui-master/server/scripts.ts index 3e84a6e39c905..85ebaa8ccba6e 100644 --- a/apps/meteor/app/ui-master/server/scripts.ts +++ b/apps/meteor/app/ui-master/server/scripts.ts @@ -1,5 +1,5 @@ -import { settings } from '../../settings/server'; import { addScript } from './inject'; +import { settings } from '../../settings/server'; const getContent = (): string => ` diff --git a/apps/meteor/app/ui-message/client/ActionManager.ts b/apps/meteor/app/ui-message/client/ActionManager.ts index 4c892d6d32f27..91d635bee4dbc 100644 --- a/apps/meteor/app/ui-message/client/ActionManager.ts +++ b/apps/meteor/app/ui-message/client/ActionManager.ts @@ -7,12 +7,12 @@ import { t } from 'i18next'; import type { ContextType } from 'react'; import { lazy } from 'react'; +import { UiKitTriggerTimeoutError } from './UiKitTriggerTimeoutError'; import * as banners from '../../../client/lib/banners'; import { imperativeModal } from '../../../client/lib/imperativeModal'; import { dispatchToastMessage } from '../../../client/lib/toast'; import { exhaustiveCheck } from '../../../lib/utils/exhaustiveCheck'; import { sdk } from '../../utils/client/lib/SDKClient'; -import { UiKitTriggerTimeoutError } from './UiKitTriggerTimeoutError'; const UiKitModal = lazy(() => import('../../../client/views/modal/uikit/UiKitModal')); diff --git a/apps/meteor/app/ui-message/client/findParentMessage.ts b/apps/meteor/app/ui-message/client/findParentMessage.ts index 0a3197c463a6e..ca221d79812b0 100644 --- a/apps/meteor/app/ui-message/client/findParentMessage.ts +++ b/apps/meteor/app/ui-message/client/findParentMessage.ts @@ -2,7 +2,7 @@ import type { IMessage } from '@rocket.chat/core-typings'; import { callWithErrorHandling } from '../../../client/lib/utils/callWithErrorHandling'; import { withDebouncing } from '../../../lib/utils/highOrderFunctions'; -import { ChatMessage } from '../../models/client'; +import { Messages } from '../../models/client'; export const findParentMessage = (() => { const waiting: string[] = []; @@ -27,7 +27,7 @@ export const findParentMessage = (() => { }; return async (tmid: IMessage['_id']) => { - const message = ChatMessage.findOne({ _id: tmid }); + const message = Messages.findOne({ _id: tmid }); if (message) { return message; diff --git a/apps/meteor/app/ui-message/client/messageBox/createComposerAPI.ts b/apps/meteor/app/ui-message/client/messageBox/createComposerAPI.ts index 741f7959fa903..eab54850f3bfb 100644 --- a/apps/meteor/app/ui-message/client/messageBox/createComposerAPI.ts +++ b/apps/meteor/app/ui-message/client/messageBox/createComposerAPI.ts @@ -2,10 +2,10 @@ import type { IMessage } from '@rocket.chat/core-typings'; import { Emitter } from '@rocket.chat/emitter'; import { Accounts } from 'meteor/accounts-base'; -import type { ComposerAPI } from '../../../../client/lib/chats/ChatAPI'; -import { withDebouncing } from '../../../../lib/utils/highOrderFunctions'; import type { FormattingButton } from './messageBoxFormatting'; import { formattingButtons } from './messageBoxFormatting'; +import type { ComposerAPI } from '../../../../client/lib/chats/ChatAPI'; +import { withDebouncing } from '../../../../lib/utils/highOrderFunctions'; export const createComposerAPI = (input: HTMLTextAreaElement, storageID: string): ComposerAPI => { const triggerEvent = (input: HTMLTextAreaElement, evt: string): void => { diff --git a/apps/meteor/app/ui-message/client/messageBox/messageBoxFormatting.ts b/apps/meteor/app/ui-message/client/messageBox/messageBoxFormatting.ts index 84ca6dcc1035d..3c35d0fee3011 100644 --- a/apps/meteor/app/ui-message/client/messageBox/messageBoxFormatting.ts +++ b/apps/meteor/app/ui-message/client/messageBox/messageBoxFormatting.ts @@ -1,10 +1,10 @@ import type { Keys as IconName } from '@rocket.chat/icons'; import type { TranslationKey } from '@rocket.chat/ui-contexts'; +import AddLinkComposerActionModal from './AddLinkComposerActionModal'; import type { ComposerAPI } from '../../../../client/lib/chats/ChatAPI'; import { imperativeModal } from '../../../../client/lib/imperativeModal'; import { settings } from '../../../settings/client'; -import AddLinkComposerActionModal from './AddLinkComposerActionModal'; type FormattingButtonDefault = { label: TranslationKey; condition?: () => boolean }; diff --git a/apps/meteor/app/ui-utils/client/lib/LegacyRoomManager.ts b/apps/meteor/app/ui-utils/client/lib/LegacyRoomManager.ts index 91b848ffefde4..5f82e47921f87 100644 --- a/apps/meteor/app/ui-utils/client/lib/LegacyRoomManager.ts +++ b/apps/meteor/app/ui-utils/client/lib/LegacyRoomManager.ts @@ -3,15 +3,15 @@ import type { Mongo } from 'meteor/mongo'; import { ReactiveVar } from 'meteor/reactive-var'; import { Tracker } from 'meteor/tracker'; +import { upsertMessage, RoomHistoryManager } from './RoomHistoryManager'; +import { mainReady } from './mainReady'; import { RoomManager } from '../../../../client/lib/RoomManager'; import { roomCoordinator } from '../../../../client/lib/rooms/roomCoordinator'; import { fireGlobalEvent } from '../../../../client/lib/utils/fireGlobalEvent'; import { getConfig } from '../../../../client/lib/utils/getConfig'; import { callbacks } from '../../../../lib/callbacks'; -import { CachedChatRoom, ChatMessage, ChatSubscription, CachedChatSubscription } from '../../../models/client'; +import { CachedChatRoom, Messages, Subscriptions, CachedChatSubscription } from '../../../models/client'; import { sdk } from '../../../utils/client/lib/SDKClient'; -import { upsertMessage, RoomHistoryManager } from './RoomHistoryManager'; -import { mainReady } from './mainReady'; const maxRoomsOpen = parseInt(getConfig('maxRoomsOpen') ?? '5') || 5; @@ -106,8 +106,8 @@ const computation = Tracker.autorun(() => { // } // Do not load command messages into channel if (msg.t !== 'command') { - const subscription = ChatSubscription.findOne({ rid: record.rid }, { reactive: false }); - const isNew = !ChatMessage.findOne({ _id: msg._id, temp: { $ne: true } }); + const subscription = Subscriptions.findOne({ rid: record.rid }, { reactive: false }); + const isNew = !Messages.findOne({ _id: msg._id, temp: { $ne: true } }); await upsertMessage({ msg, subscription }); if (isNew) { @@ -140,10 +140,10 @@ const computation = Tracker.autorun(() => { }); sdk.stream('notify-room', [`${record.rid}/deleteMessage`], (msg) => { - ChatMessage.remove({ _id: msg._id }); + Messages.remove({ _id: msg._id }); // remove thread refenrece from deleted message - ChatMessage.update({ tmid: msg._id }, { $unset: { tmid: 1 } }, { multi: true }); + Messages.update({ tmid: msg._id }, { $unset: { tmid: 1 } }, { multi: true }); }); sdk.stream( @@ -168,19 +168,19 @@ const computation = Tracker.autorun(() => { } if (showDeletedStatus) { - return ChatMessage.update( + return Messages.update( query, { $set: { t: 'rm', msg: '', urls: [], mentions: [], attachments: [], reactions: {} } }, { multi: true }, ); } - return ChatMessage.remove(query); + return Messages.remove(query); }, ); sdk.stream('notify-room', [`${record.rid}/messagesRead`], ({ tmid, until }) => { if (tmid) { - return ChatMessage.update( + return Messages.update( { tmid, unread: true, @@ -189,7 +189,7 @@ const computation = Tracker.autorun(() => { { multi: true }, ); } - ChatMessage.update( + Messages.update( { rid: record.rid, unread: true, diff --git a/apps/meteor/app/ui-utils/client/lib/RoomHistoryManager.ts b/apps/meteor/app/ui-utils/client/lib/RoomHistoryManager.ts index 4e2f0c020a12b..bbe8abb515f5d 100644 --- a/apps/meteor/app/ui-utils/client/lib/RoomHistoryManager.ts +++ b/apps/meteor/app/ui-utils/client/lib/RoomHistoryManager.ts @@ -11,7 +11,7 @@ import { onClientMessageReceived } from '../../../../client/lib/onClientMessageR import { callWithErrorHandling } from '../../../../client/lib/utils/callWithErrorHandling'; import { getConfig } from '../../../../client/lib/utils/getConfig'; import { waitForElement } from '../../../../client/lib/utils/waitForElement'; -import { ChatMessage, ChatSubscription } from '../../../models/client'; +import { Messages, Subscriptions } from '../../../models/client'; import { getUserPreference } from '../../../utils/client'; export async function upsertMessage( @@ -22,7 +22,7 @@ export async function upsertMessage( msg: IMessage & { ignored?: boolean }; subscription?: ISubscription; }, - collection: MinimongoCollection = ChatMessage, + collection: MinimongoCollection = Messages, ) { const userId = msg.u?._id; @@ -42,7 +42,7 @@ export async function upsertMessage( export function upsertMessageBulk( { msgs, subscription }: { msgs: IMessage[]; subscription?: ISubscription }, - collection: MinimongoCollection = ChatMessage, + collection: MinimongoCollection = Messages, ) { const { queries } = collection; collection.queries = []; @@ -135,7 +135,7 @@ class RoomHistoryManagerClass extends Emitter { let ls = undefined; - const subscription = ChatSubscription.findOne({ rid }); + const subscription = Subscriptions.findOne({ rid }); if (subscription) { ({ ls } = subscription); } @@ -214,9 +214,9 @@ class RoomHistoryManagerClass extends Emitter { room.isLoading.set(true); - const lastMessage = ChatMessage.findOne({ rid, _hidden: { $ne: true } }, { sort: { ts: -1 } }); + const lastMessage = Messages.findOne({ rid, _hidden: { $ne: true } }, { sort: { ts: -1 } }); - const subscription = ChatSubscription.findOne({ rid }); + const subscription = Subscriptions.findOne({ rid }); if (lastMessage?.ts) { const { ts } = lastMessage; @@ -264,7 +264,7 @@ class RoomHistoryManagerClass extends Emitter { public async clear(rid: IRoom['_id']) { const room = this.getRoom(rid); - ChatMessage.remove({ rid }); + Messages.remove({ rid }); room.isLoading.set(true); room.hasMore.set(true); room.hasMoreNext.set(false); @@ -277,7 +277,7 @@ class RoomHistoryManagerClass extends Emitter { return; } - const messageAlreadyLoaded = Boolean(ChatMessage.findOne({ _id: message._id, _hidden: { $ne: true } })); + const messageAlreadyLoaded = Boolean(Messages.findOne({ _id: message._id, _hidden: { $ne: true } })); if (messageAlreadyLoaded) { return; @@ -286,7 +286,7 @@ class RoomHistoryManagerClass extends Emitter { const room = this.getRoom(message.rid); void this.clear(message.rid); - const subscription = ChatSubscription.findOne({ rid: message.rid }); + const subscription = Subscriptions.findOne({ rid: message.rid }); const result = await callWithErrorHandling('loadSurroundingMessages', message, defaultLimit); diff --git a/apps/meteor/app/ui-utils/client/lib/messageActionDefault.ts b/apps/meteor/app/ui-utils/client/lib/messageActionDefault.ts index ae2ff1cf80d29..460ac2941e82d 100644 --- a/apps/meteor/app/ui-utils/client/lib/messageActionDefault.ts +++ b/apps/meteor/app/ui-utils/client/lib/messageActionDefault.ts @@ -3,6 +3,7 @@ import { isE2EEMessage, isRoomFederated } from '@rocket.chat/core-typings'; import { Meteor } from 'meteor/meteor'; import moment from 'moment'; +import { MessageAction } from './MessageAction'; import { getPermaLink } from '../../../../client/lib/getPermaLink'; import { imperativeModal } from '../../../../client/lib/imperativeModal'; import { roomCoordinator } from '../../../../client/lib/rooms/roomCoordinator'; @@ -12,9 +13,8 @@ import ForwardMessageModal from '../../../../client/views/room/modals/ForwardMes import ReactionListModal from '../../../../client/views/room/modals/ReactionListModal'; import ReportMessageModal from '../../../../client/views/room/modals/ReportMessageModal'; import { hasAtLeastOnePermission, hasPermission } from '../../../authorization/client'; -import { ChatRoom, Subscriptions } from '../../../models/client'; +import { Rooms, Subscriptions } from '../../../models/client'; import { t } from '../../../utils/lib/i18n'; -import { MessageAction } from './MessageAction'; const getMainMessageText = (message: IMessage): IMessage => { const newMessage = { ...message }; @@ -51,7 +51,7 @@ Meteor.startup(async () => { // Check if we already have a DM started with the message user (not ourselves) or we can start one if (!!user && user._id !== message.u._id && !hasPermission('create-d')) { - const dmRoom = ChatRoom.findOne({ _id: [user._id, message.u._id].sort().join('') }); + const dmRoom = Rooms.findOne({ _id: [user._id, message.u._id].sort().join('') }); if (!dmRoom || !Subscriptions.findOne({ 'rid': dmRoom._id, 'u._id': user._id })) { return false; } diff --git a/apps/meteor/app/ui/client/lib/ChatMessages.ts b/apps/meteor/app/ui/client/lib/ChatMessages.ts index 681d93aab82c3..f7fff0b2a2aab 100644 --- a/apps/meteor/app/ui/client/lib/ChatMessages.ts +++ b/apps/meteor/app/ui/client/lib/ChatMessages.ts @@ -2,6 +2,7 @@ import type { IMessage, IRoom, IUser } from '@rocket.chat/core-typings'; import { isVideoConfMessage } from '@rocket.chat/core-typings'; import type { IActionManager } from '@rocket.chat/ui-contexts'; +import { UserAction } from './UserAction'; import type { ChatAPI, ComposerAPI, DataAPI, UploadsAPI } from '../../../../client/lib/chats/ChatAPI'; import { createDataAPI } from '../../../../client/lib/chats/data'; import { processMessageEditing } from '../../../../client/lib/chats/flows/processMessageEditing'; @@ -18,7 +19,6 @@ import { setHighlightMessage, clearHighlightMessage, } from '../../../../client/views/room/MessageList/providers/messageHighlightSubscription'; -import { UserAction } from './UserAction'; type DeepWritable = T extends (...args: any) => any ? T diff --git a/apps/meteor/app/ui/client/lib/KonchatNotification.ts b/apps/meteor/app/ui/client/lib/KonchatNotification.ts index dbffdf2a80a1f..38fa4a3ac263a 100644 --- a/apps/meteor/app/ui/client/lib/KonchatNotification.ts +++ b/apps/meteor/app/ui/client/lib/KonchatNotification.ts @@ -10,7 +10,7 @@ import { router } from '../../../../client/providers/RouterProvider'; import { stripTags } from '../../../../lib/utils/stringUtils'; import { CustomSounds } from '../../../custom-sounds/client/lib/CustomSounds'; import { e2e } from '../../../e2e/client'; -import { ChatSubscription } from '../../../models/client'; +import { Subscriptions } from '../../../models/client'; import { getUserPreference } from '../../../utils/client'; import { getUserAvatarURL } from '../../../utils/client/getUserAvatarURL'; import { sdk } from '../../../utils/client/lib/SDKClient'; @@ -182,7 +182,7 @@ class KonchatNotification { return; } - const sub = ChatSubscription.findOne({ rid }, { fields: { audioNotificationValue: 1 } }); + const sub = Subscriptions.findOne({ rid }, { fields: { audioNotificationValue: 1 } }); if (!sub || sub.audioNotificationValue === 'none') { return; diff --git a/apps/meteor/app/ui/client/lib/recorderjs/AudioRecorder.ts b/apps/meteor/app/ui/client/lib/recorderjs/AudioRecorder.ts index 85a7853c1ece9..d8bd8cbb323cb 100644 --- a/apps/meteor/app/ui/client/lib/recorderjs/AudioRecorder.ts +++ b/apps/meteor/app/ui/client/lib/recorderjs/AudioRecorder.ts @@ -1,5 +1,5 @@ -import { settings } from '../../../../settings/client'; import { AudioEncoder } from './AudioEncoder'; +import { settings } from '../../../../settings/client'; export class AudioRecorder { private audioContext: AudioContext | undefined; diff --git a/apps/meteor/app/utils/client/getRoomAvatarURL.ts b/apps/meteor/app/utils/client/getRoomAvatarURL.ts index 061f62107b445..8f7dd9dec5337 100644 --- a/apps/meteor/app/utils/client/getRoomAvatarURL.ts +++ b/apps/meteor/app/utils/client/getRoomAvatarURL.ts @@ -1,7 +1,7 @@ import type { IRoom } from '@rocket.chat/core-typings'; -import { settings } from '../../settings/client'; import { getAvatarURL } from './getAvatarURL'; +import { settings } from '../../settings/client'; export const getRoomAvatarURL = ({ roomId, cache = '' }: { roomId: IRoom['_id']; cache: IRoom['avatarETag'] }) => { const externalSource = (settings.get('Accounts_RoomAvatarExternalProviderUrl') || '').trim().replace(/\/$/, ''); diff --git a/apps/meteor/app/utils/client/getURL.ts b/apps/meteor/app/utils/client/getURL.ts index 040b6dfa9dc28..42970bc388691 100644 --- a/apps/meteor/app/utils/client/getURL.ts +++ b/apps/meteor/app/utils/client/getURL.ts @@ -4,7 +4,13 @@ import { Info } from '../rocketchat.info'; export const getURL = function ( path: string, // eslint-disable-next-line @typescript-eslint/naming-convention - params: Record = {}, + params: { + cdn?: boolean; + full?: boolean; + cloud?: boolean; + cloud_route?: string; + cloud_params?: Record; + } = {}, cloudDeepLinkUrl?: string, cacheKey?: boolean, ): string { diff --git a/apps/meteor/app/utils/client/lib/RestApiClient.ts b/apps/meteor/app/utils/client/lib/RestApiClient.ts index 53c95ee3e4fa3..219c297406bc1 100644 --- a/apps/meteor/app/utils/client/lib/RestApiClient.ts +++ b/apps/meteor/app/utils/client/lib/RestApiClient.ts @@ -1,3 +1,4 @@ +/* eslint-disable react-hooks/rules-of-hooks */ import { RestClient } from '@rocket.chat/api-client'; import { Accounts } from 'meteor/accounts-base'; diff --git a/apps/meteor/app/version-check/server/index.ts b/apps/meteor/app/version-check/server/index.ts index 6736e527f3d81..45e9c5197c305 100644 --- a/apps/meteor/app/version-check/server/index.ts +++ b/apps/meteor/app/version-check/server/index.ts @@ -1,8 +1,8 @@ import { cronJobs } from '@rocket.chat/cron'; import { Meteor } from 'meteor/meteor'; -import { settings } from '../../settings/server'; import { checkVersionUpdate } from './functions/checkVersionUpdate'; +import { settings } from '../../settings/server'; import './methods/banner_dismiss'; const jobName = 'version_check'; diff --git a/apps/meteor/app/webrtc/client/WebRTCClass.ts b/apps/meteor/app/webrtc/client/WebRTCClass.ts index 08bf68f515380..5d942c3656346 100644 --- a/apps/meteor/app/webrtc/client/WebRTCClass.ts +++ b/apps/meteor/app/webrtc/client/WebRTCClass.ts @@ -5,15 +5,15 @@ import { Meteor } from 'meteor/meteor'; import { ReactiveVar } from 'meteor/reactive-var'; import { Tracker } from 'meteor/tracker'; +import { ChromeScreenShare } from './screenShare'; import GenericModal from '../../../client/components/GenericModal'; import { imperativeModal } from '../../../client/lib/imperativeModal'; import { goToRoomById } from '../../../client/lib/utils/goToRoomById'; -import { ChatSubscription } from '../../models/client'; +import { Subscriptions } from '../../models/client'; import { settings } from '../../settings/client'; import { sdk } from '../../utils/client/lib/SDKClient'; import { t } from '../../utils/lib/i18n'; import { WEB_RTC_EVENTS } from '../lib/constants'; -import { ChromeScreenShare } from './screenShare'; // FIXME: there is a mix of obsolete definitions and incorrect field assignments @@ -827,7 +827,7 @@ class WebRTCClass { if (user?.username) { fromUsername = user.username; } - const subscription = ChatSubscription.findOne({ + const subscription = Subscriptions.findOne({ rid: data.room, })!; @@ -1037,7 +1037,7 @@ const WebRTC = new (class { getInstanceByRoomId(rid: IRoom['_id'], visitorId: string | null = null) { let enabled = false; if (!visitorId) { - const subscription = ChatSubscription.findOne({ rid }); + const subscription = Subscriptions.findOne({ rid }); if (!subscription) { return; } diff --git a/apps/meteor/app/webrtc/client/actionLink.tsx b/apps/meteor/app/webrtc/client/actionLink.tsx index d4575f2dd60f3..90258eeedce8e 100644 --- a/apps/meteor/app/webrtc/client/actionLink.tsx +++ b/apps/meteor/app/webrtc/client/actionLink.tsx @@ -2,12 +2,12 @@ import type { IMessage } from '@rocket.chat/core-typings'; import { actionLinks } from '../../../client/lib/actionLinks'; import { dispatchToastMessage } from '../../../client/lib/toast'; -import { ChatRoom } from '../../models/client'; +import { Rooms } from '../../models/client'; import { sdk } from '../../utils/client/lib/SDKClient'; import { t } from '../../utils/lib/i18n'; actionLinks.register('joinLivechatWebRTCCall', (message: IMessage) => { - const room = ChatRoom.findOne({ _id: message.rid }); + const room = Rooms.findOne({ _id: message.rid }); if (!room) { throw new Error('Room not found'); } @@ -20,7 +20,7 @@ actionLinks.register('joinLivechatWebRTCCall', (message: IMessage) => { }); actionLinks.register('endLivechatWebRTCCall', async (message: IMessage) => { - const room = ChatRoom.findOne({ _id: message.rid }); + const room = Rooms.findOne({ _id: message.rid }); if (!room) { throw new Error('Room not found'); } diff --git a/apps/meteor/app/wordpress/client/wordpress-login-button.css b/apps/meteor/app/wordpress/client/wordpress-login-button.css index edc54f247ae19..35c6d2e78eb40 100644 --- a/apps/meteor/app/wordpress/client/wordpress-login-button.css +++ b/apps/meteor/app/wordpress/client/wordpress-login-button.css @@ -1,3 +1,3 @@ #login-buttons-image-wordpress { - background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiP…A3LDI3LjUsMjUuOTQsMjMuMjE1LDI4LjQzNHoiLz4NCgk8L2c+DQo8L2c+DQo8L3N2Zz4NCg==); + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiP…A3LDI3LjUsMjUuOTQsMjMuMjE1LDI4LjQzNHoiLz4NCgk8L2c+DQo8L2c+DQo8L3N2Zz4NCg=="); } diff --git a/apps/meteor/client/NavBarV2/NavBar.tsx b/apps/meteor/client/NavBarV2/NavBar.tsx index 7e61d53e5eff1..cc2b005a929f0 100644 --- a/apps/meteor/client/NavBarV2/NavBar.tsx +++ b/apps/meteor/client/NavBarV2/NavBar.tsx @@ -4,10 +4,6 @@ import { usePermission, useTranslation, useUser } from '@rocket.chat/ui-contexts import { useVoipState } from '@rocket.chat/ui-voip'; import React, { useRef } from 'react'; -import { useIsCallEnabled, useIsCallReady } from '../contexts/CallContext'; -import { useOmnichannelEnabled } from '../hooks/omnichannel/useOmnichannelEnabled'; -import { useOmnichannelShowQueueLink } from '../hooks/omnichannel/useOmnichannelShowQueueLink'; -import { useHasLicenseModule } from '../hooks/useHasLicenseModule'; import { NavBarItemOmniChannelCallDialPad, NavBarItemOmnichannelContact, @@ -18,6 +14,10 @@ import { import { NavBarItemMarketPlaceMenu, NavBarItemAuditMenu, NavBarItemDirectoryPage, NavBarItemHomePage } from './NavBarPagesToolbar'; import { NavBarItemLoginPage, NavBarItemAdministrationMenu, UserMenu } from './NavBarSettingsToolbar'; import { NavBarItemVoipDialer } from './NavBarVoipToolbar'; +import { useIsCallEnabled, useIsCallReady } from '../contexts/CallContext'; +import { useOmnichannelEnabled } from '../hooks/omnichannel/useOmnichannelEnabled'; +import { useOmnichannelShowQueueLink } from '../hooks/omnichannel/useOmnichannelShowQueueLink'; +import { useHasLicenseModule } from '../hooks/useHasLicenseModule'; const NavBar = () => { const t = useTranslation(); diff --git a/apps/meteor/client/NavBarV2/NavBarOmnichannelToolbar/NavBarItemOmnichannelCallToggle.tsx b/apps/meteor/client/NavBarV2/NavBarOmnichannelToolbar/NavBarItemOmnichannelCallToggle.tsx index ce62cb51864b7..0df36e6e73c34 100644 --- a/apps/meteor/client/NavBarV2/NavBarOmnichannelToolbar/NavBarItemOmnichannelCallToggle.tsx +++ b/apps/meteor/client/NavBarV2/NavBarOmnichannelToolbar/NavBarItemOmnichannelCallToggle.tsx @@ -1,10 +1,10 @@ import type { ComponentPropsWithoutRef } from 'react'; import React from 'react'; -import { useIsCallReady, useIsCallError } from '../../contexts/CallContext'; import NavBarItemOmnichannelCallToggleError from './NavBarItemOmnichannelCallToggleError'; import NavBarItemOmnichannelCallToggleLoading from './NavBarItemOmnichannelCallToggleLoading'; import NavBarItemOmnichannelCallToggleReady from './NavBarItemOmnichannelCallToggleReady'; +import { useIsCallReady, useIsCallError } from '../../contexts/CallContext'; type NavBarItemOmnichannelCallToggleProps = ComponentPropsWithoutRef< typeof NavBarItemOmnichannelCallToggleError | typeof NavBarItemOmnichannelCallToggleLoading | typeof NavBarItemOmnichannelCallToggleReady diff --git a/apps/meteor/client/NavBarV2/NavBarSettingsToolbar/UserMenu/hooks/useStatusItems.tsx b/apps/meteor/client/NavBarV2/NavBarSettingsToolbar/UserMenu/hooks/useStatusItems.tsx index 1f012c520adae..910aa228902aa 100644 --- a/apps/meteor/client/NavBarV2/NavBarSettingsToolbar/UserMenu/hooks/useStatusItems.tsx +++ b/apps/meteor/client/NavBarV2/NavBarSettingsToolbar/UserMenu/hooks/useStatusItems.tsx @@ -5,13 +5,13 @@ import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import React, { useEffect } from 'react'; import { useTranslation } from 'react-i18next'; +import { useCustomStatusModalHandler } from './useCustomStatusModalHandler'; import { callbacks } from '../../../../../lib/callbacks'; import MarkdownText from '../../../../components/MarkdownText'; import { UserStatus } from '../../../../components/UserStatus'; import { userStatuses } from '../../../../lib/userStatuses'; import type { UserStatusDescriptor } from '../../../../lib/userStatuses'; import { useStatusDisabledModal } from '../../../../views/admin/customUserStatus/hooks/useStatusDisabledModal'; -import { useCustomStatusModalHandler } from './useCustomStatusModalHandler'; export const useStatusItems = (): GenericMenuItemProps[] => { // We should lift this up to somewhere else if we want to use it in other places diff --git a/apps/meteor/client/apps/RealAppsEngineUIHost.ts b/apps/meteor/client/apps/RealAppsEngineUIHost.ts index 2293952fe75da..7125fd04e8b47 100644 --- a/apps/meteor/client/apps/RealAppsEngineUIHost.ts +++ b/apps/meteor/client/apps/RealAppsEngineUIHost.ts @@ -2,7 +2,7 @@ import { AppsEngineUIHost } from '@rocket.chat/apps-engine/client/AppsEngineUIHo import type { IExternalComponentRoomInfo, IExternalComponentUserInfo } from '@rocket.chat/apps-engine/client/definition'; import { Meteor } from 'meteor/meteor'; -import { ChatRoom } from '../../app/models/client'; +import { Rooms } from '../../app/models/client'; import { getUserAvatarURL } from '../../app/utils/client/getUserAvatarURL'; import { sdk } from '../../app/utils/client/lib/SDKClient'; import { RoomManager } from '../lib/RoomManager'; @@ -30,7 +30,7 @@ export class RealAppsEngineUIHost extends AppsEngineUIHost { } async getClientRoomInfo(): Promise { - const { name: slugifiedName, _id: id } = ChatRoom.findOne(RoomManager.opened)!; + const { name: slugifiedName, _id: id } = Rooms.findOne(RoomManager.opened)!; let cachedMembers: IExternalComponentUserInfo[] = []; try { diff --git a/apps/meteor/client/apps/gameCenter/GameCenter.tsx b/apps/meteor/client/apps/gameCenter/GameCenter.tsx index 3261d1e1c51e3..6eb5c6fdeb3e3 100644 --- a/apps/meteor/client/apps/gameCenter/GameCenter.tsx +++ b/apps/meteor/client/apps/gameCenter/GameCenter.tsx @@ -3,11 +3,11 @@ import { useMutableCallback } from '@rocket.chat/fuselage-hooks'; import React, { useState } from 'react'; import type { ReactElement } from 'react'; -import { preventSyntheticEvent } from '../../lib/utils/preventSyntheticEvent'; -import { useRoomToolbox } from '../../views/room/contexts/RoomToolboxContext'; import GameCenterContainer from './GameCenterContainer'; import GameCenterList from './GameCenterList'; import { useExternalComponentsQuery } from './hooks/useExternalComponentsQuery'; +import { preventSyntheticEvent } from '../../lib/utils/preventSyntheticEvent'; +import { useRoomToolbox } from '../../views/room/contexts/RoomToolboxContext'; export type IGame = IExternalComponent; diff --git a/apps/meteor/client/apps/gameCenter/GameCenterContainer.tsx b/apps/meteor/client/apps/gameCenter/GameCenterContainer.tsx index dbaea02ace4a4..69a73161ab1c4 100644 --- a/apps/meteor/client/apps/gameCenter/GameCenterContainer.tsx +++ b/apps/meteor/client/apps/gameCenter/GameCenterContainer.tsx @@ -3,6 +3,7 @@ import type { ReactElement } from 'react'; import React from 'react'; import { useTranslation } from 'react-i18next'; +import type { IGame } from './GameCenter'; import { ContextualbarTitle, ContextualbarHeader, @@ -10,7 +11,6 @@ import { ContextualbarContent, ContextualbarClose, } from '../../components/Contextualbar'; -import type { IGame } from './GameCenter'; interface IGameCenterContainerProps { handleClose: (e: any) => void; diff --git a/apps/meteor/client/apps/gameCenter/GameCenterInvitePlayersModal.tsx b/apps/meteor/client/apps/gameCenter/GameCenterInvitePlayersModal.tsx index 871e82f3ff565..5c20758cde3b9 100644 --- a/apps/meteor/client/apps/gameCenter/GameCenterInvitePlayersModal.tsx +++ b/apps/meteor/client/apps/gameCenter/GameCenterInvitePlayersModal.tsx @@ -4,12 +4,12 @@ import type { ReactElement } from 'react'; import React, { useState } from 'react'; import { useTranslation } from 'react-i18next'; +import type { IGame } from './GameCenter'; import GenericModal from '../../components/GenericModal'; import UserAutoCompleteMultipleFederated from '../../components/UserAutoCompleteMultiple/UserAutoCompleteMultipleFederated'; import { useOpenedRoom } from '../../lib/RoomManager'; import { roomCoordinator } from '../../lib/rooms/roomCoordinator'; import { callWithErrorHandling } from '../../lib/utils/callWithErrorHandling'; -import type { IGame } from './GameCenter'; type Username = Exclude; diff --git a/apps/meteor/client/apps/gameCenter/GameCenterList.tsx b/apps/meteor/client/apps/gameCenter/GameCenterList.tsx index 9cee87204a1a1..03f57f0f1b6a9 100644 --- a/apps/meteor/client/apps/gameCenter/GameCenterList.tsx +++ b/apps/meteor/client/apps/gameCenter/GameCenterList.tsx @@ -4,10 +4,10 @@ import type { ReactElement } from 'react'; import React, { useCallback } from 'react'; import { useTranslation } from 'react-i18next'; -import { ContextualbarHeader, ContextualbarTitle, ContextualbarClose, ContextualbarContent } from '../../components/Contextualbar'; -import { FormSkeleton } from '../../components/Skeleton'; import type { IGame } from './GameCenter'; import GameCenterInvitePlayersModal from './GameCenterInvitePlayersModal'; +import { ContextualbarHeader, ContextualbarTitle, ContextualbarClose, ContextualbarContent } from '../../components/Contextualbar'; +import { FormSkeleton } from '../../components/Skeleton'; interface IGameCenterListProps { handleClose: (e: any) => void; diff --git a/apps/meteor/client/apps/orchestrator.ts b/apps/meteor/client/apps/orchestrator.ts index 86d4df829aa98..aa0958b544728 100644 --- a/apps/meteor/client/apps/orchestrator.ts +++ b/apps/meteor/client/apps/orchestrator.ts @@ -4,12 +4,12 @@ import type { IPermission } from '@rocket.chat/apps-engine/definition/permission import type { ISetting } from '@rocket.chat/apps-engine/definition/settings'; import type { Serialized } from '@rocket.chat/core-typings'; +import type { IAppExternalURL, ICategory } from './@types/IOrchestrator'; +import { RealAppsEngineUIHost } from './RealAppsEngineUIHost'; import { hasAtLeastOnePermission } from '../../app/authorization/client'; import { sdk } from '../../app/utils/client/lib/SDKClient'; import { dispatchToastMessage } from '../lib/toast'; import type { App } from '../views/marketplace/types'; -import type { IAppExternalURL, ICategory } from './@types/IOrchestrator'; -import { RealAppsEngineUIHost } from './RealAppsEngineUIHost'; const isErrorObject = (e: unknown): e is { error: string } => typeof e === 'object' && e !== null && 'error' in e && typeof e.error === 'string'; diff --git a/apps/meteor/client/components/Contextualbar/ContextualbarDialog.tsx b/apps/meteor/client/components/Contextualbar/ContextualbarDialog.tsx index 4e46402700879..528b01e8854a1 100644 --- a/apps/meteor/client/components/Contextualbar/ContextualbarDialog.tsx +++ b/apps/meteor/client/components/Contextualbar/ContextualbarDialog.tsx @@ -5,9 +5,9 @@ import React, { useCallback, useRef } from 'react'; import type { AriaDialogProps } from 'react-aria'; import { FocusScope, useDialog } from 'react-aria'; -import { useRoomToolbox } from '../../views/room/contexts/RoomToolboxContext'; import Contextualbar from './Contextualbar'; import ContextualbarResizable from './ContextualbarResizable'; +import { useRoomToolbox } from '../../views/room/contexts/RoomToolboxContext'; type ContextualbarDialogProps = AriaDialogProps & ComponentProps; diff --git a/apps/meteor/client/components/Contextualbar/ContextualbarResizable.tsx b/apps/meteor/client/components/Contextualbar/ContextualbarResizable.tsx index 8eb35d0c9c93c..69adfd4bc7e16 100644 --- a/apps/meteor/client/components/Contextualbar/ContextualbarResizable.tsx +++ b/apps/meteor/client/components/Contextualbar/ContextualbarResizable.tsx @@ -9,6 +9,8 @@ type ContextualbarResizableProps = { defaultWidth: string } & ComponentProps { const [contextualbarWidth, setContextualbarWidth] = useLocalStorage('contextualbarWidth', defaultWidth); + const [expanded] = useLocalStorage('expand-threads', false); + const handleStyle = css` height: 100%; &:hover { @@ -29,7 +31,7 @@ const ContextualbarResizable = ({ defaultWidth, children, ...props }: Contextual minWidth={defaultWidth} maxWidth='50%' minHeight='100%' - handleStyles={{ left: { width: '3px', zIndex: 99, left: 0 } }} + handleStyles={{ left: { width: '3px', zIndex: expanded ? 5 : 99, left: 0 } }} handleComponent={{ left: }} > {children} diff --git a/apps/meteor/client/components/GazzodownText.tsx b/apps/meteor/client/components/GazzodownText.tsx index abee977b9baab..05c6788062a9d 100644 --- a/apps/meteor/client/components/GazzodownText.tsx +++ b/apps/meteor/client/components/GazzodownText.tsx @@ -10,9 +10,9 @@ import React, { useCallback, memo, useMemo } from 'react'; import { detectEmoji } from '../lib/utils/detectEmoji'; import { fireGlobalEvent } from '../lib/utils/fireGlobalEvent'; +import { useMessageListHighlights } from './message/list/MessageListContext'; import { useUserCard } from '../views/room/contexts/UserCardContext'; import { useGoToRoom } from '../views/room/hooks/useGoToRoom'; -import { useMessageListHighlights } from './message/list/MessageListContext'; type GazzodownTextProps = { children: JSX.Element; diff --git a/apps/meteor/client/components/GenericModal/GenericModal.spec.tsx b/apps/meteor/client/components/GenericModal/GenericModal.spec.tsx index b47b6abf7b007..aa220edcc651e 100644 --- a/apps/meteor/client/components/GenericModal/GenericModal.spec.tsx +++ b/apps/meteor/client/components/GenericModal/GenericModal.spec.tsx @@ -4,8 +4,8 @@ import userEvent from '@testing-library/user-event'; import type { ReactElement } from 'react'; import React, { Suspense } from 'react'; -import ModalProviderWithRegion from '../../providers/ModalProvider/ModalProviderWithRegion'; import GenericModal from './GenericModal'; +import ModalProviderWithRegion from '../../providers/ModalProvider/ModalProviderWithRegion'; const renderModal = (modalElement: ReactElement) => { const { diff --git a/apps/meteor/client/components/GenericTable/GenericTable.tsx b/apps/meteor/client/components/GenericTable/GenericTable.tsx index 05173fbe7004b..dcefd8de12d8a 100644 --- a/apps/meteor/client/components/GenericTable/GenericTable.tsx +++ b/apps/meteor/client/components/GenericTable/GenericTable.tsx @@ -1,6 +1,6 @@ import { Box, Table } from '@rocket.chat/fuselage'; -import type { ComponentProps } from 'react'; -import React, { type ForwardedRef, type ReactNode, forwardRef } from 'react'; +import type { ComponentProps, ForwardedRef, ReactNode } from 'react'; +import React, { forwardRef } from 'react'; import { CustomScrollbars } from '../CustomScrollbars'; diff --git a/apps/meteor/client/components/ImageGallery/ImageGallery.tsx b/apps/meteor/client/components/ImageGallery/ImageGallery.tsx index e04bc003cf9b7..214b76667b0b2 100644 --- a/apps/meteor/client/components/ImageGallery/ImageGallery.tsx +++ b/apps/meteor/client/components/ImageGallery/ImageGallery.tsx @@ -5,15 +5,12 @@ import React, { useRef, useState } from 'react'; import { FocusScope } from 'react-aria'; import { createPortal } from 'react-dom'; import { useTranslation } from 'react-i18next'; -import { Keyboard, Navigation, Zoom, A11y } from 'swiper'; -import type { SwiperClass, SwiperRef } from 'swiper/react'; -import { Swiper, SwiperSlide } from 'swiper/react'; +import { Navigation, Zoom, Keyboard, A11y } from 'swiper/modules/index.mjs'; +import type { SwiperClass, SwiperRef } from 'swiper/swiper-react'; +import { Swiper, SwiperSlide } from 'swiper/swiper-react.mjs'; -// Import Swiper styles import 'swiper/swiper.css'; -import 'swiper/modules/navigation/navigation.min.css'; -import 'swiper/modules/keyboard/keyboard.min.css'; -import 'swiper/modules/zoom/zoom.min.css'; +import 'swiper/modules/zoom.css'; import { usePreventPropagation } from '../../hooks/usePreventPropagation'; @@ -172,10 +169,10 @@ export const ImageGallery = ({ images, onClose, loadMore }: { images: IUpload[]; zoom={{ toggle: false }} lazyPreloaderClass='rcx-lazy-preloader' runCallbacksOnInit - onKeyPress={(_, keyCode) => String(keyCode) === '27' && onClose()} + onKeyPress={(_: SwiperClass, keyCode: string) => String(keyCode) === '27' && onClose()} modules={[Navigation, Zoom, Keyboard, A11y]} - onInit={(swiper) => setSwiperInst(swiper)} - onSlidesGridLengthChange={(swiper) => { + onInit={(swiper: SwiperClass) => setSwiperInst(swiper)} + onSlidesGridLengthChange={(swiper: SwiperClass) => { swiper.slideTo(images.length - gridSize, 0); setGridSize(images.length); }} diff --git a/apps/meteor/client/components/InfoPanel/InfoPanel.stories.tsx b/apps/meteor/client/components/InfoPanel/InfoPanel.stories.tsx index 5727c355cc08b..d40884e60ba80 100644 --- a/apps/meteor/client/components/InfoPanel/InfoPanel.stories.tsx +++ b/apps/meteor/client/components/InfoPanel/InfoPanel.stories.tsx @@ -13,8 +13,8 @@ import { InfoPanelText, InfoPanelTitle, } from '.'; -import { createFakeRoom } from '../../../tests/mocks/data'; import RetentionPolicyCallout from './RetentionPolicyCallout'; +import { createFakeRoom } from '../../../tests/mocks/data'; export default { title: 'Info Panel/InfoPanel', diff --git a/apps/meteor/client/components/InfoPanel/RetentionPolicyCallout.spec.tsx b/apps/meteor/client/components/InfoPanel/RetentionPolicyCallout.spec.tsx index a9305b5f1f15c..332c70f26dd4e 100644 --- a/apps/meteor/client/components/InfoPanel/RetentionPolicyCallout.spec.tsx +++ b/apps/meteor/client/components/InfoPanel/RetentionPolicyCallout.spec.tsx @@ -1,9 +1,9 @@ import { render, screen } from '@testing-library/react'; import React from 'react'; +import RetentionPolicyCallout from './RetentionPolicyCallout'; import { createRenteionPolicySettingsMock as createMock } from '../../../tests/mocks/client/mockRetentionPolicySettings'; import { createFakeRoom } from '../../../tests/mocks/data'; -import RetentionPolicyCallout from './RetentionPolicyCallout'; jest.useFakeTimers(); diff --git a/apps/meteor/client/components/MarkdownText.tsx b/apps/meteor/client/components/MarkdownText.tsx index 9ce44f8a9ff41..7f13c7e469c45 100644 --- a/apps/meteor/client/components/MarkdownText.tsx +++ b/apps/meteor/client/components/MarkdownText.tsx @@ -132,7 +132,7 @@ const MarkdownText = ({ // Add a hook to make all external links open a new window dompurify.addHook('afterSanitizeAttributes', (node) => { - if ('target' in node) { + if (isElement(node) && 'target' in node) { const href = node.getAttribute('href') || ''; node.setAttribute('title', `${t('Go_to_href', { href: href.replace(getBaseURI(), '') })}`); @@ -157,4 +157,6 @@ const MarkdownText = ({ ) : null; }; +const isElement = (node: Node): node is Element => node.nodeType === Node.ELEMENT_NODE; + export default MarkdownText; diff --git a/apps/meteor/client/components/Omnichannel/Tags.tsx b/apps/meteor/client/components/Omnichannel/Tags.tsx index 7c9e51d220f06..d96c560b9e585 100644 --- a/apps/meteor/client/components/Omnichannel/Tags.tsx +++ b/apps/meteor/client/components/Omnichannel/Tags.tsx @@ -5,9 +5,9 @@ import type { ChangeEvent, ReactElement } from 'react'; import React, { useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { CurrentChatTags } from '../../views/omnichannel/additionalForms'; import { FormSkeleton } from './Skeleton'; import { useLivechatTags } from './hooks/useLivechatTags'; +import { CurrentChatTags } from '../../views/omnichannel/additionalForms'; type TagsProps = { tags?: string[]; diff --git a/apps/meteor/client/components/RoomIcon/OmnichannelRoomIcon/OmnichannelAppSourceRoomIcon.tsx b/apps/meteor/client/components/RoomIcon/OmnichannelRoomIcon/OmnichannelAppSourceRoomIcon.tsx index 6a841c30491be..b6cc94007002e 100644 --- a/apps/meteor/client/components/RoomIcon/OmnichannelRoomIcon/OmnichannelAppSourceRoomIcon.tsx +++ b/apps/meteor/client/components/RoomIcon/OmnichannelRoomIcon/OmnichannelAppSourceRoomIcon.tsx @@ -3,8 +3,8 @@ import { Icon, Box } from '@rocket.chat/fuselage'; import type { ComponentProps } from 'react'; import React from 'react'; -import { AsyncStatePhase } from '../../../lib/asyncState/AsyncStatePhase'; import { useOmnichannelRoomIcon } from './context/OmnichannelRoomIconContext'; +import { AsyncStatePhase } from '../../../lib/asyncState/AsyncStatePhase'; type OmnichannelAppSourceRoomIconProps = { source: IOmnichannelSourceFromApp; diff --git a/apps/meteor/client/components/RoomIcon/RoomIcon.tsx b/apps/meteor/client/components/RoomIcon/RoomIcon.tsx index d757071fedf51..12f4a13d1f33c 100644 --- a/apps/meteor/client/components/RoomIcon/RoomIcon.tsx +++ b/apps/meteor/client/components/RoomIcon/RoomIcon.tsx @@ -4,8 +4,8 @@ import { Icon } from '@rocket.chat/fuselage'; import type { ComponentProps, ReactElement } from 'react'; import React, { isValidElement } from 'react'; -import { useRoomIcon } from '../../hooks/useRoomIcon'; import { OmnichannelRoomIcon } from './OmnichannelRoomIcon'; +import { useRoomIcon } from '../../hooks/useRoomIcon'; export const RoomIcon = ({ room, diff --git a/apps/meteor/client/components/Sidebar/SidebarItemsAssembler.tsx b/apps/meteor/client/components/Sidebar/SidebarItemsAssembler.tsx index b588e223d922e..8507ff950dc4a 100644 --- a/apps/meteor/client/components/Sidebar/SidebarItemsAssembler.tsx +++ b/apps/meteor/client/components/Sidebar/SidebarItemsAssembler.tsx @@ -2,9 +2,9 @@ import { Divider } from '@rocket.chat/fuselage'; import React, { Fragment, memo } from 'react'; import { useTranslation } from 'react-i18next'; +import SidebarNavigationItem from './SidebarNavigationItem'; import type { SidebarItem } from '../../lib/createSidebarItems'; import { isSidebarItem } from '../../lib/createSidebarItems'; -import SidebarNavigationItem from './SidebarNavigationItem'; type SidebarItemsAssemblerProps = { items: SidebarItem[]; diff --git a/apps/meteor/client/components/SidebarToggler/SidebarToggler.tsx b/apps/meteor/client/components/SidebarToggler/SidebarToggler.tsx index 2102621a35d73..1cdb993d433f2 100644 --- a/apps/meteor/client/components/SidebarToggler/SidebarToggler.tsx +++ b/apps/meteor/client/components/SidebarToggler/SidebarToggler.tsx @@ -3,8 +3,8 @@ import { useLayout, useSession } from '@rocket.chat/ui-contexts'; import type { ReactElement } from 'react'; import React, { memo } from 'react'; -import { useEmbeddedLayout } from '../../hooks/useEmbeddedLayout'; import SidebarTogglerButton from './SidebarTogglerButton'; +import { useEmbeddedLayout } from '../../hooks/useEmbeddedLayout'; const SideBarToggler = (): ReactElement => { const { sidebar } = useLayout(); diff --git a/apps/meteor/client/components/avatar/UserAvatarEditor/UserAvatarEditor.tsx b/apps/meteor/client/components/avatar/UserAvatarEditor/UserAvatarEditor.tsx index 823fcabd57cf0..95659d762d302 100644 --- a/apps/meteor/client/components/avatar/UserAvatarEditor/UserAvatarEditor.tsx +++ b/apps/meteor/client/components/avatar/UserAvatarEditor/UserAvatarEditor.tsx @@ -7,11 +7,11 @@ import type { ReactElement, ChangeEvent } from 'react'; import React, { useState, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; -import { useSingleFileInput } from '../../../hooks/useSingleFileInput'; -import { isValidImageFormat } from '../../../lib/utils/isValidImageFormat'; import type { UserAvatarSuggestion } from './UserAvatarSuggestion'; import UserAvatarSuggestions from './UserAvatarSuggestions'; import { readFileAsDataURL } from './readFileAsDataURL'; +import { useSingleFileInput } from '../../../hooks/useSingleFileInput'; +import { isValidImageFormat } from '../../../lib/utils/isValidImageFormat'; type UserAvatarEditorProps = { currentUsername: IUser['username']; diff --git a/apps/meteor/client/components/dataView/Growth.stories.tsx b/apps/meteor/client/components/dataView/Growth.stories.tsx index 11092d52f9937..28f52cd01f3fc 100644 --- a/apps/meteor/client/components/dataView/Growth.stories.tsx +++ b/apps/meteor/client/components/dataView/Growth.stories.tsx @@ -2,8 +2,8 @@ import { Box } from '@rocket.chat/fuselage'; import type { Meta, StoryFn } from '@storybook/react'; import React from 'react'; -import { useAutoSequence } from '../../stories/hooks/useAutoSequence'; import Growth from './Growth'; +import { useAutoSequence } from '../../stories/hooks/useAutoSequence'; export default { title: 'Components/Data/Growth', diff --git a/apps/meteor/client/components/dataView/NegativeGrowthSymbol.stories.tsx b/apps/meteor/client/components/dataView/NegativeGrowthSymbol.stories.tsx index 9c5ca3f4d44de..19be0dde4af66 100644 --- a/apps/meteor/client/components/dataView/NegativeGrowthSymbol.stories.tsx +++ b/apps/meteor/client/components/dataView/NegativeGrowthSymbol.stories.tsx @@ -2,8 +2,8 @@ import { Box } from '@rocket.chat/fuselage'; import type { Meta, StoryFn } from '@storybook/react'; import React from 'react'; -import { useAutoSequence } from '../../stories/hooks/useAutoSequence'; import NegativeGrowthSymbol from './NegativeGrowthSymbol'; +import { useAutoSequence } from '../../stories/hooks/useAutoSequence'; export default { title: 'Components/Data/NegativeGrowthSymbol', diff --git a/apps/meteor/client/components/dataView/PositiveGrowthSymbol.stories.tsx b/apps/meteor/client/components/dataView/PositiveGrowthSymbol.stories.tsx index 8f08dfee9c0ed..603c97edf7885 100644 --- a/apps/meteor/client/components/dataView/PositiveGrowthSymbol.stories.tsx +++ b/apps/meteor/client/components/dataView/PositiveGrowthSymbol.stories.tsx @@ -2,8 +2,8 @@ import { Box } from '@rocket.chat/fuselage'; import type { Meta, StoryFn } from '@storybook/react'; import React from 'react'; -import { useAutoSequence } from '../../stories/hooks/useAutoSequence'; import PositiveGrowthSymbol from './PositiveGrowthSymbol'; +import { useAutoSequence } from '../../stories/hooks/useAutoSequence'; export default { title: 'Components/Data/PositiveGrowthSymbol', diff --git a/apps/meteor/client/components/message/MessageHeader.tsx b/apps/meteor/client/components/message/MessageHeader.tsx index 21a4d8484f8f1..e2d7fb6f26691 100644 --- a/apps/meteor/client/components/message/MessageHeader.tsx +++ b/apps/meteor/client/components/message/MessageHeader.tsx @@ -11,16 +11,16 @@ import type { KeyboardEvent, ReactElement } from 'react'; import React, { memo } from 'react'; import { useTranslation } from 'react-i18next'; +import StatusIndicators from './StatusIndicators'; +import MessageRoles from './header/MessageRoles'; +import { useMessageListShowUsername, useMessageListShowRealName, useMessageListShowRoles } from './list/MessageListContext'; import { getUserDisplayName } from '../../../lib/getUserDisplayName'; import { useFormatDateAndTime } from '../../hooks/useFormatDateAndTime'; import { useFormatTime } from '../../hooks/useFormatTime'; import { useUserData } from '../../hooks/useUserData'; import type { UserPresence } from '../../lib/presence'; -import { useUserCard } from '../../views/room/contexts/UserCardContext'; -import StatusIndicators from './StatusIndicators'; -import MessageRoles from './header/MessageRoles'; import { useMessageRoles } from './header/hooks/useMessageRoles'; -import { useMessageListShowUsername, useMessageListShowRealName, useMessageListShowRoles } from './list/MessageListContext'; +import { useUserCard } from '../../views/room/contexts/UserCardContext'; type MessageHeaderProps = { message: IMessage; diff --git a/apps/meteor/client/components/message/content/MessageActions.tsx b/apps/meteor/client/components/message/content/MessageActions.tsx index d38fbb6c64dfa..3700067a72720 100644 --- a/apps/meteor/client/components/message/content/MessageActions.tsx +++ b/apps/meteor/client/components/message/content/MessageActions.tsx @@ -6,8 +6,8 @@ import type { TranslationKey } from '@rocket.chat/ui-contexts'; import type { ReactElement } from 'react'; import React from 'react'; -import { actionLinks } from '../../../lib/actionLinks'; import MessageAction from './actions/MessageAction'; +import { actionLinks } from '../../../lib/actionLinks'; type MessageActionOptions = { icon: IconName; diff --git a/apps/meteor/client/components/message/content/attachments/DefaultAttachment.tsx b/apps/meteor/client/components/message/content/attachments/DefaultAttachment.tsx index c3f0fdcbf26d8..0bb6fb37da1ea 100644 --- a/apps/meteor/client/components/message/content/attachments/DefaultAttachment.tsx +++ b/apps/meteor/client/components/message/content/attachments/DefaultAttachment.tsx @@ -3,8 +3,6 @@ import { isActionAttachment } from '@rocket.chat/core-typings'; import type { ReactNode, ComponentProps, ReactElement } from 'react'; import React from 'react'; -import MarkdownText from '../../../MarkdownText'; -import { useCollapse } from '../../hooks/useCollapse'; import { ActionAttachment } from './default/ActionAttachtment'; import FieldsAttachment from './default/FieldsAttachment'; import AttachmentAuthor from './structure/AttachmentAuthor'; @@ -17,6 +15,8 @@ import AttachmentRow from './structure/AttachmentRow'; import AttachmentText from './structure/AttachmentText'; import AttachmentThumb from './structure/AttachmentThumb'; import AttachmentTitle from './structure/AttachmentTitle'; +import MarkdownText from '../../../MarkdownText'; +import { useCollapse } from '../../hooks/useCollapse'; const applyMarkdownIfRequires = ( list: MessageAttachmentDefault['mrkdwn_in'] = ['text', 'pretext'], diff --git a/apps/meteor/client/components/message/content/attachments/default/ActionAttachtment.tsx b/apps/meteor/client/components/message/content/attachments/default/ActionAttachtment.tsx index 2ecd19598b3b8..1ca98ca3d9b3f 100644 --- a/apps/meteor/client/components/message/content/attachments/default/ActionAttachtment.tsx +++ b/apps/meteor/client/components/message/content/attachments/default/ActionAttachtment.tsx @@ -2,8 +2,8 @@ import type { MessageAttachmentAction } from '@rocket.chat/core-typings'; import { Box, Button, ButtonGroup } from '@rocket.chat/fuselage'; import React from 'react'; -import { useExternalLink } from '../../../../../hooks/useExternalLink'; import ActionAttachmentButton from './ActionAttachmentButton'; +import { useExternalLink } from '../../../../../hooks/useExternalLink'; type ActionAttachmentProps = MessageAttachmentAction; diff --git a/apps/meteor/client/components/message/content/attachments/default/FieldsAttachment.tsx b/apps/meteor/client/components/message/content/attachments/default/FieldsAttachment.tsx index 4e6650e5ec98a..b42463131a1f6 100644 --- a/apps/meteor/client/components/message/content/attachments/default/FieldsAttachment.tsx +++ b/apps/meteor/client/components/message/content/attachments/default/FieldsAttachment.tsx @@ -15,7 +15,7 @@ type FieldsAttachmentProps = { const FieldsAttachment = ({ fields }: FieldsAttachmentProps) => ( - {fields.map((field, index) => (field.short ? : ))} + {fields.map((field, index) => (field.short ? : ))} ); diff --git a/apps/meteor/client/components/message/content/attachments/structure/AttachmentDownload.tsx b/apps/meteor/client/components/message/content/attachments/structure/AttachmentDownload.tsx index ea81f48c034e4..0ca7dce3c6386 100644 --- a/apps/meteor/client/components/message/content/attachments/structure/AttachmentDownload.tsx +++ b/apps/meteor/client/components/message/content/attachments/structure/AttachmentDownload.tsx @@ -1,9 +1,9 @@ import type { ComponentPropsWithoutRef } from 'react'; import React from 'react'; -import type Action from '../../Action'; import AttachmentDownloadBase from './AttachmentDownloadBase'; import AttachmentEncryptedDownload from './AttachmentEncryptedDownload'; +import type Action from '../../Action'; type AttachmentDownloadProps = Omit, 'icon'> & { title?: string | undefined; href: string }; diff --git a/apps/meteor/client/components/message/content/attachments/structure/AttachmentEncryptedDownload.tsx b/apps/meteor/client/components/message/content/attachments/structure/AttachmentEncryptedDownload.tsx index f75b044c69a53..6a2cf0f0bc74a 100644 --- a/apps/meteor/client/components/message/content/attachments/structure/AttachmentEncryptedDownload.tsx +++ b/apps/meteor/client/components/message/content/attachments/structure/AttachmentEncryptedDownload.tsx @@ -1,8 +1,8 @@ import type { ComponentProps } from 'react'; import React from 'react'; -import { useDownloadFromServiceWorker } from '../../../../../hooks/useDownloadFromServiceWorker'; import AttachmentDownloadBase from './AttachmentDownloadBase'; +import { useDownloadFromServiceWorker } from '../../../../../hooks/useDownloadFromServiceWorker'; type AttachmentDownloadProps = ComponentProps; diff --git a/apps/meteor/client/components/message/content/attachments/structure/AttachmentSize.tsx b/apps/meteor/client/components/message/content/attachments/structure/AttachmentSize.tsx index 75a13e6cba344..2d05a7d4c6708 100644 --- a/apps/meteor/client/components/message/content/attachments/structure/AttachmentSize.tsx +++ b/apps/meteor/client/components/message/content/attachments/structure/AttachmentSize.tsx @@ -2,8 +2,8 @@ import type { Box } from '@rocket.chat/fuselage'; import type { ComponentPropsWithoutRef } from 'react'; import React from 'react'; -import { useFormatMemorySize } from '../../../../../hooks/useFormatMemorySize'; import Title from './AttachmentTitle'; +import { useFormatMemorySize } from '../../../../../hooks/useFormatMemorySize'; type AttachmentSizeProps = ComponentPropsWithoutRef & { size: number; wrapper?: boolean }; diff --git a/apps/meteor/client/components/message/content/reactions/Reaction.tsx b/apps/meteor/client/components/message/content/reactions/Reaction.tsx index dd85cfdc787ab..46121e6220128 100644 --- a/apps/meteor/client/components/message/content/reactions/Reaction.tsx +++ b/apps/meteor/client/components/message/content/reactions/Reaction.tsx @@ -4,9 +4,9 @@ import type { ComponentProps, ReactElement } from 'react'; import React, { useRef, useContext } from 'react'; import { useTranslation } from 'react-i18next'; +import ReactionTooltip from './ReactionTooltip'; import { getEmojiClassNameAndDataTitle } from '../../../../lib/utils/renderEmoji'; import { MessageListContext } from '../../list/MessageListContext'; -import ReactionTooltip from './ReactionTooltip'; // TODO: replace it with proper usage of i18next plurals type ReactionProps = { diff --git a/apps/meteor/client/components/message/content/urlPreviews/OEmbedCollapsible.tsx b/apps/meteor/client/components/message/content/urlPreviews/OEmbedCollapsible.tsx index 8761b60cc68f2..78a79cb50d444 100644 --- a/apps/meteor/client/components/message/content/urlPreviews/OEmbedCollapsible.tsx +++ b/apps/meteor/client/components/message/content/urlPreviews/OEmbedCollapsible.tsx @@ -3,9 +3,9 @@ import type { ReactElement, ReactNode } from 'react'; import React from 'react'; import { useTranslation } from 'react-i18next'; -import MessageCollapsible from '../../MessageCollapsible'; import OEmbedPreviewContent from './OEmbedPreviewContent'; import type { OEmbedPreviewMetadata } from './OEmbedPreviewMetadata'; +import MessageCollapsible from '../../MessageCollapsible'; type OEmbedCollapsibleProps = { children?: ReactNode } & OEmbedPreviewMetadata; diff --git a/apps/meteor/client/components/message/content/urlPreviews/OEmbedPreviewContent.tsx b/apps/meteor/client/components/message/content/urlPreviews/OEmbedPreviewContent.tsx index 550b325012ed7..68d29b6440b8d 100644 --- a/apps/meteor/client/components/message/content/urlPreviews/OEmbedPreviewContent.tsx +++ b/apps/meteor/client/components/message/content/urlPreviews/OEmbedPreviewContent.tsx @@ -8,8 +8,8 @@ import { import type { ReactElement, ReactNode } from 'react'; import React from 'react'; -import MarkdownText from '../../../MarkdownText'; import type { OEmbedPreviewMetadata } from './OEmbedPreviewMetadata'; +import MarkdownText from '../../../MarkdownText'; type OEmbedPreviewContentProps = { thumb?: ReactElement; children?: ReactNode } & OEmbedPreviewMetadata; diff --git a/apps/meteor/client/components/message/content/urlPreviews/UrlImagePreview.tsx b/apps/meteor/client/components/message/content/urlPreviews/UrlImagePreview.tsx index 8106a01004e0f..449ad1edd7901 100644 --- a/apps/meteor/client/components/message/content/urlPreviews/UrlImagePreview.tsx +++ b/apps/meteor/client/components/message/content/urlPreviews/UrlImagePreview.tsx @@ -2,8 +2,8 @@ import { Box, MessageGenericPreviewImage } from '@rocket.chat/fuselage'; import type { ReactElement } from 'react'; import React from 'react'; -import { useOembedLayout } from '../../hooks/useOembedLayout'; import type { UrlPreviewMetadata } from './UrlPreviewMetadata'; +import { useOembedLayout } from '../../hooks/useOembedLayout'; const UrlImagePreview = ({ url }: Pick): ReactElement => { const { maxHeight: oembedMaxHeight } = useOembedLayout(); diff --git a/apps/meteor/client/components/message/content/urlPreviews/UrlPreview.tsx b/apps/meteor/client/components/message/content/urlPreviews/UrlPreview.tsx index f4ea4fb2d6f9d..a302c1c32ac2f 100644 --- a/apps/meteor/client/components/message/content/urlPreviews/UrlPreview.tsx +++ b/apps/meteor/client/components/message/content/urlPreviews/UrlPreview.tsx @@ -4,9 +4,9 @@ import type { ReactElement } from 'react'; import React from 'react'; import { useTranslation } from 'react-i18next'; -import { useCollapse } from '../../hooks/useCollapse'; import type { UrlPreviewMetadata } from './UrlPreviewMetadata'; import UrlPreviewResolver from './UrlPreviewResolver'; +import { useCollapse } from '../../hooks/useCollapse'; const UrlPreview = (props: UrlPreviewMetadata): ReactElement => { const autoLoadMedia = useAttachmentAutoLoadEmbedMedia(); diff --git a/apps/meteor/client/components/message/hooks/useNormalizedMessage.ts b/apps/meteor/client/components/message/hooks/useNormalizedMessage.ts index a2693d704d41a..2a433abc4e2f1 100644 --- a/apps/meteor/client/components/message/hooks/useNormalizedMessage.ts +++ b/apps/meteor/client/components/message/hooks/useNormalizedMessage.ts @@ -11,12 +11,12 @@ import type { Options } from '@rocket.chat/message-parser'; import { useSetting } from '@rocket.chat/ui-contexts'; import { useMemo } from 'react'; +import { useSubscriptionFromMessageQuery } from './useSubscriptionFromMessageQuery'; import type { MessageWithMdEnforced } from '../../../lib/parseMessageTextToAstMarkdown'; import { parseMessageTextToAstMarkdown } from '../../../lib/parseMessageTextToAstMarkdown'; import { useAutoLinkDomains } from '../../../views/room/MessageList/hooks/useAutoLinkDomains'; import { useAutoTranslate } from '../../../views/room/MessageList/hooks/useAutoTranslate'; import { useKatex } from '../../../views/room/MessageList/hooks/useKatex'; -import { useSubscriptionFromMessageQuery } from './useSubscriptionFromMessageQuery'; const normalizeAttachments = (attachments: MessageAttachment[], name?: string, type?: string): MessageAttachment[] => { if (name) { diff --git a/apps/meteor/client/components/message/toolbar/MessageToolbar.tsx b/apps/meteor/client/components/message/toolbar/MessageToolbar.tsx index 17357be8b6ab7..6ba7e1b434d6c 100644 --- a/apps/meteor/client/components/message/toolbar/MessageToolbar.tsx +++ b/apps/meteor/client/components/message/toolbar/MessageToolbar.tsx @@ -8,6 +8,9 @@ import { useQuery } from '@tanstack/react-query'; import type { ComponentProps, ReactElement } from 'react'; import React, { memo, useMemo, useRef } from 'react'; +import MessageActionMenu from './MessageActionMenu'; +import MessageToolbarStarsActionMenu from './MessageToolbarStarsActionMenu'; +import { useWebDAVMessageAction } from './useWebDAVMessageAction'; import type { MessageActionContext } from '../../../../app/ui-utils/client/lib/MessageAction'; import { MessageAction } from '../../../../app/ui-utils/client/lib/MessageAction'; import { useEmojiPickerData } from '../../../contexts/EmojiPickerContext'; @@ -18,9 +21,6 @@ import { useIsSelecting } from '../../../views/room/MessageList/contexts/Selecte import { useAutoTranslate } from '../../../views/room/MessageList/hooks/useAutoTranslate'; import { useChat } from '../../../views/room/contexts/ChatContext'; import { useRoomToolbox } from '../../../views/room/contexts/RoomToolboxContext'; -import MessageActionMenu from './MessageActionMenu'; -import MessageToolbarStarsActionMenu from './MessageToolbarStarsActionMenu'; -import { useWebDAVMessageAction } from './useWebDAVMessageAction'; const getMessageContext = (message: IMessage, room: IRoom, context?: MessageActionContext): MessageActionContext => { if (context) { diff --git a/apps/meteor/client/hooks/lists/useScrollableMessageList.ts b/apps/meteor/client/hooks/lists/useScrollableMessageList.ts index d78b13c3030f5..679ba23b5cd24 100644 --- a/apps/meteor/client/hooks/lists/useScrollableMessageList.ts +++ b/apps/meteor/client/hooks/lists/useScrollableMessageList.ts @@ -1,10 +1,10 @@ import type { IMessage, Serialized } from '@rocket.chat/core-typings'; import { useCallback } from 'react'; +import { useScrollableRecordList } from './useScrollableRecordList'; import type { MessageList } from '../../lib/lists/MessageList'; import type { RecordListBatchChanges } from '../../lib/lists/RecordList'; import { mapMessageFromApi } from '../../lib/utils/mapMessageFromApi'; -import { useScrollableRecordList } from './useScrollableRecordList'; export const useScrollableMessageList = ( messageList: MessageList, diff --git a/apps/meteor/client/hooks/omnichannel/useIsRoomOverMacLimit.tsx b/apps/meteor/client/hooks/omnichannel/useIsRoomOverMacLimit.tsx index bf4e4b1bf9575..310bea690a33d 100644 --- a/apps/meteor/client/hooks/omnichannel/useIsRoomOverMacLimit.tsx +++ b/apps/meteor/client/hooks/omnichannel/useIsRoomOverMacLimit.tsx @@ -1,5 +1,5 @@ -import type { IRoom } from '@rocket.chat/core-typings'; -import { isOmnichannelRoom, type IOmnichannelGenericRoom, isVoipRoom } from '@rocket.chat/core-typings'; +import { isOmnichannelRoom, isVoipRoom } from '@rocket.chat/core-typings'; +import type { IRoom, IOmnichannelGenericRoom } from '@rocket.chat/core-typings'; import { useIsOverMacLimit } from './useIsOverMacLimit'; diff --git a/apps/meteor/client/hooks/roomActions/useContactProfileRoomAction.ts b/apps/meteor/client/hooks/roomActions/useContactProfileRoomAction.ts index 17dbc34254936..a78b9f4be261a 100644 --- a/apps/meteor/client/hooks/roomActions/useContactProfileRoomAction.ts +++ b/apps/meteor/client/hooks/roomActions/useContactProfileRoomAction.ts @@ -2,7 +2,7 @@ import { lazy, useMemo } from 'react'; import type { RoomToolboxActionConfig } from '../../views/room/contexts/RoomToolboxContext'; -const ContactsContextualBar = lazy(() => import('../../views/omnichannel/directory/contacts/contextualBar/ContactsContextualBar')); +const ContactInfoRouter = lazy(() => import('../../views/omnichannel/directory/contacts/contactInfo/ContactInfoRouter')); export const useContactProfileRoomAction = () => { return useMemo( @@ -11,7 +11,7 @@ export const useContactProfileRoomAction = () => { groups: ['live' /* , 'voip'*/], title: 'Contact_Info', icon: 'user', - tabComponent: ContactsContextualBar, + tabComponent: ContactInfoRouter, order: 1, }), [], diff --git a/apps/meteor/client/hooks/roomActions/useStartCallRoomAction/useStartCallRoomAction.tsx b/apps/meteor/client/hooks/roomActions/useStartCallRoomAction/useStartCallRoomAction.tsx index 18d3efd010536..a275fe755560b 100644 --- a/apps/meteor/client/hooks/roomActions/useStartCallRoomAction/useStartCallRoomAction.tsx +++ b/apps/meteor/client/hooks/roomActions/useStartCallRoomAction/useStartCallRoomAction.tsx @@ -1,10 +1,10 @@ import { GenericMenu } from '@rocket.chat/ui-client'; import React, { useMemo } from 'react'; -import HeaderToolbarAction from '../../../components/Header/HeaderToolbarAction'; -import type { RoomToolboxActionConfig } from '../../../views/room/contexts/RoomToolboxContext'; import useVideoConfMenuOptions from './useVideoConfMenuOptions'; import useVoipMenuOptions from './useVoipMenuOptions'; +import HeaderToolbarAction from '../../../components/Header/HeaderToolbarAction'; +import type { RoomToolboxActionConfig } from '../../../views/room/contexts/RoomToolboxContext'; export const useStartCallRoomAction = () => { const videoCall = useVideoConfMenuOptions(); diff --git a/apps/meteor/client/hooks/useAppActionButtons.ts b/apps/meteor/client/hooks/useAppActionButtons.ts index 2a074fcc3be1a..0dcb2d380d465 100644 --- a/apps/meteor/client/hooks/useAppActionButtons.ts +++ b/apps/meteor/client/hooks/useAppActionButtons.ts @@ -7,13 +7,13 @@ import { useQuery, useQueryClient } from '@tanstack/react-query'; import { useEffect, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; +import { useApplyButtonFilters, useApplyButtonAuthFilter } from './useApplyButtonFilters'; +import { useFilterActionsByContext } from './useFilterActions'; import { UiKitTriggerTimeoutError } from '../../app/ui-message/client/UiKitTriggerTimeoutError'; import type { MessageActionConfig, MessageActionContext } from '../../app/ui-utils/client/lib/MessageAction'; import type { MessageBoxAction } from '../../app/ui-utils/client/lib/messageBox'; import { Utilities } from '../../ee/lib/misc/Utilities'; import { useUiKitActionManager } from '../uikit/hooks/useUiKitActionManager'; -import { useApplyButtonFilters, useApplyButtonAuthFilter } from './useApplyButtonFilters'; -import { useFilterActionsByContext } from './useFilterActions'; const getIdForActionButton = ({ appId, actionId }: IUIActionButton): string => `${appId}/${actionId}`; diff --git a/apps/meteor/client/hooks/useDecryptedMessage.spec.ts b/apps/meteor/client/hooks/useDecryptedMessage.spec.ts index 62e77a77b096f..404ee4b857397 100644 --- a/apps/meteor/client/hooks/useDecryptedMessage.spec.ts +++ b/apps/meteor/client/hooks/useDecryptedMessage.spec.ts @@ -1,8 +1,8 @@ import { isE2EEMessage } from '@rocket.chat/core-typings'; import { renderHook, waitFor } from '@testing-library/react'; -import { e2e } from '../../app/e2e/client/rocketchat.e2e'; import { useDecryptedMessage } from './useDecryptedMessage'; +import { e2e } from '../../app/e2e/client/rocketchat.e2e'; // Mock the dependencies jest.mock('@rocket.chat/core-typings', () => ({ diff --git a/apps/meteor/client/hooks/useDeviceLogout.tsx b/apps/meteor/client/hooks/useDeviceLogout.tsx index c9c089aa2ce0c..64cfde76b68b7 100644 --- a/apps/meteor/client/hooks/useDeviceLogout.tsx +++ b/apps/meteor/client/hooks/useDeviceLogout.tsx @@ -1,8 +1,8 @@ import { useSetModal, useTranslation, useToastMessageDispatch, useRoute, useRouteParameter } from '@rocket.chat/ui-contexts'; import React, { useCallback } from 'react'; -import GenericModal from '../components/GenericModal'; import { useEndpointAction } from './useEndpointAction'; +import GenericModal from '../components/GenericModal'; export const useDeviceLogout = ( sessionId: string, diff --git a/apps/meteor/client/hooks/useDevicesMenuOption.tsx b/apps/meteor/client/hooks/useDevicesMenuOption.tsx index a32b54920feee..e6395fcb936c5 100644 --- a/apps/meteor/client/hooks/useDevicesMenuOption.tsx +++ b/apps/meteor/client/hooks/useDevicesMenuOption.tsx @@ -4,8 +4,8 @@ import type { ReactNode } from 'react'; import React from 'react'; import { useTranslation } from 'react-i18next'; -import DeviceSettingsModal from '../voip/modals/DeviceSettingsModal'; import { useHasLicenseModule } from './useHasLicenseModule'; +import DeviceSettingsModal from '../voip/modals/DeviceSettingsModal'; type DevicesMenuOption = { type?: 'option' | 'heading' | 'divider'; diff --git a/apps/meteor/client/hooks/useEndpointData.ts b/apps/meteor/client/hooks/useEndpointData.ts index 93942946ede03..0c0615d3ffdb5 100644 --- a/apps/meteor/client/hooks/useEndpointData.ts +++ b/apps/meteor/client/hooks/useEndpointData.ts @@ -3,9 +3,9 @@ import type { OperationParams, OperationResult, PathPattern, UrlParams } from '@ import { useToastMessageDispatch, useEndpoint } from '@rocket.chat/ui-contexts'; import { useCallback, useEffect } from 'react'; -import { getConfig } from '../lib/utils/getConfig'; import type { AsyncState } from './useAsyncState'; import { useAsyncState } from './useAsyncState'; +import { getConfig } from '../lib/utils/getConfig'; const log = (name: string): Console['log'] => process.env.NODE_ENV !== 'production' || getConfig('debug') === 'true' diff --git a/apps/meteor/client/hooks/useOTR.spec.tsx b/apps/meteor/client/hooks/useOTR.spec.tsx index 89082c0729527..dbef63f3f5c64 100644 --- a/apps/meteor/client/hooks/useOTR.spec.tsx +++ b/apps/meteor/client/hooks/useOTR.spec.tsx @@ -1,10 +1,10 @@ import { useUserId } from '@rocket.chat/ui-contexts'; import { renderHook } from '@testing-library/react'; +import { useOTR } from './useOTR'; import OTR from '../../app/otr/client/OTR'; import { OtrRoomState } from '../../app/otr/lib/OtrRoomState'; import { useRoom } from '../views/room/contexts/RoomContext'; -import { useOTR } from './useOTR'; jest.mock('@rocket.chat/ui-contexts', () => ({ useUserId: jest.fn(), diff --git a/apps/meteor/client/hooks/useOTR.ts b/apps/meteor/client/hooks/useOTR.ts index 65f9004cf323d..3c6008b15bbed 100644 --- a/apps/meteor/client/hooks/useOTR.ts +++ b/apps/meteor/client/hooks/useOTR.ts @@ -1,11 +1,11 @@ import { useUserId } from '@rocket.chat/ui-contexts'; import { useMemo, useCallback } from 'react'; +import { useReactiveValue } from './useReactiveValue'; import OTR from '../../app/otr/client/OTR'; import type { OTRRoom } from '../../app/otr/client/OTRRoom'; import { OtrRoomState } from '../../app/otr/lib/OtrRoomState'; import { useRoom } from '../views/room/contexts/RoomContext'; -import { useReactiveValue } from './useReactiveValue'; export const useOTR = (): { otr: OTRRoom | undefined; otrState: OtrRoomState } => { const uid = useUserId(); diff --git a/apps/meteor/client/hooks/usePruneWarningMessage.spec.ts b/apps/meteor/client/hooks/usePruneWarningMessage.spec.ts index 2bf4b813be12b..1ca06d70308cf 100644 --- a/apps/meteor/client/hooks/usePruneWarningMessage.spec.ts +++ b/apps/meteor/client/hooks/usePruneWarningMessage.spec.ts @@ -1,9 +1,9 @@ import type { IRoomWithRetentionPolicy } from '@rocket.chat/core-typings'; import { renderHook } from '@testing-library/react'; +import { usePruneWarningMessage } from './usePruneWarningMessage'; import { createRenteionPolicySettingsMock as createMock } from '../../tests/mocks/client/mockRetentionPolicySettings'; import { createFakeRoom } from '../../tests/mocks/data'; -import { usePruneWarningMessage } from './usePruneWarningMessage'; jest.useFakeTimers(); diff --git a/apps/meteor/client/hooks/usePruneWarningMessage.ts b/apps/meteor/client/hooks/usePruneWarningMessage.ts index 8794115b26ba8..35cdb6596bc48 100644 --- a/apps/meteor/client/hooks/usePruneWarningMessage.ts +++ b/apps/meteor/client/hooks/usePruneWarningMessage.ts @@ -6,9 +6,9 @@ import { sendAt } from 'cron'; import intlFormat from 'date-fns/intlFormat'; import { useEffect, useState } from 'react'; +import { useFormattedRelativeTime } from './useFormattedRelativeTime'; import { getCronAdvancedTimerFromPrecisionSetting } from '../../lib/getCronAdvancedTimerFromPrecisionSetting'; import { useRetentionPolicy } from '../views/room/hooks/useRetentionPolicy'; -import { useFormattedRelativeTime } from './useFormattedRelativeTime'; const getMessage = ({ filesOnly, excludePinned }: { filesOnly: boolean; excludePinned: boolean }): TranslationKey => { if (filesOnly) { diff --git a/apps/meteor/client/hooks/useRoomsList.ts b/apps/meteor/client/hooks/useRoomsList.ts index f09a361c92161..66582d3b62f2c 100644 --- a/apps/meteor/client/hooks/useRoomsList.ts +++ b/apps/meteor/client/hooks/useRoomsList.ts @@ -2,9 +2,9 @@ import type { IRoom } from '@rocket.chat/core-typings'; import { useEndpoint } from '@rocket.chat/ui-contexts'; import { useCallback, useState } from 'react'; -import { RecordList } from '../lib/lists/RecordList'; import { useScrollableRecordList } from './lists/useScrollableRecordList'; import { useComponentDidUpdate } from './useComponentDidUpdate'; +import { RecordList } from '../lib/lists/RecordList'; type RoomListOptions = { text: string; diff --git a/apps/meteor/client/hooks/useTagsList.ts b/apps/meteor/client/hooks/useTagsList.ts index 3aa80b4e07b3a..9ca827331d42e 100644 --- a/apps/meteor/client/hooks/useTagsList.ts +++ b/apps/meteor/client/hooks/useTagsList.ts @@ -1,9 +1,9 @@ import { useEndpoint } from '@rocket.chat/ui-contexts'; import { useCallback, useState } from 'react'; -import { RecordList } from '../lib/lists/RecordList'; import { useScrollableRecordList } from './lists/useScrollableRecordList'; import { useComponentDidUpdate } from './useComponentDidUpdate'; +import { RecordList } from '../lib/lists/RecordList'; type TagsListOptions = { filter: string; diff --git a/apps/meteor/client/hooks/useVoipClient.ts b/apps/meteor/client/hooks/useVoipClient.ts index eb1884576d2d5..995880f73c1fe 100644 --- a/apps/meteor/client/hooks/useVoipClient.ts +++ b/apps/meteor/client/hooks/useVoipClient.ts @@ -5,10 +5,10 @@ import { useUser, useSetting, useEndpoint, useStream } from '@rocket.chat/ui-con import { KJUR } from 'jsrsasign'; import { useEffect, useState } from 'react'; +import { useHasLicenseModule } from './useHasLicenseModule'; import { EEVoipClient } from '../lib/voip/EEVoipClient'; import { VoIPUser } from '../lib/voip/VoIPUser'; import { useWebRtcServers } from '../providers/CallProvider/hooks/useWebRtcServers'; -import { useHasLicenseModule } from './useHasLicenseModule'; type UseVoipClientResult = { voipClient?: VoIPUser; diff --git a/apps/meteor/client/lib/RoomManager.ts b/apps/meteor/client/lib/RoomManager.ts index 840493aae4069..c70d2278511c6 100644 --- a/apps/meteor/client/lib/RoomManager.ts +++ b/apps/meteor/client/lib/RoomManager.ts @@ -2,8 +2,8 @@ import type { IRoom } from '@rocket.chat/core-typings'; import { Emitter } from '@rocket.chat/emitter'; import { useSyncExternalStore } from 'use-sync-external-store/shim'; -import { RoomHistoryManager } from '../../app/ui-utils/client/lib/RoomHistoryManager'; import { getConfig } from './utils/getConfig'; +import { RoomHistoryManager } from '../../app/ui-utils/client/lib/RoomHistoryManager'; const debug = !!(getConfig('debug') || getConfig('debug-RoomStore')); diff --git a/apps/meteor/client/lib/VideoConfManager.ts b/apps/meteor/client/lib/VideoConfManager.ts index 2ee480925d6d2..a47d75179d92e 100644 --- a/apps/meteor/client/lib/VideoConfManager.ts +++ b/apps/meteor/client/lib/VideoConfManager.ts @@ -3,8 +3,8 @@ import { Emitter } from '@rocket.chat/emitter'; import { Meteor } from 'meteor/meteor'; import { Tracker } from 'meteor/tracker'; -import { sdk } from '../../app/utils/client/lib/SDKClient'; import { getConfig } from './utils/getConfig'; +import { sdk } from '../../app/utils/client/lib/SDKClient'; const debug = !!(getConfig('debug') || getConfig('debug-VideoConf')); diff --git a/apps/meteor/client/lib/cachedCollections/CachedCollection.ts b/apps/meteor/client/lib/cachedCollections/CachedCollection.ts index a435c5768860e..8a12e3ed677aa 100644 --- a/apps/meteor/client/lib/cachedCollections/CachedCollection.ts +++ b/apps/meteor/client/lib/cachedCollections/CachedCollection.ts @@ -6,14 +6,14 @@ import { Mongo } from 'meteor/mongo'; import { ReactiveVar } from 'meteor/reactive-var'; import { Tracker } from 'meteor/tracker'; -import { sdk } from '../../../app/utils/client/lib/SDKClient'; -import { isTruthy } from '../../../lib/isTruthy'; -import { withDebouncing } from '../../../lib/utils/highOrderFunctions'; import type { MinimongoCollection } from '../../definitions/MinimongoCollection'; import { baseURI } from '../baseURI'; import { onLoggedIn } from '../loggedIn'; -import { getConfig } from '../utils/getConfig'; import { CachedCollectionManager } from './CachedCollectionManager'; +import { sdk } from '../../../app/utils/client/lib/SDKClient'; +import { isTruthy } from '../../../lib/isTruthy'; +import { withDebouncing } from '../../../lib/utils/highOrderFunctions'; +import { getConfig } from '../utils/getConfig'; export type EventType = 'notify-logged' | 'notify-all' | 'notify-user'; diff --git a/apps/meteor/client/lib/chats/ChatAPI.ts b/apps/meteor/client/lib/chats/ChatAPI.ts index 325073d438373..6a782faafa1fc 100644 --- a/apps/meteor/client/lib/chats/ChatAPI.ts +++ b/apps/meteor/client/lib/chats/ChatAPI.ts @@ -1,10 +1,10 @@ import type { IMessage, IRoom, ISubscription, IE2EEMessage, IUpload } from '@rocket.chat/core-typings'; import type { IActionManager } from '@rocket.chat/ui-contexts'; -import type { FormattingButton } from '../../../app/ui-message/client/messageBox/messageBoxFormatting'; -import type { Subscribable } from '../../definitions/Subscribable'; import type { Upload } from './Upload'; import type { ReadStateManager } from './readStateManager'; +import type { FormattingButton } from '../../../app/ui-message/client/messageBox/messageBoxFormatting'; +import type { Subscribable } from '../../definitions/Subscribable'; export type ComposerAPI = { release(): void; diff --git a/apps/meteor/client/lib/chats/data.ts b/apps/meteor/client/lib/chats/data.ts index 4f6263147ba6f..ffb5259983d7b 100644 --- a/apps/meteor/client/lib/chats/data.ts +++ b/apps/meteor/client/lib/chats/data.ts @@ -2,13 +2,13 @@ import type { IEditedMessage, IMessage, IRoom, ISubscription } from '@rocket.cha import { Random } from '@rocket.chat/random'; import moment from 'moment'; +import type { DataAPI } from './ChatAPI'; import { hasAtLeastOnePermission, hasPermission } from '../../../app/authorization/client'; -import { Messages, ChatRoom, ChatSubscription } from '../../../app/models/client'; +import { Messages, Rooms, Subscriptions } from '../../../app/models/client'; import { settings } from '../../../app/settings/client'; import { MessageTypes } from '../../../app/ui-utils/client'; import { sdk } from '../../../app/utils/client/lib/SDKClient'; import { prependReplies } from '../utils/prependReplies'; -import type { DataAPI } from './ChatAPI'; export const createDataAPI = ({ rid, tmid }: { rid: IRoom['_id']; tmid: IMessage['_id'] | undefined }): DataAPI => { const composeMessage = async ( @@ -244,7 +244,7 @@ export const createDataAPI = ({ rid, tmid }: { rid: IRoom['_id']; tmid: IMessage drafts.set(mid, draft); }; - const findRoom = async (): Promise => ChatRoom.findOne({ _id: rid }, { reactive: false }); + const findRoom = async (): Promise => Rooms.findOne({ _id: rid }, { reactive: false }); const getRoom = async (): Promise => { const room = await findRoom(); @@ -256,14 +256,14 @@ export const createDataAPI = ({ rid, tmid }: { rid: IRoom['_id']; tmid: IMessage return room; }; - const isSubscribedToRoom = async (): Promise => !!ChatSubscription.findOne({ rid }, { reactive: false }); + const isSubscribedToRoom = async (): Promise => !!Subscriptions.findOne({ rid }, { reactive: false }); const joinRoom = async (): Promise => { await sdk.call('joinRoom', rid); }; const findDiscussionByID = async (drid: IRoom['_id']): Promise => - ChatRoom.findOne({ _id: drid, prid: { $exists: true } }, { reactive: false }); + Rooms.findOne({ _id: drid, prid: { $exists: true } }, { reactive: false }); const getDiscussionByID = async (drid: IRoom['_id']): Promise => { const discussion = await findDiscussionByID(drid); @@ -291,13 +291,13 @@ export const createDataAPI = ({ rid, tmid }: { rid: IRoom['_id']; tmid: IMessage }; const findSubscription = async (): Promise => { - return ChatSubscription.findOne({ rid }, { reactive: false }); + return Subscriptions.findOne({ rid }, { reactive: false }); }; const getSubscription = createStrictGetter(findSubscription, 'Subscription not found'); const findSubscriptionFromMessage = async (message: IMessage): Promise => { - return ChatSubscription.findOne({ rid: message.rid }, { reactive: false }); + return Subscriptions.findOne({ rid: message.rid }, { reactive: false }); }; const getSubscriptionFromMessage = createStrictGetter(findSubscriptionFromMessage, 'Subscription not found'); diff --git a/apps/meteor/client/lib/chats/readStateManager.ts b/apps/meteor/client/lib/chats/readStateManager.ts index 5f4aa3d7ad978..89b85c52401f9 100644 --- a/apps/meteor/client/lib/chats/readStateManager.ts +++ b/apps/meteor/client/lib/chats/readStateManager.ts @@ -2,7 +2,7 @@ import type { IMessage, IRoom, ISubscription } from '@rocket.chat/core-typings'; import { Emitter } from '@rocket.chat/emitter'; import { Meteor } from 'meteor/meteor'; -import { ChatMessage } from '../../../app/models/client'; +import { Messages } from '../../../app/models/client'; import { LegacyRoomManager } from '../../../app/ui-utils/client/lib/LegacyRoomManager'; import { RoomHistoryManager } from '../../../app/ui-utils/client/lib/RoomHistoryManager'; import { sdk } from '../../../app/utils/client/lib/SDKClient'; @@ -70,7 +70,7 @@ export class ReadStateManager extends Emitter { return; } - const firstUnreadRecord = ChatMessage.findOne( + const firstUnreadRecord = Messages.findOne( { 'rid': this.subscription.rid, 'ts': { diff --git a/apps/meteor/client/lib/createRouteGroup.tsx b/apps/meteor/client/lib/createRouteGroup.tsx index 70eab4782dd19..7391ababd39d7 100644 --- a/apps/meteor/client/lib/createRouteGroup.tsx +++ b/apps/meteor/client/lib/createRouteGroup.tsx @@ -1,9 +1,9 @@ import type { IRouterPaths, RouteName, RouterPathPattern } from '@rocket.chat/ui-contexts'; import React, { type ElementType, type ReactNode } from 'react'; +import { appLayout } from './appLayout'; import { router } from '../providers/RouterProvider'; import MainLayout from '../views/root/MainLayout'; -import { appLayout } from './appLayout'; type GroupName = 'omnichannel' | 'marketplace' | 'account' | 'admin'; diff --git a/apps/meteor/client/lib/federation/Federation.spec.ts b/apps/meteor/client/lib/federation/Federation.spec.ts index 1e367cbb9c6de..e4753f7e54220 100644 --- a/apps/meteor/client/lib/federation/Federation.spec.ts +++ b/apps/meteor/client/lib/federation/Federation.spec.ts @@ -1,8 +1,8 @@ import type { IRoom, ISubscription, IUser, ValueOf } from '@rocket.chat/core-typings'; +import * as Federation from './Federation'; import { RoomRoles } from '../../../app/models/client'; import { RoomMemberActions, RoomSettingsEnum } from '../../../definition/IRoomTypeConfig'; -import * as Federation from './Federation'; jest.mock('../../../app/models/client', () => ({ RoomRoles: { diff --git a/apps/meteor/client/lib/fetchFeatures.ts b/apps/meteor/client/lib/fetchFeatures.ts index 3814eda0f5ddb..e287b6bb895aa 100644 --- a/apps/meteor/client/lib/fetchFeatures.ts +++ b/apps/meteor/client/lib/fetchFeatures.ts @@ -1,4 +1,4 @@ -import { sdk } from '../../app/utils/client/lib/SDKClient'; import { whenLoggedIn } from './loggedIn'; +import { sdk } from '../../app/utils/client/lib/SDKClient'; export const fetchFeatures = (): Promise => whenLoggedIn().then(() => sdk.call('license:getModules')); diff --git a/apps/meteor/client/lib/getPermaLink.ts b/apps/meteor/client/lib/getPermaLink.ts index 8c74bc7933a93..279786c003750 100644 --- a/apps/meteor/client/lib/getPermaLink.ts +++ b/apps/meteor/client/lib/getPermaLink.ts @@ -16,13 +16,13 @@ export const getPermaLink = async (msgId: string): Promise => { throw new Error('invalid-parameter'); } - const { ChatMessage, ChatRoom, ChatSubscription } = await import('../../app/models/client'); + const { Messages, Rooms, Subscriptions } = await import('../../app/models/client'); - const msg = ChatMessage.findOne(msgId) || (await getMessage(msgId)); + const msg = Messages.findOne(msgId) || (await getMessage(msgId)); if (!msg) { throw new Error('message-not-found'); } - const roomData = ChatRoom.findOne({ + const roomData = Rooms.findOne({ _id: msg.rid, }); @@ -30,7 +30,7 @@ export const getPermaLink = async (msgId: string): Promise => { throw new Error('room-not-found'); } - const subData = ChatSubscription.findOne({ 'rid': roomData._id, 'u._id': Meteor.userId() }); + const subData = Subscriptions.findOne({ 'rid': roomData._id, 'u._id': Meteor.userId() }); const { roomCoordinator } = await import('./rooms/roomCoordinator'); diff --git a/apps/meteor/client/lib/rooms/roomCoordinator.tsx b/apps/meteor/client/lib/rooms/roomCoordinator.tsx index 31eda2982a125..aa71a3a7e9df6 100644 --- a/apps/meteor/client/lib/rooms/roomCoordinator.tsx +++ b/apps/meteor/client/lib/rooms/roomCoordinator.tsx @@ -5,7 +5,7 @@ import { Meteor } from 'meteor/meteor'; import React from 'react'; import { hasPermission } from '../../../app/authorization/client'; -import { ChatRoom, ChatSubscription } from '../../../app/models/client'; +import { Rooms, Subscriptions } from '../../../app/models/client'; import { settings } from '../../../app/settings/client'; import type { RoomSettingsEnum, @@ -61,7 +61,7 @@ class RoomCoordinatorClient extends RoomCoordinator { return false; }, canSendMessage(rid: string): boolean { - return ChatSubscription.find({ rid }).count() > 0; + return Subscriptions.find({ rid }).count() > 0; }, ...directives, config: roomConfig, @@ -118,7 +118,7 @@ class RoomCoordinatorClient extends RoomCoordinator { t: 1, ...(user && { muted: 1, unmuted: 1 }), }; - const room = ChatRoom.findOne({ _id: rid }, { fields }); + const room = Rooms.findOne({ _id: rid }, { fields }); if (!room) { return false; } @@ -157,12 +157,12 @@ class RoomCoordinatorClient extends RoomCoordinator { // #ToDo: Move this out of the RoomCoordinator public archived(rid: string): boolean { - const room = ChatRoom.findOne({ _id: rid }, { fields: { archived: 1 } }); + const room = Rooms.findOne({ _id: rid }, { fields: { archived: 1 } }); return Boolean(room?.archived); } public verifyCanSendMessage(rid: string): boolean { - const room = ChatRoom.findOne({ _id: rid }, { fields: { t: 1, federated: 1 } }); + const room = Rooms.findOne({ _id: rid }, { fields: { t: 1, federated: 1 } }); if (!room?.t) { return false; } diff --git a/apps/meteor/client/lib/rooms/roomTypes/direct.ts b/apps/meteor/client/lib/rooms/roomTypes/direct.ts index 776c309c85447..d9c954ff13d46 100644 --- a/apps/meteor/client/lib/rooms/roomTypes/direct.ts +++ b/apps/meteor/client/lib/rooms/roomTypes/direct.ts @@ -4,7 +4,7 @@ import { Meteor } from 'meteor/meteor'; import type { Mongo } from 'meteor/mongo'; import { hasAtLeastOnePermission } from '../../../../app/authorization/client'; -import { Subscriptions, Users, ChatRoom } from '../../../../app/models/client'; +import { Subscriptions, Users, Rooms } from '../../../../app/models/client'; import { settings } from '../../../../app/settings/client'; import { getUserPreference } from '../../../../app/utils/client'; import { getAvatarURL } from '../../../../app/utils/client/getAvatarURL'; @@ -153,7 +153,7 @@ roomCoordinator.add( const subscription = Subscriptions.findOne(query); if (subscription?.rid) { - return ChatRoom.findOne(subscription.rid); + return Rooms.findOne(subscription.rid); } }, } as AtLeast, diff --git a/apps/meteor/client/lib/rooms/roomTypes/livechat.ts b/apps/meteor/client/lib/rooms/roomTypes/livechat.ts index 26919ac83b99e..23a813d6b81a6 100644 --- a/apps/meteor/client/lib/rooms/roomTypes/livechat.ts +++ b/apps/meteor/client/lib/rooms/roomTypes/livechat.ts @@ -1,7 +1,7 @@ import type { AtLeast, ValueOf } from '@rocket.chat/core-typings'; import { hasPermission } from '../../../../app/authorization/client'; -import { ChatRoom, ChatSubscription } from '../../../../app/models/client'; +import { Rooms, Subscriptions } from '../../../../app/models/client'; import { settings } from '../../../../app/settings/client'; import { getAvatarURL } from '../../../../app/utils/client/getAvatarURL'; import type { IRoomTypeClientDirectives } from '../../../../definition/IRoomTypeConfig'; @@ -54,7 +54,7 @@ roomCoordinator.add( }, findRoom(identifier) { - return ChatRoom.findOne({ _id: identifier }); + return Rooms.findOne({ _id: identifier }); }, isLivechatRoom() { @@ -62,17 +62,17 @@ roomCoordinator.add( }, canSendMessage(rid) { - const room = ChatRoom.findOne({ _id: rid }, { fields: { open: 1 } }); + const room = Rooms.findOne({ _id: rid }, { fields: { open: 1 } }); return Boolean(room?.open); }, readOnly(rid, _user) { - const room = ChatRoom.findOne({ _id: rid }, { fields: { open: 1, servedBy: 1 } }); + const room = Rooms.findOne({ _id: rid }, { fields: { open: 1, servedBy: 1 } }); if (!room?.open) { return true; } - const subscription = ChatSubscription.findOne({ rid }); + const subscription = Subscriptions.findOne({ rid }); return !subscription; }, diff --git a/apps/meteor/client/lib/rooms/roomTypes/private.ts b/apps/meteor/client/lib/rooms/roomTypes/private.ts index b99e172e83960..d25da3410c54e 100644 --- a/apps/meteor/client/lib/rooms/roomTypes/private.ts +++ b/apps/meteor/client/lib/rooms/roomTypes/private.ts @@ -4,7 +4,7 @@ import { Meteor } from 'meteor/meteor'; import type { Mongo } from 'meteor/mongo'; import { hasPermission } from '../../../../app/authorization/client'; -import { ChatRoom } from '../../../../app/models/client'; +import { Rooms } from '../../../../app/models/client'; import { settings } from '../../../../app/settings/client'; import { getUserPreference } from '../../../../app/utils/client'; import { getRoomAvatarURL } from '../../../../app/utils/client/getRoomAvatarURL'; @@ -115,7 +115,7 @@ roomCoordinator.add( name: identifier, }; - return ChatRoom.findOne(query); + return Rooms.findOne(query); }, } as AtLeast, ); diff --git a/apps/meteor/client/lib/rooms/roomTypes/public.ts b/apps/meteor/client/lib/rooms/roomTypes/public.ts index cf9d4c1a978c7..1da42356fee9d 100644 --- a/apps/meteor/client/lib/rooms/roomTypes/public.ts +++ b/apps/meteor/client/lib/rooms/roomTypes/public.ts @@ -4,7 +4,7 @@ import { Meteor } from 'meteor/meteor'; import type { Mongo } from 'meteor/mongo'; import { hasAtLeastOnePermission } from '../../../../app/authorization/client'; -import { ChatRoom } from '../../../../app/models/client'; +import { Rooms } from '../../../../app/models/client'; import { settings } from '../../../../app/settings/client'; import { getUserPreference } from '../../../../app/utils/client'; import { getRoomAvatarURL } from '../../../../app/utils/client/getRoomAvatarURL'; @@ -114,11 +114,11 @@ roomCoordinator.add( name: identifier, }; - return ChatRoom.findOne(query); + return Rooms.findOne(query); }, showJoinLink(roomId) { - return !!ChatRoom.findOne({ _id: roomId, t: 'c' }); + return !!Rooms.findOne({ _id: roomId, t: 'c' }); }, } as AtLeast, ); diff --git a/apps/meteor/client/lib/rooms/roomTypes/voip.ts b/apps/meteor/client/lib/rooms/roomTypes/voip.ts index 30b07aaec1eec..4777aa13f210e 100644 --- a/apps/meteor/client/lib/rooms/roomTypes/voip.ts +++ b/apps/meteor/client/lib/rooms/roomTypes/voip.ts @@ -1,7 +1,7 @@ import type { AtLeast } from '@rocket.chat/core-typings'; import { hasPermission } from '../../../../app/authorization/client'; -import { ChatRoom } from '../../../../app/models/client'; +import { Rooms } from '../../../../app/models/client'; import { settings } from '../../../../app/settings/client'; import { getAvatarURL } from '../../../../app/utils/client/getAvatarURL'; import type { IRoomTypeClientDirectives } from '../../../../definition/IRoomTypeConfig'; @@ -29,7 +29,7 @@ roomCoordinator.add( }, findRoom(identifier) { - return ChatRoom.findOne({ _id: identifier }); + return Rooms.findOne({ _id: identifier }); }, canSendMessage(_rid) { diff --git a/apps/meteor/client/lib/utils/getUidDirectMessage.ts b/apps/meteor/client/lib/utils/getUidDirectMessage.ts index 761b849f78839..6073de5f53c52 100644 --- a/apps/meteor/client/lib/utils/getUidDirectMessage.ts +++ b/apps/meteor/client/lib/utils/getUidDirectMessage.ts @@ -1,10 +1,10 @@ import type { IRoom, IUser } from '@rocket.chat/core-typings'; import { Meteor } from 'meteor/meteor'; -import { ChatRoom } from '../../../app/models/client'; +import { Rooms } from '../../../app/models/client'; export const getUidDirectMessage = (rid: IRoom['_id'], uid: IUser['_id'] | null = Meteor.userId()): string | undefined => { - const room = ChatRoom.findOne({ _id: rid }, { fields: { t: 1, uids: 1 } }); + const room = Rooms.findOne({ _id: rid }, { fields: { t: 1, uids: 1 } }); if (!room || room.t !== 'd' || !room.uids || room.uids.length > 2) { return undefined; diff --git a/apps/meteor/client/lib/utils/goToRoomById.ts b/apps/meteor/client/lib/utils/goToRoomById.ts index 2bb5936d55109..12c6a2a768ee1 100644 --- a/apps/meteor/client/lib/utils/goToRoomById.ts +++ b/apps/meteor/client/lib/utils/goToRoomById.ts @@ -1,10 +1,10 @@ import type { IRoom, ISubscription } from '@rocket.chat/core-typings'; import { memoize } from '@rocket.chat/memo'; -import { ChatSubscription } from '../../../app/models/client'; +import { callWithErrorHandling } from './callWithErrorHandling'; +import { Subscriptions } from '../../../app/models/client'; import { router } from '../../providers/RouterProvider'; import { roomCoordinator } from '../rooms/roomCoordinator'; -import { callWithErrorHandling } from './callWithErrorHandling'; const getRoomById = memoize((rid: IRoom['_id']) => callWithErrorHandling('getRoomById', rid)); @@ -13,7 +13,7 @@ export const goToRoomById = async (rid: IRoom['_id']): Promise => { return; } - const subscription: ISubscription | undefined = ChatSubscription.findOne({ rid }); + const subscription: ISubscription | undefined = Subscriptions.findOne({ rid }); if (subscription) { roomCoordinator.openRouteLink(subscription.t, subscription, router.getSearchParameters()); diff --git a/apps/meteor/client/lib/utils/legacyJumpToMessage.ts b/apps/meteor/client/lib/utils/legacyJumpToMessage.ts index c1fcbbbb8f351..9ae917e8cae9a 100644 --- a/apps/meteor/client/lib/utils/legacyJumpToMessage.ts +++ b/apps/meteor/client/lib/utils/legacyJumpToMessage.ts @@ -1,7 +1,7 @@ import type { IMessage } from '@rocket.chat/core-typings'; import { isThreadMessage } from '@rocket.chat/core-typings'; -import { ChatRoom } from '../../../app/models/client'; +import { Rooms } from '../../../app/models/client'; import { RoomHistoryManager } from '../../../app/ui-utils/client'; import { router } from '../../providers/RouterProvider'; import { RoomManager } from '../RoomManager'; @@ -23,7 +23,7 @@ export const legacyJumpToMessage = async (message: IMessage) => { tab: 'thread', context: message.tmid || message._id, rid: message.rid, - name: ChatRoom.findOne({ _id: message.rid })?.name ?? '', + name: Rooms.findOne({ _id: message.rid })?.name ?? '', }, search: { ...router.getSearchParameters(), diff --git a/apps/meteor/client/meteorOverrides/login/facebook.ts b/apps/meteor/client/meteorOverrides/login/facebook.ts index 72a91775818e8..c72b26be542fe 100644 --- a/apps/meteor/client/meteorOverrides/login/facebook.ts +++ b/apps/meteor/client/meteorOverrides/login/facebook.ts @@ -4,9 +4,9 @@ import { Facebook } from 'meteor/facebook-oauth'; import { Meteor } from 'meteor/meteor'; import { OAuth } from 'meteor/oauth'; +import { createOAuthTotpLoginMethod } from './oauth'; import { overrideLoginMethod } from '../../lib/2fa/overrideLoginMethod'; import { wrapRequestCredentialFn } from '../../lib/wrapRequestCredentialFn'; -import { createOAuthTotpLoginMethod } from './oauth'; const { loginWithFacebook } = Meteor; const loginWithFacebookAndTOTP = createOAuthTotpLoginMethod(Facebook); diff --git a/apps/meteor/client/meteorOverrides/login/github.ts b/apps/meteor/client/meteorOverrides/login/github.ts index 2a1aa3903317f..8ee2a057921fe 100644 --- a/apps/meteor/client/meteorOverrides/login/github.ts +++ b/apps/meteor/client/meteorOverrides/login/github.ts @@ -4,9 +4,9 @@ import { Github } from 'meteor/github-oauth'; import { Meteor } from 'meteor/meteor'; import { OAuth } from 'meteor/oauth'; +import { createOAuthTotpLoginMethod } from './oauth'; import { overrideLoginMethod } from '../../lib/2fa/overrideLoginMethod'; import { wrapRequestCredentialFn } from '../../lib/wrapRequestCredentialFn'; -import { createOAuthTotpLoginMethod } from './oauth'; const { loginWithGithub } = Meteor; const loginWithGithubAndTOTP = createOAuthTotpLoginMethod(Github); diff --git a/apps/meteor/client/meteorOverrides/login/google.ts b/apps/meteor/client/meteorOverrides/login/google.ts index 2cf56e7853d86..55ca6e0c35ed8 100644 --- a/apps/meteor/client/meteorOverrides/login/google.ts +++ b/apps/meteor/client/meteorOverrides/login/google.ts @@ -4,9 +4,9 @@ import { Google } from 'meteor/google-oauth'; import { Meteor } from 'meteor/meteor'; import { OAuth } from 'meteor/oauth'; +import { createOAuthTotpLoginMethod } from './oauth'; import { overrideLoginMethod, type LoginCallback } from '../../lib/2fa/overrideLoginMethod'; import { wrapRequestCredentialFn } from '../../lib/wrapRequestCredentialFn'; -import { createOAuthTotpLoginMethod } from './oauth'; declare module 'meteor/meteor' { // eslint-disable-next-line @typescript-eslint/no-namespace diff --git a/apps/meteor/client/meteorOverrides/login/meteorDeveloperAccount.ts b/apps/meteor/client/meteorOverrides/login/meteorDeveloperAccount.ts index 56823fee6b6a0..2550630caac11 100644 --- a/apps/meteor/client/meteorOverrides/login/meteorDeveloperAccount.ts +++ b/apps/meteor/client/meteorOverrides/login/meteorDeveloperAccount.ts @@ -2,9 +2,9 @@ import { Meteor } from 'meteor/meteor'; import { MeteorDeveloperAccounts } from 'meteor/meteor-developer-oauth'; import { OAuth } from 'meteor/oauth'; +import { createOAuthTotpLoginMethod } from './oauth'; import { overrideLoginMethod } from '../../lib/2fa/overrideLoginMethod'; import { wrapRequestCredentialFn } from '../../lib/wrapRequestCredentialFn'; -import { createOAuthTotpLoginMethod } from './oauth'; const { loginWithMeteorDeveloperAccount } = Meteor; const loginWithMeteorDeveloperAccountAndTOTP = createOAuthTotpLoginMethod(MeteorDeveloperAccounts); diff --git a/apps/meteor/client/meteorOverrides/login/twitter.ts b/apps/meteor/client/meteorOverrides/login/twitter.ts index e19ce234e5e91..b74ffadfe12d8 100644 --- a/apps/meteor/client/meteorOverrides/login/twitter.ts +++ b/apps/meteor/client/meteorOverrides/login/twitter.ts @@ -4,9 +4,9 @@ import { Meteor } from 'meteor/meteor'; import { OAuth } from 'meteor/oauth'; import { Twitter } from 'meteor/twitter-oauth'; +import { createOAuthTotpLoginMethod } from './oauth'; import { overrideLoginMethod } from '../../lib/2fa/overrideLoginMethod'; import { wrapRequestCredentialFn } from '../../lib/wrapRequestCredentialFn'; -import { createOAuthTotpLoginMethod } from './oauth'; const { loginWithTwitter } = Meteor; const loginWithTwitterAndTOTP = createOAuthTotpLoginMethod(Twitter); diff --git a/apps/meteor/client/methods/hideRoom.ts b/apps/meteor/client/methods/hideRoom.ts index 91cf2a3de04ca..0f45717fd494d 100644 --- a/apps/meteor/client/methods/hideRoom.ts +++ b/apps/meteor/client/methods/hideRoom.ts @@ -1,7 +1,7 @@ import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; -import { ChatSubscription } from '../../app/models/client'; +import { Subscriptions } from '../../app/models/client'; Meteor.methods({ async hideRoom(rid) { @@ -9,7 +9,7 @@ Meteor.methods({ return 0; } - return ChatSubscription.update( + return Subscriptions.update( { rid, 'u._id': Meteor.userId(), diff --git a/apps/meteor/client/methods/openRoom.ts b/apps/meteor/client/methods/openRoom.ts index 81a40989e6966..afe12060ad50d 100644 --- a/apps/meteor/client/methods/openRoom.ts +++ b/apps/meteor/client/methods/openRoom.ts @@ -1,7 +1,7 @@ import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; -import { ChatSubscription } from '../../app/models/client'; +import { Subscriptions } from '../../app/models/client'; Meteor.methods({ async openRoom(rid) { @@ -11,7 +11,7 @@ Meteor.methods({ }); } - return ChatSubscription.update( + return Subscriptions.update( { rid, 'u._id': Meteor.userId(), diff --git a/apps/meteor/client/methods/pinMessage.ts b/apps/meteor/client/methods/pinMessage.ts index 2fba64be2bf91..06c58657cec92 100644 --- a/apps/meteor/client/methods/pinMessage.ts +++ b/apps/meteor/client/methods/pinMessage.ts @@ -2,7 +2,7 @@ import type { IMessage } from '@rocket.chat/core-typings'; import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; -import { ChatMessage, ChatSubscription } from '../../app/models/client'; +import { Messages, Subscriptions } from '../../app/models/client'; import { settings } from '../../app/settings/client'; Meteor.methods({ @@ -17,7 +17,7 @@ Meteor.methods({ method: 'pinMessage', }); } - if (!ChatSubscription.findOne({ rid: message.rid })) { + if (!Subscriptions.findOne({ rid: message.rid })) { throw new Meteor.Error('error-pinning-message', 'Pinning messages is not allowed', { method: 'pinMessage', }); @@ -28,7 +28,7 @@ Meteor.methods({ }); } - ChatMessage.update( + Messages.update( { _id: message._id, rid: message.rid, @@ -40,7 +40,7 @@ Meteor.methods({ }, ); - const msg = ChatMessage.findOne({ _id: message._id }); + const msg = Messages.findOne({ _id: message._id }); if (!msg) { throw new Meteor.Error('error-pinning-message', 'Error pinning message', { diff --git a/apps/meteor/client/methods/starMessage.ts b/apps/meteor/client/methods/starMessage.ts index bfa74738e283e..80572549c6b68 100644 --- a/apps/meteor/client/methods/starMessage.ts +++ b/apps/meteor/client/methods/starMessage.ts @@ -1,7 +1,7 @@ import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; -import { ChatMessage, ChatSubscription } from '../../app/models/client'; +import { Messages, Subscriptions } from '../../app/models/client'; import { settings } from '../../app/settings/client'; import { t } from '../../app/utils/lib/i18n'; import { dispatchToastMessage } from '../lib/toast'; @@ -15,12 +15,12 @@ Meteor.methods({ return false; } - if (!ChatSubscription.findOne({ rid: message.rid })) { + if (!Subscriptions.findOne({ rid: message.rid })) { dispatchToastMessage({ type: 'error', message: t('error-starring-message') }); return false; } - if (!ChatMessage.findOneByRoomIdAndMessageId(message.rid, message._id)) { + if (!Messages.findOne({ _id: message._id, rid: message.rid })) { dispatchToastMessage({ type: 'error', message: t('error-starring-message') }); return false; } @@ -31,7 +31,7 @@ Meteor.methods({ } if (message.starred) { - ChatMessage.update( + Messages.update( { _id: message._id }, { $addToSet: { @@ -45,7 +45,7 @@ Meteor.methods({ return true; } - ChatMessage.update( + Messages.update( { _id: message._id }, { $pull: { diff --git a/apps/meteor/client/methods/toggleFavorite.ts b/apps/meteor/client/methods/toggleFavorite.ts index 5db56fa682f7c..a6deb281fea59 100644 --- a/apps/meteor/client/methods/toggleFavorite.ts +++ b/apps/meteor/client/methods/toggleFavorite.ts @@ -1,7 +1,7 @@ import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; -import { ChatSubscription } from '../../app/models/client'; +import { Subscriptions } from '../../app/models/client'; Meteor.methods({ async toggleFavorite(rid, f) { @@ -9,7 +9,7 @@ Meteor.methods({ return 0; } - return ChatSubscription.update( + return Subscriptions.update( { rid, 'u._id': Meteor.userId(), diff --git a/apps/meteor/client/methods/unpinMessage.ts b/apps/meteor/client/methods/unpinMessage.ts index f05c07e5314d3..deee1f51f5fae 100644 --- a/apps/meteor/client/methods/unpinMessage.ts +++ b/apps/meteor/client/methods/unpinMessage.ts @@ -2,7 +2,7 @@ import type { IMessage } from '@rocket.chat/core-typings'; import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; -import { ChatMessage, ChatSubscription } from '../../app/models/client'; +import { Messages, Subscriptions } from '../../app/models/client'; import { settings } from '../../app/settings/client'; import { t } from '../../app/utils/lib/i18n'; import { dispatchToastMessage } from '../lib/toast'; @@ -17,7 +17,7 @@ Meteor.methods({ dispatchToastMessage({ type: 'error', message: t('unpinning-not-allowed') }); return false; } - if (!ChatSubscription.findOne({ rid: message.rid })) { + if (!Subscriptions.findOne({ rid: message.rid })) { dispatchToastMessage({ type: 'error', message: t('error-unpinning-message') }); return false; } @@ -26,7 +26,7 @@ Meteor.methods({ return false; } dispatchToastMessage({ type: 'success', message: t('Message_has_been_unpinned') }); - ChatMessage.update( + Messages.update( { _id: message._id, rid: message.rid, diff --git a/apps/meteor/client/methods/updateMessage.ts b/apps/meteor/client/methods/updateMessage.ts index 8efffbe73ee6a..f9638fc1629d8 100644 --- a/apps/meteor/client/methods/updateMessage.ts +++ b/apps/meteor/client/methods/updateMessage.ts @@ -5,7 +5,7 @@ import { Tracker } from 'meteor/tracker'; import moment from 'moment'; import { hasAtLeastOnePermission, hasPermission } from '../../app/authorization/client'; -import { ChatMessage } from '../../app/models/client'; +import { Messages } from '../../app/models/client'; import { settings } from '../../app/settings/client'; import { t } from '../../app/utils/lib/i18n'; import { dispatchToastMessage } from '../lib/toast'; @@ -17,7 +17,7 @@ Meteor.methods({ return; } - const originalMessage = ChatMessage.findOne(message._id); + const originalMessage = Messages.findOne(message._id); if (!originalMessage) { return; @@ -85,7 +85,7 @@ Meteor.methods({ originalMessage.attachments[0].description = message.msg; } } - ChatMessage.update( + Messages.update( { '_id': message._id, 'u._id': uid, diff --git a/apps/meteor/client/omnichannel/businessHours/BusinessHoursRow.tsx b/apps/meteor/client/omnichannel/businessHours/BusinessHoursRow.tsx index ae0183d45d2b6..30dfe1c99557d 100644 --- a/apps/meteor/client/omnichannel/businessHours/BusinessHoursRow.tsx +++ b/apps/meteor/client/omnichannel/businessHours/BusinessHoursRow.tsx @@ -6,8 +6,8 @@ import type { KeyboardEvent } from 'react'; import React, { memo, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; -import { GenericTableRow, GenericTableCell } from '../../components/GenericTable'; import { useRemoveBusinessHour } from './useRemoveBusinessHour'; +import { GenericTableRow, GenericTableCell } from '../../components/GenericTable'; const BusinessHoursRow = ({ _id, name, timezone, workHours, active, type }: Serialized) => { const { t } = useTranslation(); diff --git a/apps/meteor/client/omnichannel/businessHours/BusinessHoursTable.tsx b/apps/meteor/client/omnichannel/businessHours/BusinessHoursTable.tsx index f561a324068c2..c98eb3e961e98 100644 --- a/apps/meteor/client/omnichannel/businessHours/BusinessHoursTable.tsx +++ b/apps/meteor/client/omnichannel/businessHours/BusinessHoursTable.tsx @@ -4,6 +4,7 @@ import { useTranslation, useEndpoint } from '@rocket.chat/ui-contexts'; import { useQuery } from '@tanstack/react-query'; import React, { useMemo, useState } from 'react'; +import BusinessHoursRow from './BusinessHoursRow'; import FilterByText from '../../components/FilterByText'; import GenericNoResults from '../../components/GenericNoResults'; import { @@ -14,7 +15,6 @@ import { GenericTableLoadingRow, } from '../../components/GenericTable'; import { usePagination } from '../../components/GenericTable/hooks/usePagination'; -import BusinessHoursRow from './BusinessHoursRow'; const BusinessHoursTable = () => { const t = useTranslation(); diff --git a/apps/meteor/client/omnichannel/cannedResponses/CannedResponseEdit.tsx b/apps/meteor/client/omnichannel/cannedResponses/CannedResponseEdit.tsx index 28116cb26a13c..f2a959a587fea 100644 --- a/apps/meteor/client/omnichannel/cannedResponses/CannedResponseEdit.tsx +++ b/apps/meteor/client/omnichannel/cannedResponses/CannedResponseEdit.tsx @@ -6,9 +6,9 @@ import { useQueryClient } from '@tanstack/react-query'; import React, { memo, useCallback } from 'react'; import { FormProvider, useForm } from 'react-hook-form'; -import { Page, PageHeader, PageScrollableContentWithShadow, PageFooter } from '../../components/Page'; import CannedResponseForm from './components/cannedResponseForm'; import { useRemoveCannedResponse } from './useRemoveCannedResponse'; +import { Page, PageHeader, PageScrollableContentWithShadow, PageFooter } from '../../components/Page'; type CannedResponseEditProps = { cannedResponseData?: Serialized; diff --git a/apps/meteor/client/omnichannel/cannedResponses/CannedResponseEditWithData.tsx b/apps/meteor/client/omnichannel/cannedResponses/CannedResponseEditWithData.tsx index 4d5779f85fd50..0d3504c02e5b8 100644 --- a/apps/meteor/client/omnichannel/cannedResponses/CannedResponseEditWithData.tsx +++ b/apps/meteor/client/omnichannel/cannedResponses/CannedResponseEditWithData.tsx @@ -5,9 +5,9 @@ import { useQuery } from '@tanstack/react-query'; import React from 'react'; import { useTranslation } from 'react-i18next'; -import { FormSkeleton } from '../../components/Skeleton'; import CannedResponseEdit from './CannedResponseEdit'; import CannedResponseEditWithDepartmentData from './CannedResponseEditWithDepartmentData'; +import { FormSkeleton } from '../../components/Skeleton'; const CannedResponseEditWithData = ({ cannedResponseId }: { cannedResponseId: IOmnichannelCannedResponse['_id'] }) => { const { t } = useTranslation(); diff --git a/apps/meteor/client/omnichannel/cannedResponses/CannedResponseEditWithDepartmentData.tsx b/apps/meteor/client/omnichannel/cannedResponses/CannedResponseEditWithDepartmentData.tsx index 6f57a29e116f3..5d2ffa537fb2d 100644 --- a/apps/meteor/client/omnichannel/cannedResponses/CannedResponseEditWithDepartmentData.tsx +++ b/apps/meteor/client/omnichannel/cannedResponses/CannedResponseEditWithDepartmentData.tsx @@ -3,10 +3,10 @@ import { Callout } from '@rocket.chat/fuselage'; import React, { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; +import CannedResponseEdit from './CannedResponseEdit'; import { FormSkeleton } from '../../components/Skeleton'; import { AsyncStatePhase } from '../../hooks/useAsyncState'; import { useEndpointData } from '../../hooks/useEndpointData'; -import CannedResponseEdit from './CannedResponseEdit'; const CannedResponseEditWithDepartmentData = ({ cannedResponseData }: { cannedResponseData: Serialized }) => { const departmentId = useMemo(() => cannedResponseData?.departmentId, [cannedResponseData]) as string; diff --git a/apps/meteor/client/omnichannel/cannedResponses/CannedResponsesPage.tsx b/apps/meteor/client/omnichannel/cannedResponses/CannedResponsesPage.tsx index 427f80b61333b..db56156263666 100644 --- a/apps/meteor/client/omnichannel/cannedResponses/CannedResponsesPage.tsx +++ b/apps/meteor/client/omnichannel/cannedResponses/CannedResponsesPage.tsx @@ -3,10 +3,10 @@ import { useRouteParameter, useRouter } from '@rocket.chat/ui-contexts'; import React from 'react'; import { useTranslation } from 'react-i18next'; -import { Page, PageHeader, PageContent } from '../../components/Page'; import CannedResponseEdit from './CannedResponseEdit'; import CannedResponseEditWithData from './CannedResponseEditWithData'; import CannedResponsesTable from './CannedResponsesTable'; +import { Page, PageHeader, PageContent } from '../../components/Page'; const CannedResponsesPage = () => { const { t } = useTranslation(); diff --git a/apps/meteor/client/omnichannel/cannedResponses/CannedResponsesRoute.tsx b/apps/meteor/client/omnichannel/cannedResponses/CannedResponsesRoute.tsx index dc6a489320d1e..5ae08ac73e048 100644 --- a/apps/meteor/client/omnichannel/cannedResponses/CannedResponsesRoute.tsx +++ b/apps/meteor/client/omnichannel/cannedResponses/CannedResponsesRoute.tsx @@ -1,8 +1,8 @@ import { usePermission } from '@rocket.chat/ui-contexts'; import React from 'react'; -import NotAuthorizedPage from '../../views/notAuthorized/NotAuthorizedPage'; import CannedResponsesPage from './CannedResponsesPage'; +import NotAuthorizedPage from '../../views/notAuthorized/NotAuthorizedPage'; const CannedResponsesRoute = () => { const canViewCannedResponses = usePermission('manage-livechat-canned-responses'); diff --git a/apps/meteor/client/omnichannel/cannedResponses/CannedResponsesTable.tsx b/apps/meteor/client/omnichannel/cannedResponses/CannedResponsesTable.tsx index 8bf1d52e5ca97..2b718cb539bfe 100644 --- a/apps/meteor/client/omnichannel/cannedResponses/CannedResponsesTable.tsx +++ b/apps/meteor/client/omnichannel/cannedResponses/CannedResponsesTable.tsx @@ -5,6 +5,8 @@ import { useTranslation, usePermission, useToastMessageDispatch, useEndpoint, us import { useQuery, hashQueryKey } from '@tanstack/react-query'; import React, { useMemo, useState } from 'react'; +import CannedResponseFilter from './CannedResponseFilter'; +import { useRemoveCannedResponse } from './useRemoveCannedResponse'; import GenericNoResults from '../../components/GenericNoResults'; import { GenericTable, @@ -18,8 +20,6 @@ import { import { usePagination } from '../../components/GenericTable/hooks/usePagination'; import { useSort } from '../../components/GenericTable/hooks/useSort'; import { useFormatDateAndTime } from '../../hooks/useFormatDateAndTime'; -import CannedResponseFilter from './CannedResponseFilter'; -import { useRemoveCannedResponse } from './useRemoveCannedResponse'; type Scope = 'global' | 'department' | 'user'; diff --git a/apps/meteor/client/omnichannel/cannedResponses/components/CannedResponsesComposer/CannedResponsesComposer.tsx b/apps/meteor/client/omnichannel/cannedResponses/components/CannedResponsesComposer/CannedResponsesComposer.tsx index d66182dc09669..43d2b14d06286 100644 --- a/apps/meteor/client/omnichannel/cannedResponses/components/CannedResponsesComposer/CannedResponsesComposer.tsx +++ b/apps/meteor/client/omnichannel/cannedResponses/components/CannedResponsesComposer/CannedResponsesComposer.tsx @@ -12,9 +12,9 @@ import type { ComponentProps } from 'react'; import React, { memo, useCallback, useRef, useState } from 'react'; import { useTranslation } from 'react-i18next'; +import InsertPlaceholderDropdown from './InsertPlaceholderDropdown'; import { Backdrop } from '../../../../components/Backdrop'; import { useEmojiPicker } from '../../../../contexts/EmojiPickerContext'; -import InsertPlaceholderDropdown from './InsertPlaceholderDropdown'; const CannedResponsesComposer = ({ onChange, ...props }: ComponentProps) => { const { t } = useTranslation(); diff --git a/apps/meteor/client/omnichannel/cannedResponses/components/cannedResponseForm.tsx b/apps/meteor/client/omnichannel/cannedResponses/components/cannedResponseForm.tsx index 1be2284c87271..620b58e33a1ed 100644 --- a/apps/meteor/client/omnichannel/cannedResponses/components/cannedResponseForm.tsx +++ b/apps/meteor/client/omnichannel/cannedResponses/components/cannedResponseForm.tsx @@ -6,10 +6,10 @@ import React, { useState } from 'react'; import { useFormContext, Controller } from 'react-hook-form'; import { useTranslation } from 'react-i18next'; -import AutoCompleteDepartment from '../../../components/AutoCompleteDepartment'; -import Tags from '../../../components/Omnichannel/Tags'; import CannedResponsesComposer from './CannedResponsesComposer/CannedResponsesComposer'; import CannedResponsesComposerPreview from './CannedResponsesComposer/CannedResponsesComposerPreview'; +import AutoCompleteDepartment from '../../../components/AutoCompleteDepartment'; +import Tags from '../../../components/Omnichannel/Tags'; // TODO: refactor Tags field to get proper validation const CannedResponseForm = () => { diff --git a/apps/meteor/client/omnichannel/cannedResponses/contextualBar/CannedResponse/CannedResponseList.stories.tsx b/apps/meteor/client/omnichannel/cannedResponses/contextualBar/CannedResponse/CannedResponseList.stories.tsx index 27fcb651120d6..312a907224ba4 100644 --- a/apps/meteor/client/omnichannel/cannedResponses/contextualBar/CannedResponse/CannedResponseList.stories.tsx +++ b/apps/meteor/client/omnichannel/cannedResponses/contextualBar/CannedResponse/CannedResponseList.stories.tsx @@ -3,8 +3,8 @@ import { action } from '@storybook/addon-actions'; import type { Meta, StoryFn } from '@storybook/react'; import React from 'react'; -import { Contextualbar } from '../../../../components/Contextualbar'; import CannedResponseList from './CannedResponseList'; +import { Contextualbar } from '../../../../components/Contextualbar'; export default { title: 'Omnichannel/CannedResponseList', diff --git a/apps/meteor/client/omnichannel/cannedResponses/contextualBar/CannedResponse/CannedResponseList.tsx b/apps/meteor/client/omnichannel/cannedResponses/contextualBar/CannedResponse/CannedResponseList.tsx index 5734cf2e93bf2..0f3d642ce19cf 100644 --- a/apps/meteor/client/omnichannel/cannedResponses/contextualBar/CannedResponse/CannedResponseList.tsx +++ b/apps/meteor/client/omnichannel/cannedResponses/contextualBar/CannedResponse/CannedResponseList.tsx @@ -6,6 +6,8 @@ import React, { memo } from 'react'; import { useTranslation } from 'react-i18next'; import { Virtuoso } from 'react-virtuoso'; +import Item from './Item'; +import WrapCannedResponse from './WrapCannedResponse'; import { ContextualbarHeader, ContextualbarTitle, @@ -16,8 +18,6 @@ import { } from '../../../../components/Contextualbar'; import { VirtuosoScrollbars } from '../../../../components/CustomScrollbars'; import { useRoomToolbox } from '../../../../views/room/contexts/RoomToolboxContext'; -import Item from './Item'; -import WrapCannedResponse from './WrapCannedResponse'; type CannedResponseListProps = { loadMoreItems: (start: number, end: number) => void; diff --git a/apps/meteor/client/omnichannel/cannedResponses/contextualBar/CannedResponse/WrapCannedResponse.tsx b/apps/meteor/client/omnichannel/cannedResponses/contextualBar/CannedResponse/WrapCannedResponse.tsx index eb118f50a7eff..36b5b2ea5bcb5 100644 --- a/apps/meteor/client/omnichannel/cannedResponses/contextualBar/CannedResponse/WrapCannedResponse.tsx +++ b/apps/meteor/client/omnichannel/cannedResponses/contextualBar/CannedResponse/WrapCannedResponse.tsx @@ -3,8 +3,8 @@ import { useSetModal, usePermission } from '@rocket.chat/ui-contexts'; import type { MouseEvent, MouseEventHandler } from 'react'; import React, { memo } from 'react'; -import CreateCannedResponse from '../../modals/CreateCannedResponse'; import CannedResponse from './CannedResponse'; +import CreateCannedResponse from '../../modals/CreateCannedResponse'; type WrapCannedResponseProps = { allowUse: boolean; diff --git a/apps/meteor/client/omnichannel/cannedResponses/contextualBar/CannedResponse/WrapCannedResponseList.tsx b/apps/meteor/client/omnichannel/cannedResponses/contextualBar/CannedResponse/WrapCannedResponseList.tsx index 6fd0ee420dbf7..c213cf2be46b0 100644 --- a/apps/meteor/client/omnichannel/cannedResponses/contextualBar/CannedResponse/WrapCannedResponseList.tsx +++ b/apps/meteor/client/omnichannel/cannedResponses/contextualBar/CannedResponse/WrapCannedResponseList.tsx @@ -3,6 +3,7 @@ import { useSetModal, useRouter } from '@rocket.chat/ui-contexts'; import type { MouseEvent } from 'react'; import React, { memo, useCallback, useMemo, useState } from 'react'; +import CannedResponseList from './CannedResponseList'; import { useRecordList } from '../../../../hooks/lists/useRecordList'; import { useIsRoomOverMacLimit } from '../../../../hooks/omnichannel/useIsRoomOverMacLimit'; import { AsyncStatePhase } from '../../../../lib/asyncState'; @@ -12,7 +13,6 @@ import { useRoomToolbox } from '../../../../views/room/contexts/RoomToolboxConte import { useCannedResponseFilterOptions } from '../../../hooks/useCannedResponseFilterOptions'; import { useCannedResponseList } from '../../../hooks/useCannedResponseList'; import CreateCannedResponse from '../../modals/CreateCannedResponse'; -import CannedResponseList from './CannedResponseList'; export const WrapCannedResponseList = () => { const room = useRoom(); diff --git a/apps/meteor/client/omnichannel/hooks/useOmnichannelPrioritiesMenu.tsx b/apps/meteor/client/omnichannel/hooks/useOmnichannelPrioritiesMenu.tsx index f4580a2793279..01f20a799b7b6 100644 --- a/apps/meteor/client/omnichannel/hooks/useOmnichannelPrioritiesMenu.tsx +++ b/apps/meteor/client/omnichannel/hooks/useOmnichannelPrioritiesMenu.tsx @@ -7,9 +7,9 @@ import type { ComponentProps } from 'react'; import React, { useCallback, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; +import { useOmnichannelPriorities } from './useOmnichannelPriorities'; import { dispatchToastMessage } from '../../lib/toast'; import { PriorityIcon } from '../priorities/PriorityIcon'; -import { useOmnichannelPriorities } from './useOmnichannelPriorities'; export const useOmnichannelPrioritiesMenu = (rid: string): ComponentProps['options'] | Record => { const { t } = useTranslation(); diff --git a/apps/meteor/client/omnichannel/monitors/MonitorsPage.tsx b/apps/meteor/client/omnichannel/monitors/MonitorsPage.tsx index cbf2e6ec88fff..a394b11343e5b 100644 --- a/apps/meteor/client/omnichannel/monitors/MonitorsPage.tsx +++ b/apps/meteor/client/omnichannel/monitors/MonitorsPage.tsx @@ -1,8 +1,8 @@ import React from 'react'; import { useTranslation } from 'react-i18next'; -import { Page, PageHeader, PageContent } from '../../components/Page'; import MonitorsTable from './MonitorsTable'; +import { Page, PageHeader, PageContent } from '../../components/Page'; const MonitorsPage = () => { const { t } = useTranslation(); diff --git a/apps/meteor/client/omnichannel/monitors/MonitorsPageContainer.tsx b/apps/meteor/client/omnichannel/monitors/MonitorsPageContainer.tsx index b86f8a1ced2cb..3a803555f9af5 100644 --- a/apps/meteor/client/omnichannel/monitors/MonitorsPageContainer.tsx +++ b/apps/meteor/client/omnichannel/monitors/MonitorsPageContainer.tsx @@ -1,9 +1,9 @@ import React from 'react'; +import MonitorsPage from './MonitorsPage'; import PageSkeleton from '../../components/PageSkeleton'; import { useHasLicenseModule } from '../../hooks/useHasLicenseModule'; import NotAuthorizedPage from '../../views/notAuthorized/NotAuthorizedPage'; -import MonitorsPage from './MonitorsPage'; const MonitorsPageContainer = () => { const license = useHasLicenseModule('livechat-enterprise'); diff --git a/apps/meteor/client/omnichannel/priorities/PrioritiesPage.tsx b/apps/meteor/client/omnichannel/priorities/PrioritiesPage.tsx index 9b64eb90c473b..d0e064e27d3f4 100644 --- a/apps/meteor/client/omnichannel/priorities/PrioritiesPage.tsx +++ b/apps/meteor/client/omnichannel/priorities/PrioritiesPage.tsx @@ -6,12 +6,12 @@ import type { ReactElement } from 'react'; import React, { useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { Page, PageHeader, PageContent } from '../../components/Page'; -import { useOmnichannelPriorities } from '../hooks/useOmnichannelPriorities'; import { PrioritiesResetModal } from './PrioritiesResetModal'; import { PrioritiesTable } from './PrioritiesTable'; import type { PriorityFormData } from './PriorityEditForm'; import PriorityList from './PriorityList'; +import { Page, PageHeader, PageContent } from '../../components/Page'; +import { useOmnichannelPriorities } from '../hooks/useOmnichannelPriorities'; type PrioritiesPageProps = { priorityId: string; diff --git a/apps/meteor/client/omnichannel/priorities/PrioritiesRoute.tsx b/apps/meteor/client/omnichannel/priorities/PrioritiesRoute.tsx index fd3b73a3f4a5e..d845162620e4c 100644 --- a/apps/meteor/client/omnichannel/priorities/PrioritiesRoute.tsx +++ b/apps/meteor/client/omnichannel/priorities/PrioritiesRoute.tsx @@ -2,8 +2,8 @@ import { usePermission, useRouteParameter } from '@rocket.chat/ui-contexts'; import type { ReactElement } from 'react'; import React from 'react'; -import NotAuthorizedPage from '../../views/notAuthorized/NotAuthorizedPage'; import { PrioritiesPage } from './PrioritiesPage'; +import NotAuthorizedPage from '../../views/notAuthorized/NotAuthorizedPage'; const PrioritiesRoute = (): ReactElement => { const canViewPriorities = usePermission('manage-livechat-priorities'); diff --git a/apps/meteor/client/omnichannel/priorities/PrioritiesTable.tsx b/apps/meteor/client/omnichannel/priorities/PrioritiesTable.tsx index 008147d49e1b6..453705bddf1a8 100644 --- a/apps/meteor/client/omnichannel/priorities/PrioritiesTable.tsx +++ b/apps/meteor/client/omnichannel/priorities/PrioritiesTable.tsx @@ -3,6 +3,7 @@ import type { ReactElement } from 'react'; import React from 'react'; import { useTranslation } from 'react-i18next'; +import { PriorityIcon } from './PriorityIcon'; import GenericNoResults from '../../components/GenericNoResults'; import { GenericTable, @@ -13,7 +14,6 @@ import { GenericTableBody, GenericTableLoadingTable, } from '../../components/GenericTable'; -import { PriorityIcon } from './PriorityIcon'; type PrioritiesTableProps = { priorities?: Serialized[]; diff --git a/apps/meteor/client/omnichannel/priorities/PriorityEditFormWithData.tsx b/apps/meteor/client/omnichannel/priorities/PriorityEditFormWithData.tsx index b0232c6076a60..0f3eecbd0f2c8 100644 --- a/apps/meteor/client/omnichannel/priorities/PriorityEditFormWithData.tsx +++ b/apps/meteor/client/omnichannel/priorities/PriorityEditFormWithData.tsx @@ -3,10 +3,10 @@ import type { ReactElement } from 'react'; import React from 'react'; import { useTranslation } from 'react-i18next'; -import { FormSkeleton } from '../../components/Skeleton'; -import { usePriorityInfo } from '../../views/omnichannel/directory/hooks/usePriorityInfo'; import type { PriorityEditFormProps } from './PriorityEditForm'; import PriorityEditForm from './PriorityEditForm'; +import { FormSkeleton } from '../../components/Skeleton'; +import { usePriorityInfo } from '../../views/omnichannel/directory/hooks/usePriorityInfo'; type PriorityEditFormWithDataProps = Omit & { priorityId: string; diff --git a/apps/meteor/client/omnichannel/priorities/PriorityList.tsx b/apps/meteor/client/omnichannel/priorities/PriorityList.tsx index 16091476d10c9..cb5e0eab576ac 100644 --- a/apps/meteor/client/omnichannel/priorities/PriorityList.tsx +++ b/apps/meteor/client/omnichannel/priorities/PriorityList.tsx @@ -2,6 +2,8 @@ import type { ReactElement } from 'react'; import React from 'react'; import { useTranslation } from 'react-i18next'; +import type { PriorityFormData } from './PriorityEditForm'; +import PriorityEditFormWithData from './PriorityEditFormWithData'; import { Contextualbar, ContextualbarTitle, @@ -10,8 +12,6 @@ import { ContextualbarScrollableContent, ContextualbarDialog, } from '../../components/Contextualbar'; -import type { PriorityFormData } from './PriorityEditForm'; -import PriorityEditFormWithData from './PriorityEditFormWithData'; type PriorityListProps = { context: 'edit'; diff --git a/apps/meteor/client/omnichannel/reports/ReportsPage.tsx b/apps/meteor/client/omnichannel/reports/ReportsPage.tsx index 6eac20b575122..ed8625304be71 100644 --- a/apps/meteor/client/omnichannel/reports/ReportsPage.tsx +++ b/apps/meteor/client/omnichannel/reports/ReportsPage.tsx @@ -3,10 +3,10 @@ import { usePermission } from '@rocket.chat/ui-contexts'; import React from 'react'; import { useTranslation } from 'react-i18next'; +import { AgentsSection, ChannelsSection, DepartmentsSection, StatusSection, TagsSection } from './sections'; import { Page, PageHeader, PageScrollableContentWithShadow } from '../../components/Page'; import { useHasLicenseModule } from '../../hooks/useHasLicenseModule'; import NotAuthorizedPage from '../../views/notAuthorized/NotAuthorizedPage'; -import { AgentsSection, ChannelsSection, DepartmentsSection, StatusSection, TagsSection } from './sections'; const BREAKPOINTS = { xs: 4, sm: 8, md: 8, lg: 12, xl: 6 } as const; diff --git a/apps/meteor/client/omnichannel/reports/components/ReportCard.tsx b/apps/meteor/client/omnichannel/reports/components/ReportCard.tsx index 76cf1758495d6..8be93c9e1c211 100644 --- a/apps/meteor/client/omnichannel/reports/components/ReportCard.tsx +++ b/apps/meteor/client/omnichannel/reports/components/ReportCard.tsx @@ -2,9 +2,9 @@ import { Box, Card, CardTitle, CardBody, CardCol, CardRow } from '@rocket.chat/f import type { ReactElement, ComponentProps } from 'react'; import React, { forwardRef } from 'react'; +import { ReportCardContent } from './ReportCardContent'; import DownloadDataButton from '../../../components/dashboards/DownloadDataButton'; import PeriodSelector from '../../../components/dashboards/PeriodSelector'; -import { ReportCardContent } from './ReportCardContent'; type ReportCardProps = { id: string; diff --git a/apps/meteor/client/omnichannel/reports/hooks/useAgentsSection.tsx b/apps/meteor/client/omnichannel/reports/hooks/useAgentsSection.tsx index 23a6c21d33d85..bf0f5f8e80bfd 100644 --- a/apps/meteor/client/omnichannel/reports/hooks/useAgentsSection.tsx +++ b/apps/meteor/client/omnichannel/reports/hooks/useAgentsSection.tsx @@ -3,12 +3,12 @@ import { useQuery } from '@tanstack/react-query'; import { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; +import { useDefaultDownload } from './useDefaultDownload'; import { useSort } from '../../../components/GenericTable/hooks/useSort'; import { getPeriodRange } from '../../../components/dashboards/periods'; import { usePeriodSelectorStorage } from '../../../components/dashboards/usePeriodSelectorStorage'; import { COLORS, PERIOD_OPTIONS } from '../components/constants'; import { formatPeriodDescription } from '../utils/formatPeriodDescription'; -import { useDefaultDownload } from './useDefaultDownload'; const formatChartData = (data: { label: string; value: number }[] | undefined = []) => data.map((item) => ({ diff --git a/apps/meteor/client/omnichannel/reports/hooks/useChannelsSection.tsx b/apps/meteor/client/omnichannel/reports/hooks/useChannelsSection.tsx index 864181a6464ef..9a90fb982814d 100644 --- a/apps/meteor/client/omnichannel/reports/hooks/useChannelsSection.tsx +++ b/apps/meteor/client/omnichannel/reports/hooks/useChannelsSection.tsx @@ -6,13 +6,13 @@ import type { TFunction } from 'i18next'; import { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; +import { useDefaultDownload } from './useDefaultDownload'; import { getPeriodRange } from '../../../components/dashboards/periods'; import { usePeriodSelectorStorage } from '../../../components/dashboards/usePeriodSelectorStorage'; import { PERIOD_OPTIONS } from '../components/constants'; import { formatPeriodDescription } from '../utils/formatPeriodDescription'; import { getTop } from '../utils/getTop'; import { round } from '../utils/round'; -import { useDefaultDownload } from './useDefaultDownload'; type DataItem = { label: string; value: number; id: string; rawLabel: string }; diff --git a/apps/meteor/client/omnichannel/reports/hooks/useDepartmentsSection.tsx b/apps/meteor/client/omnichannel/reports/hooks/useDepartmentsSection.tsx index fe4bfaf7d7230..57f30d0d38de4 100644 --- a/apps/meteor/client/omnichannel/reports/hooks/useDepartmentsSection.tsx +++ b/apps/meteor/client/omnichannel/reports/hooks/useDepartmentsSection.tsx @@ -3,11 +3,11 @@ import { useQuery } from '@tanstack/react-query'; import { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; +import { useDefaultDownload } from './useDefaultDownload'; import { getPeriodRange } from '../../../components/dashboards/periods'; import { usePeriodSelectorStorage } from '../../../components/dashboards/usePeriodSelectorStorage'; import { COLORS, PERIOD_OPTIONS } from '../components/constants'; import { formatPeriodDescription } from '../utils/formatPeriodDescription'; -import { useDefaultDownload } from './useDefaultDownload'; const formatChartData = (data: { label: string; value: number }[] | undefined = []) => data.map((item) => ({ diff --git a/apps/meteor/client/omnichannel/reports/hooks/useStatusSection.tsx b/apps/meteor/client/omnichannel/reports/hooks/useStatusSection.tsx index d8f17dd5b79fe..d001a8bbeb5f8 100644 --- a/apps/meteor/client/omnichannel/reports/hooks/useStatusSection.tsx +++ b/apps/meteor/client/omnichannel/reports/hooks/useStatusSection.tsx @@ -5,12 +5,12 @@ import type { TFunction } from 'i18next'; import { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; +import { useDefaultDownload } from './useDefaultDownload'; import { getPeriodRange } from '../../../components/dashboards/periods'; import { usePeriodSelectorStorage } from '../../../components/dashboards/usePeriodSelectorStorage'; import { COLORS, PERIOD_OPTIONS } from '../components/constants'; import { formatPeriodDescription } from '../utils/formatPeriodDescription'; import { round } from '../utils/round'; -import { useDefaultDownload } from './useDefaultDownload'; const STATUSES: Record = { Open: { label: 'Omnichannel_Reports_Status_Open', color: COLORS.success }, diff --git a/apps/meteor/client/omnichannel/reports/hooks/useTagsSection.tsx b/apps/meteor/client/omnichannel/reports/hooks/useTagsSection.tsx index 93fe56b96b8d7..5ba58a71c8799 100644 --- a/apps/meteor/client/omnichannel/reports/hooks/useTagsSection.tsx +++ b/apps/meteor/client/omnichannel/reports/hooks/useTagsSection.tsx @@ -4,11 +4,11 @@ import { useQuery } from '@tanstack/react-query'; import { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; +import { useDefaultDownload } from './useDefaultDownload'; import { getPeriodRange } from '../../../components/dashboards/periods'; import { usePeriodSelectorStorage } from '../../../components/dashboards/usePeriodSelectorStorage'; import { PERIOD_OPTIONS } from '../components/constants'; import { formatPeriodDescription } from '../utils/formatPeriodDescription'; -import { useDefaultDownload } from './useDefaultDownload'; const colors = { warning: Palette.statusColor['status-font-on-warning'].toString(), diff --git a/apps/meteor/client/omnichannel/slaPolicies/SlaEditWithData.tsx b/apps/meteor/client/omnichannel/slaPolicies/SlaEditWithData.tsx index 1e42316a62386..3136679d86782 100644 --- a/apps/meteor/client/omnichannel/slaPolicies/SlaEditWithData.tsx +++ b/apps/meteor/client/omnichannel/slaPolicies/SlaEditWithData.tsx @@ -5,8 +5,8 @@ import type { ReactElement } from 'react'; import React from 'react'; import { useTranslation } from 'react-i18next'; -import { FormSkeleton } from '../../components/Skeleton'; import SlaEdit from './SlaEdit'; +import { FormSkeleton } from '../../components/Skeleton'; type SlaEditProps = { slaId: string; diff --git a/apps/meteor/client/omnichannel/slaPolicies/SlaPage.tsx b/apps/meteor/client/omnichannel/slaPolicies/SlaPage.tsx index ea36f45fbf977..f6ff34f0cd6d4 100644 --- a/apps/meteor/client/omnichannel/slaPolicies/SlaPage.tsx +++ b/apps/meteor/client/omnichannel/slaPolicies/SlaPage.tsx @@ -4,6 +4,9 @@ import { useRouteParameter, useRoute } from '@rocket.chat/ui-contexts'; import React, { useRef, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; +import SlaEditWithData from './SlaEditWithData'; +import SlaNew from './SlaNew'; +import SlaTable from './SlaTable'; import { Contextualbar, ContextualbarTitle, @@ -12,9 +15,6 @@ import { ContextualbarDialog, } from '../../components/Contextualbar'; import { Page, PageHeader, PageContent } from '../../components/Page'; -import SlaEditWithData from './SlaEditWithData'; -import SlaNew from './SlaNew'; -import SlaTable from './SlaTable'; const SlaPage = () => { const { t } = useTranslation(); diff --git a/apps/meteor/client/omnichannel/slaPolicies/SlaRoute.tsx b/apps/meteor/client/omnichannel/slaPolicies/SlaRoute.tsx index 081c33fe3260f..3782763d52793 100644 --- a/apps/meteor/client/omnichannel/slaPolicies/SlaRoute.tsx +++ b/apps/meteor/client/omnichannel/slaPolicies/SlaRoute.tsx @@ -1,8 +1,8 @@ import { usePermission } from '@rocket.chat/ui-contexts'; import React from 'react'; -import NotAuthorizedPage from '../../views/notAuthorized/NotAuthorizedPage'; import SlaPage from './SlaPage'; +import NotAuthorizedPage from '../../views/notAuthorized/NotAuthorizedPage'; const SlaRoute = () => { const canViewSlas = usePermission('manage-livechat-sla'); diff --git a/apps/meteor/client/omnichannel/slaPolicies/SlaTable.tsx b/apps/meteor/client/omnichannel/slaPolicies/SlaTable.tsx index e2c88a6c49f2c..a53f368ec9f39 100644 --- a/apps/meteor/client/omnichannel/slaPolicies/SlaTable.tsx +++ b/apps/meteor/client/omnichannel/slaPolicies/SlaTable.tsx @@ -5,6 +5,7 @@ import { useQuery, hashQueryKey } from '@tanstack/react-query'; import type { MutableRefObject } from 'react'; import React, { useMemo, useState, useEffect } from 'react'; +import RemoveSlaButton from './RemoveSlaButton'; import FilterByText from '../../components/FilterByText'; import GenericNoResults from '../../components/GenericNoResults/GenericNoResults'; import { @@ -18,7 +19,6 @@ import { } from '../../components/GenericTable'; import { usePagination } from '../../components/GenericTable/hooks/usePagination'; import { useSort } from '../../components/GenericTable/hooks/useSort'; -import RemoveSlaButton from './RemoveSlaButton'; const SlaTable = ({ reload }: { reload: MutableRefObject<() => void> }) => { const t = useTranslation(); diff --git a/apps/meteor/client/omnichannel/tags/TagEdit.tsx b/apps/meteor/client/omnichannel/tags/TagEdit.tsx index d4ddfa6021614..8544a17f5374f 100644 --- a/apps/meteor/client/omnichannel/tags/TagEdit.tsx +++ b/apps/meteor/client/omnichannel/tags/TagEdit.tsx @@ -7,6 +7,7 @@ import React from 'react'; import { useForm, Controller } from 'react-hook-form'; import { useTranslation } from 'react-i18next'; +import { useRemoveTag } from './useRemoveTag'; import AutoCompleteDepartmentMultiple from '../../components/AutoCompleteDepartmentMultiple'; import { ContextualbarScrollableContent, @@ -16,7 +17,6 @@ import { ContextualbarHeader, ContextualbarClose, } from '../../components/Contextualbar'; -import { useRemoveTag } from './useRemoveTag'; type TagEditPayload = { name: string; diff --git a/apps/meteor/client/omnichannel/tags/TagEditWithData.tsx b/apps/meteor/client/omnichannel/tags/TagEditWithData.tsx index b8a20733a58aa..df6aa7e08537d 100644 --- a/apps/meteor/client/omnichannel/tags/TagEditWithData.tsx +++ b/apps/meteor/client/omnichannel/tags/TagEditWithData.tsx @@ -5,9 +5,9 @@ import { useQuery } from '@tanstack/react-query'; import React from 'react'; import { useTranslation } from 'react-i18next'; -import { ContextualbarSkeleton } from '../../components/Contextualbar'; import TagEdit from './TagEdit'; import TagEditWithDepartmentData from './TagEditWithDepartmentData'; +import { ContextualbarSkeleton } from '../../components/Contextualbar'; const TagEditWithData = ({ tagId }: { tagId: ILivechatTag['_id'] }) => { const { t } = useTranslation(); diff --git a/apps/meteor/client/omnichannel/tags/TagEditWithDepartmentData.tsx b/apps/meteor/client/omnichannel/tags/TagEditWithDepartmentData.tsx index ce4707417d1e9..a32fcee46fbf0 100644 --- a/apps/meteor/client/omnichannel/tags/TagEditWithDepartmentData.tsx +++ b/apps/meteor/client/omnichannel/tags/TagEditWithDepartmentData.tsx @@ -4,8 +4,8 @@ import { useTranslation, useEndpoint } from '@rocket.chat/ui-contexts'; import { useQuery } from '@tanstack/react-query'; import React from 'react'; -import { ContextualbarSkeleton } from '../../components/Contextualbar'; import TagEdit from './TagEdit'; +import { ContextualbarSkeleton } from '../../components/Contextualbar'; const TagEditWithDepartmentData = ({ tagData }: { tagData: ILivechatTag }) => { const t = useTranslation(); diff --git a/apps/meteor/client/omnichannel/tags/TagsPage.tsx b/apps/meteor/client/omnichannel/tags/TagsPage.tsx index add1c64531d9e..86c299cde240e 100644 --- a/apps/meteor/client/omnichannel/tags/TagsPage.tsx +++ b/apps/meteor/client/omnichannel/tags/TagsPage.tsx @@ -2,11 +2,11 @@ import { Button, ButtonGroup } from '@rocket.chat/fuselage'; import { useRouter, useTranslation, useRouteParameter } from '@rocket.chat/ui-contexts'; import React from 'react'; -import { ContextualbarDialog } from '../../components/Contextualbar'; -import { Page, PageHeader, PageContent } from '../../components/Page'; import TagEdit from './TagEdit'; import TagEditWithData from './TagEditWithData'; import TagsTable from './TagsTable'; +import { ContextualbarDialog } from '../../components/Contextualbar'; +import { Page, PageHeader, PageContent } from '../../components/Page'; const TagsPage = () => { const t = useTranslation(); diff --git a/apps/meteor/client/omnichannel/tags/TagsRoute.tsx b/apps/meteor/client/omnichannel/tags/TagsRoute.tsx index 11f3e4348a0bb..61d5875929e54 100644 --- a/apps/meteor/client/omnichannel/tags/TagsRoute.tsx +++ b/apps/meteor/client/omnichannel/tags/TagsRoute.tsx @@ -1,8 +1,8 @@ import { usePermission } from '@rocket.chat/ui-contexts'; import React from 'react'; -import NotAuthorizedPage from '../../views/notAuthorized/NotAuthorizedPage'; import TagsPage from './TagsPage'; +import NotAuthorizedPage from '../../views/notAuthorized/NotAuthorizedPage'; const TagsRoute = () => { const canViewTags = usePermission('manage-livechat-tags'); diff --git a/apps/meteor/client/omnichannel/tags/TagsTable.tsx b/apps/meteor/client/omnichannel/tags/TagsTable.tsx index 6405c45f409e9..e95121a2270bc 100644 --- a/apps/meteor/client/omnichannel/tags/TagsTable.tsx +++ b/apps/meteor/client/omnichannel/tags/TagsTable.tsx @@ -4,6 +4,7 @@ import { useTranslation, useEndpoint, useRouter } from '@rocket.chat/ui-contexts import { useQuery, hashQueryKey } from '@tanstack/react-query'; import React, { useMemo, useState } from 'react'; +import { useRemoveTag } from './useRemoveTag'; import FilterByText from '../../components/FilterByText'; import GenericNoResults from '../../components/GenericNoResults'; import { @@ -17,7 +18,6 @@ import { } from '../../components/GenericTable'; import { usePagination } from '../../components/GenericTable/hooks/usePagination'; import { useSort } from '../../components/GenericTable/hooks/useSort'; -import { useRemoveTag } from './useRemoveTag'; const TagsTable = () => { const t = useTranslation(); diff --git a/apps/meteor/client/omnichannel/units/UnitEdit.tsx b/apps/meteor/client/omnichannel/units/UnitEdit.tsx index b2feb1db8a8f4..0db2c57630146 100644 --- a/apps/meteor/client/omnichannel/units/UnitEdit.tsx +++ b/apps/meteor/client/omnichannel/units/UnitEdit.tsx @@ -20,6 +20,7 @@ import { useQueryClient } from '@tanstack/react-query'; import React, { useMemo, useState } from 'react'; import { useForm, Controller } from 'react-hook-form'; +import { useRemoveUnit } from './useRemoveUnit'; import { ContextualbarScrollableContent, ContextualbarFooter, @@ -32,7 +33,6 @@ import { useRecordList } from '../../hooks/lists/useRecordList'; import { AsyncStatePhase } from '../../hooks/useAsyncState'; import { useDepartmentsByUnitsList } from '../../views/hooks/useDepartmentsByUnitsList'; import { useMonitorsList } from '../../views/hooks/useMonitorsList'; -import { useRemoveUnit } from './useRemoveUnit'; type UnitEditProps = { unitData?: Serialized; diff --git a/apps/meteor/client/omnichannel/units/UnitEditWithData.tsx b/apps/meteor/client/omnichannel/units/UnitEditWithData.tsx index 8bd2294e52c5b..28d137f4b5edc 100644 --- a/apps/meteor/client/omnichannel/units/UnitEditWithData.tsx +++ b/apps/meteor/client/omnichannel/units/UnitEditWithData.tsx @@ -5,8 +5,8 @@ import { useQuery } from '@tanstack/react-query'; import React from 'react'; import { useTranslation } from 'react-i18next'; -import { ContextualbarSkeleton } from '../../components/Contextualbar'; import UnitEdit from './UnitEdit'; +import { ContextualbarSkeleton } from '../../components/Contextualbar'; const UnitEditWithData = ({ unitId }: { unitId: IOmnichannelBusinessUnit['_id'] }) => { const { t } = useTranslation(); diff --git a/apps/meteor/client/omnichannel/units/UnitsPage.tsx b/apps/meteor/client/omnichannel/units/UnitsPage.tsx index 190c22991fb53..db14a907e5690 100644 --- a/apps/meteor/client/omnichannel/units/UnitsPage.tsx +++ b/apps/meteor/client/omnichannel/units/UnitsPage.tsx @@ -2,11 +2,11 @@ import { Button, ButtonGroup } from '@rocket.chat/fuselage'; import { useTranslation, useRouteParameter, useRouter } from '@rocket.chat/ui-contexts'; import React from 'react'; -import { ContextualbarDialog } from '../../components/Contextualbar'; -import { Page, PageHeader, PageContent } from '../../components/Page'; import UnitEdit from './UnitEdit'; import UnitEditWithData from './UnitEditWithData'; import UnitsTable from './UnitsTable'; +import { ContextualbarDialog } from '../../components/Contextualbar'; +import { Page, PageHeader, PageContent } from '../../components/Page'; const UnitsPage = () => { const t = useTranslation(); diff --git a/apps/meteor/client/omnichannel/units/UnitsRoute.tsx b/apps/meteor/client/omnichannel/units/UnitsRoute.tsx index 9490fd2d2048e..6017f1f0a9789 100644 --- a/apps/meteor/client/omnichannel/units/UnitsRoute.tsx +++ b/apps/meteor/client/omnichannel/units/UnitsRoute.tsx @@ -1,9 +1,9 @@ import { usePermission } from '@rocket.chat/ui-contexts'; import React from 'react'; +import UnitsPage from './UnitsPage'; import { useHasLicenseModule } from '../../hooks/useHasLicenseModule'; import NotAuthorizedPage from '../../views/notAuthorized/NotAuthorizedPage'; -import UnitsPage from './UnitsPage'; const UnitsRoute = () => { const canViewUnits = usePermission('manage-livechat-units'); diff --git a/apps/meteor/client/omnichannel/units/UnitsTable.tsx b/apps/meteor/client/omnichannel/units/UnitsTable.tsx index f83617310fad0..8cfc2cbfbd8c8 100644 --- a/apps/meteor/client/omnichannel/units/UnitsTable.tsx +++ b/apps/meteor/client/omnichannel/units/UnitsTable.tsx @@ -5,6 +5,7 @@ import { useQuery, hashQueryKey } from '@tanstack/react-query'; import React, { useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; +import { useRemoveUnit } from './useRemoveUnit'; import FilterByText from '../../components/FilterByText'; import GenericNoResults from '../../components/GenericNoResults/GenericNoResults'; import { @@ -18,7 +19,6 @@ import { } from '../../components/GenericTable'; import { usePagination } from '../../components/GenericTable/hooks/usePagination'; import { useSort } from '../../components/GenericTable/hooks/useSort'; -import { useRemoveUnit } from './useRemoveUnit'; const UnitsTable = () => { const { t } = useTranslation(); diff --git a/apps/meteor/client/providers/AppsProvider/AppsProvider.spec.ts b/apps/meteor/client/providers/AppsProvider/AppsProvider.spec.ts index 8210fe22eec53..c05ed7f1d0861 100644 --- a/apps/meteor/client/providers/AppsProvider/AppsProvider.spec.ts +++ b/apps/meteor/client/providers/AppsProvider/AppsProvider.spec.ts @@ -1,9 +1,9 @@ import type { App } from '@rocket.chat/core-typings'; import type { UseQueryResult } from '@tanstack/react-query'; +import { storeQueryFunction } from './storeQueryFunction'; import { createFakeApp } from '../../../tests/mocks/data'; import { createFakeAppInstalledMarketplace, createFakeAppPrivate } from '../../../tests/mocks/data/marketplace'; -import { storeQueryFunction } from './storeQueryFunction'; describe(`when an app installed from the Marketplace, but has since been unpublished`, () => { it(`should still be present in the installed app data provided`, () => { diff --git a/apps/meteor/client/providers/AppsProvider/AppsProvider.tsx b/apps/meteor/client/providers/AppsProvider/AppsProvider.tsx index 672a794438fa2..dee82ce691e6f 100644 --- a/apps/meteor/client/providers/AppsProvider/AppsProvider.tsx +++ b/apps/meteor/client/providers/AppsProvider/AppsProvider.tsx @@ -4,6 +4,7 @@ import { useQuery, useQueryClient } from '@tanstack/react-query'; import type { ReactNode } from 'react'; import React, { useEffect } from 'react'; +import { storeQueryFunction } from './storeQueryFunction'; import { AppClientOrchestratorInstance } from '../../apps/orchestrator'; import { AppsContext } from '../../contexts/AppsContext'; import { useInvalidateLicense, useLicense } from '../../hooks/useLicense'; @@ -11,7 +12,6 @@ import type { AsyncState } from '../../lib/asyncState'; import { AsyncStatePhase } from '../../lib/asyncState'; import { useInvalidateAppsCountQueryCallback } from '../../views/marketplace/hooks/useAppsCountQuery'; import type { App } from '../../views/marketplace/types'; -import { storeQueryFunction } from './storeQueryFunction'; const getAppState = ( loading: boolean, diff --git a/apps/meteor/client/providers/AuthenticationProvider/AuthenticationProvider.tsx b/apps/meteor/client/providers/AuthenticationProvider/AuthenticationProvider.tsx index bb135c4f22d6f..840d6a049ab54 100644 --- a/apps/meteor/client/providers/AuthenticationProvider/AuthenticationProvider.tsx +++ b/apps/meteor/client/providers/AuthenticationProvider/AuthenticationProvider.tsx @@ -5,8 +5,8 @@ import { Meteor } from 'meteor/meteor'; import type { ContextType, ReactElement, ReactNode } from 'react'; import React, { useMemo } from 'react'; -import { loginServices } from '../../lib/loginServices'; import { useLDAPAndCrowdCollisionWarning } from './hooks/useLDAPAndCrowdCollisionWarning'; +import { loginServices } from '../../lib/loginServices'; export type LoginMethods = keyof typeof Meteor extends infer T ? (T extends `loginWith${string}` ? T : never) : never; diff --git a/apps/meteor/client/providers/CallProvider/CallProvider.tsx b/apps/meteor/client/providers/CallProvider/CallProvider.tsx index 6e728dc35eb61..2415441f0c617 100644 --- a/apps/meteor/client/providers/CallProvider/CallProvider.tsx +++ b/apps/meteor/client/providers/CallProvider/CallProvider.tsx @@ -28,6 +28,7 @@ import React, { useMemo, useRef, useCallback, useEffect, useState } from 'react' import { createPortal } from 'react-dom'; import type { OutgoingByeRequest } from 'sip.js/lib/core'; +import { useVoipSounds } from './hooks/useVoipSounds'; import type { CallContextValue } from '../../contexts/CallContext'; import { CallContext, useIsVoipEnterprise } from '../../contexts/CallContext'; import { useDialModal } from '../../hooks/useDialModal'; @@ -36,7 +37,6 @@ import { roomCoordinator } from '../../lib/rooms/roomCoordinator'; import type { QueueAggregator } from '../../lib/voip/QueueAggregator'; import { parseOutboundPhoneNumber } from '../../lib/voip/parseOutboundPhoneNumber'; import { WrapUpCallModal } from '../../voip/components/modals/WrapUpCallModal'; -import { useVoipSounds } from './hooks/useVoipSounds'; type NetworkState = 'online' | 'offline'; diff --git a/apps/meteor/client/providers/EmojiPickerProvider/EmojiPickerProvider.tsx b/apps/meteor/client/providers/EmojiPickerProvider/EmojiPickerProvider.tsx index 02b406dc2a6c2..ffc31900b0468 100644 --- a/apps/meteor/client/providers/EmojiPickerProvider/EmojiPickerProvider.tsx +++ b/apps/meteor/client/providers/EmojiPickerProvider/EmojiPickerProvider.tsx @@ -2,11 +2,11 @@ import { useDebouncedState, useLocalStorage } from '@rocket.chat/fuselage-hooks' import type { ReactNode, ReactElement, ContextType } from 'react'; import React, { useState, useCallback, useMemo, useEffect } from 'react'; +import { useUpdateCustomEmoji } from './useUpdateCustomEmoji'; import type { EmojiByCategory } from '../../../app/emoji/client'; import { emoji, getFrequentEmoji, updateRecent, createEmojiList, createPickerEmojis, CUSTOM_CATEGORY } from '../../../app/emoji/client'; import { EmojiPickerContext } from '../../contexts/EmojiPickerContext'; import EmojiPicker from '../../views/composer/EmojiPicker/EmojiPicker'; -import { useUpdateCustomEmoji } from './useUpdateCustomEmoji'; const DEFAULT_ITEMS_LIMIT = 90; diff --git a/apps/meteor/client/providers/MeteorProvider.tsx b/apps/meteor/client/providers/MeteorProvider.tsx index ad5df9503833e..53dbd4b9503fe 100644 --- a/apps/meteor/client/providers/MeteorProvider.tsx +++ b/apps/meteor/client/providers/MeteorProvider.tsx @@ -2,7 +2,6 @@ import { VoipProvider } from '@rocket.chat/ui-voip'; import type { ReactNode } from 'react'; import React from 'react'; -import { OmnichannelRoomIconProvider } from '../components/RoomIcon/OmnichannelRoomIcon/provider/OmnichannelRoomIconProvider'; import ActionManagerProvider from './ActionManagerProvider'; import AuthenticationProvider from './AuthenticationProvider/AuthenticationProvider'; import AuthorizationProvider from './AuthorizationProvider'; @@ -25,6 +24,7 @@ import TranslationProvider from './TranslationProvider'; import UserPresenceProvider from './UserPresenceProvider'; import UserProvider from './UserProvider'; import VideoConfProvider from './VideoConfProvider'; +import { OmnichannelRoomIconProvider } from '../components/RoomIcon/OmnichannelRoomIcon/provider/OmnichannelRoomIconProvider'; type MeteorProviderProps = { children?: ReactNode; diff --git a/apps/meteor/client/providers/ModalProvider/ModalProvider.spec.tsx b/apps/meteor/client/providers/ModalProvider/ModalProvider.spec.tsx index fd82af5877607..414eeb1ad92fa 100644 --- a/apps/meteor/client/providers/ModalProvider/ModalProvider.spec.tsx +++ b/apps/meteor/client/providers/ModalProvider/ModalProvider.spec.tsx @@ -3,11 +3,11 @@ import { act, render, screen } from '@testing-library/react'; import type { ForwardedRef, ReactElement } from 'react'; import React, { Suspense, createContext, createRef, forwardRef, useContext, useImperativeHandle } from 'react'; +import ModalProvider from './ModalProvider'; +import ModalProviderWithRegion from './ModalProviderWithRegion'; import GenericModal from '../../components/GenericModal'; import { imperativeModal } from '../../lib/imperativeModal'; import ModalRegion from '../../views/modal/ModalRegion'; -import ModalProvider from './ModalProvider'; -import ModalProviderWithRegion from './ModalProviderWithRegion'; const renderWithSuspense = (ui: ReactElement) => render(ui, { diff --git a/apps/meteor/client/providers/ModalProvider/ModalProviderWithRegion.tsx b/apps/meteor/client/providers/ModalProvider/ModalProviderWithRegion.tsx index e8d1f52bbd9a1..64f739bdb586c 100644 --- a/apps/meteor/client/providers/ModalProvider/ModalProviderWithRegion.tsx +++ b/apps/meteor/client/providers/ModalProvider/ModalProviderWithRegion.tsx @@ -1,8 +1,8 @@ import type { ReactNode } from 'react'; import React, { useState } from 'react'; -import ModalRegion from '../../views/modal/ModalRegion'; import ModalProvider from './ModalProvider'; +import ModalRegion from '../../views/modal/ModalRegion'; const ModalProviderWithRegion = ({ children }: { children?: ReactNode }) => { const [region] = useState(() => Symbol()); diff --git a/apps/meteor/client/providers/UserProvider/UserProvider.tsx b/apps/meteor/client/providers/UserProvider/UserProvider.tsx index 4483ae4c68919..dbca784719a9a 100644 --- a/apps/meteor/client/providers/UserProvider/UserProvider.tsx +++ b/apps/meteor/client/providers/UserProvider/UserProvider.tsx @@ -6,7 +6,11 @@ import { Meteor } from 'meteor/meteor'; import type { ContextType, ReactElement, ReactNode } from 'react'; import React, { useEffect, useMemo, useRef } from 'react'; -import { Subscriptions, ChatRoom } from '../../../app/models/client'; +import { useClearRemovedRoomsHistory } from './hooks/useClearRemovedRoomsHistory'; +import { useDeleteUser } from './hooks/useDeleteUser'; +import { useEmailVerificationWarning } from './hooks/useEmailVerificationWarning'; +import { useUpdateAvatar } from './hooks/useUpdateAvatar'; +import { Subscriptions, Rooms } from '../../../app/models/client'; import { getUserPreference } from '../../../app/utils/client'; import { sdk } from '../../../app/utils/client/lib/SDKClient'; import { afterLogoutCleanUpCallback } from '../../../lib/callbacks/afterLogoutCleanUpCallback'; @@ -14,10 +18,6 @@ import { useReactiveValue } from '../../hooks/useReactiveValue'; import { createReactiveSubscriptionFactory } from '../../lib/createReactiveSubscriptionFactory'; import { queryClient } from '../../lib/queryClient'; import { useCreateFontStyleElement } from '../../views/account/accessibility/hooks/useCreateFontStyleElement'; -import { useClearRemovedRoomsHistory } from './hooks/useClearRemovedRoomsHistory'; -import { useDeleteUser } from './hooks/useDeleteUser'; -import { useEmailVerificationWarning } from './hooks/useEmailVerificationWarning'; -import { useUpdateAvatar } from './hooks/useUpdateAvatar'; const getUser = (): IUser | null => Meteor.user() as IUser | null; @@ -69,13 +69,13 @@ const UserProvider = ({ children }: UserProviderProps): ReactElement => { querySubscription: createReactiveSubscriptionFactory((query, fields, sort) => Subscriptions.findOne(query, { fields, sort }), ), - queryRoom: createReactiveSubscriptionFactory((query, fields) => ChatRoom.findOne(query, { fields })), + queryRoom: createReactiveSubscriptionFactory((query, fields) => Rooms.findOne(query, { fields })), querySubscriptions: createReactiveSubscriptionFactory((query, options) => { if (userId) { return Subscriptions.find(query, options).fetch(); } - return ChatRoom.find(query, options).fetch(); + return Rooms.find(query, options).fetch(); }), logout, }), diff --git a/apps/meteor/client/providers/UserProvider/hooks/useDeleteUser.ts b/apps/meteor/client/providers/UserProvider/hooks/useDeleteUser.ts index db7a7d548f9e5..d292b1a5b31f1 100644 --- a/apps/meteor/client/providers/UserProvider/hooks/useDeleteUser.ts +++ b/apps/meteor/client/providers/UserProvider/hooks/useDeleteUser.ts @@ -1,7 +1,7 @@ import { useStream, useUserId } from '@rocket.chat/ui-contexts'; import { useEffect } from 'react'; -import { ChatMessage } from '../../../../app/models/client'; +import { Messages } from '../../../../app/models/client'; export const useDeleteUser = () => { const notify = useStream('notify-logged'); @@ -13,7 +13,7 @@ export const useDeleteUser = () => { } return notify('Users:Deleted', ({ userId, messageErasureType, replaceByUser }) => { if (messageErasureType === 'Unlink' && replaceByUser) { - return ChatMessage.update( + return Messages.update( { 'u._id': userId, }, @@ -28,7 +28,7 @@ export const useDeleteUser = () => { { multi: true }, ); } - ChatMessage.remove({ + Messages.remove({ 'u._id': userId, }); }); diff --git a/apps/meteor/client/sidebar/Item/Condensed.stories.tsx b/apps/meteor/client/sidebar/Item/Condensed.stories.tsx index b0936c3171ddc..09c1af25ba4e4 100644 --- a/apps/meteor/client/sidebar/Item/Condensed.stories.tsx +++ b/apps/meteor/client/sidebar/Item/Condensed.stories.tsx @@ -4,8 +4,8 @@ import { action } from '@storybook/addon-actions'; import type { Meta, StoryFn } from '@storybook/react'; import React from 'react'; -import * as Status from '../../components/UserStatus'; import Condensed from './Condensed'; +import * as Status from '../../components/UserStatus'; export default { title: 'Sidebar/Condensed', diff --git a/apps/meteor/client/sidebar/Item/Extended.stories.tsx b/apps/meteor/client/sidebar/Item/Extended.stories.tsx index ce7705b0d7d48..e076370a5900f 100644 --- a/apps/meteor/client/sidebar/Item/Extended.stories.tsx +++ b/apps/meteor/client/sidebar/Item/Extended.stories.tsx @@ -4,8 +4,8 @@ import { action } from '@storybook/addon-actions'; import type { Meta, StoryFn } from '@storybook/react'; import React from 'react'; -import * as Status from '../../components/UserStatus'; import Extended from './Extended'; +import * as Status from '../../components/UserStatus'; export default { title: 'Sidebar/Extended', diff --git a/apps/meteor/client/sidebar/Item/Medium.stories.tsx b/apps/meteor/client/sidebar/Item/Medium.stories.tsx index 44b570662ae51..9321aa09fdd43 100644 --- a/apps/meteor/client/sidebar/Item/Medium.stories.tsx +++ b/apps/meteor/client/sidebar/Item/Medium.stories.tsx @@ -4,8 +4,8 @@ import { action } from '@storybook/addon-actions'; import type { Meta, StoryFn } from '@storybook/react'; import React from 'react'; -import * as Status from '../../components/UserStatus'; import Medium from './Medium'; +import * as Status from '../../components/UserStatus'; export default { title: 'Sidebar/Medium', diff --git a/apps/meteor/client/sidebar/RoomList/RoomList.tsx b/apps/meteor/client/sidebar/RoomList/RoomList.tsx index e618663f6ed76..04c1fd8340029 100644 --- a/apps/meteor/client/sidebar/RoomList/RoomList.tsx +++ b/apps/meteor/client/sidebar/RoomList/RoomList.tsx @@ -8,6 +8,9 @@ import React, { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { Virtuoso } from 'react-virtuoso'; +import RoomListRow from './RoomListRow'; +import RoomListRowWrapper from './RoomListRowWrapper'; +import RoomListWrapper from './RoomListWrapper'; import { VirtuosoScrollbars } from '../../components/CustomScrollbars'; import { useOpenedRoom } from '../../lib/RoomManager'; import { useAvatarTemplate } from '../hooks/useAvatarTemplate'; @@ -15,9 +18,6 @@ import { usePreventDefault } from '../hooks/usePreventDefault'; import { useRoomList } from '../hooks/useRoomList'; import { useShortcutOpenMenu } from '../hooks/useShortcutOpenMenu'; import { useTemplateByViewMode } from '../hooks/useTemplateByViewMode'; -import RoomListRow from './RoomListRow'; -import RoomListRowWrapper from './RoomListRowWrapper'; -import RoomListWrapper from './RoomListWrapper'; const computeItemKey = (index: number, room: IRoom): IRoom['_id'] | number => room._id || index; diff --git a/apps/meteor/client/sidebar/RoomList/RoomListRow.tsx b/apps/meteor/client/sidebar/RoomList/RoomListRow.tsx index 22ffa3bf8cfb6..481299acdb8ec 100644 --- a/apps/meteor/client/sidebar/RoomList/RoomListRow.tsx +++ b/apps/meteor/client/sidebar/RoomList/RoomListRow.tsx @@ -4,10 +4,10 @@ import type { TFunction } from 'i18next'; import type { ReactElement } from 'react'; import React, { memo, useMemo } from 'react'; +import SideBarItemTemplateWithData from './SideBarItemTemplateWithData'; import { useVideoConfAcceptCall, useVideoConfRejectIncomingCall, useVideoConfIncomingCalls } from '../../contexts/VideoConfContext'; import type { useAvatarTemplate } from '../hooks/useAvatarTemplate'; import type { useTemplateByViewMode } from '../hooks/useTemplateByViewMode'; -import SideBarItemTemplateWithData from './SideBarItemTemplateWithData'; type RoomListRowProps = { extended: boolean; diff --git a/apps/meteor/client/sidebar/RoomList/SideBarItemTemplateWithData.tsx b/apps/meteor/client/sidebar/RoomList/SideBarItemTemplateWithData.tsx index 4c8640e96de0c..b2129efc516a3 100644 --- a/apps/meteor/client/sidebar/RoomList/SideBarItemTemplateWithData.tsx +++ b/apps/meteor/client/sidebar/RoomList/SideBarItemTemplateWithData.tsx @@ -6,6 +6,7 @@ import type { TFunction } from 'i18next'; import type { AllHTMLAttributes, ComponentType, ReactElement, ReactNode } from 'react'; import React, { memo, useMemo } from 'react'; +import { normalizeSidebarMessage } from './normalizeSidebarMessage'; import { RoomIcon } from '../../components/RoomIcon'; import { roomCoordinator } from '../../lib/rooms/roomCoordinator'; import { isIOsDevice } from '../../lib/utils/isIOsDevice'; @@ -13,7 +14,6 @@ import { useOmnichannelPriorities } from '../../omnichannel/hooks/useOmnichannel import RoomMenu from '../RoomMenu'; import { OmnichannelBadges } from '../badges/OmnichannelBadges'; import type { useAvatarTemplate } from '../hooks/useAvatarTemplate'; -import { normalizeSidebarMessage } from './normalizeSidebarMessage'; const getMessage = (room: IRoom, lastMessage: IMessage | undefined, t: TFunction): string | undefined => { if (!lastMessage) { diff --git a/apps/meteor/client/sidebar/Sidebar.tsx b/apps/meteor/client/sidebar/Sidebar.tsx index 683013b38213e..541afdfe0bee5 100644 --- a/apps/meteor/client/sidebar/Sidebar.tsx +++ b/apps/meteor/client/sidebar/Sidebar.tsx @@ -3,12 +3,12 @@ import { Box } from '@rocket.chat/fuselage'; import { useLayout, useUserPreference } from '@rocket.chat/ui-contexts'; import React, { memo } from 'react'; -import { useOmnichannelEnabled } from '../hooks/omnichannel/useOmnichannelEnabled'; import SidebarRoomList from './RoomList'; import SidebarFooter from './footer'; import SidebarHeader from './header'; import BannerSection from './sections/BannerSection'; import OmnichannelSection from './sections/OmnichannelSection'; +import { useOmnichannelEnabled } from '../hooks/omnichannel/useOmnichannelEnabled'; // TODO unit test airgappedbanner const Sidebar = () => { diff --git a/apps/meteor/client/sidebar/footer/SidebarFooter.tsx b/apps/meteor/client/sidebar/footer/SidebarFooter.tsx index f31f1a3e6b8f4..7b4da56041378 100644 --- a/apps/meteor/client/sidebar/footer/SidebarFooter.tsx +++ b/apps/meteor/client/sidebar/footer/SidebarFooter.tsx @@ -1,9 +1,9 @@ import type { ReactElement } from 'react'; import React from 'react'; -import { useIsCallEnabled, useIsCallReady } from '../../contexts/CallContext'; import SidebarFooterDefault from './SidebarFooterDefault'; import { VoipFooter } from './voip'; +import { useIsCallEnabled, useIsCallReady } from '../../contexts/CallContext'; const SidebarFooter = (): ReactElement => { const isCallEnabled = useIsCallEnabled(); diff --git a/apps/meteor/client/sidebar/footer/voip/VoipFooter.tsx b/apps/meteor/client/sidebar/footer/voip/VoipFooter.tsx index 0185c7724835d..c9145a8a12106 100644 --- a/apps/meteor/client/sidebar/footer/voip/VoipFooter.tsx +++ b/apps/meteor/client/sidebar/footer/voip/VoipFooter.tsx @@ -6,9 +6,9 @@ import type { ReactElement, MouseEvent, ReactNode } from 'react'; import React from 'react'; import { useTranslation } from 'react-i18next'; +import { useOmnichannelContactLabel } from './hooks/useOmnichannelContactLabel'; import type { CallActionsType } from '../../../contexts/CallContext'; import type { VoipFooterMenuOptions } from '../../../hooks/useVoipFooterMenu'; -import { useOmnichannelContactLabel } from './hooks/useOmnichannelContactLabel'; type VoipFooterPropsType = { caller: ICallerInfo; diff --git a/apps/meteor/client/sidebar/header/MatrixFederationSearch/FederatedRoomList.tsx b/apps/meteor/client/sidebar/header/MatrixFederationSearch/FederatedRoomList.tsx index 1b49e987faf8b..ff0fd748c8fe1 100644 --- a/apps/meteor/client/sidebar/header/MatrixFederationSearch/FederatedRoomList.tsx +++ b/apps/meteor/client/sidebar/header/MatrixFederationSearch/FederatedRoomList.tsx @@ -6,11 +6,11 @@ import React from 'react'; import { useTranslation } from 'react-i18next'; import { Virtuoso } from 'react-virtuoso'; -import { VirtuosoScrollbars } from '../../../components/CustomScrollbars'; -import { roomCoordinator } from '../../../lib/rooms/roomCoordinator'; import FederatedRoomListEmptyPlaceholder from './FederatedRoomListEmptyPlaceholder'; import FederatedRoomListItem from './FederatedRoomListItem'; import { useInfiniteFederationSearchPublicRooms } from './useInfiniteFederationSearchPublicRooms'; +import { VirtuosoScrollbars } from '../../../components/CustomScrollbars'; +import { roomCoordinator } from '../../../lib/rooms/roomCoordinator'; type FederatedRoomListProps = { serverName: string; diff --git a/apps/meteor/client/sidebar/header/actions/hooks/useCreateRoomMenu.tsx b/apps/meteor/client/sidebar/header/actions/hooks/useCreateRoomMenu.tsx index 872294a5a27c7..795944b8d819a 100644 --- a/apps/meteor/client/sidebar/header/actions/hooks/useCreateRoomMenu.tsx +++ b/apps/meteor/client/sidebar/header/actions/hooks/useCreateRoomMenu.tsx @@ -1,9 +1,9 @@ import { useAtLeastOnePermission, useSetting } from '@rocket.chat/ui-contexts'; import { useTranslation } from 'react-i18next'; -import { useIsEnterprise } from '../../../../hooks/useIsEnterprise'; import { useCreateRoomItems } from './useCreateRoomItems'; import { useMatrixFederationItems } from './useMatrixFederationItems'; +import { useIsEnterprise } from '../../../../hooks/useIsEnterprise'; const CREATE_ROOM_PERMISSIONS = ['create-c', 'create-p', 'create-d', 'start-discussion', 'start-discussion-other-user']; diff --git a/apps/meteor/client/sidebar/header/hooks/useStatusItems.tsx b/apps/meteor/client/sidebar/header/hooks/useStatusItems.tsx index db126708f515a..bd8fa009d33fe 100644 --- a/apps/meteor/client/sidebar/header/hooks/useStatusItems.tsx +++ b/apps/meteor/client/sidebar/header/hooks/useStatusItems.tsx @@ -5,13 +5,13 @@ import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import React, { useEffect } from 'react'; import { useTranslation } from 'react-i18next'; +import { useCustomStatusModalHandler } from './useCustomStatusModalHandler'; import { callbacks } from '../../../../lib/callbacks'; import MarkdownText from '../../../components/MarkdownText'; import { UserStatus } from '../../../components/UserStatus'; import { userStatuses } from '../../../lib/userStatuses'; import type { UserStatusDescriptor } from '../../../lib/userStatuses'; import { useStatusDisabledModal } from '../../../views/admin/customUserStatus/hooks/useStatusDisabledModal'; -import { useCustomStatusModalHandler } from './useCustomStatusModalHandler'; export const useStatusItems = (): GenericMenuItemProps[] => { // We should lift this up to somewhere else if we want to use it in other places diff --git a/apps/meteor/client/sidebar/hooks/useRoomList.ts b/apps/meteor/client/sidebar/hooks/useRoomList.ts index afdc57086dc44..1d387d90efe42 100644 --- a/apps/meteor/client/sidebar/hooks/useRoomList.ts +++ b/apps/meteor/client/sidebar/hooks/useRoomList.ts @@ -3,10 +3,10 @@ import { useDebouncedState } from '@rocket.chat/fuselage-hooks'; import { useUserPreference, useUserSubscriptions, useSetting } from '@rocket.chat/ui-contexts'; import { useEffect } from 'react'; +import { useQueryOptions } from './useQueryOptions'; import { useVideoConfIncomingCalls } from '../../contexts/VideoConfContext'; import { useOmnichannelEnabled } from '../../hooks/omnichannel/useOmnichannelEnabled'; import { useQueuedInquiries } from '../../hooks/omnichannel/useQueuedInquiries'; -import { useQueryOptions } from './useQueryOptions'; const query = { open: { $ne: false } }; diff --git a/apps/meteor/client/sidebar/search/Row.tsx b/apps/meteor/client/sidebar/search/Row.tsx index 68ceecd2ad887..35255390da33f 100644 --- a/apps/meteor/client/sidebar/search/Row.tsx +++ b/apps/meteor/client/sidebar/search/Row.tsx @@ -2,8 +2,8 @@ import type { IRoom, ISubscription } from '@rocket.chat/core-typings'; import type { ReactElement } from 'react'; import React, { memo } from 'react'; -import SideBarItemTemplateWithData from '../RoomList/SideBarItemTemplateWithData'; import UserItem from './UserItem'; +import SideBarItemTemplateWithData from '../RoomList/SideBarItemTemplateWithData'; type RowProps = { item: ISubscription & IRoom; diff --git a/apps/meteor/client/sidebar/search/SearchList.tsx b/apps/meteor/client/sidebar/search/SearchList.tsx index dd97678f638ae..86b8922500d7d 100644 --- a/apps/meteor/client/sidebar/search/SearchList.tsx +++ b/apps/meteor/client/sidebar/search/SearchList.tsx @@ -12,12 +12,12 @@ import type { VirtuosoHandle } from 'react-virtuoso'; import { Virtuoso } from 'react-virtuoso'; import tinykeys from 'tinykeys'; +import Row from './Row'; import { VirtuosoScrollbars } from '../../components/CustomScrollbars'; import { getConfig } from '../../lib/utils/getConfig'; import { useAvatarTemplate } from '../hooks/useAvatarTemplate'; import { usePreventDefault } from '../hooks/usePreventDefault'; import { useTemplateByViewMode } from '../hooks/useTemplateByViewMode'; -import Row from './Row'; const mobileCheck = function () { let check = false; diff --git a/apps/meteor/client/sidebar/sections/BannerSection.tsx b/apps/meteor/client/sidebar/sections/BannerSection.tsx index 73c1fdd9d5eb9..a69c1b951b652 100644 --- a/apps/meteor/client/sidebar/sections/BannerSection.tsx +++ b/apps/meteor/client/sidebar/sections/BannerSection.tsx @@ -2,9 +2,9 @@ import { useSessionStorage } from '@rocket.chat/fuselage-hooks'; import { useRole, useSetting } from '@rocket.chat/ui-contexts'; import React from 'react'; -import { useAirGappedRestriction } from '../../hooks/useAirGappedRestriction'; import AirGappedRestrictionBanner from './AirGappedRestrictionBanner/AirGappedRestrictionBanner'; import StatusDisabledBanner from './StatusDisabledBanner'; +import { useAirGappedRestriction } from '../../hooks/useAirGappedRestriction'; const BannerSection = () => { const [isRestricted, isWarning, remainingDays] = useAirGappedRestriction(); diff --git a/apps/meteor/client/sidebar/sections/OmnichannelSection.tsx b/apps/meteor/client/sidebar/sections/OmnichannelSection.tsx index f4c2d8df2c25f..75d663ea1be5d 100644 --- a/apps/meteor/client/sidebar/sections/OmnichannelSection.tsx +++ b/apps/meteor/client/sidebar/sections/OmnichannelSection.tsx @@ -5,12 +5,12 @@ import { useLayout, useRoute, usePermission } from '@rocket.chat/ui-contexts'; import React, { memo } from 'react'; import { useTranslation } from 'react-i18next'; +import { OverMacLimitSection } from './OverMacLimitSection'; +import { OmniChannelCallDialPad, OmnichannelCallToggle, OmnichannelLivechatToggle } from './actions'; import { useIsCallEnabled, useIsCallReady } from '../../contexts/CallContext'; import { useIsOverMacLimit } from '../../hooks/omnichannel/useIsOverMacLimit'; import { useOmnichannelShowQueueLink } from '../../hooks/omnichannel/useOmnichannelShowQueueLink'; import SidebarHeaderToolbar from '../header/SidebarHeaderToolbar'; -import { OverMacLimitSection } from './OverMacLimitSection'; -import { OmniChannelCallDialPad, OmnichannelCallToggle, OmnichannelLivechatToggle } from './actions'; const OmnichannelSection = () => { const { t } = useTranslation(); diff --git a/apps/meteor/client/sidebar/sections/actions/OmnichannelCallToggle.tsx b/apps/meteor/client/sidebar/sections/actions/OmnichannelCallToggle.tsx index 701286fc966bf..e4e4ea3e2c489 100644 --- a/apps/meteor/client/sidebar/sections/actions/OmnichannelCallToggle.tsx +++ b/apps/meteor/client/sidebar/sections/actions/OmnichannelCallToggle.tsx @@ -1,10 +1,10 @@ import type { ReactElement } from 'react'; import React from 'react'; -import { useIsCallReady, useIsCallError } from '../../../contexts/CallContext'; import { OmnichannelCallToggleError } from './OmnichannelCallToggleError'; import { OmnichannelCallToggleLoading } from './OmnichannelCallToggleLoading'; import { OmnichannelCallToggleReady } from './OmnichannelCallToggleReady'; +import { useIsCallReady, useIsCallError } from '../../../contexts/CallContext'; export const OmnichannelCallToggle = ({ ...props }): ReactElement => { const isCallReady = useIsCallReady(); diff --git a/apps/meteor/client/sidebarv2/Item/Condensed.stories.tsx b/apps/meteor/client/sidebarv2/Item/Condensed.stories.tsx index 497f5de0ee88d..7b780a0ca60ad 100644 --- a/apps/meteor/client/sidebarv2/Item/Condensed.stories.tsx +++ b/apps/meteor/client/sidebarv2/Item/Condensed.stories.tsx @@ -4,8 +4,8 @@ import { action } from '@storybook/addon-actions'; import type { Meta, StoryFn } from '@storybook/react'; import React from 'react'; -import * as Status from '../../components/UserStatus'; import Condensed from './Condensed'; +import * as Status from '../../components/UserStatus'; export default { title: 'SidebarV2/Condensed', diff --git a/apps/meteor/client/sidebarv2/Item/Extended.stories.tsx b/apps/meteor/client/sidebarv2/Item/Extended.stories.tsx index 162bd2706fd44..33632e900133e 100644 --- a/apps/meteor/client/sidebarv2/Item/Extended.stories.tsx +++ b/apps/meteor/client/sidebarv2/Item/Extended.stories.tsx @@ -4,8 +4,8 @@ import { action } from '@storybook/addon-actions'; import type { Meta, StoryFn } from '@storybook/react'; import React from 'react'; -import * as Status from '../../components/UserStatus'; import Extended from './Extended'; +import * as Status from '../../components/UserStatus'; export default { title: 'SidebarV2/Extended', diff --git a/apps/meteor/client/sidebarv2/Item/Medium.stories.tsx b/apps/meteor/client/sidebarv2/Item/Medium.stories.tsx index 56f22d0db4e1b..939c59a631eac 100644 --- a/apps/meteor/client/sidebarv2/Item/Medium.stories.tsx +++ b/apps/meteor/client/sidebarv2/Item/Medium.stories.tsx @@ -4,8 +4,8 @@ import { action } from '@storybook/addon-actions'; import type { Meta, StoryFn } from '@storybook/react'; import React from 'react'; -import * as Status from '../../components/UserStatus'; import Medium from './Medium'; +import * as Status from '../../components/UserStatus'; export default { title: 'SidebarV2/Medium', diff --git a/apps/meteor/client/sidebarv2/RoomList/RoomList.tsx b/apps/meteor/client/sidebarv2/RoomList/RoomList.tsx index 6afa27992fb23..828d47c6b7e6f 100644 --- a/apps/meteor/client/sidebarv2/RoomList/RoomList.tsx +++ b/apps/meteor/client/sidebarv2/RoomList/RoomList.tsx @@ -1,10 +1,14 @@ -import { Box, SidebarV2CollapseGroup } from '@rocket.chat/fuselage'; +import { Box } from '@rocket.chat/fuselage'; import { useResizeObserver } from '@rocket.chat/fuselage-hooks'; import { useUserPreference, useUserId } from '@rocket.chat/ui-contexts'; import React, { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { GroupedVirtuoso } from 'react-virtuoso'; +import RoomListCollapser from './RoomListCollapser'; +import RoomListRow from './RoomListRow'; +import RoomListRowWrapper from './RoomListRowWrapper'; +import RoomListWrapper from './RoomListWrapper'; import { VirtuosoScrollbars } from '../../components/CustomScrollbars'; import { useOpenedRoom } from '../../lib/RoomManager'; import { useAvatarTemplate } from '../hooks/useAvatarTemplate'; @@ -13,16 +17,13 @@ import { usePreventDefault } from '../hooks/usePreventDefault'; import { useRoomList } from '../hooks/useRoomList'; import { useShortcutOpenMenu } from '../hooks/useShortcutOpenMenu'; import { useTemplateByViewMode } from '../hooks/useTemplateByViewMode'; -import RoomListRow from './RoomListRow'; -import RoomListRowWrapper from './RoomListRowWrapper'; -import RoomListWrapper from './RoomListWrapper'; const RoomList = () => { const { t } = useTranslation(); const isAnonymous = !useUserId(); const { collapsedGroups, handleClick, handleKeyDown } = useCollapsedGroups(); - const { groupsCount, groupsList, roomList } = useRoomList({ collapsedGroups }); + const { groupsCount, groupsList, roomList, groupedUnreadInfo } = useRoomList({ collapsedGroups }); const avatarTemplate = useAvatarTemplate(); const sideBarItemTemplate = useTemplateByViewMode(); const { ref } = useResizeObserver({ debounceDelay: 100 }); @@ -51,11 +52,12 @@ const RoomList = () => { ( - handleClick(groupsList[index])} onKeyDown={(e) => handleKeyDown(e, groupsList[index])} - expanded={!collapsedGroups.includes(groupsList[index])} + groupTitle={groupsList[index]} + unreadCount={groupedUnreadInfo[index]} /> )} {...(roomList.length > 0 && { diff --git a/apps/meteor/client/sidebarv2/RoomList/RoomListCollapser.tsx b/apps/meteor/client/sidebarv2/RoomList/RoomListCollapser.tsx new file mode 100644 index 0000000000000..3dfd17cb74dd3 --- /dev/null +++ b/apps/meteor/client/sidebarv2/RoomList/RoomListCollapser.tsx @@ -0,0 +1,37 @@ +import type { ISubscription } from '@rocket.chat/core-typings'; +import { Badge, SidebarV2CollapseGroup } from '@rocket.chat/fuselage'; +import type { HTMLAttributes, KeyboardEvent, MouseEventHandler } from 'react'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; + +import { useUnreadDisplay } from '../hooks/useUnreadDisplay'; + +type RoomListCollapserProps = { + groupTitle: string; + collapsedGroups: string[]; + onClick: MouseEventHandler; + onKeyDown: (e: KeyboardEvent) => void; + unreadCount: Pick; +} & Omit, 'onClick' | 'onKeyDown'>; +const RoomListCollapser = ({ groupTitle, unreadCount: unreadGroupCount, collapsedGroups, ...props }: RoomListCollapserProps) => { + const { t } = useTranslation(); + + const { unreadTitle, unreadVariant, showUnread, unreadCount } = useUnreadDisplay(unreadGroupCount); + + return ( + + {unreadCount.total} + + ) : undefined + } + {...props} + /> + ); +}; + +export default RoomListCollapser; diff --git a/apps/meteor/client/sidebarv2/RoomList/RoomListRow.tsx b/apps/meteor/client/sidebarv2/RoomList/RoomListRow.tsx index 810368220ba96..473fad9b0e42c 100644 --- a/apps/meteor/client/sidebarv2/RoomList/RoomListRow.tsx +++ b/apps/meteor/client/sidebarv2/RoomList/RoomListRow.tsx @@ -2,10 +2,10 @@ import type { IRoom, ISubscription } from '@rocket.chat/core-typings'; import type { TFunction } from 'i18next'; import React, { memo, useMemo } from 'react'; +import SidebarItemTemplateWithData from './SidebarItemTemplateWithData'; import { useVideoConfAcceptCall, useVideoConfRejectIncomingCall, useVideoConfIncomingCalls } from '../../contexts/VideoConfContext'; import type { useAvatarTemplate } from '../hooks/useAvatarTemplate'; import type { useTemplateByViewMode } from '../hooks/useTemplateByViewMode'; -import SidebarItemTemplateWithData from './SidebarItemTemplateWithData'; type RoomListRowProps = { data: { diff --git a/apps/meteor/client/sidebarv2/RoomList/SidebarItemTemplateWithData.tsx b/apps/meteor/client/sidebarv2/RoomList/SidebarItemTemplateWithData.tsx index 024615153d368..5417d3075c1e4 100644 --- a/apps/meteor/client/sidebarv2/RoomList/SidebarItemTemplateWithData.tsx +++ b/apps/meteor/client/sidebarv2/RoomList/SidebarItemTemplateWithData.tsx @@ -6,6 +6,7 @@ import type { TFunction } from 'i18next'; import type { AllHTMLAttributes, ComponentType, ReactElement, ReactNode } from 'react'; import React, { memo, useMemo } from 'react'; +import { normalizeSidebarMessage } from './normalizeSidebarMessage'; import { RoomIcon } from '../../components/RoomIcon'; import { roomCoordinator } from '../../lib/rooms/roomCoordinator'; import { isIOsDevice } from '../../lib/utils/isIOsDevice'; @@ -14,7 +15,6 @@ import RoomMenu from '../RoomMenu'; import { OmnichannelBadges } from '../badges/OmnichannelBadges'; import type { useAvatarTemplate } from '../hooks/useAvatarTemplate'; import { useUnreadDisplay } from '../hooks/useUnreadDisplay'; -import { normalizeSidebarMessage } from './normalizeSidebarMessage'; export const getMessage = (room: IRoom, lastMessage: IMessage | undefined, t: TFunction): string | undefined => { if (!lastMessage) { diff --git a/apps/meteor/client/sidebarv2/footer/SidebarFooter.tsx b/apps/meteor/client/sidebarv2/footer/SidebarFooter.tsx index f31f1a3e6b8f4..7b4da56041378 100644 --- a/apps/meteor/client/sidebarv2/footer/SidebarFooter.tsx +++ b/apps/meteor/client/sidebarv2/footer/SidebarFooter.tsx @@ -1,9 +1,9 @@ import type { ReactElement } from 'react'; import React from 'react'; -import { useIsCallEnabled, useIsCallReady } from '../../contexts/CallContext'; import SidebarFooterDefault from './SidebarFooterDefault'; import { VoipFooter } from './voip'; +import { useIsCallEnabled, useIsCallReady } from '../../contexts/CallContext'; const SidebarFooter = (): ReactElement => { const isCallEnabled = useIsCallEnabled(); diff --git a/apps/meteor/client/sidebarv2/footer/voip/VoipFooter.tsx b/apps/meteor/client/sidebarv2/footer/voip/VoipFooter.tsx index 75d64d4777cf6..80154f307dd6f 100644 --- a/apps/meteor/client/sidebarv2/footer/voip/VoipFooter.tsx +++ b/apps/meteor/client/sidebarv2/footer/voip/VoipFooter.tsx @@ -6,9 +6,9 @@ import type { ReactElement, MouseEvent, ReactNode } from 'react'; import React from 'react'; import { useTranslation } from 'react-i18next'; +import { useOmnichannelContactLabel } from './hooks/useOmnichannelContactLabel'; import type { CallActionsType } from '../../../contexts/CallContext'; import type { VoipFooterMenuOptions } from '../../../hooks/useVoipFooterMenu'; -import { useOmnichannelContactLabel } from './hooks/useOmnichannelContactLabel'; type VoipFooterProps = { caller: ICallerInfo; diff --git a/apps/meteor/client/sidebarv2/header/CreateChannelModal.tsx b/apps/meteor/client/sidebarv2/header/CreateChannelModal.tsx index d374d05977b3f..964b808cb10f8 100644 --- a/apps/meteor/client/sidebarv2/header/CreateChannelModal.tsx +++ b/apps/meteor/client/sidebarv2/header/CreateChannelModal.tsx @@ -29,10 +29,10 @@ import type { ComponentProps, ReactElement } from 'react'; import React, { useEffect, useMemo } from 'react'; import { useForm, Controller } from 'react-hook-form'; +import { useEncryptedRoomDescription } from './hooks/useEncryptedRoomDescription'; import UserAutoCompleteMultipleFederated from '../../components/UserAutoCompleteMultiple/UserAutoCompleteMultipleFederated'; import { useHasLicenseModule } from '../../hooks/useHasLicenseModule'; import { goToRoomById } from '../../lib/utils/goToRoomById'; -import { useEncryptedRoomDescription } from './hooks/useEncryptedRoomDescription'; type CreateChannelModalProps = { teamId?: string; diff --git a/apps/meteor/client/sidebarv2/header/CreateTeamModal.tsx b/apps/meteor/client/sidebarv2/header/CreateTeamModal.tsx index 9de721d8bbcda..b1406b991696a 100644 --- a/apps/meteor/client/sidebarv2/header/CreateTeamModal.tsx +++ b/apps/meteor/client/sidebarv2/header/CreateTeamModal.tsx @@ -15,6 +15,7 @@ import { FieldHint, Accordion, AccordionItem, + Divider, } from '@rocket.chat/fuselage'; import { useUniqueId } from '@rocket.chat/fuselage-hooks'; import { FeaturePreview, FeaturePreviewOff, FeaturePreviewOn } from '@rocket.chat/ui-client'; @@ -30,9 +31,9 @@ import type { ComponentProps, ReactElement } from 'react'; import React, { memo, useEffect, useMemo } from 'react'; import { Controller, useForm } from 'react-hook-form'; +import { useEncryptedRoomDescription } from './hooks/useEncryptedRoomDescription'; import UserAutoCompleteMultiple from '../../components/UserAutoCompleteMultiple'; import { goToRoomById } from '../../lib/utils/goToRoomById'; -import { useEncryptedRoomDescription } from './hooks/useEncryptedRoomDescription'; type CreateTeamModalInputs = { name: string; @@ -296,6 +297,7 @@ const CreateTeamModal = ({ onClose }: CreateTeamModalProps) => { {t('Show_discussions_description')} + diff --git a/apps/meteor/client/sidebarv2/header/MatrixFederationSearch/FederatedRoomList.tsx b/apps/meteor/client/sidebarv2/header/MatrixFederationSearch/FederatedRoomList.tsx index a69cd3aec9b25..0e01cacda0ee0 100644 --- a/apps/meteor/client/sidebarv2/header/MatrixFederationSearch/FederatedRoomList.tsx +++ b/apps/meteor/client/sidebarv2/header/MatrixFederationSearch/FederatedRoomList.tsx @@ -6,11 +6,11 @@ import React from 'react'; import { useTranslation } from 'react-i18next'; import { Virtuoso } from 'react-virtuoso'; -import { VirtuosoScrollbars } from '../../../components/CustomScrollbars'; -import { roomCoordinator } from '../../../lib/rooms/roomCoordinator'; import FederatedRoomListEmptyPlaceholder from './FederatedRoomListEmptyPlaceholder'; import FederatedRoomListItem from './FederatedRoomListItem'; import { useInfiniteFederationSearchPublicRooms } from './useInfiniteFederationSearchPublicRooms'; +import { VirtuosoScrollbars } from '../../../components/CustomScrollbars'; +import { roomCoordinator } from '../../../lib/rooms/roomCoordinator'; type FederatedRoomListProps = { serverName: string; diff --git a/apps/meteor/client/sidebarv2/header/actions/hooks/useCreateRoomMenu.tsx b/apps/meteor/client/sidebarv2/header/actions/hooks/useCreateRoomMenu.tsx index 872294a5a27c7..795944b8d819a 100644 --- a/apps/meteor/client/sidebarv2/header/actions/hooks/useCreateRoomMenu.tsx +++ b/apps/meteor/client/sidebarv2/header/actions/hooks/useCreateRoomMenu.tsx @@ -1,9 +1,9 @@ import { useAtLeastOnePermission, useSetting } from '@rocket.chat/ui-contexts'; import { useTranslation } from 'react-i18next'; -import { useIsEnterprise } from '../../../../hooks/useIsEnterprise'; import { useCreateRoomItems } from './useCreateRoomItems'; import { useMatrixFederationItems } from './useMatrixFederationItems'; +import { useIsEnterprise } from '../../../../hooks/useIsEnterprise'; const CREATE_ROOM_PERMISSIONS = ['create-c', 'create-p', 'create-d', 'start-discussion', 'start-discussion-other-user']; diff --git a/apps/meteor/client/sidebarv2/hooks/useRoomList.spec.tsx b/apps/meteor/client/sidebarv2/hooks/useRoomList.spec.tsx index fc1c10c70cf74..bf4645b25db38 100644 --- a/apps/meteor/client/sidebarv2/hooks/useRoomList.spec.tsx +++ b/apps/meteor/client/sidebarv2/hooks/useRoomList.spec.tsx @@ -3,9 +3,9 @@ import type { SubscriptionWithRoom } from '@rocket.chat/ui-contexts'; import { renderHook } from '@testing-library/react'; import React from 'react'; +import { useRoomList } from './useRoomList'; import { createFakeRoom, createFakeSubscription, createFakeUser } from '../../../tests/mocks/data'; import { VideoConfContext } from '../../contexts/VideoConfContext'; -import { useRoomList } from './useRoomList'; const user = createFakeUser({ active: true, @@ -13,43 +13,53 @@ const user = createFakeUser({ type: 'user', }); -const unreadRooms = [ - { ...createFakeSubscription({ t: 'c', unread: 1 }), ...createFakeRoom({ t: 'c' }) }, - { ...createFakeSubscription({ t: 'c', unread: 1 }), ...createFakeRoom({ t: 'c' }) }, - { ...createFakeSubscription({ t: 'c', unread: 1 }), ...createFakeRoom({ t: 'c' }) }, - { ...createFakeSubscription({ t: 'c', unread: 1 }), ...createFakeRoom({ t: 'c' }) }, +const emptyUnread = { + userMentions: 0, + groupMentions: 0, + unread: 0, + tunread: undefined, + tunreadUser: undefined, + tunreadGroup: undefined, + alert: false, +}; + +const unreadChannels = [ + { ...createFakeSubscription({ t: 'c', tunread: ['1'] }), ...createFakeRoom({ t: 'c' }) }, + { ...createFakeSubscription({ t: 'c', tunread: ['1'] }), ...createFakeRoom({ t: 'c' }) }, + { ...createFakeSubscription({ t: 'c', tunreadUser: ['1'] }), ...createFakeRoom({ t: 'c' }) }, + { ...createFakeSubscription({ t: 'c', tunreadUser: ['1'] }), ...createFakeRoom({ t: 'c' }) }, ]; const favoriteRooms = [ - { ...createFakeSubscription({ t: 'c', f: true, unread: undefined }), ...createFakeRoom({ t: 'c' }) }, - { ...createFakeSubscription({ t: 'c', f: true, unread: undefined }), ...createFakeRoom({ t: 'c' }) }, - { ...createFakeSubscription({ t: 'c', f: true, unread: undefined }), ...createFakeRoom({ t: 'c' }) }, + { ...createFakeSubscription({ t: 'c', f: true, ...emptyUnread }), ...createFakeRoom({ t: 'c' }) }, + { ...createFakeSubscription({ t: 'c', f: true, ...emptyUnread }), ...createFakeRoom({ t: 'c' }) }, + { ...createFakeSubscription({ t: 'c', f: true, ...emptyUnread }), ...createFakeRoom({ t: 'c' }) }, ]; const teams = [ - { ...createFakeSubscription({ unread: undefined }), ...createFakeRoom({ teamMain: true }) }, - { ...createFakeSubscription({ unread: undefined }), ...createFakeRoom({ teamMain: true }) }, - { ...createFakeSubscription({ unread: undefined }), ...createFakeRoom({ teamMain: true }) }, - { ...createFakeSubscription({ unread: undefined }), ...createFakeRoom({ teamMain: true }) }, - { ...createFakeSubscription({ unread: undefined }), ...createFakeRoom({ teamMain: true }) }, + { ...createFakeSubscription({ ...emptyUnread }), ...createFakeRoom({ teamMain: true }) }, + { ...createFakeSubscription({ ...emptyUnread }), ...createFakeRoom({ teamMain: true }) }, + { ...createFakeSubscription({ ...emptyUnread }), ...createFakeRoom({ teamMain: true }) }, + { ...createFakeSubscription({ ...emptyUnread }), ...createFakeRoom({ teamMain: true }) }, + { ...createFakeSubscription({ ...emptyUnread }), ...createFakeRoom({ teamMain: true }) }, ]; const discussionRooms = [ - { ...createFakeSubscription({ unread: undefined }), ...createFakeRoom({ prid: '123' }) }, - { ...createFakeSubscription({ unread: undefined }), ...createFakeRoom({ prid: '124' }) }, - { ...createFakeSubscription({ unread: undefined }), ...createFakeRoom({ prid: '125' }) }, - { ...createFakeSubscription({ unread: undefined }), ...createFakeRoom({ prid: '126' }) }, - { ...createFakeSubscription({ unread: undefined }), ...createFakeRoom({ prid: '127' }) }, + { ...createFakeSubscription({ ...emptyUnread }), ...createFakeRoom({ prid: '123' }) }, + { ...createFakeSubscription({ ...emptyUnread }), ...createFakeRoom({ prid: '124' }) }, + { ...createFakeSubscription({ ...emptyUnread }), ...createFakeRoom({ prid: '125' }) }, + { ...createFakeSubscription({ ...emptyUnread }), ...createFakeRoom({ prid: '126' }) }, + { ...createFakeSubscription({ ...emptyUnread }), ...createFakeRoom({ prid: '127' }) }, ]; const directRooms = [ - { ...createFakeSubscription({ t: 'd', unread: undefined }), ...createFakeRoom({ t: 'd' }) }, - { ...createFakeSubscription({ t: 'd', unread: undefined }), ...createFakeRoom({ t: 'd' }) }, - { ...createFakeSubscription({ t: 'd', unread: undefined }), ...createFakeRoom({ t: 'd' }) }, - { ...createFakeSubscription({ t: 'd', unread: undefined }), ...createFakeRoom({ t: 'd' }) }, + { ...createFakeSubscription({ t: 'd', ...emptyUnread }), ...createFakeRoom({ t: 'd' }) }, + { ...createFakeSubscription({ t: 'd', ...emptyUnread }), ...createFakeRoom({ t: 'd' }) }, + { ...createFakeSubscription({ t: 'd', ...emptyUnread }), ...createFakeRoom({ t: 'd' }) }, + { ...createFakeSubscription({ t: 'd', ...emptyUnread }), ...createFakeRoom({ t: 'd' }) }, ]; -const fakeRooms = [...unreadRooms, ...favoriteRooms, ...teams, ...discussionRooms, ...directRooms]; +const fakeRooms = [...unreadChannels, ...favoriteRooms, ...teams, ...discussionRooms, ...directRooms]; const emptyArr: any[] = []; @@ -228,7 +238,7 @@ it('should return "Unread" group with the correct items if sidebarShowUnread is }); const unreadIndex = result.current.groupsList.indexOf('Unread'); expect(result.current.groupsList).toContain('Unread'); - expect(result.current.groupsCount[unreadIndex]).toEqual(unreadRooms.length); + expect(result.current.groupsCount[unreadIndex]).toEqual(unreadChannels.length); }); it('should not include unread room in unread group if hideUnreadStatus is enabled', async () => { @@ -246,6 +256,58 @@ it('should not include unread room in unread group if hideUnreadStatus is enable const unreadIndex = result.current.groupsList.indexOf('Unread'); const roomListUnread = result.current.roomList.filter((room) => room.unread); - expect(result.current.groupsCount[unreadIndex]).toEqual(unreadRooms.length); - expect(roomListUnread.length).not.toEqual(unreadRooms.length); + expect(result.current.groupsCount[unreadIndex]).toEqual(unreadChannels.length); + expect(roomListUnread.length).not.toEqual(unreadChannels.length); +}); + +it('should accumulate unread data into `groupedUnreadInfo` when group is collapsed', async () => { + const { result } = renderHook(() => useRoomList({ collapsedGroups: ['Channels'] }), { + legacyRoot: true, + wrapper: getWrapperSettings({ sidebarGroupByType: true }).build(), + }); + + const channelsIndex = result.current.groupsList.indexOf('Channels'); + const { groupMentions, unread, userMentions, tunread, tunreadUser } = result.current.groupedUnreadInfo[channelsIndex]; + + expect(groupMentions).toEqual(fakeRooms.reduce((acc, cv) => acc + cv.groupMentions, 0)); + expect(unread).toEqual(fakeRooms.reduce((acc, cv) => acc + cv.unread, 0)); + expect(userMentions).toEqual(fakeRooms.reduce((acc, cv) => acc + cv.userMentions, 0)); + expect(tunread).toEqual(fakeRooms.reduce((acc, cv) => [...acc, ...(cv.tunread || [])], [] as string[])); + expect(tunreadUser).toEqual(fakeRooms.reduce((acc, cv) => [...acc, ...(cv.tunreadUser || [])], [] as string[])); +}); + +it('should add to unread group when has thread unread, even if alert is false', async () => { + const fakeRoom = { + ...createFakeSubscription({ ...emptyUnread, tunread: ['1'], alert: false }), + } as unknown as SubscriptionWithRoom; + + const { result } = renderHook(() => useRoomList({ collapsedGroups: [] }), { + legacyRoot: true, + wrapper: getWrapperSettings({ + sidebarGroupByType: true, + sidebarShowUnread: true, + fakeRoom, + }).build(), + }); + + const unreadGroup = result.current.roomList.splice(0, result.current.groupsCount[0]); + expect(unreadGroup.find((room) => room.name === fakeRoom.name)).toBeDefined(); +}); + +it('should not add room to unread group if thread unread is an empty array', async () => { + const fakeRoom = { + ...createFakeSubscription({ ...emptyUnread, tunread: [] }), + } as unknown as SubscriptionWithRoom; + + const { result } = renderHook(() => useRoomList({ collapsedGroups: [] }), { + legacyRoot: true, + wrapper: getWrapperSettings({ + sidebarGroupByType: true, + sidebarShowUnread: true, + fakeRoom, + }).build(), + }); + + const unreadGroup = result.current.roomList.splice(0, result.current.groupsCount[0]); + expect(unreadGroup.find((room) => room.name === fakeRoom.name)).toBeUndefined(); }); diff --git a/apps/meteor/client/sidebarv2/hooks/useRoomList.ts b/apps/meteor/client/sidebarv2/hooks/useRoomList.ts index 5f9a1234c2694..b33fafbea8037 100644 --- a/apps/meteor/client/sidebarv2/hooks/useRoomList.ts +++ b/apps/meteor/client/sidebarv2/hooks/useRoomList.ts @@ -1,13 +1,13 @@ import type { ILivechatInquiryRecord, IRoom, ISubscription } from '@rocket.chat/core-typings'; import { useDebouncedValue } from '@rocket.chat/fuselage-hooks'; -import type { TranslationKey } from '@rocket.chat/ui-contexts'; +import type { SubscriptionWithRoom, TranslationKey } from '@rocket.chat/ui-contexts'; import { useUserPreference, useUserSubscriptions, useSetting } from '@rocket.chat/ui-contexts'; import { useMemo } from 'react'; +import { useQueryOptions } from './useQueryOptions'; import { useVideoConfIncomingCalls } from '../../contexts/VideoConfContext'; import { useOmnichannelEnabled } from '../../hooks/omnichannel/useOmnichannelEnabled'; import { useQueuedInquiries } from '../../hooks/omnichannel/useQueuedInquiries'; -import { useQueryOptions } from './useQueryOptions'; const query = { open: { $ne: false } }; @@ -27,15 +27,16 @@ const order = [ 'Conversations', ] as const; -export const useRoomList = ({ - collapsedGroups, -}: { - collapsedGroups?: string[]; -}): { +type useRoomListReturnType = { roomList: Array; groupsCount: number[]; groupsList: TranslationKey[]; -} => { + groupedUnreadInfo: Pick< + SubscriptionWithRoom, + 'userMentions' | 'groupMentions' | 'unread' | 'tunread' | 'tunreadUser' | 'tunreadGroup' | 'alert' | 'hideUnreadStatus' + >[]; +}; +export const useRoomList = ({ collapsedGroups }: { collapsedGroups?: string[] }): useRoomListReturnType => { const showOmnichannel = useOmnichannelEnabled(); const sidebarGroupByType = useUserPreference('sidebarGroupByType'); const favoritesEnabled = useUserPreference('sidebarShowFavorites'); @@ -53,7 +54,7 @@ export const useRoomList = ({ const queue = inquiries.enabled ? inquiries.queue : emptyQueue; - const { groupsCount, groupsList, roomList } = useDebouncedValue( + const { groupsCount, groupsList, roomList, groupedUnreadInfo } = useDebouncedValue( useMemo(() => { const isCollapsed = (groupTitle: string) => collapsedGroups?.includes(groupTitle); @@ -77,7 +78,7 @@ export const useRoomList = ({ return incomingCall.add(room); } - if (sidebarShowUnread && (room.alert || room.unread) && !room.hideUnreadStatus) { + if (sidebarShowUnread && (room.alert || room.unread || room.tunread?.length) && !room.hideUnreadStatus) { return unread.add(room); } @@ -133,7 +134,7 @@ export const useRoomList = ({ !sidebarGroupByType && groups.set('Conversations', conversation); - const { groupsCount, groupsList, roomList } = sidebarOrder.reduce( + const { groupsCount, groupsList, roomList, groupedUnreadInfo } = sidebarOrder.reduce( (acc, key) => { const value = groups.get(key); @@ -142,11 +143,39 @@ export const useRoomList = ({ } acc.groupsList.push(key as TranslationKey); + + const groupedUnreadInfoAcc = { + userMentions: 0, + groupMentions: 0, + tunread: [], + tunreadUser: [], + unread: 0, + }; + if (isCollapsed(key)) { + const groupedUnreadInfo = [...value].reduce( + (counter, { userMentions, groupMentions, tunread, tunreadUser, unread, alert, hideUnreadStatus }) => { + if (hideUnreadStatus) { + return counter; + } + + counter.userMentions += userMentions || 0; + counter.groupMentions += groupMentions || 0; + counter.tunread = [...counter.tunread, ...(tunread || [])]; + counter.tunreadUser = [...counter.tunreadUser, ...(tunreadUser || [])]; + counter.unread += unread || 0; + !unread && !tunread?.length && alert && (counter.unread += 1); + return counter; + }, + groupedUnreadInfoAcc, + ); + + acc.groupedUnreadInfo.push(groupedUnreadInfo); acc.groupsCount.push(0); return acc; } + acc.groupedUnreadInfo.push(groupedUnreadInfoAcc); acc.groupsCount.push(value.size); acc.roomList.push(...value); return acc; @@ -155,14 +184,11 @@ export const useRoomList = ({ groupsCount: [], groupsList: [], roomList: [], - } as { - groupsCount: number[]; - groupsList: TranslationKey[]; - roomList: Array; - }, + groupedUnreadInfo: [], + } as useRoomListReturnType, ); - return { groupsCount, groupsList, roomList }; + return { groupsCount, groupsList, roomList, groupedUnreadInfo }; }, [ rooms, showOmnichannel, @@ -183,5 +209,6 @@ export const useRoomList = ({ roomList, groupsCount, groupsList, + groupedUnreadInfo, }; }; diff --git a/apps/meteor/client/sidebarv2/hooks/useUnreadDisplay.spec.tsx b/apps/meteor/client/sidebarv2/hooks/useUnreadDisplay.spec.tsx index 30d922184022e..0ae7f82e391bf 100644 --- a/apps/meteor/client/sidebarv2/hooks/useUnreadDisplay.spec.tsx +++ b/apps/meteor/client/sidebarv2/hooks/useUnreadDisplay.spec.tsx @@ -1,8 +1,8 @@ import { mockAppRoot } from '@rocket.chat/mock-providers'; import { renderHook } from '@testing-library/react'; -import { createFakeSubscription } from '../../../tests/mocks/data'; import { useUnreadDisplay } from './useUnreadDisplay'; +import { createFakeSubscription } from '../../../tests/mocks/data'; const dmUnread = createFakeSubscription({ t: 'd', diff --git a/apps/meteor/client/sidebarv2/search/Row.tsx b/apps/meteor/client/sidebarv2/search/Row.tsx index f8541546ec4b1..c0d332c5fa7eb 100644 --- a/apps/meteor/client/sidebarv2/search/Row.tsx +++ b/apps/meteor/client/sidebarv2/search/Row.tsx @@ -2,8 +2,8 @@ import type { IRoom, ISubscription } from '@rocket.chat/core-typings'; import type { ReactElement } from 'react'; import React, { memo } from 'react'; -import SidebarItemTemplateWithData from '../RoomList/SidebarItemTemplateWithData'; import UserItem from './UserItem'; +import SidebarItemTemplateWithData from '../RoomList/SidebarItemTemplateWithData'; type RowProps = { item: ISubscription & IRoom; diff --git a/apps/meteor/client/sidebarv2/sections/BannerSection.tsx b/apps/meteor/client/sidebarv2/sections/BannerSection.tsx index 73c1fdd9d5eb9..a69c1b951b652 100644 --- a/apps/meteor/client/sidebarv2/sections/BannerSection.tsx +++ b/apps/meteor/client/sidebarv2/sections/BannerSection.tsx @@ -2,9 +2,9 @@ import { useSessionStorage } from '@rocket.chat/fuselage-hooks'; import { useRole, useSetting } from '@rocket.chat/ui-contexts'; import React from 'react'; -import { useAirGappedRestriction } from '../../hooks/useAirGappedRestriction'; import AirGappedRestrictionBanner from './AirGappedRestrictionBanner/AirGappedRestrictionBanner'; import StatusDisabledBanner from './StatusDisabledBanner'; +import { useAirGappedRestriction } from '../../hooks/useAirGappedRestriction'; const BannerSection = () => { const [isRestricted, isWarning, remainingDays] = useAirGappedRestriction(); diff --git a/apps/meteor/client/startup/e2e.ts b/apps/meteor/client/startup/e2e.ts index e45b625637260..3f439d99a6968 100644 --- a/apps/meteor/client/startup/e2e.ts +++ b/apps/meteor/client/startup/e2e.ts @@ -6,7 +6,7 @@ import { Tracker } from 'meteor/tracker'; import { E2EEState } from '../../app/e2e/client/E2EEState'; import { e2e } from '../../app/e2e/client/rocketchat.e2e'; import { MentionsParser } from '../../app/mentions/lib/MentionsParser'; -import { ChatRoom } from '../../app/models/client'; +import { Rooms } from '../../app/models/client'; import { settings } from '../../app/settings/client'; import { onClientBeforeSendMessage } from '../lib/onClientBeforeSendMessage'; import { onClientMessageReceived } from '../lib/onClientMessageReceived'; @@ -79,7 +79,7 @@ Meteor.startup(() => { return message; } - const subscription = await waitUntilFind(() => ChatRoom.findOne({ _id: message.rid })); + const subscription = await waitUntilFind(() => Rooms.findOne({ _id: message.rid })); subscription.encrypted ? e2eRoom.resume() : e2eRoom.pause(); diff --git a/apps/meteor/client/startup/incomingMessages.ts b/apps/meteor/client/startup/incomingMessages.ts index 9418871749853..8f4149e9de94d 100644 --- a/apps/meteor/client/startup/incomingMessages.ts +++ b/apps/meteor/client/startup/incomingMessages.ts @@ -1,7 +1,7 @@ import type { IMessage } from '@rocket.chat/core-typings'; import { Meteor } from 'meteor/meteor'; -import { ChatMessage } from '../../app/models/client'; +import { Messages } from '../../app/models/client'; import { sdk } from '../../app/utils/client/lib/SDKClient'; import { onLoggedIn } from '../lib/loggedIn'; @@ -13,13 +13,13 @@ Meteor.startup(() => { msg.u = msg.u || { username: 'rocket.cat' }; msg.private = true; - return ChatMessage.upsert({ _id: msg._id }, msg); + return Messages.upsert({ _id: msg._id }, msg); }); }); onLoggedIn(() => { return sdk.stream('notify-user', [`${Meteor.userId()}/subscriptions-changed`], (_action, sub) => { - ChatMessage.update( + Messages.update( { rid: sub.rid, ...('ignored' in sub && sub.ignored ? { 'u._id': { $nin: sub.ignored } } : { ignored: { $exists: true } }), @@ -28,7 +28,7 @@ Meteor.startup(() => { { multi: true }, ); if ('ignored' in sub && sub.ignored) { - ChatMessage.update( + Messages.update( { 'rid': sub.rid, 't': { $ne: 'command' }, 'u._id': { $in: sub.ignored } }, { $set: { ignored: true } }, { multi: true }, diff --git a/apps/meteor/client/startup/loadMissedMessages.ts b/apps/meteor/client/startup/loadMissedMessages.ts index e56dc5e83add2..37bd437d8af27 100644 --- a/apps/meteor/client/startup/loadMissedMessages.ts +++ b/apps/meteor/client/startup/loadMissedMessages.ts @@ -2,12 +2,12 @@ import type { IRoom } from '@rocket.chat/core-typings'; import { Meteor } from 'meteor/meteor'; import { Tracker } from 'meteor/tracker'; -import { ChatMessage, ChatSubscription } from '../../app/models/client'; +import { Messages, Subscriptions } from '../../app/models/client'; import { LegacyRoomManager, upsertMessage } from '../../app/ui-utils/client'; import { callWithErrorHandling } from '../lib/utils/callWithErrorHandling'; const loadMissedMessages = async function (rid: IRoom['_id']): Promise { - const lastMessage = ChatMessage.findOne({ rid, _hidden: { $ne: true }, temp: { $exists: false } }, { sort: { ts: -1 }, limit: 1 }); + const lastMessage = Messages.findOne({ rid, _hidden: { $ne: true }, temp: { $exists: false } }, { sort: { ts: -1 }, limit: 1 }); if (!lastMessage) { return; @@ -16,7 +16,7 @@ const loadMissedMessages = async function (rid: IRoom['_id']): Promise { try { const result = await callWithErrorHandling('loadMissedMessages', rid, lastMessage.ts); if (result) { - const subscription = ChatSubscription.findOne({ rid }); + const subscription = Subscriptions.findOne({ rid }); await Promise.all(Array.from(result).map((msg) => upsertMessage({ msg, subscription }))); } } catch (error) { diff --git a/apps/meteor/client/startup/messageObserve.ts b/apps/meteor/client/startup/messageObserve.ts index 60e730c942760..760c8b76e5c64 100644 --- a/apps/meteor/client/startup/messageObserve.ts +++ b/apps/meteor/client/startup/messageObserve.ts @@ -1,23 +1,23 @@ import { Meteor } from 'meteor/meteor'; -import { ChatMessage } from '../../app/models/client'; +import { Messages } from '../../app/models/client'; import { LegacyRoomManager } from '../../app/ui-utils/client'; Meteor.startup(() => { - ChatMessage.find().observe({ + Messages.find().observe({ removed(record) { if (!LegacyRoomManager.getOpenedRoomByRid(record.rid)) { return; } - const recordBefore = ChatMessage.findOne({ ts: { $lt: record.ts } }, { sort: { ts: -1 } }); + const recordBefore = Messages.findOne({ ts: { $lt: record.ts } }, { sort: { ts: -1 } }); if (recordBefore) { - ChatMessage.update({ _id: recordBefore._id }, { $set: { tick: new Date() } }); + Messages.update({ _id: recordBefore._id }, { $set: { tick: new Date() } }); } - const recordAfter = ChatMessage.findOne({ ts: { $gt: record.ts } }, { sort: { ts: 1 } }); + const recordAfter = Messages.findOne({ ts: { $gt: record.ts } }, { sort: { ts: 1 } }); if (recordAfter) { - return ChatMessage.update({ _id: recordAfter._id }, { $set: { tick: new Date() } }); + return Messages.update({ _id: recordAfter._id }, { $set: { tick: new Date() } }); } }, }); diff --git a/apps/meteor/client/startup/routes.tsx b/apps/meteor/client/startup/routes.tsx index 5b204a7cf18e8..e25a6795da53e 100644 --- a/apps/meteor/client/startup/routes.tsx +++ b/apps/meteor/client/startup/routes.tsx @@ -8,7 +8,7 @@ const IndexRoute = lazy(() => import('../views/root/IndexRoute')); const MeetRoute = lazy(() => import('../views/meet/MeetRoute')); const HomePage = lazy(() => import('../views/home/HomePage')); const DirectoryPage = lazy(() => import('../views/directory')); -const OmnichannelDirectoryPage = lazy(() => import('../views/omnichannel/directory/OmnichannelDirectoryPage')); +const OmnichannelDirectoryRouter = lazy(() => import('../views/omnichannel/directory/OmnichannelDirectoryRouter')); const OmnichannelQueueList = lazy(() => import('../views/omnichannel/queueList')); const CMSPage = lazy(() => import('@rocket.chat/web-ui-registration').then(({ CMSPage }) => ({ default: CMSPage }))); const SecretURLPage = lazy(() => import('../views/invite/SecretURLPage')); @@ -48,10 +48,8 @@ declare module '@rocket.chat/ui-contexts' { pattern: '/directory/:tab?'; }; 'omnichannel-directory': { - pathname: `/omnichannel-directory${`/${string}` | ''}${`/${string}` | ''}${`/${string}` | ''}${`/${string}` | ''}${ - | `/${string}` - | ''}`; - pattern: '/omnichannel-directory/:page?/:bar?/:id?/:tab?/:context?'; + pathname: `/omnichannel-directory${`/${string}` | ''}${`/${string}` | ''}${`/${string}` | ''}`; + pattern: '/omnichannel-directory/:tab?/:context?/:id?/'; }; 'livechat-queue': { pathname: '/livechat-queue'; @@ -153,11 +151,11 @@ router.defineRoutes([ ), }, { - path: '/omnichannel-directory/:page?/:bar?/:id?/:tab?/:context?', + path: '/omnichannel-directory/:tab?/:context?/:id?/', id: 'omnichannel-directory', element: appLayout.wrap( - + , ), }, diff --git a/apps/meteor/client/startup/unread.ts b/apps/meteor/client/startup/unread.ts index d9c2a35efab51..edc48fbf894b0 100644 --- a/apps/meteor/client/startup/unread.ts +++ b/apps/meteor/client/startup/unread.ts @@ -4,12 +4,12 @@ import { Meteor } from 'meteor/meteor'; import { Session } from 'meteor/session'; import { Tracker } from 'meteor/tracker'; -import { ChatSubscription, ChatRoom } from '../../app/models/client'; +import { Subscriptions, Rooms } from '../../app/models/client'; import { getUserPreference } from '../../app/utils/client'; import { fireGlobalEvent } from '../lib/utils/fireGlobalEvent'; const fetchSubscriptions = (): ISubscription[] => - ChatSubscription.find( + Subscriptions.find( { open: true, hideUnreadStatus: { $ne: true }, @@ -39,7 +39,7 @@ Meteor.startup(() => { const unreadCount = fetchSubscriptions().reduce( (ret, subscription) => Tracker.nonreactive(() => { - const room = ChatRoom.findOne({ _id: subscription.rid }, { fields: { usersCount: 1 } }); + const room = Rooms.findOne({ _id: subscription.rid }, { fields: { usersCount: 1 } }); fireGlobalEvent('unread-changed-by-subscription', { ...subscription, usersCount: room?.usersCount, diff --git a/apps/meteor/client/startup/userRoles.ts b/apps/meteor/client/startup/userRoles.ts index 77ba6978d4850..1359dfa4d423c 100644 --- a/apps/meteor/client/startup/userRoles.ts +++ b/apps/meteor/client/startup/userRoles.ts @@ -1,7 +1,7 @@ import { Meteor } from 'meteor/meteor'; import { Tracker } from 'meteor/tracker'; -import { UserRoles, ChatMessage } from '../../app/models/client'; +import { UserRoles, Messages } from '../../app/models/client'; import { sdk } from '../../app/utils/client/lib/SDKClient'; import { dispatchToastMessage } from '../lib/toast'; @@ -26,7 +26,7 @@ Meteor.startup(() => { return; } UserRoles.upsert({ _id: role.u._id }, { $addToSet: { roles: role._id }, $set: { username: role.u.username } }); - ChatMessage.update({ 'u._id': role.u._id }, { $addToSet: { roles: role._id } }, { multi: true }); + Messages.update({ 'u._id': role.u._id }, { $addToSet: { roles: role._id } }, { multi: true }); } return; @@ -38,14 +38,14 @@ Meteor.startup(() => { return; } UserRoles.update({ _id: role.u._id }, { $pull: { roles: role._id } }); - ChatMessage.update({ 'u._id': role.u._id }, { $pull: { roles: role._id } }, { multi: true }); + Messages.update({ 'u._id': role.u._id }, { $pull: { roles: role._id } }, { multi: true }); } return; } if (role.type === 'changed') { - ChatMessage.update({ roles: role._id }, { $inc: { rerender: 1 } }, { multi: true }); + Messages.update({ roles: role._id }, { $inc: { rerender: 1 } }, { multi: true }); } }); } diff --git a/apps/meteor/client/uikit/hooks/useContextualBarContextValue.ts b/apps/meteor/client/uikit/hooks/useContextualBarContextValue.ts index 1be1affad71fe..10906deab7031 100644 --- a/apps/meteor/client/uikit/hooks/useContextualBarContextValue.ts +++ b/apps/meteor/client/uikit/hooks/useContextualBarContextValue.ts @@ -1,8 +1,8 @@ import { useDebouncedCallback } from '@rocket.chat/fuselage-hooks'; import type { UiKitContext } from '@rocket.chat/fuselage-ui-kit'; import type * as UiKit from '@rocket.chat/ui-kit'; -import type { Dispatch } from 'react'; -import { useMemo, type ContextType } from 'react'; +import { useMemo } from 'react'; +import type { Dispatch, ContextType } from 'react'; import { useUiKitActionManager } from './useUiKitActionManager'; diff --git a/apps/meteor/client/uikit/hooks/useMessageBlockContextValue.ts b/apps/meteor/client/uikit/hooks/useMessageBlockContextValue.ts index 2f8fb4933628b..caf869ba39d75 100644 --- a/apps/meteor/client/uikit/hooks/useMessageBlockContextValue.ts +++ b/apps/meteor/client/uikit/hooks/useMessageBlockContextValue.ts @@ -3,6 +3,7 @@ import { useMutableCallback } from '@rocket.chat/fuselage-hooks'; import type { UiKitContext } from '@rocket.chat/fuselage-ui-kit'; import type { ContextType } from 'react'; +import { useUiKitActionManager } from './useUiKitActionManager'; import { useVideoConfDispatchOutgoing, useVideoConfIsCalling, @@ -12,7 +13,6 @@ import { useVideoConfSetPreferences, } from '../../contexts/VideoConfContext'; import { useVideoConfWarning } from '../../views/room/contextualBar/VideoConference/hooks/useVideoConfWarning'; -import { useUiKitActionManager } from './useUiKitActionManager'; export const useMessageBlockContextValue = (rid: IRoom['_id'], mid: IMessage['_id']): ContextType => { const joinCall = useVideoConfJoinCall(); diff --git a/apps/meteor/client/uikit/hooks/useModalContextValue.ts b/apps/meteor/client/uikit/hooks/useModalContextValue.ts index 4a0932c8e1e73..8e159805c7381 100644 --- a/apps/meteor/client/uikit/hooks/useModalContextValue.ts +++ b/apps/meteor/client/uikit/hooks/useModalContextValue.ts @@ -1,8 +1,8 @@ import { useDebouncedCallback } from '@rocket.chat/fuselage-hooks'; import type { UiKitContext } from '@rocket.chat/fuselage-ui-kit'; import type * as UiKit from '@rocket.chat/ui-kit'; -import type { Dispatch } from 'react'; -import { useMemo, type ContextType } from 'react'; +import { useMemo } from 'react'; +import type { Dispatch, ContextType } from 'react'; import { useUiKitActionManager } from './useUiKitActionManager'; diff --git a/apps/meteor/client/views/account/AccountRouter.tsx b/apps/meteor/client/views/account/AccountRouter.tsx index 8196a877f98cc..a59babe1a08dd 100644 --- a/apps/meteor/client/views/account/AccountRouter.tsx +++ b/apps/meteor/client/views/account/AccountRouter.tsx @@ -2,9 +2,9 @@ import { useRouter } from '@rocket.chat/ui-contexts'; import type { ReactElement, ReactNode } from 'react'; import React, { Suspense, useEffect } from 'react'; +import AccountSidebar from './AccountSidebar'; import PageSkeleton from '../../components/PageSkeleton'; import SidebarPortal from '../../sidebar/SidebarPortal'; -import AccountSidebar from './AccountSidebar'; type AccountRouterProps = { children?: ReactNode; diff --git a/apps/meteor/client/views/account/AccountSidebar.tsx b/apps/meteor/client/views/account/AccountSidebar.tsx index 27fa374a69d38..b1d87945ea5eb 100644 --- a/apps/meteor/client/views/account/AccountSidebar.tsx +++ b/apps/meteor/client/views/account/AccountSidebar.tsx @@ -2,9 +2,9 @@ import { useCurrentRoutePath, useTranslation, useLayout } from '@rocket.chat/ui- import React, { memo } from 'react'; import { useSyncExternalStore } from 'use-sync-external-store/shim'; +import { getAccountSidebarItems, subscribeToAccountSidebarItems } from './sidebarItems'; import Sidebar from '../../components/Sidebar'; import SettingsProvider from '../../providers/SettingsProvider'; -import { getAccountSidebarItems, subscribeToAccountSidebarItems } from './sidebarItems'; const AccountSidebar = () => { const t = useTranslation(); diff --git a/apps/meteor/client/views/account/accessibility/AccessibilityPage.tsx b/apps/meteor/client/views/account/accessibility/AccessibilityPage.tsx index 9bb4e57317cf4..f4f67552ddc2f 100644 --- a/apps/meteor/client/views/account/accessibility/AccessibilityPage.tsx +++ b/apps/meteor/client/views/account/accessibility/AccessibilityPage.tsx @@ -22,13 +22,13 @@ import { useMutation } from '@tanstack/react-query'; import React, { useMemo } from 'react'; import { Controller, useForm } from 'react-hook-form'; -import { Page, PageHeader, PageScrollableContentWithShadow, PageFooter } from '../../../components/Page'; -import { getDirtyFields } from '../../../lib/getDirtyFields'; import { fontSizes } from './fontSizes'; import type { AccessibilityPreferencesData } from './hooks/useAcessibilityPreferencesValues'; import { useAccessiblityPreferencesValues } from './hooks/useAcessibilityPreferencesValues'; import { useCreateFontStyleElement } from './hooks/useCreateFontStyleElement'; import { themeItems as themes } from './themeItems'; +import { Page, PageHeader, PageScrollableContentWithShadow, PageFooter } from '../../../components/Page'; +import { getDirtyFields } from '../../../lib/getDirtyFields'; const AccessibilityPage = () => { const t = useTranslation(); diff --git a/apps/meteor/client/views/account/deviceManagement/DeviceManagementAccountPage.tsx b/apps/meteor/client/views/account/deviceManagement/DeviceManagementAccountPage.tsx index d1af15f597115..f98e6608a5b7a 100644 --- a/apps/meteor/client/views/account/deviceManagement/DeviceManagementAccountPage.tsx +++ b/apps/meteor/client/views/account/deviceManagement/DeviceManagementAccountPage.tsx @@ -2,8 +2,8 @@ import type { ReactElement } from 'react'; import React from 'react'; import { useTranslation } from 'react-i18next'; -import { Page, PageHeader, PageContent } from '../../../components/Page'; import DeviceManagementAccountTable from './DeviceManagementAccountTable'; +import { Page, PageHeader, PageContent } from '../../../components/Page'; const DeviceManagementAccountPage = (): ReactElement => { const { t } = useTranslation(); diff --git a/apps/meteor/client/views/account/deviceManagement/DeviceManagementAccountTable/DeviceManagementAccountTable.tsx b/apps/meteor/client/views/account/deviceManagement/DeviceManagementAccountTable/DeviceManagementAccountTable.tsx index 411f9ad02e6f8..351021a9ab92a 100644 --- a/apps/meteor/client/views/account/deviceManagement/DeviceManagementAccountTable/DeviceManagementAccountTable.tsx +++ b/apps/meteor/client/views/account/deviceManagement/DeviceManagementAccountTable/DeviceManagementAccountTable.tsx @@ -3,12 +3,12 @@ import type { ReactElement } from 'react'; import React, { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; +import DeviceManagementAccountRow from './DeviceManagementAccountRow'; import { GenericTableHeaderCell } from '../../../../components/GenericTable'; import { usePagination } from '../../../../components/GenericTable/hooks/usePagination'; import { useSort } from '../../../../components/GenericTable/hooks/useSort'; import DeviceManagementTable from '../../../../components/deviceManagement/DeviceManagementTable'; import { useEndpointData } from '../../../../hooks/useEndpointData'; -import DeviceManagementAccountRow from './DeviceManagementAccountRow'; const sortMapping = { client: 'device.name', diff --git a/apps/meteor/client/views/account/integrations/AccountIntegrationsPage.tsx b/apps/meteor/client/views/account/integrations/AccountIntegrationsPage.tsx index 83c97319e2ca2..9a13328cc6e92 100644 --- a/apps/meteor/client/views/account/integrations/AccountIntegrationsPage.tsx +++ b/apps/meteor/client/views/account/integrations/AccountIntegrationsPage.tsx @@ -6,10 +6,10 @@ import React, { useMemo } from 'react'; import { useForm, Controller } from 'react-hook-form'; import { useTranslation } from 'react-i18next'; +import { useRemoveWebDAVAccountIntegrationMutation } from './hooks/useRemoveWebDAVAccountIntegrationMutation'; import { Page, PageHeader, PageScrollableContentWithShadow } from '../../../components/Page'; import { useWebDAVAccountIntegrationsQuery } from '../../../hooks/webdav/useWebDAVAccountIntegrationsQuery'; import { getWebdavServerName } from '../../../lib/getWebdavServerName'; -import { useRemoveWebDAVAccountIntegrationMutation } from './hooks/useRemoveWebDAVAccountIntegrationMutation'; const AccountIntegrationsPage = () => { const { data: webdavAccountIntegrations } = useWebDAVAccountIntegrationsQuery(); diff --git a/apps/meteor/client/views/account/integrations/AccountIntegrationsRoute.tsx b/apps/meteor/client/views/account/integrations/AccountIntegrationsRoute.tsx index b81a64ede8498..fa0161b061256 100644 --- a/apps/meteor/client/views/account/integrations/AccountIntegrationsRoute.tsx +++ b/apps/meteor/client/views/account/integrations/AccountIntegrationsRoute.tsx @@ -2,8 +2,8 @@ import { useSetting } from '@rocket.chat/ui-contexts'; import type { ReactElement } from 'react'; import React from 'react'; -import NotAuthorizedPage from '../../notAuthorized/NotAuthorizedPage'; import AccountIntegrationsPage from './AccountIntegrationsPage'; +import NotAuthorizedPage from '../../notAuthorized/NotAuthorizedPage'; const AccountIntegrationsRoute = (): ReactElement => { const webdavEnabled = useSetting('Webdav_Integration_Enabled', false); diff --git a/apps/meteor/client/views/account/omnichannel/OmnichannelPreferencesPage.tsx b/apps/meteor/client/views/account/omnichannel/OmnichannelPreferencesPage.tsx index a2b3f3b920c83..ddf549bd98c67 100644 --- a/apps/meteor/client/views/account/omnichannel/OmnichannelPreferencesPage.tsx +++ b/apps/meteor/client/views/account/omnichannel/OmnichannelPreferencesPage.tsx @@ -4,9 +4,9 @@ import type { ReactElement } from 'react'; import React from 'react'; import { useForm, FormProvider } from 'react-hook-form'; -import { Page, PageHeader, PageScrollableContentWithShadow, PageFooter } from '../../../components/Page'; import PreferencesConversationTranscript from './PreferencesConversationTranscript'; import { PreferencesGeneral } from './PreferencesGeneral'; +import { Page, PageHeader, PageScrollableContentWithShadow, PageFooter } from '../../../components/Page'; type FormData = { omnichannelTranscriptPDF: boolean; diff --git a/apps/meteor/client/views/account/preferences/AccountPreferencesPage.tsx b/apps/meteor/client/views/account/preferences/AccountPreferencesPage.tsx index 77997422a21e0..335b27d7c8135 100644 --- a/apps/meteor/client/views/account/preferences/AccountPreferencesPage.tsx +++ b/apps/meteor/client/views/account/preferences/AccountPreferencesPage.tsx @@ -6,8 +6,6 @@ import type { ReactElement } from 'react'; import React from 'react'; import { FormProvider, useForm } from 'react-hook-form'; -import { Page, PageHeader, PageScrollableContentWithShadow, PageFooter } from '../../../components/Page'; -import { getDirtyFields } from '../../../lib/getDirtyFields'; import PreferencesGlobalSection from './PreferencesGlobalSection'; import PreferencesHighlightsSection from './PreferencesHighlightsSection'; import PreferencesLocalizationSection from './PreferencesLocalizationSection'; @@ -18,6 +16,8 @@ import PreferencesSoundSection from './PreferencesSoundSection'; import PreferencesUserPresenceSection from './PreferencesUserPresenceSection'; import type { AccountPreferencesData } from './useAccountPreferencesValues'; import { useAccountPreferencesValues } from './useAccountPreferencesValues'; +import { Page, PageHeader, PageScrollableContentWithShadow, PageFooter } from '../../../components/Page'; +import { getDirtyFields } from '../../../lib/getDirtyFields'; const AccountPreferencesPage = (): ReactElement => { const t = useTranslation(); diff --git a/apps/meteor/client/views/account/profile/AccountProfileForm.tsx b/apps/meteor/client/views/account/profile/AccountProfileForm.tsx index 95398b3520493..54875f0686cb5 100644 --- a/apps/meteor/client/views/account/profile/AccountProfileForm.tsx +++ b/apps/meteor/client/views/account/profile/AccountProfileForm.tsx @@ -27,14 +27,14 @@ import type { AllHTMLAttributes, ReactElement } from 'react'; import React, { useCallback } from 'react'; import { Controller, useFormContext } from 'react-hook-form'; +import type { AccountProfileFormValues } from './getProfileInitialValues'; +import { useAccountProfileSettings } from './useAccountProfileSettings'; import { validateEmail } from '../../../../lib/emailValidator'; import { getUserEmailAddress } from '../../../../lib/getUserEmailAddress'; import UserStatusMenu from '../../../components/UserStatusMenu'; import UserAvatarEditor from '../../../components/avatar/UserAvatarEditor'; import { useUpdateAvatar } from '../../../hooks/useUpdateAvatar'; import { USER_STATUS_TEXT_MAX_LENGTH, BIO_TEXT_MAX_LENGTH } from '../../../lib/constants'; -import type { AccountProfileFormValues } from './getProfileInitialValues'; -import { useAccountProfileSettings } from './useAccountProfileSettings'; const AccountProfileForm = (props: AllHTMLAttributes): ReactElement => { const t = useTranslation(); diff --git a/apps/meteor/client/views/account/profile/AccountProfilePage.tsx b/apps/meteor/client/views/account/profile/AccountProfilePage.tsx index df1710b075095..0113d40a938a3 100644 --- a/apps/meteor/client/views/account/profile/AccountProfilePage.tsx +++ b/apps/meteor/client/views/account/profile/AccountProfilePage.tsx @@ -15,12 +15,12 @@ import type { ReactElement } from 'react'; import React, { useState, useCallback } from 'react'; import { FormProvider, useForm } from 'react-hook-form'; -import ConfirmOwnerChangeModal from '../../../components/ConfirmOwnerChangeModal'; -import { Page, PageFooter, PageHeader, PageScrollableContentWithShadow } from '../../../components/Page'; -import { useAllowPasswordChange } from '../security/useAllowPasswordChange'; import AccountProfileForm from './AccountProfileForm'; import ActionConfirmModal from './ActionConfirmModal'; import { getProfileInitialValues } from './getProfileInitialValues'; +import ConfirmOwnerChangeModal from '../../../components/ConfirmOwnerChangeModal'; +import { Page, PageFooter, PageHeader, PageScrollableContentWithShadow } from '../../../components/Page'; +import { useAllowPasswordChange } from '../security/useAllowPasswordChange'; // TODO: enforce useMutation const AccountProfilePage = (): ReactElement => { diff --git a/apps/meteor/client/views/account/profile/AccountProfileRoute.tsx b/apps/meteor/client/views/account/profile/AccountProfileRoute.tsx index 52d879c305373..77e184f1873ce 100644 --- a/apps/meteor/client/views/account/profile/AccountProfileRoute.tsx +++ b/apps/meteor/client/views/account/profile/AccountProfileRoute.tsx @@ -2,8 +2,8 @@ import { useSetting } from '@rocket.chat/ui-contexts'; import type { ReactElement } from 'react'; import React from 'react'; -import NotAuthorizedPage from '../../notAuthorized/NotAuthorizedPage'; import AccountProfilePage from './AccountProfilePage'; +import NotAuthorizedPage from '../../notAuthorized/NotAuthorizedPage'; const AccountProfileRoute = (): ReactElement => { const canViewProfile = useSetting('Accounts_AllowUserProfileChange'); diff --git a/apps/meteor/client/views/account/security/AccountSecurityPage.tsx b/apps/meteor/client/views/account/security/AccountSecurityPage.tsx index c7d4157ddbd7b..45b0e4c5eb3f8 100644 --- a/apps/meteor/client/views/account/security/AccountSecurityPage.tsx +++ b/apps/meteor/client/views/account/security/AccountSecurityPage.tsx @@ -5,11 +5,11 @@ import type { ReactElement } from 'react'; import React from 'react'; import { FormProvider, useForm } from 'react-hook-form'; -import { Page, PageHeader, PageScrollableContentWithShadow, PageFooter } from '../../../components/Page'; import ChangePassword from './ChangePassword'; import EndToEnd from './EndToEnd'; import TwoFactorEmail from './TwoFactorEmail'; import TwoFactorTOTP from './TwoFactorTOTP'; +import { Page, PageHeader, PageScrollableContentWithShadow, PageFooter } from '../../../components/Page'; const passwordDefaultValues = { password: '', confirmationPassword: '' }; diff --git a/apps/meteor/client/views/account/security/AccountSecurityRoute.tsx b/apps/meteor/client/views/account/security/AccountSecurityRoute.tsx index 11a0d8b638828..ed7ed0310948e 100644 --- a/apps/meteor/client/views/account/security/AccountSecurityRoute.tsx +++ b/apps/meteor/client/views/account/security/AccountSecurityRoute.tsx @@ -2,8 +2,8 @@ import { useSetting } from '@rocket.chat/ui-contexts'; import type { ReactElement } from 'react'; import React from 'react'; -import NotAuthorizedPage from '../../notAuthorized/NotAuthorizedPage'; import AccountSecurityPage from './AccountSecurityPage'; +import NotAuthorizedPage from '../../notAuthorized/NotAuthorizedPage'; const AccountSecurityRoute = (): ReactElement => { const isTwoFactorEnabled = useSetting('Accounts_TwoFactorAuthentication_Enabled'); diff --git a/apps/meteor/client/views/account/security/TwoFactorTOTP.tsx b/apps/meteor/client/views/account/security/TwoFactorTOTP.tsx index dc796caccb2a2..bbd917a1055d7 100644 --- a/apps/meteor/client/views/account/security/TwoFactorTOTP.tsx +++ b/apps/meteor/client/views/account/security/TwoFactorTOTP.tsx @@ -7,9 +7,9 @@ import { useForm } from 'react-hook-form'; import { useTranslation } from 'react-i18next'; import qrcode from 'yaqrcode'; +import BackupCodesModal from './BackupCodesModal'; import TextCopy from '../../../components/TextCopy'; import TwoFactorTotpModal from '../../../components/TwoFactorModal/TwoFactorTotpModal'; -import BackupCodesModal from './BackupCodesModal'; const TwoFactorTOTP = (props: ComponentProps): ReactElement => { const { t } = useTranslation(); diff --git a/apps/meteor/client/views/account/tokens/AccountTokensPage.tsx b/apps/meteor/client/views/account/tokens/AccountTokensPage.tsx index abf45ebedcb9f..6850615db7a4a 100644 --- a/apps/meteor/client/views/account/tokens/AccountTokensPage.tsx +++ b/apps/meteor/client/views/account/tokens/AccountTokensPage.tsx @@ -2,8 +2,8 @@ import type { ReactElement } from 'react'; import React from 'react'; import { useTranslation } from 'react-i18next'; -import { Page, PageHeader, PageContent } from '../../../components/Page'; import AccountTokensTable from './AccountTokensTable'; +import { Page, PageHeader, PageContent } from '../../../components/Page'; const AccountTokensPage = (): ReactElement => { const { t } = useTranslation(); diff --git a/apps/meteor/client/views/account/tokens/AccountTokensRoute.tsx b/apps/meteor/client/views/account/tokens/AccountTokensRoute.tsx index ed8964db15bb2..0876bd8385a75 100644 --- a/apps/meteor/client/views/account/tokens/AccountTokensRoute.tsx +++ b/apps/meteor/client/views/account/tokens/AccountTokensRoute.tsx @@ -2,8 +2,8 @@ import { usePermission } from '@rocket.chat/ui-contexts'; import type { ReactElement } from 'react'; import React from 'react'; -import NotAuthorizedPage from '../../notAuthorized/NotAuthorizedPage'; import AccountTokensPage from './AccountTokensPage'; +import NotAuthorizedPage from '../../notAuthorized/NotAuthorizedPage'; const AccountTokensRoute = (): ReactElement => { const canCreateTokens = usePermission('create-personal-access-tokens'); diff --git a/apps/meteor/client/views/account/tokens/AccountTokensTable/AccountTokensTable.tsx b/apps/meteor/client/views/account/tokens/AccountTokensTable/AccountTokensTable.tsx index 249414486d96d..78cb8414f6e71 100644 --- a/apps/meteor/client/views/account/tokens/AccountTokensTable/AccountTokensTable.tsx +++ b/apps/meteor/client/views/account/tokens/AccountTokensTable/AccountTokensTable.tsx @@ -4,6 +4,8 @@ import type { ReactElement, RefObject } from 'react'; import React, { useMemo, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; +import AccountTokensRow from './AccountTokensRow'; +import AddToken from './AddToken'; import GenericModal from '../../../../components/GenericModal'; import GenericNoResults from '../../../../components/GenericNoResults'; import { @@ -17,8 +19,6 @@ import { usePagination } from '../../../../components/GenericTable/hooks/usePagi import { useEndpointData } from '../../../../hooks/useEndpointData'; import { useResizeInlineBreakpoint } from '../../../../hooks/useResizeInlineBreakpoint'; import { AsyncStatePhase } from '../../../../lib/asyncState'; -import AccountTokensRow from './AccountTokensRow'; -import AddToken from './AddToken'; const AccountTokensTable = (): ReactElement => { const { t } = useTranslation(); @@ -155,11 +155,11 @@ const AccountTokensTable = (): ReactElement => { filteredTokens && filteredTokens.map((filteredToken) => ( ))} diff --git a/apps/meteor/client/views/admin/AdministrationLayout.tsx b/apps/meteor/client/views/admin/AdministrationLayout.tsx index 257028e723d2d..2e77f6f48d40e 100644 --- a/apps/meteor/client/views/admin/AdministrationLayout.tsx +++ b/apps/meteor/client/views/admin/AdministrationLayout.tsx @@ -1,8 +1,8 @@ import type { ReactNode } from 'react'; import React from 'react'; -import SidebarPortal from '../../sidebar/SidebarPortal'; import AdminSidebar from './sidebar/AdminSidebar'; +import SidebarPortal from '../../sidebar/SidebarPortal'; type AdministrationLayoutProps = { children?: ReactNode; diff --git a/apps/meteor/client/views/admin/AdministrationRouter.tsx b/apps/meteor/client/views/admin/AdministrationRouter.tsx index b210435ae2672..8ae97f463416f 100644 --- a/apps/meteor/client/views/admin/AdministrationRouter.tsx +++ b/apps/meteor/client/views/admin/AdministrationRouter.tsx @@ -2,12 +2,12 @@ import { useRouter } from '@rocket.chat/ui-contexts'; import type { ReactElement, ReactNode } from 'react'; import React, { Suspense, useEffect } from 'react'; +import AdministrationLayout from './AdministrationLayout'; +import { getAdminSidebarItems } from './sidebarItems'; import PageSkeleton from '../../components/PageSkeleton'; import type { Item, SidebarDivider, SidebarItem } from '../../lib/createSidebarItems'; import { isGoRocketChatLink } from '../../lib/createSidebarItems'; import SettingsProvider from '../../providers/SettingsProvider'; -import AdministrationLayout from './AdministrationLayout'; -import { getAdminSidebarItems } from './sidebarItems'; const isSidebarDivider = (sidebarItem: SidebarItem): sidebarItem is SidebarDivider => { return (sidebarItem as SidebarDivider).divider === true; diff --git a/apps/meteor/client/views/admin/customEmoji/CustomEmoji.spec.tsx b/apps/meteor/client/views/admin/customEmoji/CustomEmoji.spec.tsx new file mode 100644 index 0000000000000..d59a8c815150a --- /dev/null +++ b/apps/meteor/client/views/admin/customEmoji/CustomEmoji.spec.tsx @@ -0,0 +1,79 @@ +import { mockAppRoot } from '@rocket.chat/mock-providers'; +import { render, screen, waitFor } from '@testing-library/react'; +import React from 'react'; + +import '@testing-library/jest-dom'; + +import CustomEmoji from './CustomEmoji'; + +const appRoot = mockAppRoot().withEndpoint('GET', '/v1/emoji-custom.all', () => ({ + count: 1, + offset: 0, + total: 1, + success: true, + emojis: [ + { + _id: '1', + name: 'smile', + aliases: ['happy', 'joy'], + extension: 'webp', + _updatedAt: new Date().toISOString(), + etag: 'abcdef', + }, + ], +})); + +describe('CustomEmoji Component', () => { + const mockRef = { current: jest.fn() }; + const mockOnClick = jest.fn(); + + it('renders emoji list', async () => { + render(, { + legacyRoot: true, + wrapper: appRoot.build(), + }); + + await waitFor(() => { + expect(screen.getByText('smile')).toBeInTheDocument(); + }); + }); + + it("renders emoji's aliases as comma-separated values when aliases is an array", async () => { + render(, { + legacyRoot: true, + wrapper: appRoot.build(), + }); + + await waitFor(() => { + expect(screen.getByText('happy, joy')).toBeInTheDocument(); + }); + }); + + it("renders emoji's aliases values when aliases is a string", async () => { + render(, { + legacyRoot: true, + wrapper: mockAppRoot() + .withEndpoint('GET', '/v1/emoji-custom.all', () => ({ + count: 1, + offset: 0, + total: 1, + success: true, + emojis: [ + { + _id: '1', + name: 'smile', + aliases: 'happy' as any, + extension: 'webp', + _updatedAt: new Date().toISOString(), + etag: 'abcdef', + }, + ], + })) + .build(), + }); + + await waitFor(() => { + expect(screen.getByText('happy')).toBeInTheDocument(); + }); + }); +}); diff --git a/apps/meteor/client/views/admin/customEmoji/CustomEmoji.tsx b/apps/meteor/client/views/admin/customEmoji/CustomEmoji.tsx index 36d08ab6e3822..4c02776b80d51 100644 --- a/apps/meteor/client/views/admin/customEmoji/CustomEmoji.tsx +++ b/apps/meteor/client/views/admin/customEmoji/CustomEmoji.tsx @@ -95,7 +95,7 @@ const CustomEmoji = ({ onClick, reload }: CustomEmojiProps) => { {emojis.name} - {emojis.aliases} + {Array.isArray(emojis.aliases) ? emojis.aliases.join(', ') : emojis.aliases} ))} diff --git a/apps/meteor/client/views/admin/customEmoji/CustomEmojiRoute.tsx b/apps/meteor/client/views/admin/customEmoji/CustomEmojiRoute.tsx index 725edc6acf897..68daa83165dbf 100644 --- a/apps/meteor/client/views/admin/customEmoji/CustomEmojiRoute.tsx +++ b/apps/meteor/client/views/admin/customEmoji/CustomEmojiRoute.tsx @@ -4,6 +4,9 @@ import type { ReactElement } from 'react'; import React, { useCallback, useRef } from 'react'; import { useTranslation } from 'react-i18next'; +import AddCustomEmoji from './AddCustomEmoji'; +import CustomEmoji from './CustomEmoji'; +import EditCustomEmojiWithData from './EditCustomEmojiWithData'; import { Contextualbar, ContextualbarHeader, @@ -13,9 +16,6 @@ import { } from '../../../components/Contextualbar'; import { Page, PageHeader, PageContent } from '../../../components/Page'; import NotAuthorizedPage from '../../notAuthorized/NotAuthorizedPage'; -import AddCustomEmoji from './AddCustomEmoji'; -import CustomEmoji from './CustomEmoji'; -import EditCustomEmojiWithData from './EditCustomEmojiWithData'; const CustomEmojiRoute = (): ReactElement => { const { t } = useTranslation(); diff --git a/apps/meteor/client/views/admin/customEmoji/EditCustomEmoji.tsx b/apps/meteor/client/views/admin/customEmoji/EditCustomEmoji.tsx index 7d7363d2424c3..285c1a98513b3 100644 --- a/apps/meteor/client/views/admin/customEmoji/EditCustomEmoji.tsx +++ b/apps/meteor/client/views/admin/customEmoji/EditCustomEmoji.tsx @@ -30,6 +30,7 @@ type EditCustomEmojiProps = { name: string; aliases: string[]; extension: string; + etag?: string; }; }; @@ -51,7 +52,7 @@ const EditCustomEmoji = ({ close, onChange, data, ...props }: EditCustomEmojiPro } if (data) { - return absoluteUrl(`/emoji-custom/${encodeURIComponent(data.name)}.${data.extension}`); + return absoluteUrl(`/emoji-custom/${encodeURIComponent(data.name)}.${data.extension}${data.etag ? `?etag=${data.etag}` : ''}`); } return null; diff --git a/apps/meteor/client/views/admin/customEmoji/EditCustomEmojiWithData.tsx b/apps/meteor/client/views/admin/customEmoji/EditCustomEmojiWithData.tsx index b4cf80d631be2..161a007609026 100644 --- a/apps/meteor/client/views/admin/customEmoji/EditCustomEmojiWithData.tsx +++ b/apps/meteor/client/views/admin/customEmoji/EditCustomEmojiWithData.tsx @@ -4,8 +4,8 @@ import { useQuery } from '@tanstack/react-query'; import React, { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; -import { FormSkeleton } from '../../../components/Skeleton'; import EditCustomEmoji from './EditCustomEmoji'; +import { FormSkeleton } from '../../../components/Skeleton'; type EditCustomEmojiWithDataProps = { _id: string; diff --git a/apps/meteor/client/views/admin/customSounds/AddCustomSound.tsx b/apps/meteor/client/views/admin/customSounds/AddCustomSound.tsx index f109e34689a89..e9994d03ce6e3 100644 --- a/apps/meteor/client/views/admin/customSounds/AddCustomSound.tsx +++ b/apps/meteor/client/views/admin/customSounds/AddCustomSound.tsx @@ -4,9 +4,9 @@ import type { ReactElement, FormEvent } from 'react'; import React, { useState, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; +import { validate, createSoundData } from './lib'; import { ContextualbarScrollableContent, ContextualbarFooter } from '../../../components/Contextualbar'; import { useSingleFileInput } from '../../../hooks/useSingleFileInput'; -import { validate, createSoundData } from './lib'; type AddCustomSoundProps = { goToNew: (_id: string) => () => void; diff --git a/apps/meteor/client/views/admin/customSounds/CustomSoundsPage.tsx b/apps/meteor/client/views/admin/customSounds/CustomSoundsPage.tsx index fc82038125b6d..cb4d9bf3e0b2f 100644 --- a/apps/meteor/client/views/admin/customSounds/CustomSoundsPage.tsx +++ b/apps/meteor/client/views/admin/customSounds/CustomSoundsPage.tsx @@ -3,6 +3,9 @@ import { useRoute, useRouteParameter } from '@rocket.chat/ui-contexts'; import React, { useCallback, useRef } from 'react'; import { useTranslation } from 'react-i18next'; +import AddCustomSound from './AddCustomSound'; +import CustomSoundsTable from './CustomSoundsTable'; +import EditCustomSound from './EditCustomSound'; import { ContextualbarTitle, Contextualbar, @@ -11,9 +14,6 @@ import { ContextualbarDialog, } from '../../../components/Contextualbar'; import { Page, PageHeader, PageContent } from '../../../components/Page'; -import AddCustomSound from './AddCustomSound'; -import CustomSoundsTable from './CustomSoundsTable'; -import EditCustomSound from './EditCustomSound'; const CustomSoundsPage = () => { const { t } = useTranslation(); diff --git a/apps/meteor/client/views/admin/customSounds/CustomSoundsRoute.tsx b/apps/meteor/client/views/admin/customSounds/CustomSoundsRoute.tsx index 17859317917ba..1b65cb9e996f9 100644 --- a/apps/meteor/client/views/admin/customSounds/CustomSoundsRoute.tsx +++ b/apps/meteor/client/views/admin/customSounds/CustomSoundsRoute.tsx @@ -2,8 +2,8 @@ import { usePermission } from '@rocket.chat/ui-contexts'; import type { ReactElement } from 'react'; import React from 'react'; -import NotAuthorizedPage from '../../notAuthorized/NotAuthorizedPage'; import CustomSoundsPage from './CustomSoundsPage'; +import NotAuthorizedPage from '../../notAuthorized/NotAuthorizedPage'; const CustomSoundsRoute = (): ReactElement => { const canManageCustomSounds = usePermission('manage-sounds'); diff --git a/apps/meteor/client/views/admin/customSounds/CustomSoundsTable/CustomSoundsTable.tsx b/apps/meteor/client/views/admin/customSounds/CustomSoundsTable/CustomSoundsTable.tsx index 4a7151845bbe2..021bbad844b01 100644 --- a/apps/meteor/client/views/admin/customSounds/CustomSoundsTable/CustomSoundsTable.tsx +++ b/apps/meteor/client/views/admin/customSounds/CustomSoundsTable/CustomSoundsTable.tsx @@ -5,6 +5,7 @@ import { useQuery } from '@tanstack/react-query'; import type { MutableRefObject } from 'react'; import React, { useState, useMemo, useEffect } from 'react'; +import CustomSoundRow from './CustomSoundRow'; import FilterByText from '../../../../components/FilterByText'; import GenericNoResults from '../../../../components/GenericNoResults'; import { @@ -16,7 +17,6 @@ import { } from '../../../../components/GenericTable'; import { usePagination } from '../../../../components/GenericTable/hooks/usePagination'; import { useSort } from '../../../../components/GenericTable/hooks/useSort'; -import CustomSoundRow from './CustomSoundRow'; type CustomSoundsTableProps = { onClick: (soundId: string) => () => void; diff --git a/apps/meteor/client/views/admin/customSounds/EditCustomSound.tsx b/apps/meteor/client/views/admin/customSounds/EditCustomSound.tsx index 3a053c8dcb512..c69dc9e9b0f1e 100644 --- a/apps/meteor/client/views/admin/customSounds/EditCustomSound.tsx +++ b/apps/meteor/client/views/admin/customSounds/EditCustomSound.tsx @@ -4,8 +4,8 @@ import type { ReactElement } from 'react'; import React from 'react'; import { useTranslation } from 'react-i18next'; -import { FormSkeleton } from '../../../components/Skeleton'; import EditSound from './EditSound'; +import { FormSkeleton } from '../../../components/Skeleton'; type EditCustomSoundProps = { _id: string | undefined; diff --git a/apps/meteor/client/views/admin/customSounds/EditSound.tsx b/apps/meteor/client/views/admin/customSounds/EditSound.tsx index 3c0caae4cd434..b87d8df9f1942 100644 --- a/apps/meteor/client/views/admin/customSounds/EditSound.tsx +++ b/apps/meteor/client/views/admin/customSounds/EditSound.tsx @@ -4,10 +4,10 @@ import type { ReactElement, SyntheticEvent } from 'react'; import React, { useCallback, useState, useMemo, useEffect } from 'react'; import { useTranslation } from 'react-i18next'; +import { validate, createSoundData } from './lib'; import { ContextualbarScrollableContent, ContextualbarFooter } from '../../../components/Contextualbar'; import GenericModal from '../../../components/GenericModal'; import { useSingleFileInput } from '../../../hooks/useSingleFileInput'; -import { validate, createSoundData } from './lib'; type EditSoundProps = { close?: () => void; diff --git a/apps/meteor/client/views/admin/customUserStatus/CustomUserStatusFormWithData.tsx b/apps/meteor/client/views/admin/customUserStatus/CustomUserStatusFormWithData.tsx index 98f17177ef425..d86d4d39e8dcb 100644 --- a/apps/meteor/client/views/admin/customUserStatus/CustomUserStatusFormWithData.tsx +++ b/apps/meteor/client/views/admin/customUserStatus/CustomUserStatusFormWithData.tsx @@ -6,8 +6,8 @@ import type { ReactElement } from 'react'; import React, { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; -import { FormSkeleton } from '../../../components/Skeleton'; import CustomUserStatusForm from './CustomUserStatusForm'; +import { FormSkeleton } from '../../../components/Skeleton'; type CustomUserStatusFormWithDataProps = { _id?: IUserStatus['_id']; diff --git a/apps/meteor/client/views/admin/customUserStatus/CustomUserStatusRoute.tsx b/apps/meteor/client/views/admin/customUserStatus/CustomUserStatusRoute.tsx index 0734c054f8612..875f3c9e0202a 100644 --- a/apps/meteor/client/views/admin/customUserStatus/CustomUserStatusRoute.tsx +++ b/apps/meteor/client/views/admin/customUserStatus/CustomUserStatusRoute.tsx @@ -3,6 +3,10 @@ import { useRoute, useRouteParameter, usePermission, useTranslation, useSetting import type { ReactElement } from 'react'; import React, { useCallback, useRef, useEffect } from 'react'; +import CustomUserActiveConnections from './CustomUserActiveConnections'; +import CustomUserStatusFormWithData from './CustomUserStatusFormWithData'; +import CustomUserStatusService from './CustomUserStatusService'; +import CustomUserStatusTable from './CustomUserStatusTable'; import { Contextualbar, ContextualbarHeader, @@ -13,10 +17,6 @@ import { import { Page, PageHeader, PageContent } from '../../../components/Page'; import { useIsEnterprise } from '../../../hooks/useIsEnterprise'; import NotAuthorizedPage from '../../notAuthorized/NotAuthorizedPage'; -import CustomUserActiveConnections from './CustomUserActiveConnections'; -import CustomUserStatusFormWithData from './CustomUserStatusFormWithData'; -import CustomUserStatusService from './CustomUserStatusService'; -import CustomUserStatusTable from './CustomUserStatusTable'; const CustomUserStatusRoute = (): ReactElement => { const t = useTranslation(); diff --git a/apps/meteor/client/views/admin/customUserStatus/CustomUserStatusTable/CustomUserStatusTable.tsx b/apps/meteor/client/views/admin/customUserStatus/CustomUserStatusTable/CustomUserStatusTable.tsx index 2aaf852898203..72551525cf3a6 100644 --- a/apps/meteor/client/views/admin/customUserStatus/CustomUserStatusTable/CustomUserStatusTable.tsx +++ b/apps/meteor/client/views/admin/customUserStatus/CustomUserStatusTable/CustomUserStatusTable.tsx @@ -7,6 +7,7 @@ import type { ReactElement, MutableRefObject } from 'react'; import React, { useState, useMemo, useEffect } from 'react'; import { useTranslation } from 'react-i18next'; +import CustomUserStatusRow from './CustomUserStatusRow'; import FilterByText from '../../../../components/FilterByText'; import GenericNoResult from '../../../../components/GenericNoResults'; import { @@ -18,7 +19,6 @@ import { } from '../../../../components/GenericTable'; import { usePagination } from '../../../../components/GenericTable/hooks/usePagination'; import { useSort } from '../../../../components/GenericTable/hooks/useSort'; -import CustomUserStatusRow from './CustomUserStatusRow'; type CustomUserStatusProps = { reload: MutableRefObject<() => void>; diff --git a/apps/meteor/client/views/admin/deviceManagement/DeviceManagementAdminPage.tsx b/apps/meteor/client/views/admin/deviceManagement/DeviceManagementAdminPage.tsx index 7a03141fc0a02..5ecb0180cc2e8 100644 --- a/apps/meteor/client/views/admin/deviceManagement/DeviceManagementAdminPage.tsx +++ b/apps/meteor/client/views/admin/deviceManagement/DeviceManagementAdminPage.tsx @@ -3,10 +3,10 @@ import type { ReactElement } from 'react'; import React, { useRef } from 'react'; import { useTranslation } from 'react-i18next'; -import { ContextualbarDialog } from '../../../components/Contextualbar'; -import { Page, PageHeader, PageContent } from '../../../components/Page'; import DeviceManagementAdminTable from './DeviceManagementAdminTable'; import DeviceManagementInfo from './DeviceManagementInfo'; +import { ContextualbarDialog } from '../../../components/Contextualbar'; +import { Page, PageHeader, PageContent } from '../../../components/Page'; const DeviceManagementAdminPage = (): ReactElement => { const { t } = useTranslation(); diff --git a/apps/meteor/client/views/admin/deviceManagement/DeviceManagementAdminRoute.tsx b/apps/meteor/client/views/admin/deviceManagement/DeviceManagementAdminRoute.tsx index f26741512ffcb..6d7216ddf1c6c 100644 --- a/apps/meteor/client/views/admin/deviceManagement/DeviceManagementAdminRoute.tsx +++ b/apps/meteor/client/views/admin/deviceManagement/DeviceManagementAdminRoute.tsx @@ -3,13 +3,13 @@ import type { ReactElement } from 'react'; import React, { useEffect } from 'react'; import { useTranslation } from 'react-i18next'; +import DeviceManagementAdminPage from './DeviceManagementAdminPage'; import { getURL } from '../../../../app/utils/client/getURL'; import GenericUpsellModal from '../../../components/GenericUpsellModal'; import { useUpsellActions } from '../../../components/GenericUpsellModal/hooks'; import PageSkeleton from '../../../components/PageSkeleton'; import { useHasLicenseModule } from '../../../hooks/useHasLicenseModule'; import NotAuthorizedPage from '../../notAuthorized/NotAuthorizedPage'; -import DeviceManagementAdminPage from './DeviceManagementAdminPage'; const DeviceManagementAdminRoute = (): ReactElement => { const { t } = useTranslation(); diff --git a/apps/meteor/client/views/admin/deviceManagement/DeviceManagementAdminTable/DeviceManagementAdminTable.tsx b/apps/meteor/client/views/admin/deviceManagement/DeviceManagementAdminTable/DeviceManagementAdminTable.tsx index 028fa139453c1..e3ed1bc8e3aac 100644 --- a/apps/meteor/client/views/admin/deviceManagement/DeviceManagementAdminTable/DeviceManagementAdminTable.tsx +++ b/apps/meteor/client/views/admin/deviceManagement/DeviceManagementAdminTable/DeviceManagementAdminTable.tsx @@ -4,13 +4,13 @@ import type { ReactElement, MutableRefObject } from 'react'; import React, { useState, useMemo, useEffect } from 'react'; import { useTranslation } from 'react-i18next'; +import DeviceManagementAdminRow from './DeviceManagementAdminRow'; import FilterByText from '../../../../components/FilterByText'; import { GenericTableHeaderCell } from '../../../../components/GenericTable'; import { usePagination } from '../../../../components/GenericTable/hooks/usePagination'; import { useSort } from '../../../../components/GenericTable/hooks/useSort'; import DeviceManagementTable from '../../../../components/deviceManagement/DeviceManagementTable'; import { useEndpointData } from '../../../../hooks/useEndpointData'; -import DeviceManagementAdminRow from './DeviceManagementAdminRow'; const sortMapping = { client: 'device.name', diff --git a/apps/meteor/client/views/admin/deviceManagement/DeviceManagementInfo/DeviceManagementInfoWithData.tsx b/apps/meteor/client/views/admin/deviceManagement/DeviceManagementInfo/DeviceManagementInfoWithData.tsx index f884b27e0cb11..97c4f16fac61b 100644 --- a/apps/meteor/client/views/admin/deviceManagement/DeviceManagementInfo/DeviceManagementInfoWithData.tsx +++ b/apps/meteor/client/views/admin/deviceManagement/DeviceManagementInfo/DeviceManagementInfoWithData.tsx @@ -4,6 +4,7 @@ import type { ReactElement } from 'react'; import React, { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; +import DeviceManagementInfo from './DeviceManagementInfo'; import { Contextualbar, ContextualbarSkeleton, @@ -14,7 +15,6 @@ import { } from '../../../../components/Contextualbar'; import { useEndpointData } from '../../../../hooks/useEndpointData'; import { AsyncStatePhase } from '../../../../lib/asyncState'; -import DeviceManagementInfo from './DeviceManagementInfo'; const convertSessionFromAPI = ({ loginAt, diff --git a/apps/meteor/client/views/admin/emailInbox/EmailInboxFormWithData.tsx b/apps/meteor/client/views/admin/emailInbox/EmailInboxFormWithData.tsx index da6c601944e02..2f2f81c9c4e73 100644 --- a/apps/meteor/client/views/admin/emailInbox/EmailInboxFormWithData.tsx +++ b/apps/meteor/client/views/admin/emailInbox/EmailInboxFormWithData.tsx @@ -5,8 +5,8 @@ import { useQuery } from '@tanstack/react-query'; import type { ReactElement } from 'react'; import React from 'react'; -import { FormSkeleton } from '../../../components/Skeleton'; import EmailInboxForm from './EmailInboxForm'; +import { FormSkeleton } from '../../../components/Skeleton'; const EmailInboxFormWithData = ({ id }: { id: IEmailInbox['_id'] }): ReactElement => { const t = useTranslation(); diff --git a/apps/meteor/client/views/admin/emailInbox/EmailInboxPage.tsx b/apps/meteor/client/views/admin/emailInbox/EmailInboxPage.tsx index 9e341df308a78..9d953cea63a05 100644 --- a/apps/meteor/client/views/admin/emailInbox/EmailInboxPage.tsx +++ b/apps/meteor/client/views/admin/emailInbox/EmailInboxPage.tsx @@ -4,10 +4,10 @@ import type { ReactElement } from 'react'; import React from 'react'; import { useTranslation } from 'react-i18next'; -import { Page, PageHeader, PageContent } from '../../../components/Page'; import EmailInboxForm from './EmailInboxForm'; import EmailInboxFormWithData from './EmailInboxFormWithData'; import EmailInboxTable from './EmailInboxTable'; +import { Page, PageHeader, PageContent } from '../../../components/Page'; const EmailInboxPage = (): ReactElement => { const { t } = useTranslation(); diff --git a/apps/meteor/client/views/admin/emailInbox/EmailInboxRoute.tsx b/apps/meteor/client/views/admin/emailInbox/EmailInboxRoute.tsx index 7361d13b10c29..76aa229f3553a 100644 --- a/apps/meteor/client/views/admin/emailInbox/EmailInboxRoute.tsx +++ b/apps/meteor/client/views/admin/emailInbox/EmailInboxRoute.tsx @@ -2,8 +2,8 @@ import { usePermission } from '@rocket.chat/ui-contexts'; import type { ReactElement } from 'react'; import React from 'react'; -import NotAuthorizedPage from '../../notAuthorized/NotAuthorizedPage'; import EmailInboxPage from './EmailInboxPage'; +import NotAuthorizedPage from '../../notAuthorized/NotAuthorizedPage'; const EmailInboxRoute = (): ReactElement => { const canViewEmailInbox = usePermission('manage-email-inbox'); diff --git a/apps/meteor/client/views/admin/emailInbox/EmailInboxTable.tsx b/apps/meteor/client/views/admin/emailInbox/EmailInboxTable.tsx index 281eec89627fc..0990b7a30e327 100644 --- a/apps/meteor/client/views/admin/emailInbox/EmailInboxTable.tsx +++ b/apps/meteor/client/views/admin/emailInbox/EmailInboxTable.tsx @@ -4,6 +4,7 @@ import { useQuery } from '@tanstack/react-query'; import type { ReactElement } from 'react'; import React, { useMemo, useCallback } from 'react'; +import SendTestButton from './SendTestButton'; import GenericNoResults from '../../../components/GenericNoResults'; import { GenericTable, @@ -16,7 +17,6 @@ import { } from '../../../components/GenericTable'; import { usePagination } from '../../../components/GenericTable/hooks/usePagination'; import { useSort } from '../../../components/GenericTable/hooks/useSort'; -import SendTestButton from './SendTestButton'; const EmailInboxTable = (): ReactElement => { const t = useTranslation(); diff --git a/apps/meteor/client/views/admin/engagementDashboard/EngagementDashboardPage.tsx b/apps/meteor/client/views/admin/engagementDashboard/EngagementDashboardPage.tsx index 95de437462a54..c6c1864446fde 100644 --- a/apps/meteor/client/views/admin/engagementDashboard/EngagementDashboardPage.tsx +++ b/apps/meteor/client/views/admin/engagementDashboard/EngagementDashboardPage.tsx @@ -3,10 +3,10 @@ import type { ReactElement } from 'react'; import React, { useCallback, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { Page, PageHeader, PageScrollableContent } from '../../../components/Page'; import ChannelsTab from './channels/ChannelsTab'; import MessagesTab from './messages/MessagesTab'; import UsersTab from './users/UsersTab'; +import { Page, PageHeader, PageScrollableContent } from '../../../components/Page'; type EngagementDashboardPageProps = { tab: 'users' | 'messages' | 'channels'; diff --git a/apps/meteor/client/views/admin/engagementDashboard/EngagementDashboardRoute.tsx b/apps/meteor/client/views/admin/engagementDashboard/EngagementDashboardRoute.tsx index 17f6713220f99..ea5c20ca9e5bc 100644 --- a/apps/meteor/client/views/admin/engagementDashboard/EngagementDashboardRoute.tsx +++ b/apps/meteor/client/views/admin/engagementDashboard/EngagementDashboardRoute.tsx @@ -10,13 +10,13 @@ import { import type { ReactElement } from 'react'; import React, { useEffect } from 'react'; +import EngagementDashboardPage from './EngagementDashboardPage'; import { getURL } from '../../../../app/utils/client/getURL'; import GenericUpsellModal from '../../../components/GenericUpsellModal'; import { useUpsellActions } from '../../../components/GenericUpsellModal/hooks'; import PageSkeleton from '../../../components/PageSkeleton'; import { useHasLicenseModule } from '../../../hooks/useHasLicenseModule'; import NotAuthorizedPage from '../../notAuthorized/NotAuthorizedPage'; -import EngagementDashboardPage from './EngagementDashboardPage'; const isValidTab = (tab: string | undefined): tab is 'users' | 'messages' | 'channels' => typeof tab === 'string' && ['users', 'messages', 'channels'].includes(tab); diff --git a/apps/meteor/client/views/admin/engagementDashboard/messages/MessagesPerChannelSection.tsx b/apps/meteor/client/views/admin/engagementDashboard/messages/MessagesPerChannelSection.tsx index 88fad25990d06..86e7836b40d3e 100644 --- a/apps/meteor/client/views/admin/engagementDashboard/messages/MessagesPerChannelSection.tsx +++ b/apps/meteor/client/views/admin/engagementDashboard/messages/MessagesPerChannelSection.tsx @@ -18,13 +18,13 @@ import type { ReactElement } from 'react'; import React, { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; +import { useMessageOrigins } from './useMessageOrigins'; +import { useTopFivePopularChannels } from './useTopFivePopularChannels'; import DownloadDataButton from '../../../../components/dashboards/DownloadDataButton'; import PeriodSelector from '../../../../components/dashboards/PeriodSelector'; import { usePeriodSelectorState } from '../../../../components/dashboards/usePeriodSelectorState'; import EngagementDashboardCardFilter from '../EngagementDashboardCardFilter'; import LegendSymbol from '../dataView/LegendSymbol'; -import { useMessageOrigins } from './useMessageOrigins'; -import { useTopFivePopularChannels } from './useTopFivePopularChannels'; const colors = { warning: Palette.statusColor['status-font-on-warning'].toString(), diff --git a/apps/meteor/client/views/admin/engagementDashboard/users/ActiveUsersSection.tsx b/apps/meteor/client/views/admin/engagementDashboard/users/ActiveUsersSection.tsx index 7ac1b7c912898..02776ecb555ed 100644 --- a/apps/meteor/client/views/admin/engagementDashboard/users/ActiveUsersSection.tsx +++ b/apps/meteor/client/views/admin/engagementDashboard/users/ActiveUsersSection.tsx @@ -6,12 +6,12 @@ import type { ReactElement } from 'react'; import React, { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; +import { useActiveUsers } from './useActiveUsers'; import DownloadDataButton from '../../../../components/dashboards/DownloadDataButton'; import CounterSet from '../../../../components/dataView/CounterSet'; import { useFormatDate } from '../../../../hooks/useFormatDate'; import EngagementDashboardCardFilter from '../EngagementDashboardCardFilter'; import LegendSymbol from '../dataView/LegendSymbol'; -import { useActiveUsers } from './useActiveUsers'; type ActiveUsersSectionProps = { timezone: 'utc' | 'local'; diff --git a/apps/meteor/client/views/admin/featurePreview/AdminFeaturePreviewRoute.tsx b/apps/meteor/client/views/admin/featurePreview/AdminFeaturePreviewRoute.tsx index a7d6bd77d1360..3222e37a91d9b 100644 --- a/apps/meteor/client/views/admin/featurePreview/AdminFeaturePreviewRoute.tsx +++ b/apps/meteor/client/views/admin/featurePreview/AdminFeaturePreviewRoute.tsx @@ -2,10 +2,10 @@ import { usePermission } from '@rocket.chat/ui-contexts'; import type { ReactElement } from 'react'; import React, { memo } from 'react'; +import AdminFeaturePreviewPage from './AdminFeaturePreviewPage'; import SettingsProvider from '../../../providers/SettingsProvider'; import NotAuthorizedPage from '../../notAuthorized/NotAuthorizedPage'; import EditableSettingsProvider from '../settings/EditableSettingsProvider'; -import AdminFeaturePreviewPage from './AdminFeaturePreviewPage'; const AdminFeaturePreviewRoute = (): ReactElement => { const canViewFeaturesPreview = usePermission('manage-cloud'); diff --git a/apps/meteor/client/views/admin/federationDashboard/FederationDashboardPage.tsx b/apps/meteor/client/views/admin/federationDashboard/FederationDashboardPage.tsx index 14dc96283f86b..1d3bbbcfbe42e 100644 --- a/apps/meteor/client/views/admin/federationDashboard/FederationDashboardPage.tsx +++ b/apps/meteor/client/views/admin/federationDashboard/FederationDashboardPage.tsx @@ -3,9 +3,9 @@ import type { ReactElement } from 'react'; import React from 'react'; import { useTranslation } from 'react-i18next'; -import { Page, PageHeader, PageScrollableContentWithShadow } from '../../../components/Page'; import OverviewSection from './OverviewSection'; import ServersSection from './ServersSection'; +import { Page, PageHeader, PageScrollableContentWithShadow } from '../../../components/Page'; function FederationDashboardPage(): ReactElement { const { t } = useTranslation(); diff --git a/apps/meteor/client/views/admin/federationDashboard/FederationDashboardRoute.tsx b/apps/meteor/client/views/admin/federationDashboard/FederationDashboardRoute.tsx index e4a9ab4d97c32..8227a0343c723 100644 --- a/apps/meteor/client/views/admin/federationDashboard/FederationDashboardRoute.tsx +++ b/apps/meteor/client/views/admin/federationDashboard/FederationDashboardRoute.tsx @@ -1,8 +1,8 @@ import { useRole } from '@rocket.chat/ui-contexts'; import React from 'react'; -import NotAuthorizedPage from '../../notAuthorized/NotAuthorizedPage'; import FederationDashboardPage from './FederationDashboardPage'; +import NotAuthorizedPage from '../../notAuthorized/NotAuthorizedPage'; const FederationDashboardRoute = () => { const authorized = useRole('admin'); diff --git a/apps/meteor/client/views/admin/import/ImportHistoryPage.tsx b/apps/meteor/client/views/admin/import/ImportHistoryPage.tsx index 7a34705a59a0b..31db37e479687 100644 --- a/apps/meteor/client/views/admin/import/ImportHistoryPage.tsx +++ b/apps/meteor/client/views/admin/import/ImportHistoryPage.tsx @@ -4,10 +4,10 @@ import { useToastMessageDispatch, useEndpoint, useTranslation, useRouter } from import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import React, { useMemo } from 'react'; -import { ProgressStep } from '../../../../app/importer/lib/ImporterProgressStep'; -import { Page, PageHeader, PageScrollableContentWithShadow } from '../../../components/Page'; import ImportOperationSummary from './ImportOperationSummary'; import ImportOperationSummarySkeleton from './ImportOperationSummarySkeleton'; +import { ProgressStep } from '../../../../app/importer/lib/ImporterProgressStep'; +import { Page, PageHeader, PageScrollableContentWithShadow } from '../../../components/Page'; // TODO: review inner logic function ImportHistoryPage() { diff --git a/apps/meteor/client/views/admin/import/ImportProgressPage.tsx b/apps/meteor/client/views/admin/import/ImportProgressPage.tsx index 3ad95a4c6b61f..a5697f526aafe 100644 --- a/apps/meteor/client/views/admin/import/ImportProgressPage.tsx +++ b/apps/meteor/client/views/admin/import/ImportProgressPage.tsx @@ -6,10 +6,10 @@ import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import React, { useEffect } from 'react'; import { useTranslation } from 'react-i18next'; +import { useErrorHandler } from './useErrorHandler'; import { ImportingStartedStates } from '../../../../app/importer/lib/ImporterProgressStep'; import { numberFormat } from '../../../../lib/utils/stringUtils'; import { Page, PageHeader, PageScrollableContentWithShadow } from '../../../components/Page'; -import { useErrorHandler } from './useErrorHandler'; // TODO: review inner logic const ImportProgressPage = function ImportProgressPage() { diff --git a/apps/meteor/client/views/admin/import/ImportRoute.tsx b/apps/meteor/client/views/admin/import/ImportRoute.tsx index 96b5179b9ae0b..50d4cfebef317 100644 --- a/apps/meteor/client/views/admin/import/ImportRoute.tsx +++ b/apps/meteor/client/views/admin/import/ImportRoute.tsx @@ -1,11 +1,11 @@ import { usePermission } from '@rocket.chat/ui-contexts'; import React from 'react'; -import NotAuthorizedPage from '../../notAuthorized/NotAuthorizedPage'; import ImportHistoryPage from './ImportHistoryPage'; import ImportProgressPage from './ImportProgressPage'; import NewImportPage from './NewImportPage'; import PrepareImportPage from './PrepareImportPage'; +import NotAuthorizedPage from '../../notAuthorized/NotAuthorizedPage'; type ImportHistoryRouteProps = { page: 'history' | 'new' | 'prepare' | 'progress'; diff --git a/apps/meteor/client/views/admin/import/NewImportPage.tsx b/apps/meteor/client/views/admin/import/NewImportPage.tsx index 32350ee20a481..54de54e095ddb 100644 --- a/apps/meteor/client/views/admin/import/NewImportPage.tsx +++ b/apps/meteor/client/views/admin/import/NewImportPage.tsx @@ -7,9 +7,9 @@ import type { ChangeEvent, DragEvent, FormEvent, Key, SyntheticEvent } from 'rea import React, { useState, useMemo, useEffect } from 'react'; import { useTranslation } from 'react-i18next'; +import { useErrorHandler } from './useErrorHandler'; import { Page, PageHeader, PageScrollableContentWithShadow } from '../../../components/Page'; import { useFormatMemorySize } from '../../../hooks/useFormatMemorySize'; -import { useErrorHandler } from './useErrorHandler'; // TODO: review inner logic function NewImportPage() { diff --git a/apps/meteor/client/views/admin/import/PrepareImportPage.tsx b/apps/meteor/client/views/admin/import/PrepareImportPage.tsx index 5af842c4bebec..1c27cbed7b986 100644 --- a/apps/meteor/client/views/admin/import/PrepareImportPage.tsx +++ b/apps/meteor/client/views/admin/import/PrepareImportPage.tsx @@ -5,6 +5,11 @@ import type { TranslationKey } from '@rocket.chat/ui-contexts'; import { useEndpoint, useTranslation, useStream, useRouter } from '@rocket.chat/ui-contexts'; import React, { useEffect, useState, useMemo } from 'react'; +import type { ChannelDescriptor } from './ChannelDescriptor'; +import PrepareChannels from './PrepareChannels'; +import PrepareUsers from './PrepareUsers'; +import type { UserDescriptor } from './UserDescriptor'; +import { useErrorHandler } from './useErrorHandler'; import { ProgressStep, ImportWaitingStates, @@ -15,11 +20,6 @@ import { } from '../../../../app/importer/lib/ImporterProgressStep'; import { numberFormat } from '../../../../lib/utils/stringUtils'; import { Page, PageHeader, PageScrollableContentWithShadow } from '../../../components/Page'; -import type { ChannelDescriptor } from './ChannelDescriptor'; -import PrepareChannels from './PrepareChannels'; -import PrepareUsers from './PrepareUsers'; -import type { UserDescriptor } from './UserDescriptor'; -import { useErrorHandler } from './useErrorHandler'; const waitFor = (fn: () => Promise, predicate: (arg: T) => arg is U) => new Promise((resolve, reject) => { diff --git a/apps/meteor/client/views/admin/integrations/IntegrationsPage.tsx b/apps/meteor/client/views/admin/integrations/IntegrationsPage.tsx index 2035f8ed176b1..35c054109f9af 100644 --- a/apps/meteor/client/views/admin/integrations/IntegrationsPage.tsx +++ b/apps/meteor/client/views/admin/integrations/IntegrationsPage.tsx @@ -4,10 +4,10 @@ import type { ReactElement } from 'react'; import React from 'react'; import { useTranslation } from 'react-i18next'; -import { Page, PageHeader, PageContent } from '../../../components/Page'; import IntegrationsTable from './IntegrationsTable'; import NewBot from './NewBot'; import NewZapier from './NewZapier'; +import { Page, PageHeader, PageContent } from '../../../components/Page'; const IntegrationsPage = (): ReactElement => { const { t } = useTranslation(); diff --git a/apps/meteor/client/views/admin/integrations/IntegrationsRoute.tsx b/apps/meteor/client/views/admin/integrations/IntegrationsRoute.tsx index b8520f7063c18..7af9bdd55d623 100644 --- a/apps/meteor/client/views/admin/integrations/IntegrationsRoute.tsx +++ b/apps/meteor/client/views/admin/integrations/IntegrationsRoute.tsx @@ -1,10 +1,10 @@ import { useRouteParameter, useAtLeastOnePermission } from '@rocket.chat/ui-contexts'; import React, { useMemo } from 'react'; -import NotAuthorizedPage from '../../notAuthorized/NotAuthorizedPage'; import EditIntegrationsPage from './EditIntegrationsPage'; import EditIntegrationsPageWithData from './EditIntegrationsPageWithData'; import IntegrationsPage from './IntegrationsPage'; +import NotAuthorizedPage from '../../notAuthorized/NotAuthorizedPage'; import OutgoingWebhookHistoryPage from './outgoing/history/OutgoingWebhookHistoryPage'; const IntegrationsRoute = () => { diff --git a/apps/meteor/client/views/admin/integrations/IntegrationsTable.tsx b/apps/meteor/client/views/admin/integrations/IntegrationsTable.tsx index 71d0de5e1cb60..6a3e4121903a7 100644 --- a/apps/meteor/client/views/admin/integrations/IntegrationsTable.tsx +++ b/apps/meteor/client/views/admin/integrations/IntegrationsTable.tsx @@ -5,6 +5,7 @@ import { useEndpoint, useRoute, useTranslation, useLayout } from '@rocket.chat/u import { useQuery } from '@tanstack/react-query'; import React, { useMemo, useCallback, useState } from 'react'; +import IntegrationRow from './IntegrationRow'; import FilterByText from '../../../components/FilterByText'; import GenericNoResults from '../../../components/GenericNoResults'; import { @@ -16,7 +17,6 @@ import { } from '../../../components/GenericTable'; import { usePagination } from '../../../components/GenericTable/hooks/usePagination'; import { useSort } from '../../../components/GenericTable/hooks/useSort'; -import IntegrationRow from './IntegrationRow'; const IntegrationsTable = ({ type }: { type?: string }) => { const t = useTranslation(); diff --git a/apps/meteor/client/views/admin/integrations/incoming/EditIncomingWebhook.tsx b/apps/meteor/client/views/admin/integrations/incoming/EditIncomingWebhook.tsx index c14c2b19d02e5..40303e51c5f33 100644 --- a/apps/meteor/client/views/admin/integrations/incoming/EditIncomingWebhook.tsx +++ b/apps/meteor/client/views/admin/integrations/incoming/EditIncomingWebhook.tsx @@ -5,12 +5,12 @@ import { useSetModal, useTranslation, useRouter, useRouteParameter } from '@rock import React, { useCallback } from 'react'; import { FormProvider, useForm } from 'react-hook-form'; +import IncomingWebhookForm from './IncomingWebhookForm'; import GenericModal from '../../../../components/GenericModal'; import { Page, PageHeader, PageScrollableContentWithShadow, PageFooter } from '../../../../components/Page'; import { useCreateIntegration } from '../hooks/useCreateIntegration'; import { useDeleteIntegration } from '../hooks/useDeleteIntegration'; import { useUpdateIntegration } from '../hooks/useUpdateIntegration'; -import IncomingWebhookForm from './IncomingWebhookForm'; const getInitialValue = (webhookData: Serialized | undefined) => ({ enabled: webhookData?.enabled ?? true, diff --git a/apps/meteor/client/views/admin/integrations/outgoing/EditOutgoingWebhook.tsx b/apps/meteor/client/views/admin/integrations/outgoing/EditOutgoingWebhook.tsx index 1ca7d1f481cde..a9330238eee37 100644 --- a/apps/meteor/client/views/admin/integrations/outgoing/EditOutgoingWebhook.tsx +++ b/apps/meteor/client/views/admin/integrations/outgoing/EditOutgoingWebhook.tsx @@ -5,13 +5,13 @@ import { useSetModal, useTranslation, useRouter, useRouteParameter } from '@rock import React, { useCallback } from 'react'; import { FormProvider, useForm } from 'react-hook-form'; +import OutgoingWebhookForm from './OutgoingWebhookForm'; import GenericModal from '../../../../components/GenericModal'; import { Page, PageHeader, PageScrollableContentWithShadow, PageFooter } from '../../../../components/Page'; import { triggerWordsToArray, triggerWordsToString } from '../helpers/triggerWords'; import { useCreateIntegration } from '../hooks/useCreateIntegration'; import { useDeleteIntegration } from '../hooks/useDeleteIntegration'; import { useUpdateIntegration } from '../hooks/useUpdateIntegration'; -import OutgoingWebhookForm from './OutgoingWebhookForm'; const getInitialValue = (webhookData: Serialized | undefined, defaultToken: string) => ({ enabled: webhookData?.enabled ?? true, diff --git a/apps/meteor/client/views/admin/integrations/outgoing/history/OutgoingWebhookHistoryPage.tsx b/apps/meteor/client/views/admin/integrations/outgoing/history/OutgoingWebhookHistoryPage.tsx index ac05b3bf0ddd7..b5d04d9fb2d6e 100644 --- a/apps/meteor/client/views/admin/integrations/outgoing/history/OutgoingWebhookHistoryPage.tsx +++ b/apps/meteor/client/views/admin/integrations/outgoing/history/OutgoingWebhookHistoryPage.tsx @@ -4,11 +4,11 @@ import { useQuery, useQueryClient } from '@tanstack/react-query'; import type { ComponentProps } from 'react'; import React, { useMemo, useState, useEffect } from 'react'; +import HistoryContent from './HistoryContent'; import { sdk } from '../../../../../../app/utils/client/lib/SDKClient'; import { CustomScrollbars } from '../../../../../components/CustomScrollbars'; import { usePagination } from '../../../../../components/GenericTable/hooks/usePagination'; import { Page, PageHeader, PageContent } from '../../../../../components/Page'; -import HistoryContent from './HistoryContent'; const OutgoingWebhookHistoryPage = (props: ComponentProps) => { const dispatchToastMessage = useToastMessageDispatch(); diff --git a/apps/meteor/client/views/admin/invites/InvitesPage.tsx b/apps/meteor/client/views/admin/invites/InvitesPage.tsx index d8b6444ffa8b7..670446c196f94 100644 --- a/apps/meteor/client/views/admin/invites/InvitesPage.tsx +++ b/apps/meteor/client/views/admin/invites/InvitesPage.tsx @@ -5,6 +5,7 @@ import { useQuery } from '@tanstack/react-query'; import type { ReactElement } from 'react'; import React, { useMemo } from 'react'; +import InviteRow from './InviteRow'; import GenericModal from '../../../components/GenericModal'; import GenericNoResults from '../../../components/GenericNoResults'; import { @@ -15,7 +16,6 @@ import { GenericTableLoadingTable, } from '../../../components/GenericTable'; import { Page, PageHeader, PageContent } from '../../../components/Page'; -import InviteRow from './InviteRow'; const InvitesPage = (): ReactElement => { const t = useTranslation(); diff --git a/apps/meteor/client/views/admin/invites/InvitesRoute.tsx b/apps/meteor/client/views/admin/invites/InvitesRoute.tsx index cb05b33757e32..fd04e31ec09f7 100644 --- a/apps/meteor/client/views/admin/invites/InvitesRoute.tsx +++ b/apps/meteor/client/views/admin/invites/InvitesRoute.tsx @@ -2,8 +2,8 @@ import { usePermission } from '@rocket.chat/ui-contexts'; import type { ReactElement } from 'react'; import React from 'react'; -import NotAuthorizedPage from '../../notAuthorized/NotAuthorizedPage'; import InvitesPage from './InvitesPage'; +import NotAuthorizedPage from '../../notAuthorized/NotAuthorizedPage'; const InvitesRoute = (): ReactElement => { const canCreateInviteLinks = usePermission('create-invite-links'); diff --git a/apps/meteor/client/views/admin/mailer/MailerRoute.tsx b/apps/meteor/client/views/admin/mailer/MailerRoute.tsx index ab26092587539..c549fccdbe459 100644 --- a/apps/meteor/client/views/admin/mailer/MailerRoute.tsx +++ b/apps/meteor/client/views/admin/mailer/MailerRoute.tsx @@ -1,8 +1,8 @@ import { usePermission } from '@rocket.chat/ui-contexts'; import React from 'react'; -import NotAuthorizedPage from '../../notAuthorized/NotAuthorizedPage'; import MailerPage from './MailerPage'; +import NotAuthorizedPage from '../../notAuthorized/NotAuthorizedPage'; const MailerRoute = () => { const canAccessMailer = usePermission('access-mailer'); diff --git a/apps/meteor/client/views/admin/moderation/ModConsoleReportDetails.tsx b/apps/meteor/client/views/admin/moderation/ModConsoleReportDetails.tsx index 0f4460bff63a7..bde941c7719b2 100644 --- a/apps/meteor/client/views/admin/moderation/ModConsoleReportDetails.tsx +++ b/apps/meteor/client/views/admin/moderation/ModConsoleReportDetails.tsx @@ -3,9 +3,9 @@ import { Tabs, TabsItem, ContextualbarHeader, ContextualbarTitle } from '@rocket import { useTranslation, useRouter, useRouteParameter } from '@rocket.chat/ui-contexts'; import React, { useState } from 'react'; -import { Contextualbar, ContextualbarClose, ContextualbarDialog } from '../../../components/Contextualbar'; import UserMessages from './UserMessages'; import UserReportInfo from './UserReports/UserReportInfo'; +import { Contextualbar, ContextualbarClose, ContextualbarDialog } from '../../../components/Contextualbar'; type ModConsoleReportDetailsProps = { userId: IUser['_id']; diff --git a/apps/meteor/client/views/admin/moderation/ModerationConsolePage.tsx b/apps/meteor/client/views/admin/moderation/ModerationConsolePage.tsx index 56801bfe145d5..782aa97f0ffd8 100644 --- a/apps/meteor/client/views/admin/moderation/ModerationConsolePage.tsx +++ b/apps/meteor/client/views/admin/moderation/ModerationConsolePage.tsx @@ -2,11 +2,11 @@ import { Tabs, TabsItem } from '@rocket.chat/fuselage'; import { useTranslation, useRouteParameter, useToastMessageDispatch } from '@rocket.chat/ui-contexts'; import React, { useCallback } from 'react'; -import { Page, PageHeader, PageContent } from '../../../components/Page'; -import { getPermaLink } from '../../../lib/getPermaLink'; import ModConsoleReportDetails from './ModConsoleReportDetails'; import ModerationConsoleTable from './ModerationConsoleTable'; import ModConsoleUsersTable from './UserReports/ModConsoleUsersTable'; +import { Page, PageHeader, PageContent } from '../../../components/Page'; +import { getPermaLink } from '../../../lib/getPermaLink'; type TabType = 'users' | 'messages'; diff --git a/apps/meteor/client/views/admin/moderation/ModerationConsoleRoute.tsx b/apps/meteor/client/views/admin/moderation/ModerationConsoleRoute.tsx index d821c4cb90fa1..77549e5bef09a 100644 --- a/apps/meteor/client/views/admin/moderation/ModerationConsoleRoute.tsx +++ b/apps/meteor/client/views/admin/moderation/ModerationConsoleRoute.tsx @@ -1,8 +1,8 @@ import { usePermission, useRouteParameter, useRouter } from '@rocket.chat/ui-contexts'; import React, { useEffect } from 'react'; -import NotAuthorizedPage from '../../notAuthorized/NotAuthorizedPage'; import ModerationConsolePage from './ModerationConsolePage'; +import NotAuthorizedPage from '../../notAuthorized/NotAuthorizedPage'; const MODERATION_VALID_TABS = ['users', 'messages'] as const; diff --git a/apps/meteor/client/views/admin/moderation/ModerationConsoleTable.tsx b/apps/meteor/client/views/admin/moderation/ModerationConsoleTable.tsx index d009155bf58be..050cfb3efd27d 100644 --- a/apps/meteor/client/views/admin/moderation/ModerationConsoleTable.tsx +++ b/apps/meteor/client/views/admin/moderation/ModerationConsoleTable.tsx @@ -5,6 +5,8 @@ import { useQuery } from '@tanstack/react-query'; import React, { useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; +import ModerationConsoleTableRow from './ModerationConsoleTableRow'; +import ModerationFilter from './helpers/ModerationFilter'; import GenericNoResults from '../../../components/GenericNoResults'; import { GenericTable, @@ -15,8 +17,6 @@ import { } from '../../../components/GenericTable'; import { usePagination } from '../../../components/GenericTable/hooks/usePagination'; import { useSort } from '../../../components/GenericTable/hooks/useSort'; -import ModerationConsoleTableRow from './ModerationConsoleTableRow'; -import ModerationFilter from './helpers/ModerationFilter'; // TODO: Missing error state const ModerationConsoleTable = () => { diff --git a/apps/meteor/client/views/admin/moderation/ModerationConsoleTableRow.tsx b/apps/meteor/client/views/admin/moderation/ModerationConsoleTableRow.tsx index 65bf7069e074e..bb661577f9d4a 100644 --- a/apps/meteor/client/views/admin/moderation/ModerationConsoleTableRow.tsx +++ b/apps/meteor/client/views/admin/moderation/ModerationConsoleTableRow.tsx @@ -1,10 +1,10 @@ import type { IModerationAudit, IUser } from '@rocket.chat/core-typings'; import React from 'react'; -import { GenericTableCell, GenericTableRow } from '../../../components/GenericTable'; -import { useFormatDateAndTime } from '../../../hooks/useFormatDateAndTime'; import ModerationConsoleActions from './ModerationConsoleActions'; import UserColumn from './helpers/UserColumn'; +import { GenericTableCell, GenericTableRow } from '../../../components/GenericTable'; +import { useFormatDateAndTime } from '../../../hooks/useFormatDateAndTime'; export type ModerationConsoleRowProps = { report: IModerationAudit; diff --git a/apps/meteor/client/views/admin/moderation/UserMessages.tsx b/apps/meteor/client/views/admin/moderation/UserMessages.tsx index 19e351cce0dc7..c7a44ed11226f 100644 --- a/apps/meteor/client/views/admin/moderation/UserMessages.tsx +++ b/apps/meteor/client/views/admin/moderation/UserMessages.tsx @@ -5,10 +5,10 @@ import { useQuery } from '@tanstack/react-query'; import React, { Fragment } from 'react'; import { useTranslation } from 'react-i18next'; -import { ContextualbarFooter } from '../../../components/Contextualbar'; -import GenericNoResults from '../../../components/GenericNoResults'; import MessageContextFooter from './MessageContextFooter'; import ContextMessage from './helpers/ContextMessage'; +import { ContextualbarFooter } from '../../../components/Contextualbar'; +import GenericNoResults from '../../../components/GenericNoResults'; const UserMessages = ({ userId, onRedirect }: { userId: string; onRedirect: (mid: string) => void }) => { const { t } = useTranslation(); diff --git a/apps/meteor/client/views/admin/moderation/UserReports/ModConsoleUserActions.tsx b/apps/meteor/client/views/admin/moderation/UserReports/ModConsoleUserActions.tsx index 21128ff72fd3f..b9f413e4edcc4 100644 --- a/apps/meteor/client/views/admin/moderation/UserReports/ModConsoleUserActions.tsx +++ b/apps/meteor/client/views/admin/moderation/UserReports/ModConsoleUserActions.tsx @@ -2,10 +2,10 @@ import { GenericMenu } from '@rocket.chat/ui-client'; import React from 'react'; import { useTranslation } from 'react-i18next'; +import type { ModConsoleUserRowProps } from './ModConsoleUserTableRow'; import useDeactivateUserAction from '../hooks/useDeactivateUserAction'; import useDismissUserAction from '../hooks/useDismissUserAction'; import useResetAvatarAction from '../hooks/useResetAvatarAction'; -import type { ModConsoleUserRowProps } from './ModConsoleUserTableRow'; const ModConsoleUserActions = ({ report, onClick }: Omit) => { const { t } = useTranslation(); diff --git a/apps/meteor/client/views/admin/moderation/UserReports/ModConsoleUserTableRow.tsx b/apps/meteor/client/views/admin/moderation/UserReports/ModConsoleUserTableRow.tsx index b37c5330d7e04..4a8e502ba19ed 100644 --- a/apps/meteor/client/views/admin/moderation/UserReports/ModConsoleUserTableRow.tsx +++ b/apps/meteor/client/views/admin/moderation/UserReports/ModConsoleUserTableRow.tsx @@ -1,10 +1,10 @@ import type { IUser, UserReport, Serialized } from '@rocket.chat/core-typings'; import React from 'react'; +import ModConsoleUserActions from './ModConsoleUserActions'; import { GenericTableCell, GenericTableRow } from '../../../../components/GenericTable'; import { useFormatDateAndTime } from '../../../../hooks/useFormatDateAndTime'; import UserColumn from '../helpers/UserColumn'; -import ModConsoleUserActions from './ModConsoleUserActions'; export type ModConsoleUserRowProps = { report: Serialized & { count: number }>; diff --git a/apps/meteor/client/views/admin/moderation/UserReports/ModConsoleUsersTable.tsx b/apps/meteor/client/views/admin/moderation/UserReports/ModConsoleUsersTable.tsx index af3e16e56fe9b..82f9c8b7bbc62 100644 --- a/apps/meteor/client/views/admin/moderation/UserReports/ModConsoleUsersTable.tsx +++ b/apps/meteor/client/views/admin/moderation/UserReports/ModConsoleUsersTable.tsx @@ -5,6 +5,7 @@ import { useQuery } from '@tanstack/react-query'; import React, { useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; +import ModConsoleUserTableRow from './ModConsoleUserTableRow'; import GenericNoResults from '../../../../components/GenericNoResults'; import { GenericTable, @@ -16,7 +17,6 @@ import { import { usePagination } from '../../../../components/GenericTable/hooks/usePagination'; import { useSort } from '../../../../components/GenericTable/hooks/useSort'; import ModerationFilter from '../helpers/ModerationFilter'; -import ModConsoleUserTableRow from './ModConsoleUserTableRow'; const ModConsoleUsersTable = () => { const [text, setText] = useState(''); diff --git a/apps/meteor/client/views/admin/moderation/UserReports/UserReportInfo.tsx b/apps/meteor/client/views/admin/moderation/UserReports/UserReportInfo.tsx index c20b2a215aea9..625daed50359d 100644 --- a/apps/meteor/client/views/admin/moderation/UserReports/UserReportInfo.tsx +++ b/apps/meteor/client/views/admin/moderation/UserReports/UserReportInfo.tsx @@ -17,13 +17,13 @@ import { useQuery } from '@tanstack/react-query'; import React, { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; +import UserContextFooter from './UserContextFooter'; import { ContextualbarScrollableContent } from '../../../../components/Contextualbar'; import GenericNoResults from '../../../../components/GenericNoResults'; import { UserCardRole } from '../../../../components/UserCard'; import { useFormatDate } from '../../../../hooks/useFormatDate'; import ReportReason from '../helpers/ReportReason'; import UserColumn from '../helpers/UserColumn'; -import UserContextFooter from './UserContextFooter'; const UserReportInfo = ({ userId }: { userId: string }) => { const { t } = useTranslation(); diff --git a/apps/meteor/client/views/admin/moderation/helpers/ContextMessage.tsx b/apps/meteor/client/views/admin/moderation/helpers/ContextMessage.tsx index 7e8d35a325d4d..3d478755ca544 100644 --- a/apps/meteor/client/views/admin/moderation/helpers/ContextMessage.tsx +++ b/apps/meteor/client/views/admin/moderation/helpers/ContextMessage.tsx @@ -6,6 +6,7 @@ import { useSetting } from '@rocket.chat/ui-contexts'; import React from 'react'; import { useTranslation } from 'react-i18next'; +import ReportReasonCollapsible from './ReportReasonCollapsible'; import MessageContentBody from '../../../../components/message/MessageContentBody'; import Attachments from '../../../../components/message/content/Attachments'; import UiKitMessageBlock from '../../../../components/message/uikit/UiKitMessageBlock'; @@ -16,7 +17,6 @@ import { useUserDisplayName } from '../../../../hooks/useUserDisplayName'; import MessageReportInfo from '../MessageReportInfo'; import useDeleteMessage from '../hooks/useDeleteMessage'; import { useDismissMessageAction } from '../hooks/useDismissMessageAction'; -import ReportReasonCollapsible from './ReportReasonCollapsible'; const ContextMessage = ({ message, diff --git a/apps/meteor/client/views/admin/moderation/helpers/ModerationFilter.tsx b/apps/meteor/client/views/admin/moderation/helpers/ModerationFilter.tsx index 376f71d89c491..035ab6c16c139 100644 --- a/apps/meteor/client/views/admin/moderation/helpers/ModerationFilter.tsx +++ b/apps/meteor/client/views/admin/moderation/helpers/ModerationFilter.tsx @@ -1,7 +1,7 @@ import React from 'react'; -import FilterByText from '../../../../components/FilterByText'; import DateRangePicker from './DateRangePicker'; +import FilterByText from '../../../../components/FilterByText'; type ModerationFilterProps = { text: string; diff --git a/apps/meteor/client/views/admin/oauthApps/EditOauthAppWithData.tsx b/apps/meteor/client/views/admin/oauthApps/EditOauthAppWithData.tsx index e7fe18a4ef640..6803d88c00216 100644 --- a/apps/meteor/client/views/admin/oauthApps/EditOauthAppWithData.tsx +++ b/apps/meteor/client/views/admin/oauthApps/EditOauthAppWithData.tsx @@ -5,8 +5,8 @@ import type { ReactElement } from 'react'; import React, { useCallback } from 'react'; import { useTranslation } from 'react-i18next'; -import { FormSkeleton } from '../../../components/Skeleton'; import EditOauthApp from './EditOauthApp'; +import { FormSkeleton } from '../../../components/Skeleton'; const EditOauthAppWithData = ({ _id, ...props }: { _id: string }): ReactElement => { const { t } = useTranslation(); diff --git a/apps/meteor/client/views/admin/oauthApps/OAuthAppsPage.tsx b/apps/meteor/client/views/admin/oauthApps/OAuthAppsPage.tsx index cc9e174948e5c..ae7d00ae4347d 100644 --- a/apps/meteor/client/views/admin/oauthApps/OAuthAppsPage.tsx +++ b/apps/meteor/client/views/admin/oauthApps/OAuthAppsPage.tsx @@ -3,10 +3,10 @@ import { useRouteParameter, useTranslation, useRouter } from '@rocket.chat/ui-co import type { ReactElement } from 'react'; import React from 'react'; -import { Page, PageHeader, PageContent } from '../../../components/Page'; import EditOauthAppWithData from './EditOauthAppWithData'; import OAuthAddApp from './OAuthAddApp'; import OAuthAppsTable from './OAuthAppsTable'; +import { Page, PageHeader, PageContent } from '../../../components/Page'; const OAuthAppsPage = (): ReactElement => { const t = useTranslation(); diff --git a/apps/meteor/client/views/admin/oauthApps/OAuthAppsRoute.tsx b/apps/meteor/client/views/admin/oauthApps/OAuthAppsRoute.tsx index fba79bf8664f1..c9c419ba6808e 100644 --- a/apps/meteor/client/views/admin/oauthApps/OAuthAppsRoute.tsx +++ b/apps/meteor/client/views/admin/oauthApps/OAuthAppsRoute.tsx @@ -2,8 +2,8 @@ import { usePermission } from '@rocket.chat/ui-contexts'; import type { ReactElement } from 'react'; import React from 'react'; -import NotAuthorizedPage from '../../notAuthorized/NotAuthorizedPage'; import OAuthAppsPage from './OAuthAppsPage'; +import NotAuthorizedPage from '../../notAuthorized/NotAuthorizedPage'; const OAuthAppsRoute = (): ReactElement => { const canAccessOAuthApps = usePermission('manage-oauth-apps'); diff --git a/apps/meteor/client/views/admin/permissions/EditRolePage.tsx b/apps/meteor/client/views/admin/permissions/EditRolePage.tsx index b958f619ad995..c37ed2f2ee57c 100644 --- a/apps/meteor/client/views/admin/permissions/EditRolePage.tsx +++ b/apps/meteor/client/views/admin/permissions/EditRolePage.tsx @@ -7,9 +7,9 @@ import React from 'react'; import { FormProvider, useForm } from 'react-hook-form'; import { useTranslation } from 'react-i18next'; +import RoleForm from './RoleForm'; import { ContextualbarFooter, ContextualbarScrollableContent } from '../../../components/Contextualbar'; import GenericModal from '../../../components/GenericModal'; -import RoleForm from './RoleForm'; const EditRolePage = ({ role, isEnterprise }: { role?: IRole; isEnterprise: boolean }): ReactElement => { const { t } = useTranslation(); diff --git a/apps/meteor/client/views/admin/permissions/EditRolePageWithData.tsx b/apps/meteor/client/views/admin/permissions/EditRolePageWithData.tsx index d139118c550fd..7f96aa148990b 100644 --- a/apps/meteor/client/views/admin/permissions/EditRolePageWithData.tsx +++ b/apps/meteor/client/views/admin/permissions/EditRolePageWithData.tsx @@ -5,10 +5,10 @@ import type { ReactElement } from 'react'; import React from 'react'; import { useTranslation } from 'react-i18next'; -import PageSkeleton from '../../../components/PageSkeleton'; -import { useHasLicenseModule } from '../../../hooks/useHasLicenseModule'; import EditRolePage from './EditRolePage'; import { useRole } from './hooks/useRole'; +import PageSkeleton from '../../../components/PageSkeleton'; +import { useHasLicenseModule } from '../../../hooks/useHasLicenseModule'; const EditRolePageWithData = ({ roleId }: { roleId?: IRole['_id'] }): ReactElement => { const { t } = useTranslation(); diff --git a/apps/meteor/client/views/admin/permissions/PermissionsContextBar.tsx b/apps/meteor/client/views/admin/permissions/PermissionsContextBar.tsx index 3b8bea6097e4b..a386fbda7fda7 100644 --- a/apps/meteor/client/views/admin/permissions/PermissionsContextBar.tsx +++ b/apps/meteor/client/views/admin/permissions/PermissionsContextBar.tsx @@ -3,6 +3,8 @@ import { useRouteParameter, useRoute, useTranslation, useSetModal } from '@rocke import type { ReactElement } from 'react'; import React, { useEffect } from 'react'; +import CustomRoleUpsellModal from './CustomRoleUpsellModal'; +import EditRolePageWithData from './EditRolePageWithData'; import { Contextualbar, ContextualbarHeader, @@ -11,8 +13,6 @@ import { ContextualbarDialog, } from '../../../components/Contextualbar'; import { useHasLicenseModule } from '../../../hooks/useHasLicenseModule'; -import CustomRoleUpsellModal from './CustomRoleUpsellModal'; -import EditRolePageWithData from './EditRolePageWithData'; const PermissionsContextBar = (): ReactElement | null => { const t = useTranslation(); diff --git a/apps/meteor/client/views/admin/permissions/PermissionsRouter.tsx b/apps/meteor/client/views/admin/permissions/PermissionsRouter.tsx index 31ab597df9134..ddaff27eff567 100644 --- a/apps/meteor/client/views/admin/permissions/PermissionsRouter.tsx +++ b/apps/meteor/client/views/admin/permissions/PermissionsRouter.tsx @@ -2,11 +2,11 @@ import { useRouteParameter, usePermission } from '@rocket.chat/ui-contexts'; import type { ReactElement } from 'react'; import React from 'react'; +import PermissionsTable from './PermissionsTable'; +import UsersInRole from './UsersInRole'; import PageSkeleton from '../../../components/PageSkeleton'; import { useIsEnterprise } from '../../../hooks/useIsEnterprise'; import NotAuthorizedPage from '../../notAuthorized/NotAuthorizedPage'; -import PermissionsTable from './PermissionsTable'; -import UsersInRole from './UsersInRole'; const PermissionsRouter = (): ReactElement => { const canViewPermission = usePermission('access-permissions'); diff --git a/apps/meteor/client/views/admin/permissions/PermissionsTable/PermissionRow.tsx b/apps/meteor/client/views/admin/permissions/PermissionsTable/PermissionRow.tsx index 7ddd6ca9ab45a..72d9d2bf41348 100644 --- a/apps/meteor/client/views/admin/permissions/PermissionsTable/PermissionRow.tsx +++ b/apps/meteor/client/views/admin/permissions/PermissionsTable/PermissionRow.tsx @@ -6,10 +6,10 @@ import type { ReactElement } from 'react'; import React, { useState, memo } from 'react'; import { useTranslation } from 'react-i18next'; +import RoleCell from './RoleCell'; import { CONSTANTS } from '../../../../../app/authorization/lib'; import { GenericTableRow, GenericTableCell } from '../../../../components/GenericTable'; import { useChangeRole } from '../hooks/useChangeRole'; -import RoleCell from './RoleCell'; const getName = (t: TFunction, permission: IPermission): string => { if (permission.level === CONSTANTS.SETTINGS_LEVEL) { diff --git a/apps/meteor/client/views/admin/permissions/PermissionsTable/PermissionsTable.tsx b/apps/meteor/client/views/admin/permissions/PermissionsTable/PermissionsTable.tsx index 583f9d2372527..b70867e86e8d0 100644 --- a/apps/meteor/client/views/admin/permissions/PermissionsTable/PermissionsTable.tsx +++ b/apps/meteor/client/views/admin/permissions/PermissionsTable/PermissionsTable.tsx @@ -5,6 +5,9 @@ import { useRoute, usePermission, useMethod, useTranslation, useSetModal } from import type { ReactElement } from 'react'; import React, { useState } from 'react'; +import PermissionRow from './PermissionRow'; +import PermissionsTableFilter from './PermissionsTableFilter'; +import RoleHeader from './RoleHeader'; import GenericNoResults from '../../../../components/GenericNoResults'; import { GenericTable, GenericTableHeader, GenericTableHeaderCell, GenericTableBody } from '../../../../components/GenericTable'; import { usePagination } from '../../../../components/GenericTable/hooks/usePagination'; @@ -12,9 +15,6 @@ import { Page, PageHeader, PageContent } from '../../../../components/Page'; import CustomRoleUpsellModal from '../CustomRoleUpsellModal'; import PermissionsContextBar from '../PermissionsContextBar'; import { usePermissionsAndRoles } from '../hooks/usePermissionsAndRoles'; -import PermissionRow from './PermissionRow'; -import PermissionsTableFilter from './PermissionsTableFilter'; -import RoleHeader from './RoleHeader'; const PermissionsTable = ({ isEnterprise }: { isEnterprise: boolean }): ReactElement => { const t = useTranslation(); diff --git a/apps/meteor/client/views/admin/permissions/UsersInRole/UsersInRolePage.tsx b/apps/meteor/client/views/admin/permissions/UsersInRole/UsersInRolePage.tsx index 3e3c6988e6cf4..5aa29e46f14d4 100644 --- a/apps/meteor/client/views/admin/permissions/UsersInRole/UsersInRolePage.tsx +++ b/apps/meteor/client/views/admin/permissions/UsersInRole/UsersInRolePage.tsx @@ -7,10 +7,10 @@ import type { ReactElement } from 'react'; import React from 'react'; import { useForm, Controller } from 'react-hook-form'; +import UsersInRoleTable from './UsersInRoleTable'; import { Page, PageHeader, PageContent } from '../../../../components/Page'; import RoomAutoComplete from '../../../../components/RoomAutoComplete'; import UserAutoCompleteMultiple from '../../../../components/UserAutoCompleteMultiple'; -import UsersInRoleTable from './UsersInRoleTable'; type UsersInRolePayload = { rid?: IRoom['_id']; diff --git a/apps/meteor/client/views/admin/permissions/UsersInRole/UsersInRolePageWithData.tsx b/apps/meteor/client/views/admin/permissions/UsersInRole/UsersInRolePageWithData.tsx index 8639c2407a6eb..4cf421ac19a19 100644 --- a/apps/meteor/client/views/admin/permissions/UsersInRole/UsersInRolePageWithData.tsx +++ b/apps/meteor/client/views/admin/permissions/UsersInRole/UsersInRolePageWithData.tsx @@ -2,8 +2,8 @@ import { useRouteParameter } from '@rocket.chat/ui-contexts'; import type { ReactElement } from 'react'; import React from 'react'; -import { useRole } from '../hooks/useRole'; import UsersInRolePage from './UsersInRolePage'; +import { useRole } from '../hooks/useRole'; const UsersInRolePageWithData = (): ReactElement | null => { const _id = useRouteParameter('_id'); diff --git a/apps/meteor/client/views/admin/permissions/UsersInRole/UsersInRoleTable/UsersInRoleTable.tsx b/apps/meteor/client/views/admin/permissions/UsersInRole/UsersInRoleTable/UsersInRoleTable.tsx index b22792957d37b..e5a815747f1ae 100644 --- a/apps/meteor/client/views/admin/permissions/UsersInRole/UsersInRoleTable/UsersInRoleTable.tsx +++ b/apps/meteor/client/views/admin/permissions/UsersInRole/UsersInRoleTable/UsersInRoleTable.tsx @@ -7,6 +7,7 @@ import type { ReactElement } from 'react'; import React, { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; +import UsersInRoleTableRow from './UsersInRoleTableRow'; import GenericError from '../../../../../components/GenericError'; import GenericModal from '../../../../../components/GenericModal'; import GenericNoResults from '../../../../../components/GenericNoResults'; @@ -18,7 +19,6 @@ import { GenericTableLoadingTable, } from '../../../../../components/GenericTable'; import { usePagination } from '../../../../../components/GenericTable/hooks/usePagination'; -import UsersInRoleTableRow from './UsersInRoleTableRow'; type UsersInRoleTableProps = { roleName: IRole['name']; diff --git a/apps/meteor/client/views/admin/permissions/hooks/usePermissionsAndRoles.ts b/apps/meteor/client/views/admin/permissions/hooks/usePermissionsAndRoles.ts index b97863206b133..2b9ea2b8b4785 100644 --- a/apps/meteor/client/views/admin/permissions/hooks/usePermissionsAndRoles.ts +++ b/apps/meteor/client/views/admin/permissions/hooks/usePermissionsAndRoles.ts @@ -5,7 +5,7 @@ import type { Mongo } from 'meteor/mongo'; import { useCallback } from 'react'; import { CONSTANTS } from '../../../../../app/authorization/lib'; -import { ChatPermissions, Roles } from '../../../../../app/models/client'; +import { Permissions, Roles } from '../../../../../app/models/client'; import { useReactiveValue } from '../../../../hooks/useReactiveValue'; export const usePermissionsAndRoles = ( @@ -25,7 +25,7 @@ export const usePermissionsAndRoles = ( const getPermissions = useCallback( () => - ChatPermissions.find(getFilter(), { + Permissions.find(getFilter(), { sort: { _id: 1, }, @@ -34,7 +34,7 @@ export const usePermissionsAndRoles = ( }), [limit, skip, getFilter], ); - const getTotalPermissions = useCallback(() => ChatPermissions.find(getFilter()).count(), [getFilter]); + const getTotalPermissions = useCallback(() => Permissions.find(getFilter()).count(), [getFilter]); const permissions = useReactiveValue(getPermissions); const permissionsTotal = useReactiveValue(getTotalPermissions); diff --git a/apps/meteor/client/views/admin/rooms/EditRoom.tsx b/apps/meteor/client/views/admin/rooms/EditRoom.tsx index 4e1af52ac3333..ff28f2460be48 100644 --- a/apps/meteor/client/views/admin/rooms/EditRoom.tsx +++ b/apps/meteor/client/views/admin/rooms/EditRoom.tsx @@ -19,13 +19,13 @@ import React from 'react'; import { useForm, Controller } from 'react-hook-form'; import { useTranslation } from 'react-i18next'; +import { useEditAdminRoomPermissions } from './useEditAdminRoomPermissions'; import { ContextualbarScrollableContent, ContextualbarFooter } from '../../../components/Contextualbar'; import RoomAvatarEditor from '../../../components/avatar/RoomAvatarEditor'; import { getDirtyFields } from '../../../lib/getDirtyFields'; import { roomCoordinator } from '../../../lib/rooms/roomCoordinator'; import { useArchiveRoom } from '../../hooks/roomActions/useArchiveRoom'; import { useDeleteRoom } from '../../hooks/roomActions/useDeleteRoom'; -import { useEditAdminRoomPermissions } from './useEditAdminRoomPermissions'; type EditRoomProps = { room: IRoom; diff --git a/apps/meteor/client/views/admin/rooms/EditRoomWithData.tsx b/apps/meteor/client/views/admin/rooms/EditRoomWithData.tsx index 7e0f4ec06b683..9d3eb234c3aa3 100644 --- a/apps/meteor/client/views/admin/rooms/EditRoomWithData.tsx +++ b/apps/meteor/client/views/admin/rooms/EditRoomWithData.tsx @@ -4,6 +4,7 @@ import { useQuery } from '@tanstack/react-query'; import React from 'react'; import { useTranslation } from 'react-i18next'; +import EditRoom from './EditRoom'; import { Contextualbar, ContextualbarHeader, @@ -11,7 +12,6 @@ import { ContextualbarClose, ContextualbarSkeleton, } from '../../../components/Contextualbar'; -import EditRoom from './EditRoom'; type EditRoomWithDataProps = { rid?: IRoom['_id']; onReload: () => void }; diff --git a/apps/meteor/client/views/admin/rooms/RoomsPage.tsx b/apps/meteor/client/views/admin/rooms/RoomsPage.tsx index 3fadd621b01fa..35ef4b651b5f6 100644 --- a/apps/meteor/client/views/admin/rooms/RoomsPage.tsx +++ b/apps/meteor/client/views/admin/rooms/RoomsPage.tsx @@ -3,10 +3,10 @@ import type { ReactElement } from 'react'; import React, { useRef } from 'react'; import { useTranslation } from 'react-i18next'; -import { ContextualbarDialog } from '../../../components/Contextualbar'; -import { Page, PageHeader, PageContent } from '../../../components/Page'; import EditRoomWithData from './EditRoomWithData'; import RoomsTable from './RoomsTable'; +import { ContextualbarDialog } from '../../../components/Contextualbar'; +import { Page, PageHeader, PageContent } from '../../../components/Page'; const RoomsPage = (): ReactElement => { const { t } = useTranslation(); diff --git a/apps/meteor/client/views/admin/rooms/RoomsRoute.tsx b/apps/meteor/client/views/admin/rooms/RoomsRoute.tsx index bda14931282dd..9140d816fd7e8 100644 --- a/apps/meteor/client/views/admin/rooms/RoomsRoute.tsx +++ b/apps/meteor/client/views/admin/rooms/RoomsRoute.tsx @@ -2,8 +2,8 @@ import { usePermission } from '@rocket.chat/ui-contexts'; import type { ReactElement } from 'react'; import React from 'react'; -import NotAuthorizedPage from '../../notAuthorized/NotAuthorizedPage'; import RoomsPage from './RoomsPage'; +import NotAuthorizedPage from '../../notAuthorized/NotAuthorizedPage'; const RoomsRoute = (): ReactElement => { const canViewRoomAdministration = usePermission('view-room-administration'); diff --git a/apps/meteor/client/views/admin/rooms/RoomsTable.tsx b/apps/meteor/client/views/admin/rooms/RoomsTable.tsx index 0d34198bb7271..8279c454f6132 100644 --- a/apps/meteor/client/views/admin/rooms/RoomsTable.tsx +++ b/apps/meteor/client/views/admin/rooms/RoomsTable.tsx @@ -7,6 +7,8 @@ import type { ReactElement, MutableRefObject } from 'react'; import React, { useRef, useState, useEffect, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; +import RoomRow from './RoomRow'; +import RoomsTableFilters from './RoomsTableFilters'; import GenericNoResults from '../../../components/GenericNoResults'; import { GenericTable, @@ -17,8 +19,6 @@ import { } from '../../../components/GenericTable'; import { usePagination } from '../../../components/GenericTable/hooks/usePagination'; import { useSort } from '../../../components/GenericTable/hooks/useSort'; -import RoomRow from './RoomRow'; -import RoomsTableFilters from './RoomsTableFilters'; type RoomFilters = { searchText: string; diff --git a/apps/meteor/client/views/admin/settings/Setting/Setting.stories.tsx b/apps/meteor/client/views/admin/settings/Setting/Setting.stories.tsx index 4e2534356b229..7705c223491ac 100644 --- a/apps/meteor/client/views/admin/settings/Setting/Setting.stories.tsx +++ b/apps/meteor/client/views/admin/settings/Setting/Setting.stories.tsx @@ -17,7 +17,7 @@ export default { }, decorators: [ (fn) => ( -
+
{fn()}
), diff --git a/apps/meteor/client/views/admin/settings/Setting/Setting.tsx b/apps/meteor/client/views/admin/settings/Setting/Setting.tsx index 19f8ddfd781dc..9e74f2e36b751 100644 --- a/apps/meteor/client/views/admin/settings/Setting/Setting.tsx +++ b/apps/meteor/client/views/admin/settings/Setting/Setting.tsx @@ -7,9 +7,9 @@ import type { ReactElement } from 'react'; import React, { useEffect, useMemo, useState, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; +import MemoizedSetting from './MemoizedSetting'; import MarkdownText from '../../../../components/MarkdownText'; import { useEditableSetting, useEditableSettingsDispatch, useIsEnterprise } from '../../EditableSettingsContext'; -import MemoizedSetting from './MemoizedSetting'; type SettingProps = { className?: string; diff --git a/apps/meteor/client/views/admin/settings/Setting/inputs/AssetSettingInput.stories.tsx b/apps/meteor/client/views/admin/settings/Setting/inputs/AssetSettingInput.stories.tsx index 3cc7d22527560..231d3d1a42b31 100644 --- a/apps/meteor/client/views/admin/settings/Setting/inputs/AssetSettingInput.stories.tsx +++ b/apps/meteor/client/views/admin/settings/Setting/inputs/AssetSettingInput.stories.tsx @@ -9,7 +9,7 @@ export default { component: AssetSettingInput, decorators: [ (fn) => ( -
+
{fn()}
diff --git a/apps/meteor/client/views/admin/settings/Setting/inputs/AssetSettingInput.styles.css b/apps/meteor/client/views/admin/settings/Setting/inputs/AssetSettingInput.styles.css index 6bbaf26e1687b..7a8cd64f19f20 100644 --- a/apps/meteor/client/views/admin/settings/Setting/inputs/AssetSettingInput.styles.css +++ b/apps/meteor/client/views/admin/settings/Setting/inputs/AssetSettingInput.styles.css @@ -1,13 +1,12 @@ -.AssetSettingInput__input { - position: absolute !important; - z-index: 10000; - top: 0; - left: 0; - - width: 100%; - height: 100%; - - cursor: pointer; - - opacity: 0; +.asset-setting-input { + &__input { + position: absolute !important; + z-index: 10000; + top: 0; + left: 0; + width: 100%; + height: 100%; + cursor: pointer; + opacity: 0; + } } diff --git a/apps/meteor/client/views/admin/settings/Setting/inputs/AssetSettingInput.tsx b/apps/meteor/client/views/admin/settings/Setting/inputs/AssetSettingInput.tsx index 14ba6f27b4c53..39604cd1146ea 100644 --- a/apps/meteor/client/views/admin/settings/Setting/inputs/AssetSettingInput.tsx +++ b/apps/meteor/client/views/admin/settings/Setting/inputs/AssetSettingInput.tsx @@ -82,7 +82,7 @@ function AssetSettingInput({ _id, label, value, asset, required, disabled, fileC {t('Select_file')} ( -
+
{fn()}
), diff --git a/apps/meteor/client/views/admin/settings/Setting/inputs/TimespanSettingInput.spec.tsx b/apps/meteor/client/views/admin/settings/Setting/inputs/TimespanSettingInput.spec.tsx index e16bbd18a6aa2..508b55c062423 100644 --- a/apps/meteor/client/views/admin/settings/Setting/inputs/TimespanSettingInput.spec.tsx +++ b/apps/meteor/client/views/admin/settings/Setting/inputs/TimespanSettingInput.spec.tsx @@ -3,8 +3,8 @@ import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import React from 'react'; -import { TIMEUNIT } from '../../../../../lib/convertTimeUnit'; import { default as TimespanSettingInput, getHighestTimeUnit } from './TimespanSettingInput'; +import { TIMEUNIT } from '../../../../../lib/convertTimeUnit'; global.ResizeObserver = jest.fn().mockImplementation(() => ({ observe: jest.fn(), diff --git a/apps/meteor/client/views/admin/settings/SettingsPage.tsx b/apps/meteor/client/views/admin/settings/SettingsPage.tsx index 3b1e7a35e79ca..c079185e7e928 100644 --- a/apps/meteor/client/views/admin/settings/SettingsPage.tsx +++ b/apps/meteor/client/views/admin/settings/SettingsPage.tsx @@ -6,11 +6,11 @@ import type { ReactElement } from 'react'; import React, { useCallback, useState } from 'react'; import { useTranslation } from 'react-i18next'; +import SettingsGroupCard from './SettingsGroupCard'; +import { useSettingsGroups } from './hooks/useSettingsGroups'; import GenericNoResults from '../../../components/GenericNoResults'; import { Page, PageHeader, PageScrollableContentWithShadow } from '../../../components/Page'; import PageBlockWithBorder from '../../../components/Page/PageBlockWithBorder'; -import SettingsGroupCard from './SettingsGroupCard'; -import { useSettingsGroups } from './hooks/useSettingsGroups'; const SettingsPage = (): ReactElement => { const { t } = useTranslation(); diff --git a/apps/meteor/client/views/admin/settings/SettingsRoute.tsx b/apps/meteor/client/views/admin/settings/SettingsRoute.tsx index 0db9d336a02aa..590276f65ba1c 100644 --- a/apps/meteor/client/views/admin/settings/SettingsRoute.tsx +++ b/apps/meteor/client/views/admin/settings/SettingsRoute.tsx @@ -2,10 +2,10 @@ import { useRouteParameter, useIsPrivilegedSettingsContext, useRouter } from '@r import type { ReactElement } from 'react'; import React from 'react'; -import NotAuthorizedPage from '../../notAuthorized/NotAuthorizedPage'; import EditableSettingsProvider from './EditableSettingsProvider'; import SettingsGroupSelector from './SettingsGroupSelector'; import SettingsPage from './SettingsPage'; +import NotAuthorizedPage from '../../notAuthorized/NotAuthorizedPage'; const omittedSettings = ['Cloud_Workspace_AirGapped_Restrictions_Remaining_Days']; diff --git a/apps/meteor/client/views/admin/settings/groups/BaseGroupPage.tsx b/apps/meteor/client/views/admin/settings/groups/BaseGroupPage.tsx index 2b2a35b00a63c..652759da7ffba 100644 --- a/apps/meteor/client/views/admin/settings/groups/BaseGroupPage.tsx +++ b/apps/meteor/client/views/admin/settings/groups/BaseGroupPage.tsx @@ -1,9 +1,9 @@ import type { ReactElement } from 'react'; import React from 'react'; -import { useEditableSettingsGroupSections, useEditableSettingsGroupTabs } from '../../EditableSettingsContext'; import GenericGroupPage from './GenericGroupPage'; import TabbedGroupPage from './TabbedGroupPage'; +import { useEditableSettingsGroupSections, useEditableSettingsGroupTabs } from '../../EditableSettingsContext'; type BaseGroupPageProps = { _id: string; diff --git a/apps/meteor/client/views/admin/settings/groups/LDAPGroupPage.tsx b/apps/meteor/client/views/admin/settings/groups/LDAPGroupPage.tsx index 687047b9f6108..03ab25a2c2f95 100644 --- a/apps/meteor/client/views/admin/settings/groups/LDAPGroupPage.tsx +++ b/apps/meteor/client/views/admin/settings/groups/LDAPGroupPage.tsx @@ -6,10 +6,10 @@ import type { FormEvent } from 'react'; import React, { memo, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; +import BaseGroupPage from './BaseGroupPage'; import GenericModal from '../../../../components/GenericModal'; import { useExternalLink } from '../../../../hooks/useExternalLink'; import { useEditableSettings } from '../../EditableSettingsContext'; -import BaseGroupPage from './BaseGroupPage'; type LDAPGroupPageProps = ISetting & { onClickBack?: () => void; diff --git a/apps/meteor/client/views/admin/settings/groups/OAuthGroupPage/OAuthGroupPage.tsx b/apps/meteor/client/views/admin/settings/groups/OAuthGroupPage/OAuthGroupPage.tsx index a858555e46d30..ce5c54d36d7ea 100644 --- a/apps/meteor/client/views/admin/settings/groups/OAuthGroupPage/OAuthGroupPage.tsx +++ b/apps/meteor/client/views/admin/settings/groups/OAuthGroupPage/OAuthGroupPage.tsx @@ -5,12 +5,12 @@ import { useToastMessageDispatch, useAbsoluteUrl, useMethod, useTranslation, use import type { ReactElement } from 'react'; import React, { memo, useEffect, useState } from 'react'; +import CreateOAuthModal from './CreateOAuthModal'; import { strRight } from '../../../../../../lib/utils/stringUtils'; import GenericModal from '../../../../../components/GenericModal'; import { useEditableSettingsGroupSections } from '../../../EditableSettingsContext'; import SettingsGroupPage from '../../SettingsGroupPage'; import SettingsSection from '../../SettingsSection'; -import CreateOAuthModal from './CreateOAuthModal'; type OAuthGroupPageProps = ISetting & { onClickBack?: () => void; diff --git a/apps/meteor/client/views/admin/settings/groups/TabbedGroupPage.tsx b/apps/meteor/client/views/admin/settings/groups/TabbedGroupPage.tsx index 1a3c122502cff..a4917c158816c 100644 --- a/apps/meteor/client/views/admin/settings/groups/TabbedGroupPage.tsx +++ b/apps/meteor/client/views/admin/settings/groups/TabbedGroupPage.tsx @@ -4,8 +4,8 @@ import type { ReactElement } from 'react'; import React, { memo, useState, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; -import { useEditableSettingsGroupSections } from '../../EditableSettingsContext'; import GenericGroupPage from './GenericGroupPage'; +import { useEditableSettingsGroupSections } from '../../EditableSettingsContext'; type TabbedGroupPageProps = { headerButtons?: ReactElement; diff --git a/apps/meteor/client/views/admin/settings/groups/VoipGroupPage/AssignAgentButton.tsx b/apps/meteor/client/views/admin/settings/groups/VoipGroupPage/AssignAgentButton.tsx index 8b1438ade77d9..fe357b31cdb08 100644 --- a/apps/meteor/client/views/admin/settings/groups/VoipGroupPage/AssignAgentButton.tsx +++ b/apps/meteor/client/views/admin/settings/groups/VoipGroupPage/AssignAgentButton.tsx @@ -4,8 +4,8 @@ import { useSetModal } from '@rocket.chat/ui-contexts'; import React from 'react'; import { useTranslation } from 'react-i18next'; -import { GenericTableCell } from '../../../../../components/GenericTable'; import AssignAgentModal from './AssignAgentModal'; +import { GenericTableCell } from '../../../../../components/GenericTable'; type AssignAgentButtonProps = { extension: string; reload: () => void }; diff --git a/apps/meteor/client/views/admin/settings/groups/VoipGroupPage/VoipExtensionsPage.tsx b/apps/meteor/client/views/admin/settings/groups/VoipGroupPage/VoipExtensionsPage.tsx index 7494a249818cb..c7b3a4cff3873 100644 --- a/apps/meteor/client/views/admin/settings/groups/VoipGroupPage/VoipExtensionsPage.tsx +++ b/apps/meteor/client/views/admin/settings/groups/VoipGroupPage/VoipExtensionsPage.tsx @@ -4,6 +4,9 @@ import { useSetModal, useTranslation, useEndpoint } from '@rocket.chat/ui-contex import { useQuery } from '@tanstack/react-query'; import React, { useMemo } from 'react'; +import AssignAgentButton from './AssignAgentButton'; +import AssignAgentModal from './AssignAgentModal'; +import RemoveAgentButton from './RemoveAgentButton'; import GenericNoResults from '../../../../../components/GenericNoResults'; import { GenericTable, @@ -16,9 +19,6 @@ import { } from '../../../../../components/GenericTable'; import { usePagination } from '../../../../../components/GenericTable/hooks/usePagination'; import { PageContent } from '../../../../../components/Page'; -import AssignAgentButton from './AssignAgentButton'; -import AssignAgentModal from './AssignAgentModal'; -import RemoveAgentButton from './RemoveAgentButton'; const VoipExtensionsPage = () => { const t = useTranslation(); diff --git a/apps/meteor/client/views/admin/settings/groups/VoipGroupPage/VoipGroupPage.tsx b/apps/meteor/client/views/admin/settings/groups/VoipGroupPage/VoipGroupPage.tsx index a3cf978cfde31..249bdab996166 100644 --- a/apps/meteor/client/views/admin/settings/groups/VoipGroupPage/VoipGroupPage.tsx +++ b/apps/meteor/client/views/admin/settings/groups/VoipGroupPage/VoipGroupPage.tsx @@ -5,12 +5,12 @@ import { useSetting } from '@rocket.chat/ui-contexts'; import React, { memo, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; +import VoipExtensionsPage from './VoipExtensionsPage'; import GenericNoResults from '../../../../../components/GenericNoResults'; import { PageScrollableContentWithShadow } from '../../../../../components/Page'; import { useEditableSettingsGroupSections } from '../../../EditableSettingsContext'; import SettingsGroupPage from '../../SettingsGroupPage'; import SettingsSection from '../../SettingsSection'; -import VoipExtensionsPage from './VoipExtensionsPage'; type VoipGroupPageProps = ISetting & { onClickBack?: () => void; diff --git a/apps/meteor/client/views/admin/sidebar/AdminSidebar.tsx b/apps/meteor/client/views/admin/sidebar/AdminSidebar.tsx index c0c4aa08cfb4a..820033c6c53a8 100644 --- a/apps/meteor/client/views/admin/sidebar/AdminSidebar.tsx +++ b/apps/meteor/client/views/admin/sidebar/AdminSidebar.tsx @@ -1,10 +1,10 @@ import { useTranslation, useLayout, useCurrentRoutePath } from '@rocket.chat/ui-contexts'; import React, { memo } from 'react'; +import AdminSidebarPages from './AdminSidebarPages'; import PlanTag from '../../../components/PlanTag'; import Sidebar from '../../../components/Sidebar'; import SettingsProvider from '../../../providers/SettingsProvider'; -import AdminSidebarPages from './AdminSidebarPages'; const AdminSidebar = () => { const t = useTranslation(); diff --git a/apps/meteor/client/views/admin/subscription/SubscriptionCalloutLimits.tsx b/apps/meteor/client/views/admin/subscription/SubscriptionCalloutLimits.tsx index c5de629e55828..98413c837720b 100644 --- a/apps/meteor/client/views/admin/subscription/SubscriptionCalloutLimits.tsx +++ b/apps/meteor/client/views/admin/subscription/SubscriptionCalloutLimits.tsx @@ -4,8 +4,8 @@ import { ExternalLink } from '@rocket.chat/ui-client'; import React from 'react'; import { Trans, useTranslation } from 'react-i18next'; -import { useLicenseLimitsByBehavior } from '../../../hooks/useLicenseLimitsByBehavior'; import { useCheckoutUrl } from './hooks/useCheckoutUrl'; +import { useLicenseLimitsByBehavior } from '../../../hooks/useLicenseLimitsByBehavior'; export const SubscriptionCalloutLimits = () => { const manageSubscriptionUrl = useCheckoutUrl(); diff --git a/apps/meteor/client/views/admin/subscription/SubscriptionPage.tsx b/apps/meteor/client/views/admin/subscription/SubscriptionPage.tsx index 0c3fe858b4433..aaf4f984c89e4 100644 --- a/apps/meteor/client/views/admin/subscription/SubscriptionPage.tsx +++ b/apps/meteor/client/views/admin/subscription/SubscriptionPage.tsx @@ -5,12 +5,6 @@ import { t } from 'i18next'; import React, { memo, useCallback, useEffect } from 'react'; import tinykeys from 'tinykeys'; -import { Page, PageScrollableContentWithShadow } from '../../../components/Page'; -import PageBlockWithBorder from '../../../components/Page/PageBlockWithBorder'; -import PageHeaderNoShadow from '../../../components/Page/PageHeaderNoShadow'; -import { useIsEnterprise } from '../../../hooks/useIsEnterprise'; -import { useInvalidateLicense, useLicenseWithCloudAnnouncement } from '../../../hooks/useLicense'; -import { useRegistrationStatus } from '../../../hooks/useRegistrationStatus'; import { SubscriptionCalloutLimits } from './SubscriptionCalloutLimits'; import SubscriptionPageSkeleton from './SubscriptionPageSkeleton'; import UpgradeButton from './components/UpgradeButton'; @@ -25,9 +19,15 @@ import MACCard from './components/cards/MACCard'; import PlanCard from './components/cards/PlanCard'; import PlanCardCommunity from './components/cards/PlanCard/PlanCardCommunity'; import SeatsCard from './components/cards/SeatsCard'; -import { useRemoveLicense } from './hooks/useRemoveLicense'; +import { useCancelSubscriptionModal } from './hooks/useCancelSubscriptionModal'; import { useWorkspaceSync } from './hooks/useWorkspaceSync'; import UiKitSubscriptionLicense from './surface/UiKitSubscriptionLicense'; +import { Page, PageScrollableContentWithShadow } from '../../../components/Page'; +import PageBlockWithBorder from '../../../components/Page/PageBlockWithBorder'; +import PageHeaderNoShadow from '../../../components/Page/PageHeaderNoShadow'; +import { useIsEnterprise } from '../../../hooks/useIsEnterprise'; +import { useInvalidateLicense, useLicenseWithCloudAnnouncement } from '../../../hooks/useLicense'; +import { useRegistrationStatus } from '../../../hooks/useRegistrationStatus'; function useShowLicense() { const [showLicenseTab, setShowLicenseTab] = useSessionStorage('admin:showLicenseTab', false); @@ -73,6 +73,8 @@ const SubscriptionPage = () => { const macLimit = getKeyLimit('monthlyActiveContacts'); const seatsLimit = getKeyLimit('activeUsers'); + const { isLoading: isCancelSubscriptionLoading, open: openCancelSubscriptionModal } = useCancelSubscriptionModal(); + const handleSyncLicenseUpdate = useCallback(() => { syncLicenseUpdate.mutate(undefined, { onSuccess: () => invalidateLicenseQuery(100), @@ -98,8 +100,6 @@ const SubscriptionPage = () => { } }, [handleSyncLicenseUpdate, router, subscriptionSuccess, syncLicenseUpdate.isIdle]); - const removeLicense = useRemoveLicense(); - return ( @@ -185,7 +185,7 @@ const SubscriptionPage = () => { {Boolean(licensesData?.license?.information.cancellable) && ( - )} diff --git a/apps/meteor/client/views/admin/subscription/SubscriptionRoute.tsx b/apps/meteor/client/views/admin/subscription/SubscriptionRoute.tsx index 99fb216c01ce4..acda752117aa3 100644 --- a/apps/meteor/client/views/admin/subscription/SubscriptionRoute.tsx +++ b/apps/meteor/client/views/admin/subscription/SubscriptionRoute.tsx @@ -2,8 +2,8 @@ import { usePermission } from '@rocket.chat/ui-contexts'; import type { ReactElement } from 'react'; import React, { memo } from 'react'; -import NotAuthorizedPage from '../../notAuthorized/NotAuthorizedPage'; import SubscriptionPage from './SubscriptionPage'; +import NotAuthorizedPage from '../../notAuthorized/NotAuthorizedPage'; const SubscriptionRoute = (): ReactElement => { const canViewSubscription = usePermission('manage-cloud'); diff --git a/apps/meteor/client/views/admin/subscription/components/CancelSubscriptionModal.spec.tsx b/apps/meteor/client/views/admin/subscription/components/CancelSubscriptionModal.spec.tsx new file mode 100644 index 0000000000000..f35abc841b18a --- /dev/null +++ b/apps/meteor/client/views/admin/subscription/components/CancelSubscriptionModal.spec.tsx @@ -0,0 +1,69 @@ +import { mockAppRoot } from '@rocket.chat/mock-providers'; +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import React from 'react'; + +import { CancelSubscriptionModal } from './CancelSubscriptionModal'; +import { DOWNGRADE_LINK } from '../utils/links'; + +it('should display plan name in the title', async () => { + const confirmFn = jest.fn(); + render(, { + wrapper: mockAppRoot() + .withTranslations('en', 'core', { + Cancel__planName__subscription: 'Cancel {{planName}} subscription', + }) + .build(), + legacyRoot: true, + }); + + expect(screen.getByText('Cancel Starter subscription')).toBeInTheDocument(); +}); + +it('should have link to downgrade docs', async () => { + render(, { + wrapper: mockAppRoot() + .withTranslations('en', 'core', { + Cancel__planName__subscription: 'Cancel {{planName}} subscription', + Cancel_subscription_message: + 'This workspace will downgrage to Community and lose free access to premium capabilities.

While you can keep using Rocket.Chat, your team will lose access to unlimited mobile push notifications, read receipts, marketplace apps <4>and other capabilities.', + }) + .build(), + legacyRoot: true, + }); + + expect(screen.getByRole('link', { name: 'and other capabilities' })).toHaveAttribute('href', DOWNGRADE_LINK); +}); + +it('should call onConfirm when confirm button is clicked', async () => { + const confirmFn = jest.fn(); + render(, { + wrapper: mockAppRoot().build(), + legacyRoot: true, + }); + + await userEvent.click(screen.getByRole('button', { name: 'Cancel_subscription' })); + expect(confirmFn).toHaveBeenCalled(); +}); + +it('should call onCancel when "Dont cancel" button is clicked', async () => { + const cancelFn = jest.fn(); + render(, { + wrapper: mockAppRoot().build(), + legacyRoot: true, + }); + + await userEvent.click(screen.getByRole('button', { name: 'Dont_cancel' })); + expect(cancelFn).toHaveBeenCalled(); +}); + +it('should call onCancel when close button is clicked', async () => { + const cancelFn = jest.fn(); + render(, { + wrapper: mockAppRoot().build(), + legacyRoot: true, + }); + + await userEvent.click(screen.getByRole('button', { name: 'Close' })); + expect(cancelFn).toHaveBeenCalled(); +}); diff --git a/apps/meteor/client/views/admin/subscription/components/CancelSubscriptionModal.tsx b/apps/meteor/client/views/admin/subscription/components/CancelSubscriptionModal.tsx new file mode 100644 index 0000000000000..b717d5b370a64 --- /dev/null +++ b/apps/meteor/client/views/admin/subscription/components/CancelSubscriptionModal.tsx @@ -0,0 +1,36 @@ +import { ExternalLink } from '@rocket.chat/ui-client'; +import React from 'react'; +import { Trans, useTranslation } from 'react-i18next'; + +import GenericModal from '../../../../components/GenericModal'; +import { DOWNGRADE_LINK } from '../utils/links'; + +type CancelSubscriptionModalProps = { + planName: string; + onConfirm(): void; + onCancel(): void; +}; + +export const CancelSubscriptionModal = ({ planName, onCancel, onConfirm }: CancelSubscriptionModalProps) => { + const { t } = useTranslation(); + + return ( + + + This workspace will downgrade to Community and lose free access to premium capabilities. +
+
+ While you can keep using Rocket.Chat, your team will lose access to unlimited mobile push notifications, read receipts, marketplace + apps and other capabilities. +
+
+ ); +}; diff --git a/apps/meteor/client/views/admin/subscription/components/UsagePieGraph.stories.tsx b/apps/meteor/client/views/admin/subscription/components/UsagePieGraph.stories.tsx index 37985291df16f..a85262ff3eeb5 100644 --- a/apps/meteor/client/views/admin/subscription/components/UsagePieGraph.stories.tsx +++ b/apps/meteor/client/views/admin/subscription/components/UsagePieGraph.stories.tsx @@ -3,8 +3,8 @@ import type { Meta, StoryFn } from '@storybook/react'; import type { ComponentProps } from 'react'; import React from 'react'; -import { useAutoSequence } from '../../../../stories/hooks/useAutoSequence'; import UsagePieGraph from './UsagePieGraph'; +import { useAutoSequence } from '../../../../stories/hooks/useAutoSequence'; export default { title: 'Admin/Info/UsagePieGraph', diff --git a/apps/meteor/client/views/admin/subscription/components/cards/AppsUsageCard/AppsUsageCard.spec.tsx b/apps/meteor/client/views/admin/subscription/components/cards/AppsUsageCard/AppsUsageCard.spec.tsx index 480759dc53f49..b8f71b61d6ade 100644 --- a/apps/meteor/client/views/admin/subscription/components/cards/AppsUsageCard/AppsUsageCard.spec.tsx +++ b/apps/meteor/client/views/admin/subscription/components/cards/AppsUsageCard/AppsUsageCard.spec.tsx @@ -3,8 +3,8 @@ import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import React from 'react'; -import { PRICING_LINK } from '../../../utils/links'; import AppsUsageCard from './AppsUsageCard'; +import { PRICING_LINK } from '../../../utils/links'; const appRoot = mockAppRoot().withTranslations('en', 'core', { Apps_InfoText_limited: diff --git a/apps/meteor/client/views/admin/subscription/components/cards/AppsUsageCard/AppsUsageCard.tsx b/apps/meteor/client/views/admin/subscription/components/cards/AppsUsageCard/AppsUsageCard.tsx index 8b962e093a372..a87ef914aba01 100644 --- a/apps/meteor/client/views/admin/subscription/components/cards/AppsUsageCard/AppsUsageCard.tsx +++ b/apps/meteor/client/views/admin/subscription/components/cards/AppsUsageCard/AppsUsageCard.tsx @@ -4,11 +4,11 @@ import type { ReactElement } from 'react'; import React from 'react'; import { Trans, useTranslation } from 'react-i18next'; +import AppsUsageCardSection from './AppsUsageCardSection'; import { PRICING_LINK } from '../../../utils/links'; import type { CardProps } from '../../FeatureUsageCard'; import FeatureUsageCard from '../../FeatureUsageCard'; import UpgradeButton from '../../UpgradeButton'; -import AppsUsageCardSection from './AppsUsageCardSection'; // Magic numbers const marketplaceAppsMaxCountFallback = 5; diff --git a/apps/meteor/client/views/admin/subscription/components/cards/PlanCard/PlanCardPremium.tsx b/apps/meteor/client/views/admin/subscription/components/cards/PlanCard/PlanCardPremium.tsx index ea96adf32a389..8da910abe20c7 100644 --- a/apps/meteor/client/views/admin/subscription/components/cards/PlanCard/PlanCardPremium.tsx +++ b/apps/meteor/client/views/admin/subscription/components/cards/PlanCard/PlanCardPremium.tsx @@ -5,11 +5,11 @@ import type { ReactElement } from 'react'; import React from 'react'; import { Trans, useTranslation } from 'react-i18next'; +import PlanCardHeader from './PlanCardHeader'; import { useFormatDate } from '../../../../../../hooks/useFormatDate'; import { useIsSelfHosted } from '../../../../../../hooks/useIsSelfHosted'; import { useLicenseName } from '../../../../../../hooks/useLicense'; import { CONTACT_SALES_LINK } from '../../../utils/links'; -import PlanCardHeader from './PlanCardHeader'; type LicenseLimits = { activeUsers: { max: number; value?: number }; diff --git a/apps/meteor/client/views/admin/subscription/components/cards/PlanCard/PlanCardTrial.tsx b/apps/meteor/client/views/admin/subscription/components/cards/PlanCard/PlanCardTrial.tsx index eb6a020894ec1..99a52d04f5c52 100644 --- a/apps/meteor/client/views/admin/subscription/components/cards/PlanCard/PlanCardTrial.tsx +++ b/apps/meteor/client/views/admin/subscription/components/cards/PlanCard/PlanCardTrial.tsx @@ -6,10 +6,10 @@ import type { ReactElement } from 'react'; import React from 'react'; import { Trans, useTranslation } from 'react-i18next'; +import PlanCardHeader from './PlanCardHeader'; import { useLicenseName } from '../../../../../../hooks/useLicense'; import { DOWNGRADE_LINK, TRIAL_LINK } from '../../../utils/links'; import UpgradeButton from '../../UpgradeButton'; -import PlanCardHeader from './PlanCardHeader'; type PlanCardProps = { licenseInformation: ILicenseV3['information']; diff --git a/apps/meteor/client/views/admin/subscription/hooks/useCancelSubscriptionModal.spec.tsx b/apps/meteor/client/views/admin/subscription/hooks/useCancelSubscriptionModal.spec.tsx new file mode 100644 index 0000000000000..f97234398a6d5 --- /dev/null +++ b/apps/meteor/client/views/admin/subscription/hooks/useCancelSubscriptionModal.spec.tsx @@ -0,0 +1,72 @@ +import { mockAppRoot } from '@rocket.chat/mock-providers'; +import { act, renderHook, screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; + +import { useCancelSubscriptionModal } from './useCancelSubscriptionModal'; +import createDeferredMockFn from '../../../../../tests/mocks/utils/createDeferredMockFn'; + +jest.mock('../../../../hooks/useLicense', () => ({ + ...jest.requireActual('../../../../hooks/useLicense'), + useLicenseName: () => ({ data: 'Starter' }), +})); + +it('should open modal when open method is called', () => { + const { result } = renderHook(() => useCancelSubscriptionModal(), { + wrapper: mockAppRoot() + .withTranslations('en', 'core', { + Cancel__planName__subscription: 'Cancel {{planName}} subscription', + }) + .build(), + legacyRoot: true, + }); + + expect(screen.queryByText('Cancel Starter subscription')).not.toBeInTheDocument(); + + act(() => result.current.open()); + + expect(screen.getByText('Cancel Starter subscription')).toBeInTheDocument(); +}); + +it('should close modal cancel is clicked', async () => { + const { result } = renderHook(() => useCancelSubscriptionModal(), { + wrapper: mockAppRoot() + .withTranslations('en', 'core', { + Cancel__planName__subscription: 'Cancel {{planName}} subscription', + }) + .build(), + legacyRoot: true, + }); + + act(() => result.current.open()); + expect(screen.getByText('Cancel Starter subscription')).toBeInTheDocument(); + + await userEvent.click(screen.getByRole('button', { name: 'Dont_cancel' })); + + expect(screen.queryByText('Cancel Starter subscription')).not.toBeInTheDocument(); +}); + +it('should call remove license endpoint when confirm is clicked', async () => { + const { fn: removeLicenseEndpoint, resolve } = createDeferredMockFn<{ success: boolean }>(); + + const { result } = renderHook(() => useCancelSubscriptionModal(), { + wrapper: mockAppRoot() + .withEndpoint('POST', '/v1/cloud.removeLicense', removeLicenseEndpoint) + .withTranslations('en', 'core', { + Cancel__planName__subscription: 'Cancel {{planName}} subscription', + }) + .build(), + legacyRoot: true, + }); + + act(() => result.current.open()); + expect(result.current.isLoading).toBeFalsy(); + expect(screen.getByText('Cancel Starter subscription')).toBeInTheDocument(); + + await userEvent.click(screen.getByRole('button', { name: 'Cancel_subscription' })); + expect(result.current.isLoading).toBeTruthy(); + await act(() => resolve({ success: true })); + await waitFor(() => expect(result.current.isLoading).toBeFalsy()); + + expect(removeLicenseEndpoint).toHaveBeenCalled(); + expect(screen.queryByText('Cancel Starter subscription')).not.toBeInTheDocument(); +}); diff --git a/apps/meteor/client/views/admin/subscription/hooks/useCancelSubscriptionModal.tsx b/apps/meteor/client/views/admin/subscription/hooks/useCancelSubscriptionModal.tsx new file mode 100644 index 0000000000000..3e810cab45e59 --- /dev/null +++ b/apps/meteor/client/views/admin/subscription/hooks/useCancelSubscriptionModal.tsx @@ -0,0 +1,28 @@ +import { useSetModal } from '@rocket.chat/ui-contexts'; +import React, { useCallback } from 'react'; + +import { useRemoveLicense } from './useRemoveLicense'; +import { useLicenseName } from '../../../../hooks/useLicense'; +import { CancelSubscriptionModal } from '../components/CancelSubscriptionModal'; + +export const useCancelSubscriptionModal = () => { + const { data: planName = '' } = useLicenseName(); + const removeLicense = useRemoveLicense(); + const setModal = useSetModal(); + + const open = useCallback(() => { + const closeModal = () => setModal(null); + + const handleConfirm = () => { + removeLicense.mutateAsync(); + closeModal(); + }; + + setModal(); + }, [removeLicense, planName, setModal]); + + return { + open, + isLoading: removeLicense.isLoading, + }; +}; diff --git a/apps/meteor/client/views/admin/users/AdminInviteUsers.tsx b/apps/meteor/client/views/admin/users/AdminInviteUsers.tsx index 8976864f3430d..f322eb6e762ed 100644 --- a/apps/meteor/client/views/admin/users/AdminInviteUsers.tsx +++ b/apps/meteor/client/views/admin/users/AdminInviteUsers.tsx @@ -13,11 +13,11 @@ import { useTranslation, useRoute } from '@rocket.chat/ui-contexts'; import type { ChangeEvent } from 'react'; import React, { useCallback, useState } from 'react'; +import { useSendInvitationEmailMutation } from './hooks/useSendInvitationEmailMutation'; +import { useSmtpQuery } from './hooks/useSmtpQuery'; import { validateEmail } from '../../../../lib/emailValidator'; import { ContextualbarScrollableContent, ContextualbarFooter, ContextualbarContent } from '../../../components/Contextualbar'; import { FormSkeleton } from '../../../components/Skeleton'; -import { useSendInvitationEmailMutation } from './hooks/useSendInvitationEmailMutation'; -import { useSmtpQuery } from './hooks/useSmtpQuery'; // TODO: Replace using RHF const AdminInviteUsers = () => { diff --git a/apps/meteor/client/views/admin/users/AdminUserForm.tsx b/apps/meteor/client/views/admin/users/AdminUserForm.tsx index b5be16d2f93a7..ca6e07110a814 100644 --- a/apps/meteor/client/views/admin/users/AdminUserForm.tsx +++ b/apps/meteor/client/views/admin/users/AdminUserForm.tsx @@ -33,6 +33,10 @@ import { useMutation, useQueryClient } from '@tanstack/react-query'; import React, { useMemo, useState } from 'react'; import { Controller, useForm } from 'react-hook-form'; +import AdminUserSetRandomPasswordContent from './AdminUserSetRandomPasswordContent'; +import AdminUserSetRandomPasswordRadios from './AdminUserSetRandomPasswordRadios'; +import PasswordFieldSkeleton from './PasswordFieldSkeleton'; +import { useSmtpQuery } from './hooks/useSmtpQuery'; import { validateEmail } from '../../../../lib/emailValidator'; import { parseCSV } from '../../../../lib/utils/parseCSV'; import { ContextualbarScrollableContent } from '../../../components/Contextualbar'; @@ -40,10 +44,6 @@ import UserAvatarEditor from '../../../components/avatar/UserAvatarEditor'; import { useEndpointAction } from '../../../hooks/useEndpointAction'; import { useUpdateAvatar } from '../../../hooks/useUpdateAvatar'; import { USER_STATUS_TEXT_MAX_LENGTH, BIO_TEXT_MAX_LENGTH } from '../../../lib/constants'; -import AdminUserSetRandomPasswordContent from './AdminUserSetRandomPasswordContent'; -import AdminUserSetRandomPasswordRadios from './AdminUserSetRandomPasswordRadios'; -import PasswordFieldSkeleton from './PasswordFieldSkeleton'; -import { useSmtpQuery } from './hooks/useSmtpQuery'; type AdminUserFormProps = { userData?: Serialized; diff --git a/apps/meteor/client/views/admin/users/AdminUserFormWithData.tsx b/apps/meteor/client/views/admin/users/AdminUserFormWithData.tsx index 749b75903827b..5c4998b816bea 100644 --- a/apps/meteor/client/views/admin/users/AdminUserFormWithData.tsx +++ b/apps/meteor/client/views/admin/users/AdminUserFormWithData.tsx @@ -5,9 +5,9 @@ import type { ReactElement } from 'react'; import React from 'react'; import { useTranslation } from 'react-i18next'; +import AdminUserForm from './AdminUserForm'; import { FormSkeleton } from '../../../components/Skeleton'; import { useUserInfoQuery } from '../../../hooks/useUserInfoQuery'; -import AdminUserForm from './AdminUserForm'; type AdminUserFormWithDataProps = { uid: IUser['_id']; diff --git a/apps/meteor/client/views/admin/users/AdminUserInfoActions.tsx b/apps/meteor/client/views/admin/users/AdminUserInfoActions.tsx index 635706627eaf3..c6c594dcc8bc9 100644 --- a/apps/meteor/client/views/admin/users/AdminUserInfoActions.tsx +++ b/apps/meteor/client/views/admin/users/AdminUserInfoActions.tsx @@ -5,14 +5,14 @@ import type { ReactElement } from 'react'; import React, { useCallback, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; -import { UserInfoAction } from '../../../components/UserInfo'; -import { useActionSpread } from '../../hooks/useActionSpread'; import type { AdminUsersTab } from './AdminUsersPage'; import { useChangeAdminStatusAction } from './hooks/useChangeAdminStatusAction'; import { useChangeUserStatusAction } from './hooks/useChangeUserStatusAction'; import { useDeleteUserAction } from './hooks/useDeleteUserAction'; import { useResetE2EEKeyAction } from './hooks/useResetE2EEKeyAction'; import { useResetTOTPAction } from './hooks/useResetTOTPAction'; +import { UserInfoAction } from '../../../components/UserInfo'; +import { useActionSpread } from '../../hooks/useActionSpread'; type AdminUserInfoActionsProps = { username: IUser['username']; diff --git a/apps/meteor/client/views/admin/users/AdminUserInfoWithData.tsx b/apps/meteor/client/views/admin/users/AdminUserInfoWithData.tsx index 59d91ce5ada60..18c4710d42139 100644 --- a/apps/meteor/client/views/admin/users/AdminUserInfoWithData.tsx +++ b/apps/meteor/client/views/admin/users/AdminUserInfoWithData.tsx @@ -6,6 +6,8 @@ import { useQuery } from '@tanstack/react-query'; import type { ReactElement } from 'react'; import React, { useMemo } from 'react'; +import AdminUserInfoActions from './AdminUserInfoActions'; +import type { AdminUsersTab } from './AdminUsersPage'; import { getUserEmailAddress } from '../../../../lib/getUserEmailAddress'; import { ContextualbarContent } from '../../../components/Contextualbar'; import { FormSkeleton } from '../../../components/Skeleton'; @@ -13,8 +15,6 @@ import { UserCardRole } from '../../../components/UserCard'; import { UserInfo } from '../../../components/UserInfo'; import { UserStatus } from '../../../components/UserStatus'; import { getUserEmailVerified } from '../../../lib/utils/getUserEmailVerified'; -import AdminUserInfoActions from './AdminUserInfoActions'; -import type { AdminUsersTab } from './AdminUsersPage'; type AdminUserInfoWithDataProps = { uid: IUser['_id']; diff --git a/apps/meteor/client/views/admin/users/AdminUsersPage.tsx b/apps/meteor/client/views/admin/users/AdminUsersPage.tsx index afe881f64cc9f..36a1f4b8ad139 100644 --- a/apps/meteor/client/views/admin/users/AdminUsersPage.tsx +++ b/apps/meteor/client/views/admin/users/AdminUsersPage.tsx @@ -9,6 +9,17 @@ import type { ReactElement } from 'react'; import React, { useEffect, useMemo, useRef, useState } from 'react'; import { Trans } from 'react-i18next'; +import AdminInviteUsers from './AdminInviteUsers'; +import AdminUserCreated from './AdminUserCreated'; +import AdminUserForm from './AdminUserForm'; +import AdminUserFormWithData from './AdminUserFormWithData'; +import AdminUserInfoWithData from './AdminUserInfoWithData'; +import AdminUserUpgrade from './AdminUserUpgrade'; +import UsersPageHeaderContent from './UsersPageHeaderContent'; +import UsersTable from './UsersTable'; +import useFilteredUsers from './hooks/useFilteredUsers'; +import usePendingUsersCount from './hooks/usePendingUsersCount'; +import { useSeatsCap } from './useSeatsCap'; import { Contextualbar, ContextualbarHeader, @@ -22,17 +33,6 @@ import { Page, PageHeader, PageContent } from '../../../components/Page'; import { useLicenseLimitsByBehavior } from '../../../hooks/useLicenseLimitsByBehavior'; import { useShouldPreventAction } from '../../../hooks/useShouldPreventAction'; import { useCheckoutUrl } from '../subscription/hooks/useCheckoutUrl'; -import AdminInviteUsers from './AdminInviteUsers'; -import AdminUserCreated from './AdminUserCreated'; -import AdminUserForm from './AdminUserForm'; -import AdminUserFormWithData from './AdminUserFormWithData'; -import AdminUserInfoWithData from './AdminUserInfoWithData'; -import AdminUserUpgrade from './AdminUserUpgrade'; -import UsersPageHeaderContent from './UsersPageHeaderContent'; -import UsersTable from './UsersTable'; -import useFilteredUsers from './hooks/useFilteredUsers'; -import usePendingUsersCount from './hooks/usePendingUsersCount'; -import { useSeatsCap } from './useSeatsCap'; export type UsersFilters = { text: string; diff --git a/apps/meteor/client/views/admin/users/AdminUsersRoute.tsx b/apps/meteor/client/views/admin/users/AdminUsersRoute.tsx index 03f095d3f4116..3e86ad5597b95 100644 --- a/apps/meteor/client/views/admin/users/AdminUsersRoute.tsx +++ b/apps/meteor/client/views/admin/users/AdminUsersRoute.tsx @@ -2,8 +2,8 @@ import { usePermission } from '@rocket.chat/ui-contexts'; import type { ReactElement } from 'react'; import React from 'react'; -import NotAuthorizedPage from '../../notAuthorized/NotAuthorizedPage'; import AdminUsersPage from './AdminUsersPage'; +import NotAuthorizedPage from '../../notAuthorized/NotAuthorizedPage'; const AdminUsersRoute = (): ReactElement => { const canViewUserAdministration = usePermission('view-user-administration'); diff --git a/apps/meteor/client/views/admin/users/UsersPageHeaderContent.tsx b/apps/meteor/client/views/admin/users/UsersPageHeaderContent.tsx index 89916c3e6f2e7..0b6d34f235961 100644 --- a/apps/meteor/client/views/admin/users/UsersPageHeaderContent.tsx +++ b/apps/meteor/client/views/admin/users/UsersPageHeaderContent.tsx @@ -3,11 +3,11 @@ import { usePermission, useRouter } from '@rocket.chat/ui-contexts'; import React from 'react'; import { useTranslation } from 'react-i18next'; -import { useExternalLink } from '../../../hooks/useExternalLink'; -import { useCheckoutUrl } from '../subscription/hooks/useCheckoutUrl'; import SeatsCapUsage from './SeatsCapUsage'; import type { SeatCapProps } from './useSeatsCap'; import AssignExtensionButton from './voip/AssignExtensionButton'; +import { useExternalLink } from '../../../hooks/useExternalLink'; +import { useCheckoutUrl } from '../subscription/hooks/useCheckoutUrl'; import { useVoipExtensionPermission } from './voip/hooks/useVoipExtensionPermission'; type UsersPageHeaderContentProps = { diff --git a/apps/meteor/client/views/admin/users/UsersTable/UsersTable.spec.tsx b/apps/meteor/client/views/admin/users/UsersTable/UsersTable.spec.tsx index 6660461f4ac04..7473d61654c31 100644 --- a/apps/meteor/client/views/admin/users/UsersTable/UsersTable.spec.tsx +++ b/apps/meteor/client/views/admin/users/UsersTable/UsersTable.spec.tsx @@ -2,8 +2,8 @@ import { mockAppRoot } from '@rocket.chat/mock-providers'; import { render, screen } from '@testing-library/react'; import React from 'react'; -import { createFakeUser } from '../../../../../tests/mocks/data'; import UsersTable from './UsersTable'; +import { createFakeUser } from '../../../../../tests/mocks/data'; const createFakeAdminUser = (freeSwitchExtension?: string) => createFakeUser({ diff --git a/apps/meteor/client/views/admin/users/UsersTable/UsersTable.tsx b/apps/meteor/client/views/admin/users/UsersTable/UsersTable.tsx index 5a15cc58e6ba0..7cd36ed56a530 100644 --- a/apps/meteor/client/views/admin/users/UsersTable/UsersTable.tsx +++ b/apps/meteor/client/views/admin/users/UsersTable/UsersTable.tsx @@ -9,6 +9,8 @@ import type { ReactElement, Dispatch, SetStateAction } from 'react'; import React, { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; +import UsersTableFilters from './UsersTableFilters'; +import UsersTableRow from './UsersTableRow'; import GenericNoResults from '../../../../components/GenericNoResults'; import { GenericTable, @@ -21,8 +23,6 @@ import type { usePagination } from '../../../../components/GenericTable/hooks/us import type { useSort } from '../../../../components/GenericTable/hooks/useSort'; import type { AdminUsersTab, UsersFilters, UsersTableSortingOption } from '../AdminUsersPage'; import { useVoipExtensionPermission } from '../voip/hooks/useVoipExtensionPermission'; -import UsersTableFilters from './UsersTableFilters'; -import UsersTableRow from './UsersTableRow'; type UsersTableProps = { tab: AdminUsersTab; diff --git a/apps/meteor/client/views/admin/users/hooks/useChangeUserStatusAction.ts b/apps/meteor/client/views/admin/users/hooks/useChangeUserStatusAction.ts index 1fc6d35463283..bd680216c12de 100644 --- a/apps/meteor/client/views/admin/users/hooks/useChangeUserStatusAction.ts +++ b/apps/meteor/client/views/admin/users/hooks/useChangeUserStatusAction.ts @@ -2,8 +2,8 @@ import type { IUser } from '@rocket.chat/core-typings'; import { useToastMessageDispatch, useTranslation, useEndpoint, usePermission } from '@rocket.chat/ui-contexts'; import { useMemo } from 'react'; -import type { Action } from '../../../hooks/useActionSpread'; import { useConfirmOwnerChanges } from './useConfirmOwnerChanges'; +import type { Action } from '../../../hooks/useActionSpread'; export const useChangeUserStatusAction = (userId: IUser['_id'], isActive: boolean, onChange: () => void): Action | undefined => { const t = useTranslation(); diff --git a/apps/meteor/client/views/admin/users/hooks/useDeleteUserAction.tsx b/apps/meteor/client/views/admin/users/hooks/useDeleteUserAction.tsx index e80912426652d..807a92af6e9f6 100644 --- a/apps/meteor/client/views/admin/users/hooks/useDeleteUserAction.tsx +++ b/apps/meteor/client/views/admin/users/hooks/useDeleteUserAction.tsx @@ -12,9 +12,9 @@ import { } from '@rocket.chat/ui-contexts'; import React, { useMemo } from 'react'; +import { useConfirmOwnerChanges } from './useConfirmOwnerChanges'; import GenericModal from '../../../../components/GenericModal'; import type { Action } from '../../../hooks/useActionSpread'; -import { useConfirmOwnerChanges } from './useConfirmOwnerChanges'; export const useDeleteUserAction = (userId: IUser['_id'], onChange: () => void, onReload: () => void): Action | undefined => { const t = useTranslation(); diff --git a/apps/meteor/client/views/admin/viewLogs/ViewLogsPage.stories.tsx b/apps/meteor/client/views/admin/viewLogs/ViewLogsPage.stories.tsx index a013c2eaf8868..29dbe6525e13c 100644 --- a/apps/meteor/client/views/admin/viewLogs/ViewLogsPage.stories.tsx +++ b/apps/meteor/client/views/admin/viewLogs/ViewLogsPage.stories.tsx @@ -12,11 +12,7 @@ export default { controls: { hideNoControlsWarning: true }, }, decorators: [ - (fn: () => ReactNode): ReactElement => ( -
- {fn()} -
- ), + (fn: () => ReactNode): ReactElement =>
{fn()}
, ], } satisfies Meta; diff --git a/apps/meteor/client/views/admin/viewLogs/ViewLogsPage.tsx b/apps/meteor/client/views/admin/viewLogs/ViewLogsPage.tsx index 818713898b200..b6400e906ce3e 100644 --- a/apps/meteor/client/views/admin/viewLogs/ViewLogsPage.tsx +++ b/apps/meteor/client/views/admin/viewLogs/ViewLogsPage.tsx @@ -3,9 +3,9 @@ import type { ReactElement } from 'react'; import React, { useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { Page, PageHeader, PageContent } from '../../../components/Page'; import AnalyticsReports from './AnalyticsReports'; import ServerLogs from './ServerLogs'; +import { Page, PageHeader, PageContent } from '../../../components/Page'; const ViewLogsPage = (): ReactElement => { const { t } = useTranslation(); diff --git a/apps/meteor/client/views/admin/viewLogs/ViewLogsRoute.tsx b/apps/meteor/client/views/admin/viewLogs/ViewLogsRoute.tsx index 130ddf067f5d1..7578ed49fbc92 100644 --- a/apps/meteor/client/views/admin/viewLogs/ViewLogsRoute.tsx +++ b/apps/meteor/client/views/admin/viewLogs/ViewLogsRoute.tsx @@ -2,8 +2,8 @@ import { usePermission } from '@rocket.chat/ui-contexts'; import type { ReactElement } from 'react'; import React from 'react'; -import NotAuthorizedPage from '../../notAuthorized/NotAuthorizedPage'; import ViewLogsPage from './ViewLogsPage'; +import NotAuthorizedPage from '../../notAuthorized/NotAuthorizedPage'; const ViewLogsRoute = (): ReactElement => { const canViewLogs = usePermission('view-logs'); diff --git a/apps/meteor/client/views/admin/workspace/DeploymentCard/components/InstancesModal/DescriptionList.stories.tsx b/apps/meteor/client/views/admin/workspace/DeploymentCard/components/InstancesModal/DescriptionList.stories.tsx index 2626a2fb9f01d..6f4e4544c1f59 100644 --- a/apps/meteor/client/views/admin/workspace/DeploymentCard/components/InstancesModal/DescriptionList.stories.tsx +++ b/apps/meteor/client/views/admin/workspace/DeploymentCard/components/InstancesModal/DescriptionList.stories.tsx @@ -10,7 +10,7 @@ export default { parameters: { layout: 'centered', }, - decorators: [(fn) =>
{fn()}
], + decorators: [(fn) =>
{fn()}
], } satisfies Meta; export const Default: StoryFn = (args) => ( diff --git a/apps/meteor/client/views/admin/workspace/DeploymentCard/components/InstancesModal/InstancesModal.tsx b/apps/meteor/client/views/admin/workspace/DeploymentCard/components/InstancesModal/InstancesModal.tsx index 1394d7497ebd0..69644eda53f91 100644 --- a/apps/meteor/client/views/admin/workspace/DeploymentCard/components/InstancesModal/InstancesModal.tsx +++ b/apps/meteor/client/views/admin/workspace/DeploymentCard/components/InstancesModal/InstancesModal.tsx @@ -3,10 +3,10 @@ import type { IInstance } from '@rocket.chat/rest-typings'; import React from 'react'; import { useTranslation } from 'react-i18next'; -import GenericModal from '../../../../../../components/GenericModal'; -import { useFormatDateAndTime } from '../../../../../../hooks/useFormatDateAndTime'; import DescriptionList from './DescriptionList'; import DescriptionListEntry from './DescriptionListEntry'; +import GenericModal from '../../../../../../components/GenericModal'; +import { useFormatDateAndTime } from '../../../../../../hooks/useFormatDateAndTime'; type InstancesModalProps = { instances: IInstance[]; diff --git a/apps/meteor/client/views/admin/workspace/VersionCard/VersionCard.tsx b/apps/meteor/client/views/admin/workspace/VersionCard/VersionCard.tsx index 0716d920f35d2..93c05ab2e9a0d 100644 --- a/apps/meteor/client/views/admin/workspace/VersionCard/VersionCard.tsx +++ b/apps/meteor/client/views/admin/workspace/VersionCard/VersionCard.tsx @@ -9,10 +9,6 @@ import type { ReactElement, ReactNode } from 'react'; import React, { useMemo } from 'react'; import { Trans, useTranslation } from 'react-i18next'; -import { useFormatDate } from '../../../../hooks/useFormatDate'; -import { useLicense, useLicenseName } from '../../../../hooks/useLicense'; -import { useRegistrationStatus } from '../../../../hooks/useRegistrationStatus'; -import { isOverLicenseLimits } from '../../../../lib/utils/isOverLicenseLimits'; import VersionCardActionButton from './components/VersionCardActionButton'; import type { VersionActionItem } from './components/VersionCardActionItem'; import VersionCardActionItem from './components/VersionCardActionItem'; @@ -20,6 +16,10 @@ import { VersionCardSkeleton } from './components/VersionCardSkeleton'; import { VersionTag } from './components/VersionTag'; import { getVersionStatus } from './getVersionStatus'; import RegisterWorkspaceModal from './modals/RegisterWorkspaceModal'; +import { useFormatDate } from '../../../../hooks/useFormatDate'; +import { useLicense, useLicenseName } from '../../../../hooks/useLicense'; +import { useRegistrationStatus } from '../../../../hooks/useRegistrationStatus'; +import { isOverLicenseLimits } from '../../../../lib/utils/isOverLicenseLimits'; const SUPPORT_EXTERNAL_LINK = 'https://go.rocket.chat/i/version-support'; const RELEASES_EXTERNAL_LINK = 'https://go.rocket.chat/i/update-product'; diff --git a/apps/meteor/client/views/admin/workspace/VersionCard/modals/RegisterWorkspaceModal.tsx b/apps/meteor/client/views/admin/workspace/VersionCard/modals/RegisterWorkspaceModal.tsx index 498de62f20021..0f3891f4e42d4 100644 --- a/apps/meteor/client/views/admin/workspace/VersionCard/modals/RegisterWorkspaceModal.tsx +++ b/apps/meteor/client/views/admin/workspace/VersionCard/modals/RegisterWorkspaceModal.tsx @@ -4,9 +4,9 @@ import { useSetModal } from '@rocket.chat/ui-contexts'; import React from 'react'; import { useTranslation } from 'react-i18next'; -import useFeatureBullets from '../hooks/useFeatureBullets'; import RegisterWorkspaceSetupModal from './RegisterWorkspaceSetupModal'; import RegisterWorkspaceTokenModal from './RegisterWorkspaceTokenModal'; +import useFeatureBullets from '../hooks/useFeatureBullets'; type RegisterWorkspaceModalProps = { onClose: () => void; diff --git a/apps/meteor/client/views/admin/workspace/WorkspacePage.tsx b/apps/meteor/client/views/admin/workspace/WorkspacePage.tsx index b3288c1b99c52..1ae00a9e66675 100644 --- a/apps/meteor/client/views/admin/workspace/WorkspacePage.tsx +++ b/apps/meteor/client/views/admin/workspace/WorkspacePage.tsx @@ -4,12 +4,12 @@ import type { IInstance } from '@rocket.chat/rest-typings'; import React, { memo } from 'react'; import { useTranslation } from 'react-i18next'; -import { Page, PageHeader, PageScrollableContentWithShadow } from '../../../components/Page'; -import { useIsEnterprise } from '../../../hooks/useIsEnterprise'; import DeploymentCard from './DeploymentCard/DeploymentCard'; import MessagesRoomsCard from './MessagesRoomsCard/MessagesRoomsCard'; import UsersUploadsCard from './UsersUploadsCard/UsersUploadsCard'; import VersionCard from './VersionCard/VersionCard'; +import { Page, PageHeader, PageScrollableContentWithShadow } from '../../../components/Page'; +import { useIsEnterprise } from '../../../hooks/useIsEnterprise'; type WorkspaceStatusPageProps = { canViewStatistics: boolean; diff --git a/apps/meteor/client/views/admin/workspace/WorkspaceRoute.tsx b/apps/meteor/client/views/admin/workspace/WorkspaceRoute.tsx index 9df91587828e5..31d723a24e782 100644 --- a/apps/meteor/client/views/admin/workspace/WorkspaceRoute.tsx +++ b/apps/meteor/client/views/admin/workspace/WorkspaceRoute.tsx @@ -4,12 +4,12 @@ import type { ReactElement } from 'react'; import React, { memo, useState } from 'react'; import { useTranslation } from 'react-i18next'; +import WorkspacePage from './WorkspacePage'; import { Page, PageHeader, PageScrollableContentWithShadow } from '../../../components/Page'; import PageSkeleton from '../../../components/PageSkeleton'; import { useWorkspaceInfo } from '../../../hooks/useWorkspaceInfo'; import { downloadJsonAs } from '../../../lib/download'; import NotAuthorizedPage from '../../notAuthorized/NotAuthorizedPage'; -import WorkspacePage from './WorkspacePage'; const WorkspaceRoute = (): ReactElement => { const { t } = useTranslation(); diff --git a/apps/meteor/client/views/audit/AuditLogPage.tsx b/apps/meteor/client/views/audit/AuditLogPage.tsx index 95fbc39abca88..76b6cbd0d8ff3 100644 --- a/apps/meteor/client/views/audit/AuditLogPage.tsx +++ b/apps/meteor/client/views/audit/AuditLogPage.tsx @@ -2,8 +2,8 @@ import type { ReactElement } from 'react'; import React from 'react'; import { useTranslation } from 'react-i18next'; -import { Page, PageHeader, PageContent } from '../../components/Page'; import AuditLogTable from './components/AuditLogTable'; +import { Page, PageHeader, PageContent } from '../../components/Page'; const AuditLogPage = (): ReactElement => { const { t } = useTranslation(); diff --git a/apps/meteor/client/views/audit/AuditPage.tsx b/apps/meteor/client/views/audit/AuditPage.tsx index 3dce9be56a8ed..90f72a6e90c39 100644 --- a/apps/meteor/client/views/audit/AuditPage.tsx +++ b/apps/meteor/client/views/audit/AuditPage.tsx @@ -3,13 +3,13 @@ import { Box, Callout, Margins, States, StatesIcon, StatesSubtitle, StatesTitle, import React, { useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { Page, PageHeader, PageScrollableContentWithShadow } from '../../components/Page'; -import MessageListSkeleton from '../../components/message/list/MessageListSkeleton'; -import { getErrorMessage } from '../../lib/errorHandling'; import AuditForm from './components/AuditForm'; import AuditResult from './components/AuditResult'; import { useAuditMutation } from './hooks/useAuditMutation'; import { useAuditTab } from './hooks/useAuditTab'; +import { Page, PageHeader, PageScrollableContentWithShadow } from '../../components/Page'; +import MessageListSkeleton from '../../components/message/list/MessageListSkeleton'; +import { getErrorMessage } from '../../lib/errorHandling'; const AuditPage = () => { const [type, setType] = useAuditTab(); diff --git a/apps/meteor/client/views/audit/components/AuditLogEntry.tsx b/apps/meteor/client/views/audit/components/AuditLogEntry.tsx index c6c4e204a6824..5cb1100cad32a 100644 --- a/apps/meteor/client/views/audit/components/AuditLogEntry.tsx +++ b/apps/meteor/client/views/audit/components/AuditLogEntry.tsx @@ -6,9 +6,9 @@ import type { ReactElement } from 'react'; import React, { memo, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; +import AuditFiltersDisplay from './AuditFiltersDisplay'; import { GenericTableRow, GenericTableCell } from '../../../components/GenericTable'; import { useFormatDateAndTime } from '../../../hooks/useFormatDateAndTime'; -import AuditFiltersDisplay from './AuditFiltersDisplay'; type AuditLogEntryProps = { value: IAuditLog }; diff --git a/apps/meteor/client/views/audit/components/AuditLogTable.tsx b/apps/meteor/client/views/audit/components/AuditLogTable.tsx index faf650e903dee..a2bff0b37514f 100644 --- a/apps/meteor/client/views/audit/components/AuditLogTable.tsx +++ b/apps/meteor/client/views/audit/components/AuditLogTable.tsx @@ -4,6 +4,7 @@ import { useQuery } from '@tanstack/react-query'; import type { ReactElement } from 'react'; import React, { useState } from 'react'; +import AuditLogEntry from './AuditLogEntry'; import GenericNoResults from '../../../components/GenericNoResults'; import { GenericTable, @@ -14,7 +15,6 @@ import { } from '../../../components/GenericTable'; import { createEndOfToday, createStartOfToday } from '../utils/dateRange'; import type { DateRange } from '../utils/dateRange'; -import AuditLogEntry from './AuditLogEntry'; import DateRangePicker from './forms/DateRangePicker'; const AuditLogTable = (): ReactElement => { diff --git a/apps/meteor/client/views/audit/components/AuditResult.tsx b/apps/meteor/client/views/audit/components/AuditResult.tsx index 79b904d38f979..8a98f63aaea01 100644 --- a/apps/meteor/client/views/audit/components/AuditResult.tsx +++ b/apps/meteor/client/views/audit/components/AuditResult.tsx @@ -2,8 +2,8 @@ import type { IMessage } from '@rocket.chat/core-typings'; import type { ReactElement } from 'react'; import React, { memo } from 'react'; -import GenericNoResults from '../../../components/GenericNoResults'; import AuditMessageList from './AuditMessageList'; +import GenericNoResults from '../../../components/GenericNoResults'; type AuditResultProps = { className?: string; diff --git a/apps/meteor/client/views/banners/BannerRegion.tsx b/apps/meteor/client/views/banners/BannerRegion.tsx index e70b6c608eab8..1dc79cbe43c82 100644 --- a/apps/meteor/client/views/banners/BannerRegion.tsx +++ b/apps/meteor/client/views/banners/BannerRegion.tsx @@ -2,11 +2,11 @@ import type { ReactElement } from 'react'; import React from 'react'; import { useSyncExternalStore } from 'use-sync-external-store/shim'; -import { withErrorBoundary } from '../../components/withErrorBoundary'; -import * as banners from '../../lib/banners'; import LegacyBanner from './LegacyBanner'; import UiKitBanner from './UiKitBanner'; import { useUserBanners } from './hooks/useUserBanners'; +import { withErrorBoundary } from '../../components/withErrorBoundary'; +import * as banners from '../../lib/banners'; const BannerRegion = (): ReactElement | null => { const payload = useSyncExternalStore(...banners.firstSubscription); diff --git a/apps/meteor/client/views/banners/hooks/useUserBanners.ts b/apps/meteor/client/views/banners/hooks/useUserBanners.ts index d78c9ce430a6d..8623173b348ef 100644 --- a/apps/meteor/client/views/banners/hooks/useUserBanners.ts +++ b/apps/meteor/client/views/banners/hooks/useUserBanners.ts @@ -2,8 +2,8 @@ import { useUser } from '@rocket.chat/ui-contexts'; import { useEffect } from 'react'; import { useTranslation } from 'react-i18next'; -import * as banners from '../../../lib/banners'; import { useDismissUserBannerMutation } from './useDismissUserBannerMutation'; +import * as banners from '../../../lib/banners'; export const useUserBanners = () => { const user = useUser(); diff --git a/apps/meteor/client/views/composer/EmojiPicker/CategoriesResult.tsx b/apps/meteor/client/views/composer/EmojiPicker/CategoriesResult.tsx index fe609da8640de..7c61c0caa94bc 100644 --- a/apps/meteor/client/views/composer/EmojiPicker/CategoriesResult.tsx +++ b/apps/meteor/client/views/composer/EmojiPicker/CategoriesResult.tsx @@ -5,9 +5,9 @@ import React, { forwardRef, useRef } from 'react'; import type { VirtuosoHandle } from 'react-virtuoso'; import { Virtuoso } from 'react-virtuoso'; +import EmojiCategoryRow from './EmojiCategoryRow'; import type { EmojiCategoryPosition, EmojiByCategory } from '../../../../app/emoji/client'; import { VirtuosoScrollbars } from '../../../components/CustomScrollbars'; -import EmojiCategoryRow from './EmojiCategoryRow'; type CategoriesResultProps = { emojiListByCategory: EmojiByCategory[]; diff --git a/apps/meteor/client/views/composer/EmojiPicker/EmojiCategoryRow.tsx b/apps/meteor/client/views/composer/EmojiPicker/EmojiCategoryRow.tsx index 10f0ed5655846..0238153aea53d 100644 --- a/apps/meteor/client/views/composer/EmojiPicker/EmojiCategoryRow.tsx +++ b/apps/meteor/client/views/composer/EmojiPicker/EmojiCategoryRow.tsx @@ -5,9 +5,9 @@ import type { MouseEvent, MutableRefObject } from 'react'; import React from 'react'; import { useTranslation } from 'react-i18next'; +import EmojiElement from './EmojiElement'; import { CUSTOM_CATEGORY } from '../../../../app/emoji/client'; import type { EmojiByCategory, EmojiCategoryPosition } from '../../../../app/emoji/client'; -import EmojiElement from './EmojiElement'; type EmojiCategoryRowProps = EmojiByCategory & { categoryKey: EmojiByCategory['key']; diff --git a/apps/meteor/client/views/composer/EmojiPicker/EmojiPicker.tsx b/apps/meteor/client/views/composer/EmojiPicker/EmojiPicker.tsx index f2e68a60d690f..9cbd5e131f976 100644 --- a/apps/meteor/client/views/composer/EmojiPicker/EmojiPicker.tsx +++ b/apps/meteor/client/views/composer/EmojiPicker/EmojiPicker.tsx @@ -14,16 +14,16 @@ import type { ChangeEvent, KeyboardEvent, MouseEvent, RefObject } from 'react'; import React, { useLayoutEffect, useState, useEffect, useRef } from 'react'; import type { VirtuosoHandle } from 'react-virtuoso'; -import type { EmojiItem, EmojiCategoryPosition } from '../../../../app/emoji/client'; -import { emoji, getCategoriesList, getEmojisBySearchTerm } from '../../../../app/emoji/client'; -import { usePreviewEmoji, useEmojiPickerData } from '../../../contexts/EmojiPickerContext'; -import { useIsVisible } from '../../room/hooks/useIsVisible'; import CategoriesResult from './CategoriesResult'; import EmojiPickerCategoryItem from './EmojiPickerCategoryItem'; import EmojiPickerDropdown from './EmojiPickerDropDown'; import SearchingResult from './SearchingResult'; import ToneSelector from './ToneSelector'; import ToneSelectorWrapper from './ToneSelector/ToneSelectorWrapper'; +import { emoji, getCategoriesList, getEmojisBySearchTerm } from '../../../../app/emoji/client'; +import type { EmojiItem, EmojiCategoryPosition } from '../../../../app/emoji/client'; +import { usePreviewEmoji, useEmojiPickerData } from '../../../contexts/EmojiPickerContext'; +import { useIsVisible } from '../../room/hooks/useIsVisible'; type EmojiPickerProps = { reference: Element; diff --git a/apps/meteor/client/views/composer/EmojiPicker/SearchingResult.tsx b/apps/meteor/client/views/composer/EmojiPicker/SearchingResult.tsx index 152d13bae5dea..ee559ea47d72c 100644 --- a/apps/meteor/client/views/composer/EmojiPicker/SearchingResult.tsx +++ b/apps/meteor/client/views/composer/EmojiPicker/SearchingResult.tsx @@ -5,10 +5,10 @@ import { useTranslation } from 'react-i18next'; import type { VirtuosoGridHandle } from 'react-virtuoso'; import { VirtuosoGrid } from 'react-virtuoso'; -import type { EmojiItem } from '../../../../app/emoji/client'; -import { VirtuosoScrollbars } from '../../../components/CustomScrollbars'; import EmojiElement from './EmojiElement'; import SearchingResultWrapper from './SearchingResultWrapper'; +import type { EmojiItem } from '../../../../app/emoji/client'; +import { VirtuosoScrollbars } from '../../../components/CustomScrollbars'; /** * the `SearchingResults` is missing the previous loadMore function that was implemented before on the latest version of EmojiPicker using the Blaze Template. It can't be implemented because of the issue with react-virtuoso and the custom scrollbars, since its using virtual list its not gonna be an issue rendering bigger results for search diff --git a/apps/meteor/client/views/conference/ConferencePage.tsx b/apps/meteor/client/views/conference/ConferencePage.tsx index 0b05e8b2b4d25..3db9777cf0790 100644 --- a/apps/meteor/client/views/conference/ConferencePage.tsx +++ b/apps/meteor/client/views/conference/ConferencePage.tsx @@ -2,10 +2,10 @@ import { useRoute, useSetModal, useUser } from '@rocket.chat/ui-contexts'; import type { ReactElement } from 'react'; import React, { useEffect } from 'react'; +import ConferencePageError from './ConferencePageError'; import { useUserDisplayName } from '../../hooks/useUserDisplayName'; import { useVideoConfOpenCall } from '../room/contextualBar/VideoConference/hooks/useVideoConfOpenCall'; import PageLoading from '../root/PageLoading'; -import ConferencePageError from './ConferencePageError'; const getQueryParams = () => { const queryString = window.location.search; diff --git a/apps/meteor/client/views/conference/ConferenceRoute.tsx b/apps/meteor/client/views/conference/ConferenceRoute.tsx index 4b27917c2d3ea..4917058b246cc 100644 --- a/apps/meteor/client/views/conference/ConferenceRoute.tsx +++ b/apps/meteor/client/views/conference/ConferenceRoute.tsx @@ -1,8 +1,8 @@ import type { ReactElement } from 'react'; import React from 'react'; -import AuthenticationCheck from '../root/MainLayout/AuthenticationCheck'; import ConferencePage from './ConferencePage'; +import AuthenticationCheck from '../root/MainLayout/AuthenticationCheck'; const ConferenceRoute = (): ReactElement => { return ( diff --git a/apps/meteor/client/views/directory/tabs/channels/ChannelsTab.tsx b/apps/meteor/client/views/directory/tabs/channels/ChannelsTab.tsx index e1627e63e067f..93bda21319d1f 100644 --- a/apps/meteor/client/views/directory/tabs/channels/ChannelsTab.tsx +++ b/apps/meteor/client/views/directory/tabs/channels/ChannelsTab.tsx @@ -2,8 +2,8 @@ import { usePermission } from '@rocket.chat/ui-contexts'; import type { ReactElement } from 'react'; import React from 'react'; -import NotAuthorizedPage from '../../../notAuthorized/NotAuthorizedPage'; import ChannelsTable from './ChannelsTable'; +import NotAuthorizedPage from '../../../notAuthorized/NotAuthorizedPage'; const ChannelsTab = (): ReactElement => { const canViewPublicRooms = usePermission('view-c-room'); diff --git a/apps/meteor/client/views/directory/tabs/channels/ChannelsTable/ChannelsTable.tsx b/apps/meteor/client/views/directory/tabs/channels/ChannelsTable/ChannelsTable.tsx index 5ccd6d0bc9159..2c73e36393d45 100644 --- a/apps/meteor/client/views/directory/tabs/channels/ChannelsTable/ChannelsTable.tsx +++ b/apps/meteor/client/views/directory/tabs/channels/ChannelsTable/ChannelsTable.tsx @@ -5,6 +5,7 @@ import { useRoute, useTranslation, useEndpoint } from '@rocket.chat/ui-contexts' import { useQuery } from '@tanstack/react-query'; import React, { useMemo, useState } from 'react'; +import ChannelsTableRow from './ChannelsTableRow'; import FilterByText from '../../../../../components/FilterByText'; import GenericNoResults from '../../../../../components/GenericNoResults'; import { @@ -17,7 +18,6 @@ import { import { usePagination } from '../../../../../components/GenericTable/hooks/usePagination'; import { useSort } from '../../../../../components/GenericTable/hooks/useSort'; import { useDirectoryQuery } from '../../../hooks/useDirectoryQuery'; -import ChannelsTableRow from './ChannelsTableRow'; const ChannelsTable = () => { const t = useTranslation(); diff --git a/apps/meteor/client/views/directory/tabs/teams/TeamsTab.tsx b/apps/meteor/client/views/directory/tabs/teams/TeamsTab.tsx index 42814f4235928..001d1c959ee22 100644 --- a/apps/meteor/client/views/directory/tabs/teams/TeamsTab.tsx +++ b/apps/meteor/client/views/directory/tabs/teams/TeamsTab.tsx @@ -2,8 +2,8 @@ import { usePermission } from '@rocket.chat/ui-contexts'; import type { ReactElement } from 'react'; import React from 'react'; -import NotAuthorizedPage from '../../../notAuthorized/NotAuthorizedPage'; import TeamsTable from './TeamsTable'; +import NotAuthorizedPage from '../../../notAuthorized/NotAuthorizedPage'; const TeamsTab = (): ReactElement => { const canViewPublicRooms = usePermission('view-c-room'); diff --git a/apps/meteor/client/views/directory/tabs/teams/TeamsTable/TeamsTable.tsx b/apps/meteor/client/views/directory/tabs/teams/TeamsTable/TeamsTable.tsx index 92ca68d173e9c..ce114484caac5 100644 --- a/apps/meteor/client/views/directory/tabs/teams/TeamsTable/TeamsTable.tsx +++ b/apps/meteor/client/views/directory/tabs/teams/TeamsTable/TeamsTable.tsx @@ -5,6 +5,7 @@ import { useRoute, useTranslation, useEndpoint } from '@rocket.chat/ui-contexts' import { useQuery } from '@tanstack/react-query'; import React, { useMemo, useState } from 'react'; +import TeamsTableRow from './TeamsTableRow'; import FilterByText from '../../../../../components/FilterByText'; import GenericNoResults from '../../../../../components/GenericNoResults'; import { @@ -17,7 +18,6 @@ import { import { usePagination } from '../../../../../components/GenericTable/hooks/usePagination'; import { useSort } from '../../../../../components/GenericTable/hooks/useSort'; import { useDirectoryQuery } from '../../../hooks/useDirectoryQuery'; -import TeamsTableRow from './TeamsTableRow'; const TeamsTable = () => { const t = useTranslation(); diff --git a/apps/meteor/client/views/directory/tabs/users/UsersTab.tsx b/apps/meteor/client/views/directory/tabs/users/UsersTab.tsx index da3134ec8a7a0..ac1ad6965096b 100644 --- a/apps/meteor/client/views/directory/tabs/users/UsersTab.tsx +++ b/apps/meteor/client/views/directory/tabs/users/UsersTab.tsx @@ -2,8 +2,8 @@ import { usePermission } from '@rocket.chat/ui-contexts'; import type { ReactElement } from 'react'; import React from 'react'; -import NotAuthorizedPage from '../../../notAuthorized/NotAuthorizedPage'; import UsersTable from './UsersTable'; +import NotAuthorizedPage from '../../../notAuthorized/NotAuthorizedPage'; const UsersTab = (props: { workspace?: 'external' | 'local' }): ReactElement => { const canViewOutsideRoom = usePermission('view-outside-room'); diff --git a/apps/meteor/client/views/directory/tabs/users/UsersTable/UsersTable.tsx b/apps/meteor/client/views/directory/tabs/users/UsersTable/UsersTable.tsx index f9f94f86dd476..00ccc5ef436c6 100644 --- a/apps/meteor/client/views/directory/tabs/users/UsersTable/UsersTable.tsx +++ b/apps/meteor/client/views/directory/tabs/users/UsersTable/UsersTable.tsx @@ -6,6 +6,7 @@ import { useQuery } from '@tanstack/react-query'; import type { ReactElement } from 'react'; import React, { useCallback, useMemo, useState } from 'react'; +import UsersTableRow from './UsersTableRow'; import FilterByText from '../../../../../components/FilterByText'; import GenericNoResults from '../../../../../components/GenericNoResults'; import { @@ -18,7 +19,6 @@ import { import { usePagination } from '../../../../../components/GenericTable/hooks/usePagination'; import { useSort } from '../../../../../components/GenericTable/hooks/useSort'; import { useDirectoryQuery } from '../../../hooks/useDirectoryQuery'; -import UsersTableRow from './UsersTableRow'; const UsersTable = ({ workspace = 'local' }): ReactElement => { const t = useTranslation(); diff --git a/apps/meteor/client/views/home/CustomHomePage.tsx b/apps/meteor/client/views/home/CustomHomePage.tsx index 16cb3c31744da..90f54e11360c6 100644 --- a/apps/meteor/client/views/home/CustomHomePage.tsx +++ b/apps/meteor/client/views/home/CustomHomePage.tsx @@ -1,10 +1,10 @@ import type { ReactElement } from 'react'; import React from 'react'; -import Page from '../../components/Page/Page'; -import PageScrollableContentWithShadow from '../../components/Page/PageScrollableContentWithShadow'; import HomePageHeader from './HomePageHeader'; import CustomContentCard from './cards/CustomContentCard'; +import Page from '../../components/Page/Page'; +import PageScrollableContentWithShadow from '../../components/Page/PageScrollableContentWithShadow'; const CustomHomePage = (): ReactElement => { return ( diff --git a/apps/meteor/client/views/home/DefaultHomePage.tsx b/apps/meteor/client/views/home/DefaultHomePage.tsx index 19fb03c29171e..9f06d3e09d7a8 100644 --- a/apps/meteor/client/views/home/DefaultHomePage.tsx +++ b/apps/meteor/client/views/home/DefaultHomePage.tsx @@ -3,8 +3,6 @@ import { useAtLeastOnePermission, useSetting, useTranslation, useRole, usePermis import type { ReactElement } from 'react'; import React from 'react'; -import Page from '../../components/Page/Page'; -import PageScrollableContent from '../../components/Page/PageScrollableContent'; import HomePageHeader from './HomePageHeader'; import AddUsersCard from './cards/AddUsersCard'; import CreateChannelsCard from './cards/CreateChannelsCard'; @@ -13,6 +11,8 @@ import DesktopAppsCard from './cards/DesktopAppsCard'; import DocumentationCard from './cards/DocumentationCard'; import JoinRoomsCard from './cards/JoinRoomsCard'; import MobileAppsCard from './cards/MobileAppsCard'; +import Page from '../../components/Page/Page'; +import PageScrollableContent from '../../components/Page/PageScrollableContent'; const CREATE_CHANNEL_PERMISSIONS = ['create-c', 'create-p']; diff --git a/apps/meteor/client/views/home/HomePage.tsx b/apps/meteor/client/views/home/HomePage.tsx index 54a627d14fcfa..f99dae9cea299 100644 --- a/apps/meteor/client/views/home/HomePage.tsx +++ b/apps/meteor/client/views/home/HomePage.tsx @@ -2,9 +2,9 @@ import { useSetting } from '@rocket.chat/ui-contexts'; import type { ReactElement } from 'react'; import React, { useEffect } from 'react'; -import { KonchatNotification } from '../../../app/ui/client/lib/KonchatNotification'; import CustomHomePage from './CustomHomePage'; import DefaultHomePage from './DefaultHomePage'; +import { KonchatNotification } from '../../../app/ui/client/lib/KonchatNotification'; const HomePage = (): ReactElement => { useEffect(() => { diff --git a/apps/meteor/client/views/marketplace/AppDetailsPage/AppDetailsPage.tsx b/apps/meteor/client/views/marketplace/AppDetailsPage/AppDetailsPage.tsx index f594dcfa1f212..f3b3cabf1f568 100644 --- a/apps/meteor/client/views/marketplace/AppDetailsPage/AppDetailsPage.tsx +++ b/apps/meteor/client/views/marketplace/AppDetailsPage/AppDetailsPage.tsx @@ -7,19 +7,19 @@ import type { ReactElement } from 'react'; import React, { useMemo, useCallback } from 'react'; import { FormProvider, useForm } from 'react-hook-form'; -import { AppClientOrchestratorInstance } from '../../../apps/orchestrator'; -import { Page, PageFooter, PageHeader, PageScrollableContentWithShadow } from '../../../components/Page'; -import { handleAPIError } from '../helpers/handleAPIError'; -import { useAppInfo } from '../hooks/useAppInfo'; import AppDetailsPageHeader from './AppDetailsPageHeader'; import AppDetailsPageLoading from './AppDetailsPageLoading'; import AppDetailsPageTabs from './AppDetailsPageTabs'; +import { handleAPIError } from '../helpers/handleAPIError'; +import { useAppInfo } from '../hooks/useAppInfo'; import AppDetails from './tabs/AppDetails'; import AppLogs from './tabs/AppLogs'; import AppReleases from './tabs/AppReleases'; import AppRequests from './tabs/AppRequests/AppRequests'; import AppSecurity from './tabs/AppSecurity/AppSecurity'; import AppSettings from './tabs/AppSettings'; +import { AppClientOrchestratorInstance } from '../../../apps/orchestrator'; +import { Page, PageFooter, PageHeader, PageScrollableContentWithShadow } from '../../../components/Page'; const AppDetailsPage = ({ id }: { id: App['id'] }): ReactElement => { const t = useTranslation(); diff --git a/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppDetails/AppDetails.tsx b/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppDetails/AppDetails.tsx index 917b4de07bc2c..e55ee6dd9f1fc 100644 --- a/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppDetails/AppDetails.tsx +++ b/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppDetails/AppDetails.tsx @@ -5,14 +5,14 @@ import DOMPurify from 'dompurify'; import React from 'react'; import { useTranslation } from 'react-i18next'; +import AppDetailsAPIs from './AppDetailsAPIs'; +import { normalizeUrl } from './normalizeUrl'; import { useExternalLink } from '../../../../../hooks/useExternalLink'; import { useHasLicenseModule } from '../../../../../hooks/useHasLicenseModule'; import { GET_ADDONS_LINK } from '../../../../admin/subscription/utils/links'; import ScreenshotCarouselAnchor from '../../../components/ScreenshotCarouselAnchor'; import type { AppInfo } from '../../../definitions/AppInfo'; import { purifyOptions } from '../../../lib/purifyOptions'; -import AppDetailsAPIs from './AppDetailsAPIs'; -import { normalizeUrl } from './normalizeUrl'; type AppDetailsProps = { app: AppInfo; diff --git a/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppLogs/AppLogs.tsx b/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppLogs/AppLogs.tsx index 278a72345ddab..251960a24b7cf 100644 --- a/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppLogs/AppLogs.tsx +++ b/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppLogs/AppLogs.tsx @@ -3,10 +3,10 @@ import type { ReactElement } from 'react'; import React from 'react'; import { useTranslation } from 'react-i18next'; +import AppLogsItem from './AppLogsItem'; import { useFormatDateAndTime } from '../../../../../hooks/useFormatDateAndTime'; import AccordionLoading from '../../../components/AccordionLoading'; import { useLogs } from '../../../hooks/useLogs'; -import AppLogsItem from './AppLogsItem'; const AppLogs = ({ id }: { id: string }): ReactElement => { const { t } = useTranslation(); diff --git a/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppReleases/AppReleases.tsx b/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppReleases/AppReleases.tsx index 2514e72fc0cf7..c907330f6a5af 100644 --- a/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppReleases/AppReleases.tsx +++ b/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppReleases/AppReleases.tsx @@ -6,8 +6,8 @@ import type { ReactElement } from 'react'; import React from 'react'; import { useTranslation } from 'react-i18next'; -import AccordionLoading from '../../../components/AccordionLoading'; import AppReleasesItem from './AppReleasesItem'; +import AccordionLoading from '../../../components/AccordionLoading'; const AppReleases = ({ id }: { id: App['id'] }): ReactElement => { const getVersions = useEndpoint('GET', '/apps/:id/versions', { id }); diff --git a/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppRequests/AppRequests.tsx b/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppRequests/AppRequests.tsx index c2964c9b83e04..60e4819f56f84 100644 --- a/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppRequests/AppRequests.tsx +++ b/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppRequests/AppRequests.tsx @@ -6,11 +6,11 @@ import type { ReactElement, SetStateAction } from 'react'; import React, { useState, useEffect } from 'react'; import { useTranslation } from 'react-i18next'; +import AppRequestItem from './AppRequestItem'; +import AppRequestsLoading from './AppRequestsLoading'; import { useAppsReload } from '../../../../../contexts/hooks/useAppsReload'; import { queryClient } from '../../../../../lib/queryClient'; import { useAppRequests } from '../../../hooks/useAppRequests'; -import AppRequestItem from './AppRequestItem'; -import AppRequestsLoading from './AppRequestsLoading'; type itemsPerPage = 25 | 50 | 100; diff --git a/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppSecurity/AppSecurity.tsx b/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppSecurity/AppSecurity.tsx index 5554bde2651c7..56bb42825f18f 100644 --- a/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppSecurity/AppSecurity.tsx +++ b/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppSecurity/AppSecurity.tsx @@ -4,8 +4,8 @@ import type { ReactElement } from 'react'; import React from 'react'; import { useTranslation } from 'react-i18next'; -import AppPermissionsList from '../../../components/AppPermissionsList'; import AppSecurityLabel from './AppSecurityLabel'; +import AppPermissionsList from '../../../components/AppPermissionsList'; type AppSecurityProps = { privacyPolicySummary?: string; diff --git a/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppSettings/AppSettings.tsx b/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppSettings/AppSettings.tsx index 59080c7f32377..72ad863787472 100644 --- a/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppSettings/AppSettings.tsx +++ b/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppSettings/AppSettings.tsx @@ -2,8 +2,8 @@ import { Box, FieldGroup } from '@rocket.chat/fuselage'; import React from 'react'; import { useTranslation } from 'react-i18next'; -import type { ISettings } from '../../../../../apps/@types/IOrchestrator'; import AppSetting from './AppSetting'; +import type { ISettings } from '../../../../../apps/@types/IOrchestrator'; const AppSettings = ({ settings }: { settings: ISettings }) => { const { t } = useTranslation(); diff --git a/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppStatus/AppStatus.spec.tsx b/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppStatus/AppStatus.spec.tsx index 3d48bb398e266..ccf0c9d426ec7 100644 --- a/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppStatus/AppStatus.spec.tsx +++ b/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppStatus/AppStatus.spec.tsx @@ -4,9 +4,9 @@ import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import React from 'react'; +import AppStatus from './AppStatus'; import { mockedAppsContext } from '../../../../../../tests/mocks/client/marketplace'; import { createFakeApp, createFakeLicenseInfo } from '../../../../../../tests/mocks/data'; -import AppStatus from './AppStatus'; it('should look good', async () => { const app = createFakeApp(); diff --git a/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppStatus/AppStatus.tsx b/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppStatus/AppStatus.tsx index f0339e6daee4f..5608c78684117 100644 --- a/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppStatus/AppStatus.tsx +++ b/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppStatus/AppStatus.tsx @@ -8,6 +8,7 @@ import React, { useCallback, useState, memo } from 'react'; import { useTranslation } from 'react-i18next'; import semver from 'semver'; +import AppStatusPriceDisplay from './AppStatusPriceDisplay'; import { useHasLicenseModule } from '../../../../../hooks/useHasLicenseModule'; import { useIsEnterprise } from '../../../../../hooks/useIsEnterprise'; import AddonRequiredModal from '../../../AppsList/AddonRequiredModal'; @@ -16,7 +17,6 @@ import { appButtonProps, appMultiStatusProps } from '../../../helpers'; import type { AppInstallationHandlerParams } from '../../../hooks/useAppInstallationHandler'; import { useAppInstallationHandler } from '../../../hooks/useAppInstallationHandler'; import { useMarketplaceActions } from '../../../hooks/useMarketplaceActions'; -import AppStatusPriceDisplay from './AppStatusPriceDisplay'; type AppStatusProps = { app: App; diff --git a/apps/meteor/client/views/marketplace/AppExemptModal.tsx b/apps/meteor/client/views/marketplace/AppExemptModal.tsx new file mode 100644 index 0000000000000..ed386b27df0c4 --- /dev/null +++ b/apps/meteor/client/views/marketplace/AppExemptModal.tsx @@ -0,0 +1,49 @@ +import { Box, Modal } from '@rocket.chat/fuselage'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; + +import GenericModal from '../../components/GenericModal'; +import { useExternalLink } from '../../hooks/useExternalLink'; +import { useCheckoutUrl } from '../admin/subscription/hooks/useCheckoutUrl'; +import { PRICING_LINK } from '../admin/subscription/utils/links'; + +type AppExemptModalProps = { + onCancel: () => void; + appName: string; +}; + +const AppExemptModal = ({ onCancel, appName }: AppExemptModalProps) => { + const { t } = useTranslation(); + + const openExternalLink = useExternalLink(); + const manageSubscriptionUrl = useCheckoutUrl()({ target: 'private-apps-page', action: 'upgrade' }); + + const goToManageSubscriptionPage = (): void => { + openExternalLink(manageSubscriptionUrl); + onCancel(); + }; + + return ( + + + {t('Compare_plans')} + + + } + variant='warning' + cancelText={t('Cancel')} + confirmText={t('Upgrade')} + onCancel={onCancel} + onConfirm={goToManageSubscriptionPage} + > + {t('Apps_Private_App_Is_Exempt', { appName })} + {t('Upgrade_subscription_to_enable_private_apps')} + + ); +}; + +export default AppExemptModal; diff --git a/apps/meteor/client/views/marketplace/AppInstallPage.tsx b/apps/meteor/client/views/marketplace/AppInstallPage.tsx index 68ecc313991ab..dfc58b5a47bf2 100644 --- a/apps/meteor/client/views/marketplace/AppInstallPage.tsx +++ b/apps/meteor/client/views/marketplace/AppInstallPage.tsx @@ -4,9 +4,9 @@ import { useTranslation, useRouter } from '@rocket.chat/ui-contexts'; import React, { useCallback } from 'react'; import { useForm, Controller } from 'react-hook-form'; +import { useInstallApp } from './hooks/useInstallApp'; import { Page, PageHeader, PageScrollableContent } from '../../components/Page'; import { useSingleFileInput } from '../../hooks/useSingleFileInput'; -import { useInstallApp } from './hooks/useInstallApp'; const AppInstallPage = () => { const t = useTranslation(); diff --git a/apps/meteor/client/views/marketplace/AppMenu.spec.tsx b/apps/meteor/client/views/marketplace/AppMenu.spec.tsx index 00316b1930142..3f231f59a9eb0 100644 --- a/apps/meteor/client/views/marketplace/AppMenu.spec.tsx +++ b/apps/meteor/client/views/marketplace/AppMenu.spec.tsx @@ -3,9 +3,9 @@ import { mockAppRoot } from '@rocket.chat/mock-providers'; import { render, screen } from '@testing-library/react'; import React from 'react'; +import AppMenu from './AppMenu'; import { mockedAppsContext } from '../../../tests/mocks/client/marketplace'; import { createFakeApp } from '../../../tests/mocks/data'; -import AppMenu from './AppMenu'; describe('without app details', () => { it('should look good', async () => { diff --git a/apps/meteor/client/views/marketplace/AppPermissionsReviewModal.tsx b/apps/meteor/client/views/marketplace/AppPermissionsReviewModal.tsx index d06c6bc9f2f51..721a904a43a98 100644 --- a/apps/meteor/client/views/marketplace/AppPermissionsReviewModal.tsx +++ b/apps/meteor/client/views/marketplace/AppPermissionsReviewModal.tsx @@ -3,8 +3,8 @@ import { Box } from '@rocket.chat/fuselage'; import React from 'react'; import { useTranslation } from 'react-i18next'; -import GenericModal from '../../components/GenericModal'; import AppPermissionsList from './components/AppPermissionsList'; +import GenericModal from '../../components/GenericModal'; export type AppPermissionsReviewModalProps = { appPermissions: App['permissions']; diff --git a/apps/meteor/client/views/marketplace/AppsPage/AppsPage.tsx b/apps/meteor/client/views/marketplace/AppsPage/AppsPage.tsx index af0b8f384c8ad..729b4ea11f479 100644 --- a/apps/meteor/client/views/marketplace/AppsPage/AppsPage.tsx +++ b/apps/meteor/client/views/marketplace/AppsPage/AppsPage.tsx @@ -1,8 +1,8 @@ import type { ReactElement } from 'react'; import React from 'react'; -import { Page } from '../../../components/Page'; import AppsPageContent from './AppsPageContent'; +import { Page } from '../../../components/Page'; const AppsPage = (): ReactElement => { return ( diff --git a/apps/meteor/client/views/marketplace/AppsPage/AppsPageContent.tsx b/apps/meteor/client/views/marketplace/AppsPage/AppsPageContent.tsx index 7bf6bf3000edf..699257c7f357f 100644 --- a/apps/meteor/client/views/marketplace/AppsPage/AppsPageContent.tsx +++ b/apps/meteor/client/views/marketplace/AppsPage/AppsPageContent.tsx @@ -4,15 +4,6 @@ import type { ReactElement } from 'react'; import React, { useEffect, useMemo, useState, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; -import { usePagination } from '../../../components/GenericTable/hooks/usePagination'; -import { useAppsResult } from '../../../contexts/hooks/useAppsResult'; -import { AsyncStatePhase } from '../../../lib/asyncState'; -import MarketplaceHeader from '../components/MarketplaceHeader'; -import type { RadioDropDownGroup } from '../definitions/RadioDropDownDefinitions'; -import { useCategories } from '../hooks/useCategories'; -import type { appsDataType } from '../hooks/useFilteredApps'; -import { useFilteredApps } from '../hooks/useFilteredApps'; -import { useRadioToggle } from '../hooks/useRadioToggle'; import AppsFilters from './AppsFilters'; import AppsPageConnectionError from './AppsPageConnectionError'; import AppsPageContentBody from './AppsPageContentBody'; @@ -23,6 +14,15 @@ import NoInstalledAppsEmptyState from './NoInstalledAppsEmptyState'; import NoMarketplaceOrInstalledAppMatchesEmptyState from './NoMarketplaceOrInstalledAppMatchesEmptyState'; import PrivateEmptyState from './PrivateEmptyState'; import UnsupportedEmptyState from './UnsupportedEmptyState'; +import { usePagination } from '../../../components/GenericTable/hooks/usePagination'; +import { useAppsResult } from '../../../contexts/hooks/useAppsResult'; +import { AsyncStatePhase } from '../../../lib/asyncState'; +import MarketplaceHeader from '../components/MarketplaceHeader'; +import type { RadioDropDownGroup } from '../definitions/RadioDropDownDefinitions'; +import { useCategories } from '../hooks/useCategories'; +import { useFilteredApps } from '../hooks/useFilteredApps'; +import type { appsDataType } from '../hooks/useFilteredApps'; +import { useRadioToggle } from '../hooks/useRadioToggle'; type AppsContext = 'explore' | 'installed' | 'premium' | 'private' | 'requested'; diff --git a/apps/meteor/client/views/marketplace/AppsPage/PrivateEmptyState.spec.tsx b/apps/meteor/client/views/marketplace/AppsPage/PrivateEmptyState.spec.tsx index c2d309d6102fb..8725d5e8f29f9 100644 --- a/apps/meteor/client/views/marketplace/AppsPage/PrivateEmptyState.spec.tsx +++ b/apps/meteor/client/views/marketplace/AppsPage/PrivateEmptyState.spec.tsx @@ -2,9 +2,9 @@ import { mockAppRoot } from '@rocket.chat/mock-providers'; import { render, screen } from '@testing-library/react'; import React from 'react'; +import PrivateEmptyState from './PrivateEmptyState'; import { AppsContext } from '../../../contexts/AppsContext'; import { asyncState } from '../../../lib/asyncState'; -import PrivateEmptyState from './PrivateEmptyState'; describe('with private apps enabled', () => { const appRoot = mockAppRoot() diff --git a/apps/meteor/client/views/marketplace/AppsPage/PrivateEmptyState.tsx b/apps/meteor/client/views/marketplace/AppsPage/PrivateEmptyState.tsx index aaa2be18ee3f8..a7c345f86a628 100644 --- a/apps/meteor/client/views/marketplace/AppsPage/PrivateEmptyState.tsx +++ b/apps/meteor/client/views/marketplace/AppsPage/PrivateEmptyState.tsx @@ -1,9 +1,9 @@ import { Box } from '@rocket.chat/fuselage'; import React from 'react'; -import { usePrivateAppsEnabled } from '../hooks/usePrivateAppsEnabled'; import PrivateEmptyStateDefault from './PrivateEmptyStateDefault'; import PrivateEmptyStateUpgrade from './PrivateEmptyStateUpgrade'; +import { usePrivateAppsEnabled } from '../hooks/usePrivateAppsEnabled'; const PrivateEmptyState = () => { const privateAppsEnabled = usePrivateAppsEnabled(); diff --git a/apps/meteor/client/views/marketplace/AppsPage/UnsupportedEmptyState.spec.tsx b/apps/meteor/client/views/marketplace/AppsPage/UnsupportedEmptyState.spec.tsx index d53da3c55f615..2d801b6e3b605 100644 --- a/apps/meteor/client/views/marketplace/AppsPage/UnsupportedEmptyState.spec.tsx +++ b/apps/meteor/client/views/marketplace/AppsPage/UnsupportedEmptyState.spec.tsx @@ -2,9 +2,9 @@ import { mockAppRoot } from '@rocket.chat/mock-providers'; import { render, screen } from '@testing-library/react'; import React from 'react'; +import UnsupportedEmptyState from './UnsupportedEmptyState'; import { AppsContext } from '../../../contexts/AppsContext'; import { asyncState } from '../../../lib/asyncState'; -import UnsupportedEmptyState from './UnsupportedEmptyState'; describe('with private apps enabled', () => { const appRoot = mockAppRoot() diff --git a/apps/meteor/client/views/marketplace/AppsRoute.tsx b/apps/meteor/client/views/marketplace/AppsRoute.tsx index d779ae459d4d7..908d8f8579d35 100644 --- a/apps/meteor/client/views/marketplace/AppsRoute.tsx +++ b/apps/meteor/client/views/marketplace/AppsRoute.tsx @@ -2,13 +2,13 @@ import { useRouteParameter, useRoute, usePermission } from '@rocket.chat/ui-cont import type { ReactElement } from 'react'; import React, { useState, useEffect } from 'react'; -import PageSkeleton from '../../components/PageSkeleton'; -import AppsProvider from '../../providers/AppsProvider'; -import NotAuthorizedPage from '../notAuthorized/NotAuthorizedPage'; import AppDetailsPage from './AppDetailsPage'; import AppInstallPage from './AppInstallPage'; import AppsPage from './AppsPage'; import BannerEnterpriseTrialEnded from './components/BannerEnterpriseTrialEnded'; +import PageSkeleton from '../../components/PageSkeleton'; +import AppsProvider from '../../providers/AppsProvider'; +import NotAuthorizedPage from '../notAuthorized/NotAuthorizedPage'; const AppsRoute = (): ReactElement => { const [isLoading, setLoading] = useState(true); diff --git a/apps/meteor/client/views/marketplace/MarketplaceRouter.tsx b/apps/meteor/client/views/marketplace/MarketplaceRouter.tsx index f2b3218218213..2dc5ff1df6c6e 100644 --- a/apps/meteor/client/views/marketplace/MarketplaceRouter.tsx +++ b/apps/meteor/client/views/marketplace/MarketplaceRouter.tsx @@ -2,10 +2,10 @@ import { useAtLeastOnePermission, useRoute, useRouteParameter } from '@rocket.ch import type { ReactElement, ReactNode } from 'react'; import React, { Suspense, useEffect } from 'react'; +import MarketPlaceSidebar from './MarketplaceSidebar'; import PageSkeleton from '../../components/PageSkeleton'; import SidebarPortal from '../../sidebar/SidebarPortal'; import NotFoundPage from '../notFound/NotFoundPage'; -import MarketPlaceSidebar from './MarketplaceSidebar'; const MarketplaceRouter = ({ children }: { children?: ReactNode }): ReactElement => { const currentContext = useRouteParameter('context') || 'all'; diff --git a/apps/meteor/client/views/marketplace/MarketplaceSidebar.tsx b/apps/meteor/client/views/marketplace/MarketplaceSidebar.tsx index df851c0c1d3db..72e084eb13574 100644 --- a/apps/meteor/client/views/marketplace/MarketplaceSidebar.tsx +++ b/apps/meteor/client/views/marketplace/MarketplaceSidebar.tsx @@ -3,10 +3,10 @@ import type { ReactElement } from 'react'; import React, { memo } from 'react'; import { useSyncExternalStore } from 'use-sync-external-store/shim'; +import { getMarketplaceSidebarItems, subscribeToMarketplaceSidebarItems } from './sidebarItems'; import Sidebar from '../../components/Sidebar'; import SidebarItemsAssembler from '../../components/Sidebar/SidebarItemsAssembler'; import SettingsProvider from '../../providers/SettingsProvider'; -import { getMarketplaceSidebarItems, subscribeToMarketplaceSidebarItems } from './sidebarItems'; const MarketplaceSidebar = (): ReactElement => { const items = useSyncExternalStore(subscribeToMarketplaceSidebarItems, getMarketplaceSidebarItems); diff --git a/apps/meteor/client/views/marketplace/components/CategoryFilter/CategoryDropDown.stories.tsx b/apps/meteor/client/views/marketplace/components/CategoryFilter/CategoryDropDown.stories.tsx index b4e16445bb812..3bfc89a0bce45 100644 --- a/apps/meteor/client/views/marketplace/components/CategoryFilter/CategoryDropDown.stories.tsx +++ b/apps/meteor/client/views/marketplace/components/CategoryFilter/CategoryDropDown.stories.tsx @@ -2,13 +2,13 @@ import { Box, ButtonGroup } from '@rocket.chat/fuselage'; import type { StoryFn } from '@storybook/react'; import React, { useState } from 'react'; -import type { CategoryDropDownListProps } from '../../definitions/CategoryDropdownDefinitions'; -import { useCategories } from '../../hooks/useCategories'; -import { useCategoryToggle } from '../../hooks/useCategoryToggle'; import CategoryDropDown from './CategoryDropDown'; import CategoryDropDownAnchor from './CategoryDropDownAnchor'; import CategoryDropDownList from './CategoryDropDownList'; import TagList from './TagList'; +import type { CategoryDropDownListProps } from '../../definitions/CategoryDropdownDefinitions'; +import { useCategories } from '../../hooks/useCategories'; +import { useCategoryToggle } from '../../hooks/useCategoryToggle'; export default { title: 'Admin/Apps/CategoryDropDown', diff --git a/apps/meteor/client/views/marketplace/components/MarketplaceHeader.tsx b/apps/meteor/client/views/marketplace/components/MarketplaceHeader.tsx index fc847ee30d131..0be91b54228b0 100644 --- a/apps/meteor/client/views/marketplace/components/MarketplaceHeader.tsx +++ b/apps/meteor/client/views/marketplace/components/MarketplaceHeader.tsx @@ -8,9 +8,9 @@ import { GenericResourceUsageSkeleton } from '../../../components/GenericResourc import { PageHeader } from '../../../components/Page'; import UpgradeButton from '../../admin/subscription/components/UpgradeButton'; import UnlimitedAppsUpsellModal from '../UnlimitedAppsUpsellModal'; +import EnabledAppsCount from './EnabledAppsCount'; import { useAppsCountQuery } from '../hooks/useAppsCountQuery'; import { usePrivateAppsEnabled } from '../hooks/usePrivateAppsEnabled'; -import EnabledAppsCount from './EnabledAppsCount'; import PrivateAppInstallModal from './PrivateAppInstallModal/PrivateAppInstallModal'; import UpdateRocketChatButton from './UpdateRocketChatButton'; diff --git a/apps/meteor/client/views/marketplace/helpers.ts b/apps/meteor/client/views/marketplace/helpers.ts index 5307b007b1c36..08bf9667ade58 100644 --- a/apps/meteor/client/views/marketplace/helpers.ts +++ b/apps/meteor/client/views/marketplace/helpers.ts @@ -3,8 +3,8 @@ import type { App } from '@rocket.chat/core-typings'; import semver from 'semver'; // import { t } from '../../../app/utils/client'; -import { t } from '../../../app/utils/lib/i18n'; import { appErroredStatuses } from './helpers/appErroredStatuses'; +import { t } from '../../../app/utils/lib/i18n'; export const appEnabledStatuses = [AppStatus.AUTO_ENABLED, AppStatus.MANUALLY_ENABLED]; diff --git a/apps/meteor/client/views/marketplace/helpers/formatPricingPlan.ts b/apps/meteor/client/views/marketplace/helpers/formatPricingPlan.ts index fcd591b8df21b..b65745a497329 100644 --- a/apps/meteor/client/views/marketplace/helpers/formatPricingPlan.ts +++ b/apps/meteor/client/views/marketplace/helpers/formatPricingPlan.ts @@ -1,7 +1,7 @@ import type { AppPricingPlan } from '@rocket.chat/core-typings'; -import { t } from '../../../../app/utils/lib/i18n'; import { formatPrice } from './formatPrice'; +import { t } from '../../../../app/utils/lib/i18n'; export const formatPricingPlan = ({ strategy, price, tiers = [], trialDays }: AppPricingPlan): string => { const { perUnit = false } = (Array.isArray(tiers) && tiers.find((tier) => tier.price === price)) || {}; diff --git a/apps/meteor/client/views/marketplace/helpers/installApp.ts b/apps/meteor/client/views/marketplace/helpers/installApp.ts index 1021ab16ffd91..e1d1256d16e25 100644 --- a/apps/meteor/client/views/marketplace/helpers/installApp.ts +++ b/apps/meteor/client/views/marketplace/helpers/installApp.ts @@ -1,8 +1,8 @@ import type { App, AppPermission } from '@rocket.chat/core-typings'; -import { AppClientOrchestratorInstance } from '../../../apps/orchestrator'; import { handleAPIError } from './handleAPIError'; import { warnAppInstall } from './warnAppInstall'; +import { AppClientOrchestratorInstance } from '../../../apps/orchestrator'; type installAppProps = App & { permissionsGranted?: AppPermission[]; diff --git a/apps/meteor/client/views/marketplace/helpers/updateApp.ts b/apps/meteor/client/views/marketplace/helpers/updateApp.ts index 076478717ad4b..d6d558b157300 100644 --- a/apps/meteor/client/views/marketplace/helpers/updateApp.ts +++ b/apps/meteor/client/views/marketplace/helpers/updateApp.ts @@ -1,8 +1,8 @@ import type { App, AppPermission } from '@rocket.chat/core-typings'; -import { AppClientOrchestratorInstance } from '../../../apps/orchestrator'; import { handleAPIError } from './handleAPIError'; import { warnStatusChange } from './warnStatusChange'; +import { AppClientOrchestratorInstance } from '../../../apps/orchestrator'; type updateAppProps = App & { permissionsGranted?: AppPermission[]; diff --git a/apps/meteor/client/views/marketplace/helpers/warnAppInstall.ts b/apps/meteor/client/views/marketplace/helpers/warnAppInstall.ts index 78d40829c0ce7..e130098a99a89 100644 --- a/apps/meteor/client/views/marketplace/helpers/warnAppInstall.ts +++ b/apps/meteor/client/views/marketplace/helpers/warnAppInstall.ts @@ -1,8 +1,8 @@ import type { AppStatus } from '@rocket.chat/apps-engine/definition/AppStatus'; +import { appErroredStatuses } from './appErroredStatuses'; import { t } from '../../../../app/utils/lib/i18n'; import { dispatchToastMessage } from '../../../lib/toast'; -import { appErroredStatuses } from './appErroredStatuses'; export const warnAppInstall = (appName: string, status: AppStatus): void => { if (appErroredStatuses.includes(status)) { diff --git a/apps/meteor/client/views/marketplace/helpers/warnEnableDisableApp.ts b/apps/meteor/client/views/marketplace/helpers/warnEnableDisableApp.ts index 2ca50d67c7849..79e55cea62755 100644 --- a/apps/meteor/client/views/marketplace/helpers/warnEnableDisableApp.ts +++ b/apps/meteor/client/views/marketplace/helpers/warnEnableDisableApp.ts @@ -1,8 +1,8 @@ import type { AppStatus } from '@rocket.chat/apps-engine/definition/AppStatus'; +import { appErroredStatuses } from './appErroredStatuses'; import { t } from '../../../../app/utils/lib/i18n'; import { dispatchToastMessage } from '../../../lib/toast'; -import { appErroredStatuses } from './appErroredStatuses'; export const warnEnableDisableApp = (appName: string, status: AppStatus, type: string): void => { if (appErroredStatuses.includes(status)) { diff --git a/apps/meteor/client/views/marketplace/helpers/warnStatusChange.ts b/apps/meteor/client/views/marketplace/helpers/warnStatusChange.ts index 3fc01514ec768..db1979583ea5f 100644 --- a/apps/meteor/client/views/marketplace/helpers/warnStatusChange.ts +++ b/apps/meteor/client/views/marketplace/helpers/warnStatusChange.ts @@ -1,8 +1,8 @@ import type { AppStatus } from '@rocket.chat/apps-engine/definition/AppStatus'; +import { appErroredStatuses } from './appErroredStatuses'; import { t } from '../../../../app/utils/lib/i18n'; import { dispatchToastMessage } from '../../../lib/toast'; -import { appErroredStatuses } from './appErroredStatuses'; export const warnStatusChange = (appName: string, status: AppStatus): void => { if (appErroredStatuses.includes(status)) { diff --git a/apps/meteor/client/views/marketplace/hooks/useAppInstallationHandler.tsx b/apps/meteor/client/views/marketplace/hooks/useAppInstallationHandler.tsx index 42bf388648941..a69582a64d1a4 100644 --- a/apps/meteor/client/views/marketplace/hooks/useAppInstallationHandler.tsx +++ b/apps/meteor/client/views/marketplace/hooks/useAppInstallationHandler.tsx @@ -2,16 +2,16 @@ import type { App } from '@rocket.chat/core-typings'; import { useEndpoint, useRouteParameter, useSetModal, useToastMessageDispatch } from '@rocket.chat/ui-contexts'; import React, { useCallback } from 'react'; +import { isMarketplaceRouteContext, useAppsCountQuery } from './useAppsCountQuery'; +import { useOpenAppPermissionsReviewModal } from './useOpenAppPermissionsReviewModal'; import { useExternalLink } from '../../../hooks/useExternalLink'; import { useCheckoutUrl } from '../../admin/subscription/hooks/useCheckoutUrl'; import IframeModal from '../IframeModal'; import AppInstallModal from '../components/AppInstallModal/AppInstallModal'; import type { Actions } from '../helpers'; -import { handleAPIError } from '../helpers/handleAPIError'; -import { isMarketplaceRouteContext, useAppsCountQuery } from './useAppsCountQuery'; import { useAppsOrchestration } from './useAppsOrchestration'; -import { useOpenAppPermissionsReviewModal } from './useOpenAppPermissionsReviewModal'; import { useOpenIncompatibleModal } from './useOpenIncompatibleModal'; +import { handleAPIError } from '../helpers/handleAPIError'; export type AppInstallationHandlerParams = { app: App; diff --git a/apps/meteor/client/views/marketplace/hooks/useAppMenu.tsx b/apps/meteor/client/views/marketplace/hooks/useAppMenu.tsx index b47e48299735a..820c0c52965a3 100644 --- a/apps/meteor/client/views/marketplace/hooks/useAppMenu.tsx +++ b/apps/meteor/client/views/marketplace/hooks/useAppMenu.tsx @@ -14,6 +14,12 @@ import type { MouseEvent, ReactNode } from 'react'; import React, { useMemo, useCallback, useState } from 'react'; import semver from 'semver'; +import { useAppInstallationHandler } from './useAppInstallationHandler'; +import type { MarketplaceRouteContext } from './useAppsCountQuery'; +import { useAppsCountQuery } from './useAppsCountQuery'; +import { useMarketplaceActions } from './useMarketplaceActions'; +import { useOpenAppPermissionsReviewModal } from './useOpenAppPermissionsReviewModal'; +import { useOpenIncompatibleModal } from './useOpenIncompatibleModal'; import WarningModal from '../../../components/WarningModal'; import { useHasLicenseModule } from '../../../hooks/useHasLicenseModule'; import { useIsEnterprise } from '../../../hooks/useIsEnterprise'; @@ -25,12 +31,6 @@ import type { Actions } from '../helpers'; import { appEnabledStatuses, appButtonProps } from '../helpers'; import { handleAPIError } from '../helpers/handleAPIError'; import { warnEnableDisableApp } from '../helpers/warnEnableDisableApp'; -import { useAppInstallationHandler } from './useAppInstallationHandler'; -import type { MarketplaceRouteContext } from './useAppsCountQuery'; -import { useAppsCountQuery } from './useAppsCountQuery'; -import { useMarketplaceActions } from './useMarketplaceActions'; -import { useOpenAppPermissionsReviewModal } from './useOpenAppPermissionsReviewModal'; -import { useOpenIncompatibleModal } from './useOpenIncompatibleModal'; export type AppMenuOption = { id: string; diff --git a/apps/meteor/client/views/marketplace/hooks/useCategories.ts b/apps/meteor/client/views/marketplace/hooks/useCategories.ts index 17a7c878e6e4c..4a1169ee151ec 100644 --- a/apps/meteor/client/views/marketplace/hooks/useCategories.ts +++ b/apps/meteor/client/views/marketplace/hooks/useCategories.ts @@ -1,6 +1,8 @@ import { useCallback, useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; +import { useCategoryFlatList } from './useCategoryFlatList'; +import { useCategoryToggle } from './useCategoryToggle'; import { AppClientOrchestratorInstance } from '../../../apps/orchestrator'; import type { CategoryDropDownGroups, @@ -10,8 +12,6 @@ import type { selectedCategoriesList, } from '../definitions/CategoryDropdownDefinitions'; import { handleAPIError } from '../helpers/handleAPIError'; -import { useCategoryFlatList } from './useCategoryFlatList'; -import { useCategoryToggle } from './useCategoryToggle'; export const useCategories = (): [CategoryDropDownGroups, selectedCategoriesList, selectedCategoriesList, CategoryOnSelected] => { const { t } = useTranslation(); diff --git a/apps/meteor/client/views/marketplace/hooks/useInstallApp.tsx b/apps/meteor/client/views/marketplace/hooks/useInstallApp.tsx index 16499c0b07a20..cf9ea98d933b6 100644 --- a/apps/meteor/client/views/marketplace/hooks/useInstallApp.tsx +++ b/apps/meteor/client/views/marketplace/hooks/useInstallApp.tsx @@ -5,12 +5,14 @@ import React, { useCallback, useState } from 'react'; import { AppClientOrchestratorInstance } from '../../../apps/orchestrator'; import { useAppsReload } from '../../../contexts/hooks/useAppsReload'; +import { useIsEnterprise } from '../../../hooks/useIsEnterprise'; +import AppExemptModal from '../AppExemptModal'; import AppPermissionsReviewModal from '../AppPermissionsReviewModal'; import AppUpdateModal from '../AppUpdateModal'; +import { useAppsCountQuery } from './useAppsCountQuery'; import { handleAPIError } from '../helpers/handleAPIError'; import { handleInstallError } from '../helpers/handleInstallError'; import { getManifestFromZippedApp } from '../lib/getManifestFromZippedApp'; -import { useAppsCountQuery } from './useAppsCountQuery'; export const useInstallApp = (file: File): { install: () => void; isInstalling: boolean } => { const reloadAppsList = useAppsReload(); @@ -22,6 +24,7 @@ export const useInstallApp = (file: File): { install: () => void; isInstalling: const uploadAppEndpoint = useUpload('/apps'); const uploadUpdateEndpoint = useUpload('/apps/update'); + const { data } = useIsEnterprise(); const [isInstalling, setInstalling] = useState(false); @@ -87,6 +90,11 @@ export const useInstallApp = (file: File): { install: () => void; isInstalling: const uploadFile = async (appFile: File, { id, permissions }: { id: string; permissions: AppPermission[] }) => { const isInstalled = await isAppInstalled(id); + const isExempt = !data?.isEnterprise && isInstalled; + if (isInstalled && isExempt) { + return setModal(); + } + if (isInstalled) { return setModal( handleAppPermissionsReview(permissions, appFile, id)} />); } diff --git a/apps/meteor/client/views/marketplace/hooks/useMarketplaceActions.ts b/apps/meteor/client/views/marketplace/hooks/useMarketplaceActions.ts index 84882e35de8b1..efc614a90d93c 100644 --- a/apps/meteor/client/views/marketplace/hooks/useMarketplaceActions.ts +++ b/apps/meteor/client/views/marketplace/hooks/useMarketplaceActions.ts @@ -1,10 +1,10 @@ import type { App, AppPermission } from '@rocket.chat/core-typings'; import { useMutation } from '@tanstack/react-query'; +import { useAppsOrchestration } from './useAppsOrchestration'; import { handleAPIError } from '../helpers/handleAPIError'; import { warnAppInstall } from '../helpers/warnAppInstall'; import { warnStatusChange } from '../helpers/warnStatusChange'; -import { useAppsOrchestration } from './useAppsOrchestration'; type InstallAppParams = App & { permissionsGranted?: AppPermission[]; diff --git a/apps/meteor/client/views/marketplace/hooks/useOpenIncompatibleModal.tsx b/apps/meteor/client/views/marketplace/hooks/useOpenIncompatibleModal.tsx index 1645f47f44321..7409e0b608c8c 100644 --- a/apps/meteor/client/views/marketplace/hooks/useOpenIncompatibleModal.tsx +++ b/apps/meteor/client/views/marketplace/hooks/useOpenIncompatibleModal.tsx @@ -2,8 +2,8 @@ import { useSetModal } from '@rocket.chat/ui-contexts'; import React, { useCallback } from 'react'; import IframeModal from '../IframeModal'; -import { handleAPIError } from '../helpers/handleAPIError'; import { useAppsOrchestration } from './useAppsOrchestration'; +import { handleAPIError } from '../helpers/handleAPIError'; export const useOpenIncompatibleModal = () => { const setModal = useSetModal(); diff --git a/apps/meteor/client/views/marketplace/sidebarItems.tsx b/apps/meteor/client/views/marketplace/sidebarItems.tsx index f829cccf32387..985a80151e8bb 100644 --- a/apps/meteor/client/views/marketplace/sidebarItems.tsx +++ b/apps/meteor/client/views/marketplace/sidebarItems.tsx @@ -1,8 +1,8 @@ import React from 'react'; +import MarketplaceRequestBadge from './components/MarketplaceRequestBadge'; import { hasAtLeastOnePermission, hasPermission } from '../../../app/authorization/client'; import { createSidebarItems } from '../../lib/createSidebarItems'; -import MarketplaceRequestBadge from './components/MarketplaceRequestBadge'; export const { registerSidebarItem: registerMarketplaceSidebarItem, diff --git a/apps/meteor/client/views/meet/CallPage.tsx b/apps/meteor/client/views/meet/CallPage.tsx index 97b5c93c3ded2..3ffaa26756898 100644 --- a/apps/meteor/client/views/meet/CallPage.tsx +++ b/apps/meteor/client/views/meet/CallPage.tsx @@ -4,10 +4,10 @@ import { useTranslation, useStream } from '@rocket.chat/ui-contexts'; import moment from 'moment'; import React, { useEffect, useState } from 'react'; +import OngoingCallDuration from './OngoingCallDuration'; import { sdk } from '../../../app/utils/client/lib/SDKClient'; import { WebRTC } from '../../../app/webrtc/client'; import { WEB_RTC_EVENTS } from '../../../app/webrtc/lib/constants'; -import OngoingCallDuration from './OngoingCallDuration'; import './styles.css'; type CallPageProps = { @@ -213,7 +213,7 @@ const CallPage = ({ top: '5%', right: '2%', }} - className='Self_Video' + className='meet__video--self' alignItems='center' backgroundColor='dark' > @@ -250,7 +250,7 @@ const CallPage = ({ square title={isMicOn ? t('Mute_microphone') : t('Unmute_microphone')} onClick={(): any => toggleButton('mic')} - className={isMicOn ? 'On' : 'Off'} + className={isMicOn ? 'meet__button--on' : 'meet__button--off'} size={Number(buttonSize)} > {isMicOn ? : } @@ -260,7 +260,7 @@ const CallPage = ({ square title={isCameraOn ? t('Turn_off_video') : t('Turn_on_video')} onClick={(): void => toggleButton('camera')} - className={isCameraOn ? 'On' : 'Off'} + className={isCameraOn ? 'meet__button--on' : 'meet__button--off'} size={parseInt(buttonSize)} > {isCameraOn ? : } @@ -344,7 +344,7 @@ const CallPage = ({ top: '5%', right: '2%', }} - className='Self_Video' + className='meet__video--self' backgroundColor='dark' alignItems='center' > diff --git a/apps/meteor/client/views/meet/MeetPage.tsx b/apps/meteor/client/views/meet/MeetPage.tsx index 4876c8eb94717..afbfd3ff7294a 100644 --- a/apps/meteor/client/views/meet/MeetPage.tsx +++ b/apps/meteor/client/views/meet/MeetPage.tsx @@ -5,11 +5,11 @@ import { Meteor } from 'meteor/meteor'; import React, { useEffect, useState, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; +import CallPage from './CallPage'; import { sdk } from '../../../app/utils/client/lib/SDKClient'; import { useEmbeddedLayout } from '../../hooks/useEmbeddedLayout'; import NotFoundPage from '../notFound/NotFoundPage'; import PageLoading from '../root/PageLoading'; -import CallPage from './CallPage'; import './styles.css'; const MeetPage = () => { @@ -87,7 +87,7 @@ const MeetPage = () => { top: '5%', right: '2%', }} - className='Self_Video' + className='meet__video--self' backgroundColor='dark' alignItems='center' > diff --git a/apps/meteor/client/views/meet/MeetRoute.tsx b/apps/meteor/client/views/meet/MeetRoute.tsx index bbc20356a30b1..7e2df4e3e342b 100644 --- a/apps/meteor/client/views/meet/MeetRoute.tsx +++ b/apps/meteor/client/views/meet/MeetRoute.tsx @@ -3,9 +3,9 @@ import { useQuery } from '@tanstack/react-query'; import React from 'react'; import { useTranslation } from 'react-i18next'; +import MeetPage from './MeetPage'; import { VisitorDoesNotExistError } from '../../lib/errors/VisitorDoesNotExistError'; import PageLoading from '../root/PageLoading'; -import MeetPage from './MeetPage'; const MeetRoute = () => { const router = useRouter(); diff --git a/apps/meteor/client/views/meet/styles.css b/apps/meteor/client/views/meet/styles.css index 799fd59faec80..6e4b30b45a710 100644 --- a/apps/meteor/client/views/meet/styles.css +++ b/apps/meteor/client/views/meet/styles.css @@ -1,41 +1,49 @@ -.Off { - color: #ffffff !important; - border-color: #2f343d !important; - background-color: #2f343d !important; -} - -.On { - color: #000000 !important; - border-color: #ffffff !important; - background-color: #ffffff !important; -} +.meet { + &__button { + &--off { + color: #ffffff !important; + border-color: #2f343d !important; + background-color: #2f343d !important; + } -.Self_Video { - display: flex; - - width: 15%; - height: 17.5%; + &--on { + color: #000000 !important; + border-color: #ffffff !important; + background-color: #ffffff !important; + } + } - justify-content: center; + &__video--self { + display: flex; + width: 15%; + height: 17.5%; + justify-content: center; + } } -@media (max-width: 900px) and (min-height: 500px) { - .Self_Video { - width: 30%; - height: 20%; +@media (width <= 900px) and (height >= 500px) { + .meet { + &__video--self { + width: 30%; + height: 20%; + } } } -@media (max-width: 900px) and (max-height: 500px) { - .Self_Video { - width: 30%; - height: 35%; +@media (width <= 900px) and (height <= 500px) { + .meet { + &__video--self { + width: 30%; + height: 35%; + } } } -@media (min-width: 901px) and (max-width: 1300px) and (max-height: 500px) { - .Self_Video { - width: 20%; - height: 40%; +@media (width >= 901px) and (width <= 1300px) and (height <= 500px) { + .meet { + &__video--self { + width: 20%; + height: 40%; + } } } diff --git a/apps/meteor/client/views/modal/uikit/ModalBlock.tsx b/apps/meteor/client/views/modal/uikit/ModalBlock.tsx index 402ccb7e27ad5..57016f0df6370 100644 --- a/apps/meteor/client/views/modal/uikit/ModalBlock.tsx +++ b/apps/meteor/client/views/modal/uikit/ModalBlock.tsx @@ -6,8 +6,8 @@ import type { FormEventHandler, ReactElement } from 'react'; import React, { useCallback, useEffect, useMemo, useRef } from 'react'; import { FocusScope } from 'react-aria'; -import { getURL } from '../../../../app/utils/client/getURL'; import { getButtonStyle } from './getButtonStyle'; +import { getURL } from '../../../../app/utils/client/getURL'; const focusableElementsString = ` a[href]:not([tabindex="-1"]), diff --git a/apps/meteor/client/views/modal/uikit/UiKitModal.tsx b/apps/meteor/client/views/modal/uikit/UiKitModal.tsx index 55c6c8a32d71f..fcdaecfacb714 100644 --- a/apps/meteor/client/views/modal/uikit/UiKitModal.tsx +++ b/apps/meteor/client/views/modal/uikit/UiKitModal.tsx @@ -5,12 +5,12 @@ import type * as UiKit from '@rocket.chat/ui-kit'; import React from 'react'; import type { FormEvent } from 'react'; +import ModalBlock from './ModalBlock'; import { detectEmoji } from '../../../lib/utils/detectEmoji'; import { preventSyntheticEvent } from '../../../lib/utils/preventSyntheticEvent'; import { useModalContextValue } from '../../../uikit/hooks/useModalContextValue'; import { useUiKitActionManager } from '../../../uikit/hooks/useUiKitActionManager'; import { useUiKitView } from '../../../uikit/hooks/useUiKitView'; -import ModalBlock from './ModalBlock'; type UiKitModalProps = { key: UiKit.ModalView['id']; // force re-mount when viewId changes diff --git a/apps/meteor/client/views/notFound/NotFoundPage.spec.tsx b/apps/meteor/client/views/notFound/NotFoundPage.spec.tsx index 19d2238cefc4c..868cef2066d83 100644 --- a/apps/meteor/client/views/notFound/NotFoundPage.spec.tsx +++ b/apps/meteor/client/views/notFound/NotFoundPage.spec.tsx @@ -3,8 +3,8 @@ import userEvent from '@testing-library/user-event'; import type { MutableRefObject } from 'react'; import React from 'react'; -import RouterContextMock from '../../../tests/mocks/client/RouterContextMock'; import NotFoundPage from './NotFoundPage'; +import RouterContextMock from '../../../tests/mocks/client/RouterContextMock'; it('should look good', async () => { render(, { legacyRoot: true }); diff --git a/apps/meteor/client/views/oauth/components/AuthorizationFormPage.tsx b/apps/meteor/client/views/oauth/components/AuthorizationFormPage.tsx index 6232143523723..f068a81014ed3 100644 --- a/apps/meteor/client/views/oauth/components/AuthorizationFormPage.tsx +++ b/apps/meteor/client/views/oauth/components/AuthorizationFormPage.tsx @@ -7,9 +7,9 @@ import { Accounts } from 'meteor/accounts-base'; import React, { useEffect, useMemo, useRef } from 'react'; import { Trans, useTranslation } from 'react-i18next'; -import { queueMicrotask } from '../../../lib/utils/queueMicrotask'; import CurrentUserDisplay from './CurrentUserDisplay'; import Layout from './Layout'; +import { queueMicrotask } from '../../../lib/utils/queueMicrotask'; type AuthorizationFormPageProps = { oauthApp: IOAuthApps; @@ -60,14 +60,10 @@ const AuthorizationFormPage = ({ oauthApp, redirectUri, user }: AuthorizationFor

- - The application {{ appName: oauthApp.name }} will be able to: + + {{ appName: oauthApp.name }}

- -
    -
  • {t('core.access_your_basic_information')}
  • -
diff --git a/apps/meteor/client/views/oauth/components/ErrorPage.tsx b/apps/meteor/client/views/oauth/components/ErrorPage.tsx index 812a5badf1149..9c0f0a14e915c 100644 --- a/apps/meteor/client/views/oauth/components/ErrorPage.tsx +++ b/apps/meteor/client/views/oauth/components/ErrorPage.tsx @@ -2,8 +2,8 @@ import { States, StatesIcon, StatesSubtitle, StatesTitle } from '@rocket.chat/fu import React from 'react'; import { useTranslation } from 'react-i18next'; -import { getErrorMessage } from '../../../lib/errorHandling'; import Layout from './Layout'; +import { getErrorMessage } from '../../../lib/errorHandling'; type ErrorPageProps = { error: unknown; diff --git a/apps/meteor/client/views/omnichannel/ExternalFrameContainer.tsx b/apps/meteor/client/views/omnichannel/ExternalFrameContainer.tsx index f1a2e3a7d32bc..f59cf8c0c20c4 100644 --- a/apps/meteor/client/views/omnichannel/ExternalFrameContainer.tsx +++ b/apps/meteor/client/views/omnichannel/ExternalFrameContainer.tsx @@ -39,7 +39,7 @@ function ExternalFrameContainer() { return (
-