From bd231a06ba509f17882fb8aaf4c25d418c28fe2c Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Tue, 11 Jul 2023 18:22:38 -0300 Subject: [PATCH] refactor: Remove Accountbox usage (#29786) --- apps/meteor/app/lib/README.md | 13 --- apps/meteor/app/livechat/client/ui.js | 12 +-- apps/meteor/app/ui-utils/client/index.ts | 1 - .../app/ui-utils/client/lib/AccountBox.ts | 32 ------- .../actions/hooks/useAdministrationItems.tsx | 84 +++++++++++++------ .../actions/hooks/useAdministrationMenu.tsx | 70 ++-------------- .../header/actions/hooks/useAuditItems.tsx | 19 +++-- .../sidebar/header/hooks/useStatusItems.tsx | 10 +-- apps/meteor/client/startup/iframeCommands.ts | 2 +- 9 files changed, 86 insertions(+), 157 deletions(-) diff --git a/apps/meteor/app/lib/README.md b/apps/meteor/app/lib/README.md index 708a9a21790e..5201c4cadf0e 100644 --- a/apps/meteor/app/lib/README.md +++ b/apps/meteor/app/lib/README.md @@ -47,19 +47,6 @@ settingsRegistry.addGroup('Settings_Group', function() { * `enableQuery` - Only enable this setting if the correspondent setting has the value specified * `alert` - Shows an alert message with the given text -### AccountBox - -You can add items to the left upper corner drop menu: -```javascript -AccountBox.addItem({ - name: 'Livechat', - icon: 'icon-chat-empty', - class: 'livechat-manager', - condition: () => { - return RocketChat.authz.hasPermission('view-livechat-manager'); - } -}); -``` ### Functions n/a diff --git a/apps/meteor/app/livechat/client/ui.js b/apps/meteor/app/livechat/client/ui.js index 614b410cda2e..5d8cc1696d44 100644 --- a/apps/meteor/app/livechat/client/ui.js +++ b/apps/meteor/app/livechat/client/ui.js @@ -1,14 +1,4 @@ -import { settings } from '../../settings/client'; -import { hasAllPermission } from '../../authorization/client'; -import { AccountBox, MessageTypes } from '../../ui-utils/client'; - -AccountBox.addItem({ - name: 'Omnichannel', - icon: 'headset', - href: '/omnichannel/current', - sideNav: 'omnichannelFlex', - condition: () => settings.get('Livechat_enabled') && hasAllPermission('view-livechat-manager'), -}); +import { MessageTypes } from '../../ui-utils/client'; MessageTypes.registerType({ id: 'livechat-close', diff --git a/apps/meteor/app/ui-utils/client/index.ts b/apps/meteor/app/ui-utils/client/index.ts index 83a1057a7287..aaa5a0825706 100644 --- a/apps/meteor/app/ui-utils/client/index.ts +++ b/apps/meteor/app/ui-utils/client/index.ts @@ -1,6 +1,5 @@ import './lib/messageActionDefault'; -export { AccountBox } from './lib/AccountBox'; export { MessageAction } from './lib/MessageAction'; export { messageBox } from './lib/messageBox'; export { readMessage } from './lib/readMessages'; diff --git a/apps/meteor/app/ui-utils/client/lib/AccountBox.ts b/apps/meteor/app/ui-utils/client/lib/AccountBox.ts index 3ed3a60b3bf6..c7bda9df1659 100644 --- a/apps/meteor/app/ui-utils/client/lib/AccountBox.ts +++ b/apps/meteor/app/ui-utils/client/lib/AccountBox.ts @@ -1,12 +1,9 @@ import type { IUIActionButton, IUActionButtonWhen } from '@rocket.chat/apps-engine/definition/ui/IUIActionButtonDescriptor'; import type { UserStatus } from '@rocket.chat/core-typings'; -import { ReactiveVar } from 'meteor/reactive-var'; -import { Tracker } from 'meteor/tracker'; import type { TranslationKey, LocationPathname } from '@rocket.chat/ui-contexts'; import type { Icon } from '@rocket.chat/fuselage'; import type { ComponentProps } from 'react'; -import { applyDropdownActionButtonFilters } from '../../../ui-message/client/actionButtons/lib/applyButtonFilters'; import { sdk } from '../../../utils/client/lib/SDKClient'; export interface IAppAccountBoxItem extends IUIActionButton { @@ -30,38 +27,9 @@ export type AccountBoxItem = { export const isAppAccountBoxItem = (item: IAppAccountBoxItem | AccountBoxItem): item is IAppAccountBoxItem => 'isAppButtonItem' in item; class AccountBoxBase { - private items = new ReactiveVar([]); - public setStatus(status: UserStatus, statusText?: string): any { return sdk.rest.post('/v1/users.setStatus', { status, message: statusText }); } - - public async addItem(newItem: IAppAccountBoxItem): Promise { - Tracker.nonreactive(() => { - const actual = this.items.get(); - actual.push(newItem); - this.items.set(actual); - }); - } - - public async deleteItem(item: IAppAccountBoxItem): Promise { - Tracker.nonreactive(() => { - const actual = this.items.get(); - const itemIndex = actual.findIndex((actualItem: IAppAccountBoxItem) => actualItem.appId === item.appId); - actual.splice(itemIndex, 1); - this.items.set(actual); - }); - } - - public getItems(): (IAppAccountBoxItem | AccountBoxItem)[] { - return this.items.get().filter((item: IAppAccountBoxItem | AccountBoxItem) => { - if ('condition' in item) { - return item.condition(); - } - - return applyDropdownActionButtonFilters(item); - }); - } } export const AccountBox = new AccountBoxBase(); diff --git a/apps/meteor/client/sidebar/header/actions/hooks/useAdministrationItems.tsx b/apps/meteor/client/sidebar/header/actions/hooks/useAdministrationItems.tsx index 97bcb291a37e..c0dc83fb62c1 100644 --- a/apps/meteor/client/sidebar/header/actions/hooks/useAdministrationItems.tsx +++ b/apps/meteor/client/sidebar/header/actions/hooks/useAdministrationItems.tsx @@ -1,8 +1,16 @@ -import { useTranslation, useRoute, useMethod, useSetModal, useRole, useRouter } from '@rocket.chat/ui-contexts'; +import { + useTranslation, + useRoute, + useMethod, + useSetModal, + useRole, + useRouter, + useAtLeastOnePermission, + usePermission, +} from '@rocket.chat/ui-contexts'; import { useQuery } from '@tanstack/react-query'; import React from 'react'; -import type { AccountBoxItem } from '../../../../../app/ui-utils/client/lib/AccountBox'; import type { UpgradeTabVariant } from '../../../../../lib/upgradeTab'; import { getUpgradeTabLabel, isFullyFeature } from '../../../../../lib/upgradeTab'; import Emoji from '../../../../components/Emoji'; @@ -10,17 +18,45 @@ import type { GenericMenuItemProps } from '../../../../components/GenericMenu/Ge import RegisterWorkspaceModal from '../../../../views/admin/cloud/modals/RegisterWorkspaceModal'; import { useUpgradeTabParams } from '../../../../views/hooks/useUpgradeTabParams'; -type useAdministrationItemProps = { - accountBoxItems: AccountBoxItem[]; - showWorkspace: boolean; -}; -export const useAdministrationItems = ({ accountBoxItems, showWorkspace }: useAdministrationItemProps): GenericMenuItemProps[] => { +const ADMIN_PERMISSIONS = [ + 'view-statistics', + 'run-import', + 'view-user-administration', + 'view-room-administration', + 'create-invite-links', + 'manage-cloud', + 'view-logs', + 'manage-sounds', + 'view-federation-data', + 'manage-email-inbox', + 'manage-emoji', + 'manage-outgoing-integrations', + 'manage-own-outgoing-integrations', + 'manage-incoming-integrations', + 'manage-own-incoming-integrations', + 'manage-oauth-apps', + 'access-mailer', + 'manage-user-status', + 'access-permissions', + 'access-setting-permissions', + 'view-privileged-setting', + 'edit-privileged-setting', + 'manage-selected-settings', + 'view-engagement-dashboard', + 'view-moderation-console', +]; + +export const useAdministrationItems = (): GenericMenuItemProps[] => { const router = useRouter(); const t = useTranslation(); + const shouldShowAdminMenu = useAtLeastOnePermission(ADMIN_PERMISSIONS); + const { tabType, trialEndDate, isLoading } = useUpgradeTabParams(); const shouldShowEmoji = isFullyFeature(tabType); + const label = getUpgradeTabLabel(tabType); + const isAdmin = useRole('admin'); const setModal = useSetModal(); @@ -36,8 +72,18 @@ export const useAdministrationItems = ({ accountBoxItems, showWorkspace }: useAd const adminRoute = useRoute('admin-index'); const upgradeRoute = useRoute('upgrade'); const cloudRoute = useRoute('cloud'); + + const omnichannel = usePermission('view-livechat-manager'); + const showUpgradeItem = !isLoading && tabType; + const omnichannelItem: GenericMenuItemProps = { + id: 'omnichannel', + content: t('Omnichannel'), + icon: 'headset', + onClick: () => router.navigate('/omnichannel/current'), + }; + const upgradeItem: GenericMenuItemProps = { id: 'showUpgradeItem', content: ( @@ -71,24 +117,10 @@ export const useAdministrationItems = ({ accountBoxItems, showWorkspace }: useAd }, }; - const accountBoxItem: GenericMenuItemProps[] = accountBoxItems.map((item, key) => { - const action = () => { - if (item.href) { - router.navigate(item.href); - } - }; - return { - id: `account-box-item-${key}`, - content: t(item.name), - icon: item.icon, - onClick: action, - }; - }); - return [ - ...(showUpgradeItem ? [upgradeItem] : []), - ...(isAdmin ? [adminItem] : []), - ...(showWorkspace ? [workspaceItem] : []), - ...(accountBoxItems.length ? accountBoxItem : []), - ]; + showUpgradeItem && upgradeItem, + isAdmin && adminItem, + omnichannel && omnichannelItem, + shouldShowAdminMenu && workspaceItem, + ].filter(Boolean) as GenericMenuItemProps[]; }; diff --git a/apps/meteor/client/sidebar/header/actions/hooks/useAdministrationMenu.tsx b/apps/meteor/client/sidebar/header/actions/hooks/useAdministrationMenu.tsx index 72b9b90419a5..5be021cf0b7e 100644 --- a/apps/meteor/client/sidebar/header/actions/hooks/useAdministrationMenu.tsx +++ b/apps/meteor/client/sidebar/header/actions/hooks/useAdministrationMenu.tsx @@ -1,72 +1,20 @@ -import { useMutableCallback } from '@rocket.chat/fuselage-hooks'; -import { useAtLeastOnePermission, usePermission, useTranslation } from '@rocket.chat/ui-contexts'; +import { useTranslation } from '@rocket.chat/ui-contexts'; -import { AccountBox } from '../../../../../app/ui-utils/client'; -import type { IAppAccountBoxItem, AccountBoxItem } from '../../../../../app/ui-utils/client/lib/AccountBox'; -import { isAppAccountBoxItem } from '../../../../../app/ui-utils/client/lib/AccountBox'; -import { useHasLicenseModule } from '../../../../../ee/client/hooks/useHasLicenseModule'; -import { useReactiveValue } from '../../../../hooks/useReactiveValue'; +import type { GenericMenuItemProps } from '../../../../components/GenericMenu/GenericMenuItem'; import { useAdministrationItems } from './useAdministrationItems'; import { useAppsItems } from './useAppsItems'; import { useAuditItems } from './useAuditItems'; -const ADMIN_PERMISSIONS = [ - 'view-statistics', - 'run-import', - 'view-user-administration', - 'view-room-administration', - 'create-invite-links', - 'manage-cloud', - 'view-logs', - 'manage-sounds', - 'view-federation-data', - 'manage-email-inbox', - 'manage-emoji', - 'manage-outgoing-integrations', - 'manage-own-outgoing-integrations', - 'manage-incoming-integrations', - 'manage-own-incoming-integrations', - 'manage-oauth-apps', - 'access-mailer', - 'manage-user-status', - 'access-permissions', - 'access-setting-permissions', - 'view-privileged-setting', - 'edit-privileged-setting', - 'manage-selected-settings', - 'view-engagement-dashboard', - 'view-moderation-console', -]; - export const useAdministrationMenu = () => { const t = useTranslation(); - const getAccountBoxItems = useMutableCallback(() => AccountBox.getItems()); - const accountBoxItems = useReactiveValue(getAccountBoxItems); - - const hasAuditLicense = useHasLicenseModule('auditing') === true; - const hasManageAppsPermission = usePermission('manage-apps'); - const hasAccessMarketplacePermission = usePermission('access-marketplace'); - const hasAdminPermission = useAtLeastOnePermission(ADMIN_PERMISSIONS); - const hasAuditPermission = usePermission('can-audit') && hasAuditLicense; - const hasAuditLogPermission = usePermission('can-audit-log') && hasAuditLicense; - - const appBoxItems = accountBoxItems.filter((item): item is IAppAccountBoxItem => isAppAccountBoxItem(item)); - const adminBoxItems = accountBoxItems.filter((item): item is AccountBoxItem => !isAppAccountBoxItem(item)); - const showAdmin = hasAdminPermission || !!adminBoxItems.length; - const showAudit = hasAuditPermission || hasAuditLogPermission; - const showWorkspace = hasAdminPermission; - const showApps = hasAccessMarketplacePermission || hasManageAppsPermission || !!appBoxItems.length; - - const administrationItems = useAdministrationItems({ accountBoxItems: adminBoxItems, showWorkspace }); + const administrationItems = useAdministrationItems(); const appItems = useAppsItems(); - const auditItems = useAuditItems({ showAudit: hasAuditPermission, showAuditLog: hasAuditLogPermission }); - - const sections = [ - { title: t('Administration'), items: administrationItems, permission: showAdmin }, - { title: t('Apps'), items: appItems, permission: showApps }, - { title: t('Audit'), items: auditItems, permission: showAudit }, - ]; + const auditItems = useAuditItems(); - return sections.filter(({ permission }) => permission); + return [ + administrationItems.length && { title: t('Administration'), items: administrationItems }, + appItems.length && { title: t('Apps'), items: appItems }, + auditItems.length && { title: t('Audit'), items: auditItems }, + ].filter(Boolean) as Array<{ title: string; items: GenericMenuItemProps[] }>; }; diff --git a/apps/meteor/client/sidebar/header/actions/hooks/useAuditItems.tsx b/apps/meteor/client/sidebar/header/actions/hooks/useAuditItems.tsx index 3ed3ba94dcb9..07b2b9bb11c3 100644 --- a/apps/meteor/client/sidebar/header/actions/hooks/useAuditItems.tsx +++ b/apps/meteor/client/sidebar/header/actions/hooks/useAuditItems.tsx @@ -1,18 +1,23 @@ -import { useTranslation, useRoute } from '@rocket.chat/ui-contexts'; +import { useTranslation, useRoute, usePermission } from '@rocket.chat/ui-contexts'; +import { useHasLicenseModule } from '../../../../../ee/client/hooks/useHasLicenseModule'; import type { GenericMenuItemProps } from '../../../../components/GenericMenu/GenericMenuItem'; -type useAuditItemsProps = { - showAudit: boolean; - showAuditLog: boolean; -}; +export const useAuditItems = (): GenericMenuItemProps[] => { + const hasAuditLicense = useHasLicenseModule('auditing') === true; + + const hasAuditPermission = usePermission('can-audit') && hasAuditLicense; + const hasAuditLogPermission = usePermission('can-audit-log') && hasAuditLicense; -export const useAuditItems = ({ showAudit, showAuditLog }: useAuditItemsProps): GenericMenuItemProps[] => { const t = useTranslation(); const auditHomeRoute = useRoute('audit-home'); const auditSettingsRoute = useRoute('audit-log'); + if (!hasAuditPermission && !hasAuditLogPermission) { + return []; + } + const auditMessageItem: GenericMenuItemProps = { id: 'messages', icon: 'document-eye', @@ -26,5 +31,5 @@ export const useAuditItems = ({ showAudit, showAuditLog }: useAuditItemsProps): onClick: () => auditSettingsRoute.push(), }; - return [...(showAudit ? [auditMessageItem] : []), ...(showAuditLog ? [auditLogItem] : [])]; + return [hasAuditPermission && auditMessageItem, hasAuditLogPermission && auditLogItem].filter(Boolean) as GenericMenuItemProps[]; }; diff --git a/apps/meteor/client/sidebar/header/hooks/useStatusItems.tsx b/apps/meteor/client/sidebar/header/hooks/useStatusItems.tsx index 8621846456f1..ca45e53bf5e2 100644 --- a/apps/meteor/client/sidebar/header/hooks/useStatusItems.tsx +++ b/apps/meteor/client/sidebar/header/hooks/useStatusItems.tsx @@ -2,10 +2,9 @@ import type { IUser, ValueOf } from '@rocket.chat/core-typings'; import { UserStatus as UserStatusEnum } from '@rocket.chat/core-typings'; import { Box } from '@rocket.chat/fuselage'; import type { TranslationKey } from '@rocket.chat/ui-contexts'; -import { useSetting, useTranslation } from '@rocket.chat/ui-contexts'; +import { useEndpoint, useSetting, useTranslation } from '@rocket.chat/ui-contexts'; import React from 'react'; -import { AccountBox } from '../../../../app/ui-utils/client'; import { userStatus } from '../../../../app/user-status/client'; import { callbacks } from '../../../../lib/callbacks'; import type { GenericMenuItemProps } from '../../../components/GenericMenu/GenericMenuItem'; @@ -27,9 +26,10 @@ const translateStatusName = (t: ReturnType, status: (type export const useStatusItems = (user: IUser): GenericMenuItemProps[] => { const t = useTranslation(); const presenceDisabled = useSetting('Presence_broadcast_disabled'); + const setStatus = useEndpoint('POST', '/v1/users.setStatus'); - const setStatus = (status: (typeof userStatus.list)['']): void => { - AccountBox.setStatus(status.statusType, !isDefaultStatus(status.id) ? status.name : ''); + const setStatusAction = (status: (typeof userStatus.list)['']): void => { + setStatus({ status: status.statusType, message: !isDefaultStatus(status.id) ? status.name : '' }); void callbacks.run('userStatusManuallySet', status); }; @@ -64,7 +64,7 @@ export const useStatusItems = (user: IUser): GenericMenuItemProps[] => { id: status.id, status: , content: , - onClick: () => setStatus(status), + onClick: () => setStatusAction(status), disabled: presenceDisabled, }; }); diff --git a/apps/meteor/client/startup/iframeCommands.ts b/apps/meteor/client/startup/iframeCommands.ts index 3ecf578587bb..25836a38f5ca 100644 --- a/apps/meteor/client/startup/iframeCommands.ts +++ b/apps/meteor/client/startup/iframeCommands.ts @@ -5,7 +5,7 @@ import { Meteor } from 'meteor/meteor'; import { ServiceConfiguration } from 'meteor/service-configuration'; import { settings } from '../../app/settings/client'; -import { AccountBox } from '../../app/ui-utils/client'; +import { AccountBox } from '../../app/ui-utils/client/lib/AccountBox'; import { sdk } from '../../app/utils/client/lib/SDKClient'; import { callbacks } from '../../lib/callbacks'; import { capitalize, ltrim, rtrim } from '../../lib/utils/stringUtils';