Skip to content

Commit

Permalink
refactor: Invalid values as React nodes
Browse files Browse the repository at this point in the history
  • Loading branch information
tassoevan committed Jan 7, 2025
1 parent bfa92f4 commit 6586d0b
Show file tree
Hide file tree
Showing 42 changed files with 203 additions and 158 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { useEmbeddedLayout } from '../../hooks/useEmbeddedLayout';
const SideBarToggler = (): ReactElement => {
const { sidebar } = useLayout();
const isLayoutEmbedded = useEmbeddedLayout();
const unreadMessagesBadge = useSession('unread');
const unreadMessagesBadge = useSession('unread') as number | string | undefined;

const toggleSidebar = useEffectEvent(() => sidebar.toggle());

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { css } from '@rocket.chat/css-in-js';
import { Box, Badge } from '@rocket.chat/fuselage';
import type { ReactNode } from 'react';

const SidebarTogglerBadge = ({ children }: { children?: unknown }) => (
type SidebarTogglerBadgeProps = {
children?: ReactNode;
};

const SidebarTogglerBadge = ({ children }: SidebarTogglerBadgeProps) => (
<Box
className={css`
position: absolute;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { Box, IconButton } from '@rocket.chat/fuselage';
import type { ReactNode } from 'react';
import { useTranslation } from 'react-i18next';

import SidebarTogglerBadge from './SidebarTogglerBadge';

type SideBarTogglerButtonProps = {
badge?: number | unknown;
badge?: ReactNode;
onClick: () => void;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ type QuoteAttachmentProps = {

export const QuoteAttachment = ({ attachment }: QuoteAttachmentProps): ReactElement => {
const formatTime = useTimeAgo();
const displayAvatarPreference = useUserPreference('displayAvatars');
const displayAvatarPreference = useUserPreference<boolean>('displayAvatars');

return (
<>
Expand Down
2 changes: 1 addition & 1 deletion apps/meteor/client/lib/utils/timeAgo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { t } from '../../../app/utils/lib/i18n';

const dayFormat = ['h:mm A', 'H:mm'];

export const timeAgo = async (date: MomentInput): Promise<string> => {
export const timeAgo = (date: MomentInput) => {
const clockMode = Tracker.nonreactive(() => getUserPreference(Meteor.userId(), 'clockMode', false) as number | boolean);
const messageTimeFormat = Tracker.nonreactive(() => settings.get('Message_TimeFormat'));
const sameDay = (typeof clockMode === 'number' ? dayFormat[clockMode - 1] : undefined) || messageTimeFormat;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@ import { useTranslation } from 'react-i18next';

import AutoCompleteDepartmentMultiple from '../../components/AutoCompleteDepartmentMultiple';
import { useHasLicenseModule } from '../../hooks/useHasLicenseModule';
import type { BusinessHoursFormData } from '../../views/omnichannel/businessHours/BusinessHoursForm';

const BusinessHoursMultiple = ({ className }: { className?: ComponentProps<typeof Field>['className'] }) => {
const { t } = useTranslation();
const {
control,
formState: { errors },
} = useFormContext();
} = useFormContext<BusinessHoursFormData>();
const hasLicense = useHasLicenseModule('livechat-enterprise');

const enabledField = useUniqueId();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { useFormContext, Controller } from 'react-hook-form';
import { useTranslation } from 'react-i18next';

import { useHasLicenseModule } from '../../hooks/useHasLicenseModule';
import type { EditCustomFieldsFormData } from '../../views/omnichannel/customFields/EditCustomFields';

const checkIsOptionsValid = (value: string) => {
if (!value || value.trim() === '') {
Expand All @@ -22,7 +23,7 @@ const CustomFieldsAdditionalForm = ({ className }: { className?: ComponentProps<
control,
watch,
formState: { errors },
} = useFormContext();
} = useFormContext<EditCustomFieldsFormData>();
const hasLicense = useHasLicenseModule('livechat-enterprise');

const { visibility, type } = watch();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ import { useQueryClient } from '@tanstack/react-query';
import { memo, useCallback } from 'react';
import { FormProvider, useForm } from 'react-hook-form';

import CannedResponseForm from './components/cannedResponseForm';
import CannedResponseForm from './components/CannedResponseForm';
import { useRemoveCannedResponse } from './useRemoveCannedResponse';
import { Page, PageHeader, PageScrollableContentWithShadow, PageFooter } from '../../components/Page';

type CannedResponseEditFormData = {
export type CannedResponseEditFormData = {
_id: string;
shortcut: string;
text: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import CannedResponsesComposer from './CannedResponsesComposer/CannedResponsesCo
import CannedResponsesComposerPreview from './CannedResponsesComposer/CannedResponsesComposerPreview';
import AutoCompleteDepartment from '../../../components/AutoCompleteDepartment';
import Tags from '../../../components/Omnichannel/Tags';
import type { CannedResponseEditFormData } from '../CannedResponseEdit';

// TODO: refactor Tags field to get proper validation
const CannedResponseForm = () => {
Expand All @@ -21,7 +22,7 @@ const CannedResponseForm = () => {
control,
formState: { errors },
watch,
} = useFormContext();
} = useFormContext<CannedResponseEditFormData>();

const clickable = css`
cursor: pointer;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { FormProvider, useForm } from 'react-hook-form';
import { useTranslation } from 'react-i18next';

import GenericModal from '../../../../components/GenericModal';
import CannedResponseForm from '../../components/cannedResponseForm';
import CannedResponseForm from '../../components/CannedResponseForm';

type CreateCannedResponseModalFormData = {
_id: string;
Expand Down
33 changes: 16 additions & 17 deletions apps/meteor/client/sidebar/RoomList/SideBarItemTemplateWithData.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ type RoomListRowProps = {
actions: unknown;
href: string;
time?: Date;
menu?: ReactNode;
menu?: () => ReactNode;
menuOptions?: unknown;
subtitle?: ReactNode;
titleIcon?: string;
Expand Down Expand Up @@ -191,22 +191,21 @@ function SideBarItemTemplateWithData({
avatar={AvatarTemplate && <AvatarTemplate {...room} />}
actions={actions}
menu={
!isIOsDevice &&
!isAnonymous &&
(!isQueued || (isQueued && isPriorityEnabled)) &&
((): ReactElement => (
<RoomMenu
alert={alert}
threadUnread={threadUnread}
rid={rid}
unread={!!unread}
roomOpen={selected}
type={type}
cl={cl}
name={title}
hideDefaultOptions={isQueued}
/>
))
!isIOsDevice && !isAnonymous && (!isQueued || (isQueued && isPriorityEnabled))
? (): ReactElement => (
<RoomMenu
alert={alert}
threadUnread={threadUnread}
rid={rid}
unread={!!unread}
roomOpen={selected}
type={type}
cl={cl}
name={title}
hideDefaultOptions={isQueued}
/>
)
: undefined
}
/>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ const AirGappedRestrictionWarning = ({ isRestricted, remainingDays }: { isRestri
}

return (
<Trans i18nKey='Airgapped_workspace_warning2' values={{ remainingDays }}>
This air-gapped workspace will enter read-only mode in <>{{ remainingDays }}</> days.{' '}
<Trans i18nKey='Airgapped_workspace_warning' values={{ remainingDays }}>
This air-gapped workspace will enter read-only mode in {remainingDays} days.{' '}
<Box fontScale='p2' is='span'>
Connect it to the internet or upgrade to a premium plan to prevent this.
</Box>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ type RoomListRowProps = {
actions: unknown;
href: string;
time?: Date;
menu?: ReactNode;
menu?: () => ReactNode;
menuOptions?: unknown;
subtitle?: ReactNode;
titleIcon?: string;
Expand Down Expand Up @@ -154,22 +154,21 @@ const SidebarItemTemplateWithData = ({
avatar={AvatarTemplate && <AvatarTemplate {...room} />}
actions={actions}
menu={
!isIOsDevice &&
!isAnonymous &&
(!isQueued || (isQueued && isPriorityEnabled)) &&
((): ReactElement => (
<RoomMenu
alert={alert}
threadUnread={unreadCount.threads > 0}
rid={rid}
unread={!!unread}
roomOpen={selected}
type={type}
cl={cl}
name={title}
hideDefaultOptions={isQueued}
/>
))
!isIOsDevice && !isAnonymous && (!isQueued || (isQueued && isPriorityEnabled))
? (): ReactElement => (
<RoomMenu
alert={alert}
threadUnread={unreadCount.threads > 0}
rid={rid}
unread={!!unread}
roomOpen={selected}
type={type}
cl={cl}
name={title}
hideDefaultOptions={isQueued}
/>
)
: undefined
}
/>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const AirGappedRestrictionWarning = ({ isRestricted, remainingDays }: { isRestri

return (
<Trans i18nKey='Airgapped_workspace_warning' values={{ remainingDays }}>
This air-gapped workspace will enter read-only mode in <>{{ remainingDays }}</> days.{' '}
This air-gapped workspace will enter read-only mode in {remainingDays} days.{' '}
<Box fontScale='p2' is='span'>
Connect it to internet or upgrade to a premium plan to prevent this.
</Box>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { useCreateIntegration } from '../hooks/useCreateIntegration';
import { useDeleteIntegration } from '../hooks/useDeleteIntegration';
import { useUpdateIntegration } from '../hooks/useUpdateIntegration';

type EditIncomingWebhookFormData = {
export type EditIncomingWebhookFormData = {
enabled: boolean;
channel: string;
username: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { useMemo } from 'react';
import { Controller, useFormContext } from 'react-hook-form';
import { useTranslation } from 'react-i18next';

import type { EditIncomingWebhookFormData } from './EditIncomingWebhook';
import useClipboardWithToast from '../../../../hooks/useClipboardWithToast';
import { useHighlightedCode } from '../../../../hooks/useHighlightedCode';
import { useExampleData } from '../hooks/useExampleIncomingData';
Expand All @@ -35,7 +36,7 @@ const IncomingWebhookForm = ({ webhookData }: { webhookData?: Serialized<IIncomi
control,
watch,
formState: { errors },
} = useFormContext();
} = useFormContext<EditIncomingWebhookFormData>();
const { alias, emoji, avatar } = watch();

const url = absoluteUrl(`hooks/${webhookData?._id}/${webhookData?.token}`);
Expand Down
10 changes: 9 additions & 1 deletion apps/meteor/client/views/admin/permissions/EditRolePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ import RoleForm from './RoleForm';
import { ContextualbarFooter, ContextualbarScrollableContent } from '../../../components/Contextualbar';
import GenericModal from '../../../components/GenericModal';

export type EditRolePageFormData = {
roleId?: string;
name: string;
description: string;
scope: 'Users' | 'Subscriptions';
mandatory2fa: boolean;
};

const EditRolePage = ({ role, isEnterprise }: { role?: IRole; isEnterprise: boolean }): ReactElement => {
const { t } = useTranslation();
const dispatchToastMessage = useToastMessageDispatch();
Expand All @@ -21,7 +29,7 @@ const EditRolePage = ({ role, isEnterprise }: { role?: IRole; isEnterprise: bool
const updateRole = useEndpoint('POST', '/v1/roles.update');
const deleteRole = useEndpoint('POST', '/v1/roles.delete');

const methods = useForm({
const methods = useForm<EditRolePageFormData>({
defaultValues: {
roleId: role?._id,
name: role?.name,
Expand Down
13 changes: 6 additions & 7 deletions apps/meteor/client/views/admin/permissions/RoleForm.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
import type { SelectOption } from '@rocket.chat/fuselage';
import { Field, FieldLabel, FieldRow, FieldError, FieldHint, TextInput, Select, ToggleSwitch } from '@rocket.chat/fuselage';
import type { ReactElement } from 'react';
import { useMemo } from 'react';
import { useFormContext, Controller } from 'react-hook-form';
import { useTranslation } from 'react-i18next';

import type { EditRolePageFormData } from './EditRolePage';

type RoleFormProps = {
className?: string;
editing?: boolean;
isProtected?: boolean;
isDisabled?: boolean;
};

const RoleForm = ({ className, editing = false, isProtected = false, isDisabled = false }: RoleFormProps): ReactElement => {
const RoleForm = ({ className, editing = false, isProtected = false, isDisabled = false }: RoleFormProps) => {
const { t } = useTranslation();
const {
register,
control,
formState: { errors },
} = useFormContext();
} = useFormContext<EditRolePageFormData>();

const options: SelectOption[] = useMemo(
() => [
Expand Down Expand Up @@ -54,9 +55,7 @@ const RoleForm = ({ className, editing = false, isProtected = false, isDisabled
<Controller
name='scope'
control={control}
render={({ field }): ReactElement => (
<Select {...field} options={options} disabled={isProtected || isDisabled} placeholder={t('Scope')} />
)}
render={({ field }) => <Select {...field} options={options} disabled={isProtected || isDisabled} placeholder={t('Scope')} />}
/>
</FieldRow>
</Field>
Expand All @@ -66,7 +65,7 @@ const RoleForm = ({ className, editing = false, isProtected = false, isDisabled
<Controller
name='mandatory2fa'
control={control}
render={({ field }): ReactElement => <ToggleSwitch {...field} checked={field.value} disabled={isDisabled} />}
render={({ field: { value, ...field } }) => <ToggleSwitch {...field} checked={value} disabled={isDisabled} />}
/>
</FieldRow>
</Field>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,12 @@ export const SubscriptionCalloutLimits = () => {
<>
{start_fair_policy && (
<Callout type='warning' title={t('subscription.callout.servicesDisruptionsMayOccur')} m={8}>
<Trans i18nKey='subscription.callout.description.limitsReached' count={start_fair_policy.length}>
Your workspace reached the <>{{ val: start_fair_policy.map(toTranslationKey) }}</> limit.
<Trans
i18nKey='subscription.callout.description.limitsReached'
count={start_fair_policy.length}
value={{ val: start_fair_policy.map(toTranslationKey) }}
>
Your workspace reached the <>{start_fair_policy.map(toTranslationKey)}</> limit.
<ExternalLink
to={manageSubscriptionUrl({
target: 'callout',
Expand All @@ -43,8 +47,12 @@ export const SubscriptionCalloutLimits = () => {

{prevent_action && (
<Callout type='danger' title={t('subscription.callout.servicesDisruptionsOccurring')} m={8}>
<Trans i18nKey='subscription.callout.description.limitsExceeded' count={prevent_action.length}>
Your workspace exceeded the <>{{ val: prevent_action.map(toTranslationKey) }}</> license limit.
<Trans
i18nKey='subscription.callout.description.limitsExceeded'
count={prevent_action.length}
values={{ val: prevent_action.map(toTranslationKey) }}
>
Your workspace exceeded the <>{prevent_action.map(toTranslationKey)}</> license limit.
<ExternalLink
to={manageSubscriptionUrl({
target: 'callout',
Expand All @@ -61,8 +69,12 @@ export const SubscriptionCalloutLimits = () => {

{disable_modules && (
<Callout type='danger' title={t('subscription.callout.capabilitiesDisabled')} m={8}>
<Trans i18nKey='subscription.callout.description.limitsExceeded' count={disable_modules.length}>
Your workspace exceeded the <>{{ val: disable_modules.map(toTranslationKey) }}</> license limit.
<Trans
i18nKey='subscription.callout.description.limitsExceeded'
count={disable_modules.length}
values={{ val: disable_modules.map(toTranslationKey) }}
>
Your workspace exceeded the <>{disable_modules.map(toTranslationKey)}</> license limit.
<ExternalLink
to={manageSubscriptionUrl({
target: 'callout',
Expand All @@ -79,8 +91,12 @@ export const SubscriptionCalloutLimits = () => {

{invalidate_license && (
<Callout type='danger' title={t('subscription.callout.allPremiumCapabilitiesDisabled')} m={8}>
<Trans i18nKey='subscription.callout.description.limitsExceeded' count={disable_modules.length}>
Your workspace exceeded the <>{{ val: invalidate_license.map(toTranslationKey) }}</> license limit.
<Trans
i18nKey='subscription.callout.description.limitsExceeded'
count={disable_modules.length}
values={{ val: invalidate_license.map(toTranslationKey) }}
>
Your workspace exceeded the <>{invalidate_license.map(toTranslationKey)}</> license limit.
<ExternalLink
to={manageSubscriptionUrl({
target: 'callout',
Expand Down
Loading

0 comments on commit 6586d0b

Please sign in to comment.