diff --git a/apps/meteor/client/components/Message/Attachments/Attachments.tsx b/apps/meteor/client/components/Message/Attachments/Attachments.tsx index 730e622c6ad..5e158586940 100644 --- a/apps/meteor/client/components/Message/Attachments/Attachments.tsx +++ b/apps/meteor/client/components/Message/Attachments/Attachments.tsx @@ -5,10 +5,10 @@ import { useBlockRendered } from '../hooks/useBlockRendered'; import Item from './Item'; const Attachments: FC<{ attachments: Array; file?: FileProp }> = ({ attachments = null, file }): any => { - const { className, ref } = useBlockRendered(); + const { className, ref } = useBlockRendered(); return ( <> -
+
{attachments?.map((attachment, index) => ( ))} diff --git a/apps/meteor/client/components/Message/Metrics/Broadcast.tsx b/apps/meteor/client/components/Message/Metrics/Broadcast.tsx index e2b67214d07..d479dbb8755 100644 --- a/apps/meteor/client/components/Message/Metrics/Broadcast.tsx +++ b/apps/meteor/client/components/Message/Metrics/Broadcast.tsx @@ -13,11 +13,11 @@ type BroadcastOptions = { const BroadcastMetric: FC = ({ username, mid, replyBroadcast }) => { const t = useTranslation(); - const { className, ref } = useBlockRendered(); + const { className, ref } = useBlockRendered(); return ( -
+
{t('Reply')} diff --git a/apps/meteor/client/components/Message/Metrics/Discussion.tsx b/apps/meteor/client/components/Message/Metrics/Discussion.tsx index 41876873d06..553b9cb67f9 100644 --- a/apps/meteor/client/components/Message/Metrics/Discussion.tsx +++ b/apps/meteor/client/components/Message/Metrics/Discussion.tsx @@ -16,11 +16,11 @@ type DicussionOptions = { const DiscussionMetric: FC = ({ lm, count, rid, drid, openDiscussion }) => { const t = useTranslation(); const format = useTimeAgo(); - const { className, ref } = useBlockRendered(); + const { className, ref } = useBlockRendered(); return ( -
+
{count ? t('message_counter', { counter: count, count }) : t('Reply')} diff --git a/apps/meteor/client/components/Message/helpers/followSyle.js b/apps/meteor/client/components/Message/helpers/followSyle.ts similarity index 100% rename from apps/meteor/client/components/Message/helpers/followSyle.js rename to apps/meteor/client/components/Message/helpers/followSyle.ts diff --git a/apps/meteor/client/components/Message/hooks/useBlockRendered.js b/apps/meteor/client/components/Message/hooks/useBlockRendered.js deleted file mode 100644 index f5032aac524..00000000000 --- a/apps/meteor/client/components/Message/hooks/useBlockRendered.js +++ /dev/null @@ -1,9 +0,0 @@ -import { useRef, useEffect } from 'react'; - -export const useBlockRendered = () => { - const ref = useRef(); - useEffect(() => { - ref.current.dispatchEvent(new Event('rendered')); - }, []); - return { className: 'js-block-wrapper', ref }; -}; diff --git a/apps/meteor/client/components/Message/hooks/useBlockRendered.ts b/apps/meteor/client/components/Message/hooks/useBlockRendered.ts new file mode 100644 index 00000000000..3d35443aa53 --- /dev/null +++ b/apps/meteor/client/components/Message/hooks/useBlockRendered.ts @@ -0,0 +1,13 @@ +import { useRef, useEffect, RefObject } from 'react'; + +// @deprecated +export const useBlockRendered = (): { + className: string; + ref: RefObject; +} => { + const ref = useRef(null); + useEffect(() => { + ref.current?.dispatchEvent(new Event('rendered')); + }, []); + return { className: 'js-block-wrapper', ref }; +}; diff --git a/apps/meteor/client/components/PlanTag.js b/apps/meteor/client/components/PlanTag.js deleted file mode 100644 index 564a34fbb3d..00000000000 --- a/apps/meteor/client/components/PlanTag.js +++ /dev/null @@ -1,38 +0,0 @@ -import { Box, Tag } from '@rocket.chat/fuselage'; -import { useSafely } from '@rocket.chat/fuselage-hooks'; -import React, { useEffect, useState } from 'react'; - -import { useMethod } from '../contexts/ServerContext'; - -function PlanTag() { - const [plans, setPlans] = useSafely(useState([])); - - const getTags = useMethod('license:getTags'); - - useEffect(() => { - const developmentTag = process.env.NODE_ENV === 'development' ? { name: 'development', color: '#095ad2' } : null; - - const fetchTags = async () => { - const tags = await getTags(); - setPlans([developmentTag, ...tags].filter(Boolean).map((plan) => ({ plan: plan.name, background: plan.color }))); - }; - - fetchTags(); - }, [getTags, setPlans]); - - return plans.map(({ plan, background }) => ( - - - {plan} - - - )); -} - -export default PlanTag; diff --git a/apps/meteor/client/components/PlanTag.tsx b/apps/meteor/client/components/PlanTag.tsx new file mode 100644 index 00000000000..30e7f1993e6 --- /dev/null +++ b/apps/meteor/client/components/PlanTag.tsx @@ -0,0 +1,50 @@ +import { Box, Tag } from '@rocket.chat/fuselage'; +import { useSafely } from '@rocket.chat/fuselage-hooks'; +import React, { ReactElement, useEffect, useState } from 'react'; + +import { ILicenseTag } from '../../ee/app/license/definitions/ILicenseTag'; +import { useMethod } from '../contexts/ServerContext'; + +function PlanTag(): ReactElement { + const [plans, setPlans] = useSafely( + useState< + { + name: string; + color: string; + }[] + >([]), + ); + + const getTags = useMethod('license:getTags'); + + useEffect(() => { + const developmentTag = process.env.NODE_ENV === 'development' ? { name: 'development', color: '#095ad2' } : null; + + const fetchTags = async (): Promise => { + const tags = await getTags(); + setPlans([developmentTag, ...tags].filter(Boolean) as ILicenseTag[]); + }; + + fetchTags(); + }, [getTags, setPlans]); + + return ( + <> + {plans.map(({ name, color }) => ( + + + {name} + + + ))} + + ); +} + +export default PlanTag; diff --git a/apps/meteor/client/components/RawText.js b/apps/meteor/client/components/RawText.js deleted file mode 100644 index dbeec79f334..00000000000 --- a/apps/meteor/client/components/RawText.js +++ /dev/null @@ -1,5 +0,0 @@ -import React from 'react'; - -const RawText = ({ children }) => ; - -export default RawText; diff --git a/apps/meteor/client/components/RawText.tsx b/apps/meteor/client/components/RawText.tsx new file mode 100644 index 00000000000..ba643dc48eb --- /dev/null +++ b/apps/meteor/client/components/RawText.tsx @@ -0,0 +1,6 @@ +import React, { ReactElement } from 'react'; + +// @deprecated +const RawText = ({ children }: { children: string }): ReactElement => ; + +export default RawText; diff --git a/apps/meteor/client/components/Skeleton.js b/apps/meteor/client/components/Skeleton.tsx similarity index 63% rename from apps/meteor/client/components/Skeleton.js rename to apps/meteor/client/components/Skeleton.tsx index 5056e7c52cb..ef15454052e 100644 --- a/apps/meteor/client/components/Skeleton.js +++ b/apps/meteor/client/components/Skeleton.tsx @@ -1,7 +1,7 @@ import { Box, Skeleton } from '@rocket.chat/fuselage'; -import React from 'react'; +import React, { ComponentProps, ReactElement } from 'react'; -export const FormSkeleton = (props) => ( +export const FormSkeleton = (props: ComponentProps): ReactElement => ( diff --git a/apps/meteor/client/components/SortList/GroupingList.js b/apps/meteor/client/components/SortList/GroupingList.tsx similarity index 69% rename from apps/meteor/client/components/SortList/GroupingList.js rename to apps/meteor/client/components/SortList/GroupingList.tsx index 3dd64144b8d..443e65a0379 100644 --- a/apps/meteor/client/components/SortList/GroupingList.js +++ b/apps/meteor/client/components/SortList/GroupingList.tsx @@ -1,5 +1,5 @@ import { CheckBox, OptionTitle } from '@rocket.chat/fuselage'; -import React, { useCallback } from 'react'; +import React, { useCallback, ReactElement } from 'react'; import { useMethod } from '../../contexts/ServerContext'; import { useTranslation } from '../../contexts/TranslationContext'; @@ -15,14 +15,17 @@ const checkBoxStyle = { paddingInlineStart: '24px', }; -function GroupingList() { - const sidebarGroupByType = useUserPreference('sidebarGroupByType'); - const sidebarShowFavorites = useUserPreference('sidebarShowFavorites'); - const sidebarShowUnread = useUserPreference('sidebarShowUnread'); +// TODO: chapter day frontend: fix OptionTitle style type + +const GroupingList = function GroupingList(): ReactElement { + const sidebarGroupByType = useUserPreference('sidebarGroupByType'); + const sidebarShowFavorites = useUserPreference('sidebarShowFavorites'); + const sidebarShowUnread = useUserPreference('sidebarShowUnread'); const saveUserPreferences = useMethod('saveUserPreferences'); - const useHandleChange = (key, value) => useCallback(() => saveUserPreferences({ [key]: value }), [key, value]); + const useHandleChange = (key: 'sidebarGroupByType' | 'sidebarShowFavorites' | 'sidebarShowUnread', value: boolean): (() => void) => + useCallback(() => saveUserPreferences({ [key]: value }), [key, value]); const handleChangeGroupByType = useHandleChange('sidebarGroupByType', !sidebarGroupByType); const handleChangeShoFavorite = useHandleChange('sidebarShowFavorites', !sidebarShowFavorites); @@ -32,7 +35,7 @@ function GroupingList() { return ( <> - {t('Group_by')} + {t('Group_by')}
    ); -} +}; export default GroupingList; diff --git a/apps/meteor/client/components/SortList/SortList.js b/apps/meteor/client/components/SortList/SortList.tsx similarity index 80% rename from apps/meteor/client/components/SortList/SortList.js rename to apps/meteor/client/components/SortList/SortList.tsx index b948d18f966..9b646317e7e 100644 --- a/apps/meteor/client/components/SortList/SortList.js +++ b/apps/meteor/client/components/SortList/SortList.tsx @@ -1,11 +1,11 @@ import { Option } from '@rocket.chat/fuselage'; -import React from 'react'; +import React, { ReactElement } from 'react'; import GroupingList from './GroupingList'; import SortModeList from './SortModeList'; import ViewModeList from './ViewModeList'; -function SortList() { +function SortList(): ReactElement { return ( <> diff --git a/apps/meteor/client/components/SortList/SortModeList.js b/apps/meteor/client/components/SortList/SortModeList.tsx similarity index 73% rename from apps/meteor/client/components/SortList/SortModeList.js rename to apps/meteor/client/components/SortList/SortModeList.tsx index 39ada1770fd..2e430609d3d 100644 --- a/apps/meteor/client/components/SortList/SortModeList.js +++ b/apps/meteor/client/components/SortList/SortModeList.tsx @@ -1,5 +1,5 @@ import { RadioButton, OptionTitle } from '@rocket.chat/fuselage'; -import React, { useCallback } from 'react'; +import React, { ReactElement, useCallback } from 'react'; import { useMethod } from '../../contexts/ServerContext'; import { useTranslation } from '../../contexts/TranslationContext'; @@ -15,19 +15,20 @@ const checkBoxStyle = { paddingInlineStart: '24px', }; -function SortModeList() { +function SortModeList(): ReactElement { const t = useTranslation(); const saveUserPreferences = useMethod('saveUserPreferences'); - const sidebarSortBy = useUserPreference('sidebarSortby', 'activity'); + const sidebarSortBy = useUserPreference<'activity' | 'alphabetical'>('sidebarSortby', 'activity'); - const useHandleChange = (value) => useCallback(() => saveUserPreferences({ sidebarSortby: value }), [value]); + const useHandleChange = (value: 'alphabetical' | 'activity'): (() => void) => + useCallback(() => saveUserPreferences({ sidebarSortby: value }), [value]); const setToAlphabetical = useHandleChange('alphabetical'); const setToActivity = useHandleChange('activity'); return ( <> - {t('Sort_By')} + {t('Sort_By')}
      useCallback(() => saveUserPreferences({ sidebarViewMode: value }), [value]); + const useHandleChange = (value: 'medium' | 'extended' | 'condensed'): (() => void) => + useCallback(() => saveUserPreferences({ sidebarViewMode: value }), [value]); - const sidebarViewMode = useUserPreference('sidebarViewMode', 'extended'); + const sidebarViewMode = useUserPreference<'medium' | 'extended' | 'condensed'>('sidebarViewMode', 'extended'); const sidebarDisplayAvatar = useUserPreference('sidebarDisplayAvatar', false); const setToExtended = useHandleChange('extended'); @@ -36,7 +37,7 @@ function ViewModeList() { return ( <> - {t('Display')} + {t('Display')}
        ; } diff --git a/apps/meteor/client/contexts/ServerContext/methods.ts b/apps/meteor/client/contexts/ServerContext/methods.ts index 5e7e04b6b25..db73cd579ad 100644 --- a/apps/meteor/client/contexts/ServerContext/methods.ts +++ b/apps/meteor/client/contexts/ServerContext/methods.ts @@ -1,6 +1,7 @@ import type { IRoom, ISetting, IUser } from '@rocket.chat/core-typings'; import type { DeleteWriteOpResultObject } from 'mongodb'; +import { ILicenseTag } from '../../../ee/app/license/definitions/ILicenseTag'; import { AddWebdavAccountMethod } from './methods/addWebdavAccount'; import { FollowMessageMethod } from './methods/followMessage'; import { GetReadReceiptsMethod } from './methods/getReadReceipts'; @@ -78,7 +79,7 @@ export type ServerMethods = { 'jitsi:updateTimeout': (...args: any[]) => any; 'leaveRoom': (...args: any[]) => any; 'license:getModules': () => string[]; - 'license:getTags': (...args: any[]) => any; + 'license:getTags': () => ILicenseTag[]; 'livechat:addMonitor': (...args: any[]) => any; 'livechat:changeLivechatStatus': (...args: any[]) => any; 'livechat:closeRoom': (...args: any[]) => any; diff --git a/apps/meteor/client/lib/createSidebarItems.ts b/apps/meteor/client/lib/createSidebarItems.ts index 0a2808e70b4..79335eaaf4b 100644 --- a/apps/meteor/client/lib/createSidebarItems.ts +++ b/apps/meteor/client/lib/createSidebarItems.ts @@ -4,6 +4,7 @@ type SidebarItem = { i18nLabel: string; href?: string; icon?: string; + tag?: 'Alpha'; permissionGranted?: boolean | (() => boolean); }; diff --git a/apps/meteor/client/views/admin/sidebarItems.js b/apps/meteor/client/views/admin/sidebarItems.ts similarity index 59% rename from apps/meteor/client/views/admin/sidebarItems.js rename to apps/meteor/client/views/admin/sidebarItems.ts index 3a0d94b70de..efd69069ebf 100644 --- a/apps/meteor/client/views/admin/sidebarItems.js +++ b/apps/meteor/client/views/admin/sidebarItems.ts @@ -10,67 +10,67 @@ export const { href: 'admin-info', i18nLabel: 'Info', icon: 'info-circled', - permissionGranted: () => hasPermission('view-statistics'), + permissionGranted: (): boolean => hasPermission('view-statistics'), }, { href: 'admin-import', i18nLabel: 'Import', icon: 'import', - permissionGranted: () => hasPermission('run-import'), + permissionGranted: (): boolean => hasPermission('run-import'), }, { href: 'admin-users', i18nLabel: 'Users', icon: 'team', - permissionGranted: () => hasPermission('view-user-administration'), + permissionGranted: (): boolean => hasPermission('view-user-administration'), }, { href: 'admin-rooms', i18nLabel: 'Rooms', icon: 'hashtag', - permissionGranted: () => hasPermission('view-room-administration'), + permissionGranted: (): boolean => hasPermission('view-room-administration'), }, { href: 'invites', i18nLabel: 'Invites', icon: 'user-plus', - permissionGranted: () => hasPermission('create-invite-links'), + permissionGranted: (): boolean => hasPermission('create-invite-links'), }, { icon: 'cloud-plus', href: 'cloud', i18nLabel: 'Connectivity_Services', - permissionGranted: () => hasPermission('manage-cloud'), + permissionGranted: (): boolean => hasPermission('manage-cloud'), }, { href: 'admin-view-logs', i18nLabel: 'View_Logs', icon: 'post', - permissionGranted: () => hasPermission('view-logs'), + permissionGranted: (): boolean => hasPermission('view-logs'), }, { href: 'custom-sounds', i18nLabel: 'Custom_Sounds', icon: 'volume', - permissionGranted: () => hasPermission('manage-sounds'), + permissionGranted: (): boolean => hasPermission('manage-sounds'), }, { icon: 'discover', href: 'federation-dashboard', i18nLabel: 'Federation Dashboard', - permissionGranted: () => hasPermission('view-federation-data'), + permissionGranted: (): boolean => hasPermission('view-federation-data'), }, { icon: 'cube', href: 'admin-marketplace', i18nLabel: 'Apps', - permissionGranted: () => hasPermission('manage-apps'), + permissionGranted: (): boolean => hasPermission('manage-apps'), }, { icon: 'mail', href: 'admin-email-inboxes', i18nLabel: 'Email_Inboxes', tag: 'Alpha', - permissionGranted: () => hasPermission('manage-email-inbox'), + permissionGranted: (): boolean => hasPermission('manage-email-inbox'), }, ]); diff --git a/apps/meteor/client/views/directory/ChannelsTab.js b/apps/meteor/client/views/directory/ChannelsTab.tsx similarity index 75% rename from apps/meteor/client/views/directory/ChannelsTab.js rename to apps/meteor/client/views/directory/ChannelsTab.tsx index c0dd2e80ec2..1da12b102b8 100644 --- a/apps/meteor/client/views/directory/ChannelsTab.js +++ b/apps/meteor/client/views/directory/ChannelsTab.tsx @@ -1,14 +1,14 @@ -import React from 'react'; +import React, { ReactElement } from 'react'; import { usePermission } from '../../contexts/AuthorizationContext'; import NotAuthorizedPage from '../notAuthorized/NotAuthorizedPage'; import ChannelsTable from './ChannelsTable'; -function ChannelsTab(props) { +function ChannelsTab(): ReactElement { const canViewPublicRooms = usePermission('view-c-room'); if (canViewPublicRooms) { - return ; + return ; } return ; diff --git a/apps/meteor/client/views/directory/DirectoryPage.js b/apps/meteor/client/views/directory/DirectoryPage.tsx similarity index 76% rename from apps/meteor/client/views/directory/DirectoryPage.js rename to apps/meteor/client/views/directory/DirectoryPage.tsx index f4807ee0ae3..f551fe7eb78 100644 --- a/apps/meteor/client/views/directory/DirectoryPage.js +++ b/apps/meteor/client/views/directory/DirectoryPage.tsx @@ -1,5 +1,5 @@ import { Tabs } from '@rocket.chat/fuselage'; -import React, { useEffect, useCallback } from 'react'; +import React, { useEffect, useCallback, ReactElement } from 'react'; import Page from '../../components/Page'; import { useCurrentRoute, useRoute, useRouteParameter } from '../../contexts/RouterContext'; @@ -9,10 +9,10 @@ import ChannelsTab from './ChannelsTab'; import TeamsTab from './TeamsTab'; import UserTab from './UserTab'; -function DirectoryPage() { +function DirectoryPage(): ReactElement { const t = useTranslation(); - const defaultTab = useSetting('Accounts_Directory_DefaultView'); + const defaultTab = String(useSetting('Accounts_Directory_DefaultView')); const federationEnabled = useSetting('FEDERATION_Enabled'); const [routeName] = useCurrentRoute(); const tab = useRouteParameter('tab'); @@ -28,7 +28,7 @@ function DirectoryPage() { } }, [routeName, directoryRoute, tab, federationEnabled, defaultTab]); - const handleTabClick = useCallback((tab) => () => directoryRoute.push({ tab }), [directoryRoute]); + const handleTabClick = useCallback((tab) => (): void => directoryRoute.push({ tab }), [directoryRoute]); return ( @@ -50,10 +50,10 @@ function DirectoryPage() { )} - {(tab === 'users' && ) || - (tab === 'channels' && ) || - (tab === 'teams' && ) || - (federationEnabled && tab === 'external' && )} + {tab === 'users' && } + {tab === 'channels' && } + {tab === 'teams' && } + {federationEnabled && tab === 'external' && } ); diff --git a/apps/meteor/client/views/directory/TeamsTab.js b/apps/meteor/client/views/directory/TeamsTab.tsx similarity index 75% rename from apps/meteor/client/views/directory/TeamsTab.js rename to apps/meteor/client/views/directory/TeamsTab.tsx index 3dd6b7e6484..339e4033ea2 100644 --- a/apps/meteor/client/views/directory/TeamsTab.js +++ b/apps/meteor/client/views/directory/TeamsTab.tsx @@ -1,14 +1,14 @@ -import React from 'react'; +import React, { ReactElement } from 'react'; import { usePermission } from '../../contexts/AuthorizationContext'; import NotAuthorizedPage from '../notAuthorized/NotAuthorizedPage'; import TeamsTable from './TeamsTable'; -function TeamsTab(props) { +function TeamsTab(): ReactElement { const canViewPublicRooms = usePermission('view-c-room'); if (canViewPublicRooms) { - return ; + return ; } return ; diff --git a/apps/meteor/client/views/directory/UserTab.js b/apps/meteor/client/views/directory/UserTab.tsx similarity index 77% rename from apps/meteor/client/views/directory/UserTab.js rename to apps/meteor/client/views/directory/UserTab.tsx index f9530926316..8296ed2b196 100644 --- a/apps/meteor/client/views/directory/UserTab.js +++ b/apps/meteor/client/views/directory/UserTab.tsx @@ -1,10 +1,10 @@ -import React from 'react'; +import React, { ReactElement } from 'react'; import { usePermission } from '../../contexts/AuthorizationContext'; import NotAuthorizedPage from '../notAuthorized/NotAuthorizedPage'; import UserTable from './UserTable'; -function UserTab(props) { +function UserTab(props: { workspace?: 'external' | 'local' }): ReactElement { const canViewOutsideRoom = usePermission('view-outside-room'); const canViewDM = usePermission('view-d-room'); diff --git a/apps/meteor/packages/rocketchat-i18n/i18n/en.i18n.json b/apps/meteor/packages/rocketchat-i18n/i18n/en.i18n.json index cb97dc01c20..296c2427c2b 100644 --- a/apps/meteor/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/apps/meteor/packages/rocketchat-i18n/i18n/en.i18n.json @@ -616,6 +616,7 @@ "Available_agents": "Available agents", "Available_departments": "Available Departments", "Avatar": "Avatar", + "Avatars": "Avatars", "Avatar_changed_successfully": "Avatar changed successfully", "Avatar_URL": "Avatar URL", "Avatar_format_invalid": "Invalid Format. Only image type is allowed",