diff --git a/webapp/channels/src/components/admin_console/feature_discovery/feature_discovery.test.tsx b/webapp/channels/src/components/admin_console/feature_discovery/feature_discovery.test.tsx index 1449293f5f..914f92e0b3 100644 --- a/webapp/channels/src/components/admin_console/feature_discovery/feature_discovery.test.tsx +++ b/webapp/channels/src/components/admin_console/feature_discovery/feature_discovery.test.tsx @@ -26,10 +26,14 @@ describe('components/feature_discovery', () => { } // eslint-disable-next-line @typescript-eslint/naming-convention @@ -82,10 +86,14 @@ describe('components/feature_discovery', () => { } // eslint-disable-next-line @typescript-eslint/naming-convention @@ -139,10 +147,14 @@ describe('components/feature_discovery', () => { } // eslint-disable-next-line @typescript-eslint/naming-convention diff --git a/webapp/channels/src/components/admin_console/feature_discovery/feature_discovery.tsx b/webapp/channels/src/components/admin_console/feature_discovery/feature_discovery.tsx index 31822c923a..d9f8e0bf11 100644 --- a/webapp/channels/src/components/admin_console/feature_discovery/feature_discovery.tsx +++ b/webapp/channels/src/components/admin_console/feature_discovery/feature_discovery.tsx @@ -2,6 +2,7 @@ // See LICENSE.txt for license information. import React from 'react'; +import type {MessageDescriptor} from 'react-intl'; import {FormattedMessage} from 'react-intl'; import type {AnalyticsState} from '@mattermost/types/admin'; @@ -30,11 +31,8 @@ type Props = { featureName: string; minimumSKURequiredForFeature: LicenseSkus; - titleID: string; - titleDefault: string; - - copyID: string; - copyDefault: string; + title: MessageDescriptor; + copy: MessageDescriptor; learnMoreURL: string; @@ -230,10 +228,8 @@ export default class FeatureDiscovery extends React.PureComponent render() { const { - titleID, - titleDefault, - copyID, - copyDefault, + title, + copy, learnMoreURL, featureDiscoveryImage, isCloud, @@ -312,14 +308,12 @@ export default class FeatureDiscovery extends React.PureComponent data-testid='featureDiscovery_title' >
{this.props.prevTrialLicense?.IsLicensed === 'true' ? this.renderPostTrialCta() : this.renderStartTrial(learnMoreURL, gettingTrialError)} diff --git a/webapp/channels/src/components/admin_console/feature_discovery/features/announcement_banner.tsx b/webapp/channels/src/components/admin_console/feature_discovery/features/announcement_banner.tsx index 64ef43b41d..7137ce54c0 100644 --- a/webapp/channels/src/components/admin_console/feature_discovery/features/announcement_banner.tsx +++ b/webapp/channels/src/components/admin_console/feature_discovery/features/announcement_banner.tsx @@ -2,9 +2,9 @@ // See LICENSE.txt for license information. import React from 'react'; +import {defineMessage} from 'react-intl'; import {LicenseSkus} from 'utils/constants'; -import {t} from 'utils/i18n'; import AnnouncementBannerSVG from './images/announcement_banner_svg'; @@ -15,17 +15,18 @@ const AnnouncementBannerFeatureDiscovery: React.FC = () => { } /> ); }; -t('admin.announcement_banner_feature_discovery.title'); -t('admin.announcement_banner_feature_discovery.copy'); - export default AnnouncementBannerFeatureDiscovery; diff --git a/webapp/channels/src/components/admin_console/feature_discovery/features/compliance_export.tsx b/webapp/channels/src/components/admin_console/feature_discovery/features/compliance_export.tsx index 571842a172..dd8fd2bc3b 100644 --- a/webapp/channels/src/components/admin_console/feature_discovery/features/compliance_export.tsx +++ b/webapp/channels/src/components/admin_console/feature_discovery/features/compliance_export.tsx @@ -2,9 +2,9 @@ // See LICENSE.txt for license information. import React from 'react'; +import {defineMessage} from 'react-intl'; import {DocLinks, LicenseSkus} from 'utils/constants'; -import {t} from 'utils/i18n'; import ComplianceExportSVG from './images/compliance_export_svg'; @@ -15,17 +15,18 @@ const ComplianceExportFeatureDiscovery: React.FC = () => { } /> ); }; -t('admin.compliance_export_feature_discovery.title'); -t('admin.compliance_export_feature_discovery.copy'); - export default ComplianceExportFeatureDiscovery; diff --git a/webapp/channels/src/components/admin_console/feature_discovery/features/custom_terms_of_service.tsx b/webapp/channels/src/components/admin_console/feature_discovery/features/custom_terms_of_service.tsx index 690f31b0f1..059e156b85 100644 --- a/webapp/channels/src/components/admin_console/feature_discovery/features/custom_terms_of_service.tsx +++ b/webapp/channels/src/components/admin_console/feature_discovery/features/custom_terms_of_service.tsx @@ -2,9 +2,9 @@ // See LICENSE.txt for license information. import React from 'react'; +import {defineMessage} from 'react-intl'; import {LicenseSkus} from 'utils/constants'; -import {t} from 'utils/i18n'; import CustomTermsOfServiceSVG from './images/custom_terms_of_service_svg'; @@ -15,17 +15,18 @@ const CustomTermsOfServiceFeatureDiscovery: React.FC = () => { } /> ); }; -t('admin.custom_terms_of_service_feature_discovery.title'); -t('admin.custom_terms_of_service_feature_discovery.copy'); - export default CustomTermsOfServiceFeatureDiscovery; diff --git a/webapp/channels/src/components/admin_console/feature_discovery/features/data_retention.tsx b/webapp/channels/src/components/admin_console/feature_discovery/features/data_retention.tsx index d27803f665..3d18371dd0 100644 --- a/webapp/channels/src/components/admin_console/feature_discovery/features/data_retention.tsx +++ b/webapp/channels/src/components/admin_console/feature_discovery/features/data_retention.tsx @@ -2,9 +2,9 @@ // See LICENSE.txt for license information. import React from 'react'; +import {defineMessage} from 'react-intl'; import {LicenseSkus} from 'utils/constants'; -import {t} from 'utils/i18n'; import DataRetentionSVG from './images/data_retention_svg'; @@ -15,17 +15,18 @@ const DataRetentionFeatureDiscovery: React.FC = () => { } /> ); }; -t('admin.data_retention_feature_discovery.title'); -t('admin.data_retention_feature_discovery.copy'); - export default DataRetentionFeatureDiscovery; diff --git a/webapp/channels/src/components/admin_console/feature_discovery/features/groups.tsx b/webapp/channels/src/components/admin_console/feature_discovery/features/groups.tsx index e15a6301ab..727ce29873 100644 --- a/webapp/channels/src/components/admin_console/feature_discovery/features/groups.tsx +++ b/webapp/channels/src/components/admin_console/feature_discovery/features/groups.tsx @@ -2,9 +2,9 @@ // See LICENSE.txt for license information. import React from 'react'; +import {defineMessage} from 'react-intl'; import {LicenseSkus} from 'utils/constants'; -import {t} from 'utils/i18n'; import GroupsSVG from './images/groups_svg'; @@ -15,17 +15,18 @@ const GroupsFeatureDiscovery: React.FC = () => { } /> ); }; -t('admin.groups_feature_discovery.title'); -t('admin.groups_feature_discovery.copy'); - export default GroupsFeatureDiscovery; diff --git a/webapp/channels/src/components/admin_console/feature_discovery/features/guest_access.tsx b/webapp/channels/src/components/admin_console/feature_discovery/features/guest_access.tsx index db28372f7a..ca363f56d7 100644 --- a/webapp/channels/src/components/admin_console/feature_discovery/features/guest_access.tsx +++ b/webapp/channels/src/components/admin_console/feature_discovery/features/guest_access.tsx @@ -2,9 +2,9 @@ // See LICENSE.txt for license information. import React from 'react'; +import {defineMessage} from 'react-intl'; import {LicenseSkus} from 'utils/constants'; -import {t} from 'utils/i18n'; import GuestAccessSVG from './images/guest_access_svg'; @@ -15,17 +15,18 @@ const GuestAccessFeatureDiscovery: React.FC = () => { } /> ); }; -t('admin.guest_access_feature_discovery.title'); -t('admin.guest_access_feature_discovery.copy'); - export default GuestAccessFeatureDiscovery; diff --git a/webapp/channels/src/components/admin_console/feature_discovery/features/ldap.tsx b/webapp/channels/src/components/admin_console/feature_discovery/features/ldap.tsx index 6d7d227a35..43be7c1f97 100644 --- a/webapp/channels/src/components/admin_console/feature_discovery/features/ldap.tsx +++ b/webapp/channels/src/components/admin_console/feature_discovery/features/ldap.tsx @@ -2,9 +2,9 @@ // See LICENSE.txt for license information. import React from 'react'; +import {defineMessage} from 'react-intl'; import {LicenseSkus} from 'utils/constants'; -import {t} from 'utils/i18n'; import LdapSVG from './images/ldap_svg'; @@ -15,17 +15,18 @@ const LDAPFeatureDiscovery: React.FC = () => { } /> ); }; -t('admin.ldap_feature_discovery.title'); -t('admin.ldap_feature_discovery.copy'); - export default LDAPFeatureDiscovery; diff --git a/webapp/channels/src/components/admin_console/feature_discovery/features/openid.tsx b/webapp/channels/src/components/admin_console/feature_discovery/features/openid.tsx index be107e4eb4..0db1aafdbd 100644 --- a/webapp/channels/src/components/admin_console/feature_discovery/features/openid.tsx +++ b/webapp/channels/src/components/admin_console/feature_discovery/features/openid.tsx @@ -2,9 +2,9 @@ // See LICENSE.txt for license information. import React from 'react'; +import {defineMessage} from 'react-intl'; import {LicenseSkus} from 'utils/constants'; -import {t} from 'utils/i18n'; import SamlSVG from './images/saml_svg'; @@ -15,17 +15,18 @@ const OpenIDFeatureDiscovery: React.FC = () => { } /> ); }; -t('admin.openid_feature_discovery.title'); -t('admin.openid_feature_discovery.copy'); - export default OpenIDFeatureDiscovery; diff --git a/webapp/channels/src/components/admin_console/feature_discovery/features/openid_custom.tsx b/webapp/channels/src/components/admin_console/feature_discovery/features/openid_custom.tsx index f755c926eb..4de125b707 100644 --- a/webapp/channels/src/components/admin_console/feature_discovery/features/openid_custom.tsx +++ b/webapp/channels/src/components/admin_console/feature_discovery/features/openid_custom.tsx @@ -2,9 +2,9 @@ // See LICENSE.txt for license information. import React from 'react'; +import {defineMessage} from 'react-intl'; import {LicenseSkus} from 'utils/constants'; -import {t} from 'utils/i18n'; import SamlSVG from './images/saml_svg'; @@ -15,17 +15,18 @@ const OpenIDCustomFeatureDiscovery: React.FC = () => { } /> ); }; -t('admin.openid_custom_feature_discovery.title'); -t('admin.openid_custom_feature_discovery.copy'); - export default OpenIDCustomFeatureDiscovery; diff --git a/webapp/channels/src/components/admin_console/feature_discovery/features/saml.tsx b/webapp/channels/src/components/admin_console/feature_discovery/features/saml.tsx index abe06a3c14..38a3522359 100644 --- a/webapp/channels/src/components/admin_console/feature_discovery/features/saml.tsx +++ b/webapp/channels/src/components/admin_console/feature_discovery/features/saml.tsx @@ -2,9 +2,9 @@ // See LICENSE.txt for license information. import React from 'react'; +import {defineMessage} from 'react-intl'; import {LicenseSkus} from 'utils/constants'; -import {t} from 'utils/i18n'; import SamlSVG from './images/saml_svg'; @@ -15,17 +15,18 @@ const SAMLFeatureDiscovery: React.FC = () => { } /> ); }; -t('admin.saml_feature_discovery.title'); -t('admin.saml_feature_discovery.copy'); - export default SAMLFeatureDiscovery; diff --git a/webapp/channels/src/components/admin_console/feature_discovery/features/system_roles.tsx b/webapp/channels/src/components/admin_console/feature_discovery/features/system_roles.tsx index 6db2748f0d..0f02abf43a 100644 --- a/webapp/channels/src/components/admin_console/feature_discovery/features/system_roles.tsx +++ b/webapp/channels/src/components/admin_console/feature_discovery/features/system_roles.tsx @@ -2,9 +2,9 @@ // See LICENSE.txt for license information. import React from 'react'; +import {defineMessage} from 'react-intl'; import {LicenseSkus} from 'utils/constants'; -import {t} from 'utils/i18n'; import SystemRolesSVG from './images/system_roles_svg'; @@ -15,17 +15,18 @@ const SystemRolesFeatureDiscovery: React.FC = () => { } /> ); }; -t('admin.system_roles_feature_discovery.title'); -t('admin.system_roles_feature_discovery.copy'); - export default SystemRolesFeatureDiscovery; diff --git a/webapp/channels/src/components/admin_console/permission_schemes_settings/edit_post_time_limit_button/edit_post_time_limit_button.tsx b/webapp/channels/src/components/admin_console/permission_schemes_settings/edit_post_time_limit_button/edit_post_time_limit_button.tsx index e27b8588ea..fcbace5e55 100644 --- a/webapp/channels/src/components/admin_console/permission_schemes_settings/edit_post_time_limit_button/edit_post_time_limit_button.tsx +++ b/webapp/channels/src/components/admin_console/permission_schemes_settings/edit_post_time_limit_button/edit_post_time_limit_button.tsx @@ -5,21 +5,14 @@ import React from 'react'; import {FormattedMessage} from 'react-intl'; import {Constants} from 'utils/constants'; -import {t} from 'utils/i18n'; type Props = { timeLimit: number; onClick: () => void; isDisabled: boolean | undefined; } -export default function EditPostTimeLimitButton(props: Props) { - let messageID; - if (props.timeLimit === Constants.UNSET_POST_EDIT_TIME_LIMIT) { - messageID = t('edit_post.time_limit_button.no_limit'); - } else { - messageID = t('edit_post.time_limit_button.for_n_seconds'); - } +export default function EditPostTimeLimitButton(props: Props) { return ( ); } diff --git a/webapp/channels/src/components/admin_console/permission_schemes_settings/edit_post_time_limit_modal/edit_post_time_limit_modal.tsx b/webapp/channels/src/components/admin_console/permission_schemes_settings/edit_post_time_limit_modal/edit_post_time_limit_modal.tsx index 7e14696773..e33b945ec8 100644 --- a/webapp/channels/src/components/admin_console/permission_schemes_settings/edit_post_time_limit_modal/edit_post_time_limit_modal.tsx +++ b/webapp/channels/src/components/admin_console/permission_schemes_settings/edit_post_time_limit_modal/edit_post_time_limit_modal.tsx @@ -3,7 +3,7 @@ import React, {useState} from 'react'; import {Modal} from 'react-bootstrap'; -import {FormattedMessage} from 'react-intl'; +import {FormattedMessage, useIntl} from 'react-intl'; import type {AdminConfig} from '@mattermost/types/config'; import type {DeepPartial} from '@mattermost/types/utilities'; @@ -13,8 +13,6 @@ import type {ActionResult} from 'mattermost-redux/types/actions'; import FormattedMarkdownMessage from 'components/formatted_markdown_message'; import {Constants} from 'utils/constants'; -import {t} from 'utils/i18n'; -import {localizeMessage} from 'utils/utils'; const INT32_MAX = 2147483647; @@ -30,6 +28,8 @@ type Props ={ export default function EditPostTimeLimitModal(props: Props) { const {ServiceSettings} = props.config; + const intl = useIntl(); + const [saving, setSaving] = useState(false); const [errorMessage, setErrorMessage] = useState(''); const [postEditTimeLimit, setPostEditTimeLimit] = useState(ServiceSettings?.PostEditTimeLimit || Constants.UNSET_POST_EDIT_TIME_LIMIT); @@ -40,7 +40,7 @@ export default function EditPostTimeLimitModal(props: Props) { setErrorMessage(''); if (isNaN(postEditTimeLimit) || postEditTimeLimit < 0 || postEditTimeLimit > INT32_MAX) { - setErrorMessage(localizeMessage('edit_post.time_limit_modal.invalid_time_limit', 'Invalid time limit')); + setErrorMessage(intl.formatMessage({id: 'edit_post.time_limit_modal.invalid_time_limit', defaultMessage: 'Invalid time limit'})); setSaving(false); setPostEditTimeLimit(0); return false; @@ -170,10 +170,17 @@ export default function EditPostTimeLimitModal(props: Props) { onClick={save} disabled={saving} > - + {saving ? ( + + ) : ( + + )} diff --git a/webapp/channels/src/components/admin_console/system_user_detail/team_list/__snapshots__/abstract_list.test.tsx.snap b/webapp/channels/src/components/admin_console/system_user_detail/team_list/__snapshots__/abstract_list.test.tsx.snap index aa2291da36..76acdb0958 100644 --- a/webapp/channels/src/components/admin_console/system_user_detail/team_list/__snapshots__/abstract_list.test.tsx.snap +++ b/webapp/channels/src/components/admin_console/system_user_detail/team_list/__snapshots__/abstract_list.test.tsx.snap @@ -55,7 +55,10 @@ exports[`admin_console/system_user_detail/team_list/AbstractList should match sn } } > - Name +
- Type +
- Role +
- Name +
- Type +
- Role +
- Name +
- Type +
- Role +
{ const headerLabels = [ { - id: 'admin.team_settings.team_list.header.name', - default: 'Name', + label: { + id: 'admin.team_settings.team_list.header.name', + defaultMessage: 'Name', + }, style: { flexGrow: 1, minWidth: '284px', @@ -46,15 +48,19 @@ describe('admin_console/system_user_detail/team_list/AbstractList', () => { }, }, { - id: 'admin.systemUserDetail.teamList.header.type', - default: 'Type', + label: { + id: 'admin.systemUserDetail.teamList.header.type', + defaultMessage: 'Type', + }, style: { width: '150px', }, }, { - id: 'admin.systemUserDetail.teamList.header.role', - default: 'Role', + label: { + id: 'admin.systemUserDetail.teamList.header.role', + defaultMessage: 'Role', + }, style: { width: '150px', }, @@ -68,8 +74,10 @@ describe('admin_console/system_user_detail/team_list/AbstractList', () => { total: 0, headerLabels, renderRow, - emptyListTextId: 'admin.team_settings.team_list.no_teams_found', - emptyListTextDefaultMessage: 'No teams found', + emptyList: { + id: 'admin.team_settings.team_list.no_teams_found', + defaultMessage: 'No teams found', + }, actions: { getTeamsData: jest.fn().mockResolvedValue(Promise.resolve([])), removeGroup: jest.fn(), diff --git a/webapp/channels/src/components/admin_console/system_user_detail/team_list/abstract_list.tsx b/webapp/channels/src/components/admin_console/system_user_detail/team_list/abstract_list.tsx index 3d4d809750..d2aa9bbf29 100644 --- a/webapp/channels/src/components/admin_console/system_user_detail/team_list/abstract_list.tsx +++ b/webapp/channels/src/components/admin_console/system_user_detail/team_list/abstract_list.tsx @@ -2,6 +2,7 @@ // See LICENSE.txt for license information. import React from 'react'; +import type {MessageDescriptor} from 'react-intl'; import {FormattedMessage} from 'react-intl'; import type {Team} from '@mattermost/types/teams'; @@ -19,13 +20,15 @@ const PAGE_SIZE = 10; type Props = { userId: string; - headerLabels: Array>; + headerLabels: Array<{ + label?: MessageDescriptor; + style: React.CSSProperties; + }>; data: TeamWithMembership[]; onPageChangedCallback?: (paging: Paging) => void; total: number; renderRow: (item: TeamWithMembership) => JSX.Element; - emptyListTextId: string; - emptyListTextDefaultMessage: string; + emptyList: MessageDescriptor; actions: { getTeamsData: (userId: string) => Promise>; removeGroup?: () => void; @@ -106,7 +109,9 @@ export default class AbstractList extends React.PureComponent { key={id} className='AbstractList__header-label' style={headerLabel.style} - >{headerLabel.default}
+ > + + ))} ); @@ -125,10 +130,7 @@ export default class AbstractList extends React.PureComponent { if (this.props.data.length === 0) { return (
- +
); } diff --git a/webapp/channels/src/components/admin_console/system_user_detail/team_list/team_list.tsx b/webapp/channels/src/components/admin_console/system_user_detail/team_list/team_list.tsx index e56d9e3052..afb6b87345 100644 --- a/webapp/channels/src/components/admin_console/system_user_detail/team_list/team_list.tsx +++ b/webapp/channels/src/components/admin_console/system_user_detail/team_list/team_list.tsx @@ -2,12 +2,13 @@ // See LICENSE.txt for license information. import React from 'react'; +import type {MessageDescriptor} from 'react-intl'; +import {defineMessage} from 'react-intl'; import type {Team, TeamMembership} from '@mattermost/types/teams'; import type {ActionResult} from 'mattermost-redux/types/actions'; -import {t} from 'utils/i18n'; import {filterAndSortTeamsByDisplayName} from 'utils/team_utils'; import AbstractList from './abstract_list'; @@ -16,8 +17,10 @@ import type {TeamWithMembership} from './types'; const headerLabels = [ { - id: t('admin.systemUserDetail.teamList.header.name'), - default: 'Name', + label: defineMessage({ + id: 'admin.systemUserDetail.teamList.header.name', + defaultMessage: 'Name', + }), style: { flexGrow: 1, minWidth: '284px', @@ -25,15 +28,19 @@ const headerLabels = [ }, }, { - id: t('admin.systemUserDetail.teamList.header.type'), - default: 'Type', + label: defineMessage({ + id: 'admin.systemUserDetail.teamList.header.type', + defaultMessage: 'Type', + }), style: { width: '150px', }, }, { - id: t('admin.systemUserDetail.teamList.header.role'), - default: 'Role', + label: defineMessage({ + id: 'admin.systemUserDetail.teamList.header.role', + defaultMessage: 'Role', + }), style: { width: '150px', }, @@ -48,8 +55,7 @@ const headerLabels = [ type Props = { userId: string; locale: string; - emptyListTextId: string; - emptyListTextDefaultMessage: string; + emptyList: MessageDescriptor; actions: { getTeamsData: (userId: string) => Promise>; getTeamMembersForUser: (userId: string) => Promise>; @@ -68,8 +74,10 @@ type State = { export default class TeamList extends React.PureComponent { public static defaultProps = { - emptyListTextId: t('admin.team_settings.team_list.no_teams_found'), - emptyListTextDefaultMessage: 'No teams found', + emptyList: defineMessage({ + id: 'admin.team_settings.team_list.no_teams_found', + defaultMessage: 'No teams found', + }), refreshTeams: false, }; @@ -173,8 +181,7 @@ export default class TeamList extends React.PureComponent { total={this.state.teamsWithMemberships.length} data={this.state.teamsWithMemberships} actions={this.props.actions} - emptyListTextId={this.props.emptyListTextId} - emptyListTextDefaultMessage={this.props.emptyListTextDefaultMessage} + emptyList={this.props.emptyList} userId={this.props.userId} /> diff --git a/webapp/channels/src/components/admin_console/team_channel_settings/abstract_list.test.tsx b/webapp/channels/src/components/admin_console/team_channel_settings/abstract_list.test.tsx index 08fe82c2f5..5ceef994b0 100644 --- a/webapp/channels/src/components/admin_console/team_channel_settings/abstract_list.test.tsx +++ b/webapp/channels/src/components/admin_console/team_channel_settings/abstract_list.test.tsx @@ -55,8 +55,10 @@ describe('admin_console/team_channel_settings/AbstractList', () => { total={0} header={header} renderRow={renderRow} - emptyListTextId={'test'} - emptyListTextDefaultMessage={'test'} + emptyListText={{ + id: 'test', + defaultMessage: 'test', + }} actions={actions} />); @@ -83,8 +85,10 @@ describe('admin_console/team_channel_settings/AbstractList', () => { total={testTeams.length} header={header} renderRow={renderRow} - emptyListTextId={'test'} - emptyListTextDefaultMessage={'test'} + emptyListText={{ + id: 'test', + defaultMessage: 'test', + }} actions={actions} />); diff --git a/webapp/channels/src/components/admin_console/team_channel_settings/abstract_list.tsx b/webapp/channels/src/components/admin_console/team_channel_settings/abstract_list.tsx index 54158cd533..6326604e64 100644 --- a/webapp/channels/src/components/admin_console/team_channel_settings/abstract_list.tsx +++ b/webapp/channels/src/components/admin_console/team_channel_settings/abstract_list.tsx @@ -4,6 +4,7 @@ import classNames from 'classnames'; import React from 'react'; import type {MouseEvent} from 'react'; +import type {MessageDescriptor} from 'react-intl'; import {FormattedMessage} from 'react-intl'; import type {Group} from '@mattermost/types/groups'; @@ -28,8 +29,7 @@ type Props = { total: number; header: JSX.Element; renderRow: (item: Group | TeamWithMembership) => JSX.Element; - emptyListTextId: string; - emptyListTextDefaultMessage: string; + emptyListText: MessageDescriptor; actions: { getData: (page: number, perPage: number, notAssociatedToGroup?: string, excludeDefaultChannels?: boolean, includeDeleted?: boolean) => Promise; }; @@ -91,10 +91,7 @@ export default class AbstractList extends React.PureComponent { if (this.props.data.length === 0) { return (
- +
); } diff --git a/webapp/channels/src/components/admin_console/team_channel_settings/convert_and_remove_confirm_modal.tsx b/webapp/channels/src/components/admin_console/team_channel_settings/convert_and_remove_confirm_modal.tsx index bc0bdadac1..e32b18368d 100644 --- a/webapp/channels/src/components/admin_console/team_channel_settings/convert_and_remove_confirm_modal.tsx +++ b/webapp/channels/src/components/admin_console/team_channel_settings/convert_and_remove_confirm_modal.tsx @@ -2,13 +2,11 @@ // See LICENSE.txt for license information. import React from 'react'; -import {FormattedMessage} from 'react-intl'; +import {FormattedMessage, defineMessages} from 'react-intl'; import ConfirmModal from 'components/confirm_modal'; import FormattedMarkdownMessage from 'components/formatted_markdown_message'; -import {t} from 'utils/i18n'; - type Props = { /* @@ -43,23 +41,23 @@ type Props = { }; const ConvertAndRemoveConfirmModal = ({show, onConfirm, onCancel, displayName, toPublic, removeAmount}: Props) => { - const toPublicMsg = 'When you convert **{displayName}** to a public channel, history and membership are preserved. Public channels are discoverable and can by joined by users on the system without invitation. \n \nAre you sure you want to convert **{displayName}** to a public channel?'; - const toPrivateMsg = 'When you convert **{displayName}** to a private channel, history and membership are preserved. Publicly shared files remain accessible to anyone with the link. Membership in a private channel is by invitation only. \n \nAre you sure you want to convert **{displayName}** to a private channel?'; - const convertMessageId = toPublic ? t('admin.team_channel_settings.convertConfirmModal.toPublicMessage') : t('admin.team_channel_settings.convertConfirmModal.toPrivateMessage'); - - const toPublicTitle = 'Convert channel to public and remove {amount, number} {amount, plural, one {user} other {users}}?'; - const toPrivateTitle = 'Convert channel to private and remove {amount, number} {amount, plural, one {user} other {users}}?'; - const titleId = toPublic ? t('admin.team_channel_settings.convertAndRemoveConfirmModal.toPublicTitle') : t('admin.team_channel_settings.convertAndRemoveConfirmModal.toPrivateTitle'); - - const toPublicConfirmMsg = 'Yes, convert channel to public and remove {amount, number} {amount, plural, one {user} other {users}}'; - const toPrivateConfirmMsg = 'Yes, convert channel to private and remove {amount, number} {amount, plural, one {user} other {users}}'; - const confirmMsgId = toPublic ? t('admin.team_channel_settings.convertAndRemoveConfirmModal.toPublicConfirm') : t('admin.team_channel_settings.convertAndRemoveConfirmModal.toPrivateConfirm'); + let titleMessage; + let convertMessage; + let confirmMessage; + if (toPublic) { + titleMessage = messages.toPublicTitle; + convertMessage = messages.toPublicMessage; + confirmMessage = messages.toPublicConfirm; + } else { + titleMessage = messages.toPrivateTitle; + convertMessage = messages.toPrivateMessage; + confirmMessage = messages.toPrivateConfirm; + } const title = ( ); @@ -67,8 +65,7 @@ const ConvertAndRemoveConfirmModal = ({show, onConfirm, onCancel, displayName, t

@@ -84,8 +81,7 @@ const ConvertAndRemoveConfirmModal = ({show, onConfirm, onCancel, displayName, t const confirmButton = ( ); @@ -114,4 +110,37 @@ const ConvertAndRemoveConfirmModal = ({show, onConfirm, onCancel, displayName, t ); }; +const messages = defineMessages({ + toPrivateConfirm: { + id: 'admin.team_channel_settings.convertAndRemoveConfirmModal.toPrivateConfirm', + defaultMessage: 'Yes, convert channel to private and remove {amount, number} {amount, plural, one {user} other {users}}', + }, + toPrivateMessage: { + id: 'admin.team_channel_settings.convertConfirmModal.toPrivateMessage', + + // This eslint-disable comment can be removed once this component no longer uses FormattedMarkdownMessage + // eslint-disable-next-line formatjs/no-multiple-whitespaces + defaultMessage: 'When you convert **{displayName}** to a private channel, history and membership are preserved. Publicly shared files remain accessible to anyone with the link. Membership in a private channel is by invitation only. \n \nAre you sure you want to convert **{displayName}** to a private channel?', + }, + toPrivateTitle: { + id: 'admin.team_channel_settings.convertAndRemoveConfirmModal.toPrivateTitle', + defaultMessage: 'Convert channel to private and remove {amount, number} {amount, plural, one {user} other {users}}?', + }, + toPublicConfirm: { + id: 'admin.team_channel_settings.convertAndRemoveConfirmModal.toPublicConfirm', + defaultMessage: 'Yes, convert channel to public and remove {amount, number} {amount, plural, one {user} other {users}}', + }, + toPublicMessage: { + id: 'admin.team_channel_settings.convertConfirmModal.toPublicMessage', + + // This eslint-disable comment can be removed once this component no longer uses FormattedMarkdownMessage + // eslint-disable-next-line formatjs/no-multiple-whitespaces + defaultMessage: 'When you convert **{displayName}** to a public channel, history and membership are preserved. Public channels are discoverable and can by joined by users on the system without invitation. \n \nAre you sure you want to convert **{displayName}** to a public channel?', + }, + toPublicTitle: { + id: 'admin.team_channel_settings.convertAndRemoveConfirmModal.toPublicTitle', + defaultMessage: 'Convert channel to public and remove {amount, number} {amount, plural, one {user} other {users}}?', + }, +}); + export default ConvertAndRemoveConfirmModal; diff --git a/webapp/channels/src/components/admin_console/team_channel_settings/convert_confirm_modal.tsx b/webapp/channels/src/components/admin_console/team_channel_settings/convert_confirm_modal.tsx index e65a622322..a9b70e8a5b 100644 --- a/webapp/channels/src/components/admin_console/team_channel_settings/convert_confirm_modal.tsx +++ b/webapp/channels/src/components/admin_console/team_channel_settings/convert_confirm_modal.tsx @@ -2,13 +2,11 @@ // See LICENSE.txt for license information. import React from 'react'; -import {FormattedMessage} from 'react-intl'; +import {FormattedMessage, defineMessages} from 'react-intl'; import ConfirmModal from 'components/confirm_modal'; import FormattedMarkdownMessage from 'components/formatted_markdown_message'; -import {t} from 'utils/i18n'; - type Props = { /* @@ -38,38 +36,36 @@ type Props = { }; const ConvertConfirmModal = ({show, onConfirm, onCancel, displayName, toPublic}: Props) => { - const toPublicMsg = 'When you convert **{displayName}** to a public channel, history and membership are preserved. Public channels are discoverable and can by joined by users on the system without invitation. \n \nAre you sure you want to convert **{displayName}** to a public channel?'; - const toPrivateMsg = 'When you convert **{displayName}** to a private channel, history and membership are preserved. Publicly shared files remain accessible to anyone with the link. Membership in a private channel is by invitation only. \n \nAre you sure you want to convert **{displayName}** to a private channel?'; - const messageId = toPublic ? t('admin.team_channel_settings.convertConfirmModal.toPublicMessage') : t('admin.team_channel_settings.convertConfirmModal.toPrivateMessage'); - - const toPublicTitle = 'Convert {displayName} to a public channel?'; - const toPrivateTitle = 'Convert {displayName} to a private channel?'; - const titleId = toPublic ? t('admin.team_channel_settings.convertConfirmModal.toPublicTitle') : t('admin.team_channel_settings.convertConfirmModal.toPrivateTitle'); - - const toPublicConfirmMsg = 'Yes, convert to public channel'; - const toPrivateConfirmMsg = 'Yes, convert to private channel'; - const confirmMsgId = toPublic ? t('admin.team_channel_settings.convertConfirmModal.toPublicConfirm') : t('admin.team_channel_settings.convertConfirmModal.toPrivateConfirm'); + let titleMessage; + let convertMessage; + let confirmMessage; + if (toPublic) { + titleMessage = messages.toPublicTitle; + convertMessage = messages.toPublicMessage; + confirmMessage = messages.toPublicConfirm; + } else { + titleMessage = messages.toPrivateTitle; + convertMessage = messages.toPrivateMessage; + confirmMessage = messages.toPrivateConfirm; + } const title = ( ); const message = ( ); const confirmButton = ( ); @@ -97,4 +93,37 @@ const ConvertConfirmModal = ({show, onConfirm, onCancel, displayName, toPublic}: ); }; +const messages = defineMessages({ + toPrivateConfirm: { + id: 'admin.team_channel_settings.convertConfirmModal.toPrivateConfirm', + defaultMessage: 'Yes, convert to private channel', + }, + toPrivateMessage: { + id: 'admin.team_channel_settings.convertConfirmModal.toPrivateMessage', + + // This eslint-disable comment can be removed once this component no longer uses FormattedMarkdownMessage + // eslint-disable-next-line formatjs/no-multiple-whitespaces + defaultMessage: 'When you convert **{displayName}** to a private channel, history and membership are preserved. Publicly shared files remain accessible to anyone with the link. Membership in a private channel is by invitation only. \n \nAre you sure you want to convert **{displayName}** to a private channel?', + }, + toPrivateTitle: { + id: 'admin.team_channel_settings.convertConfirmModal.toPrivateTitle', + defaultMessage: 'Convert {displayName} to a private channel?', + }, + toPublicConfirm: { + id: 'admin.team_channel_settings.convertConfirmModal.toPublicConfirm', + defaultMessage: 'Yes, convert to public channel', + }, + toPublicMessage: { + id: 'admin.team_channel_settings.convertConfirmModal.toPublicMessage', + + // This eslint-disable comment can be removed once this component no longer uses FormattedMarkdownMessage + // eslint-disable-next-line formatjs/no-multiple-whitespaces + defaultMessage: 'When you convert **{displayName}** to a public channel, history and membership are preserved. Public channels are discoverable and can by joined by users on the system without invitation. \n \nAre you sure you want to convert **{displayName}** to a public channel?', + }, + toPublicTitle: { + id: 'admin.team_channel_settings.convertConfirmModal.toPublicTitle', + defaultMessage: 'Convert {displayName} to a public channel?', + }, +}); + export default ConvertConfirmModal; diff --git a/webapp/channels/src/components/admin_console/team_channel_settings/group/__snapshots__/group_list.test.tsx.snap b/webapp/channels/src/components/admin_console/team_channel_settings/group/__snapshots__/group_list.test.tsx.snap index a69e587cc0..5400cac0fb 100644 --- a/webapp/channels/src/components/admin_console/team_channel_settings/group/__snapshots__/group_list.test.tsx.snap +++ b/webapp/channels/src/components/admin_console/team_channel_settings/group/__snapshots__/group_list.test.tsx.snap @@ -26,11 +26,14 @@ exports[`admin_console/team_channel_settings/group/GroupList should match snapsh }, ] } - emptyListTextDefaultMessage="test" - emptyListTextId="test" + emptyListText={ + Object { + "defaultMessage": "No groups specified yet", + "id": "admin.team_channel_settings.group_list.no-groups", + } + } groups={Array []} header={
} - isModeSync={false} noPadding={false} onGroupRemoved={[MockFunction]} onPageChangedCallback={[MockFunction]} @@ -501,11 +504,14 @@ exports[`admin_console/team_channel_settings/group/GroupList should match snapsh }, ] } - emptyListTextDefaultMessage="test" - emptyListTextId="test" + emptyListText={ + Object { + "defaultMessage": "No groups specified yet", + "id": "admin.team_channel_settings.group_list.no-groups", + } + } groups={Array []} header={
} - isModeSync={false} noPadding={false} onGroupRemoved={[MockFunction]} onPageChangedCallback={[MockFunction]} diff --git a/webapp/channels/src/components/admin_console/team_channel_settings/group/group_list.test.tsx b/webapp/channels/src/components/admin_console/team_channel_settings/group/group_list.test.tsx index d5cde3e20d..4fe47e5854 100644 --- a/webapp/channels/src/components/admin_console/team_channel_settings/group/group_list.test.tsx +++ b/webapp/channels/src/components/admin_console/team_channel_settings/group/group_list.test.tsx @@ -31,8 +31,6 @@ describe('admin_console/team_channel_settings/group/GroupList', () => { totalGroups={0} onPageChangedCallback={jest.fn()} total={testGroups.length} - emptyListTextId={'test'} - emptyListTextDefaultMessage={'test'} actions={actions} removeGroup={jest.fn()} type='team' @@ -64,8 +62,6 @@ describe('admin_console/team_channel_settings/group/GroupList', () => { totalGroups={0} onPageChangedCallback={jest.fn()} total={30} - emptyListTextId={'test'} - emptyListTextDefaultMessage={'test'} actions={actions} type='team' removeGroup={jest.fn()} diff --git a/webapp/channels/src/components/admin_console/team_channel_settings/group/group_list.tsx b/webapp/channels/src/components/admin_console/team_channel_settings/group/group_list.tsx index ee8bedcd70..28ac41c419 100644 --- a/webapp/channels/src/components/admin_console/team_channel_settings/group/group_list.tsx +++ b/webapp/channels/src/components/admin_console/team_channel_settings/group/group_list.tsx @@ -2,7 +2,7 @@ // See LICENSE.txt for license information. import React, {memo, useCallback} from 'react'; -import {FormattedMessage} from 'react-intl'; +import {FormattedMessage, defineMessages} from 'react-intl'; import type {Group} from '@mattermost/types/groups'; @@ -47,6 +47,7 @@ const GroupList = ({ setNewGroupRole, type, isDisabled, + isModeSync, ...restProps }: Props) => { const renderRow = useCallback((item: Partial) => { @@ -66,9 +67,21 @@ const GroupList = ({ } renderRow={renderRow} + emptyListText={isModeSync ? messages.emptyListModeSync : messages.emptyList} {...restProps} /> ); }; +const messages = defineMessages({ + emptyListModeSync: { + id: 'admin.team_channel_settings.group_list.no-synced-groups', + defaultMessage: 'At least one group must be specified', + }, + emptyList: { + id: 'admin.team_channel_settings.group_list.no-groups', + defaultMessage: 'No groups specified yet', + }, +}); + export default memo(GroupList); diff --git a/webapp/channels/src/components/admin_console/team_channel_settings/group/index.ts b/webapp/channels/src/components/admin_console/team_channel_settings/group/index.ts index 9bf4dc7e5d..2f2bf164d1 100644 --- a/webapp/channels/src/components/admin_console/team_channel_settings/group/index.ts +++ b/webapp/channels/src/components/admin_console/team_channel_settings/group/index.ts @@ -8,8 +8,6 @@ import type {Channel} from '@mattermost/types/channels'; import type {Group} from '@mattermost/types/groups'; import type {Team} from '@mattermost/types/teams'; -import {t} from 'utils/i18n'; - import type {GlobalState} from 'types/store'; import GroupList from './group_list'; @@ -32,8 +30,6 @@ function mapStateToProps(state: GlobalState, ownProps: OwnProps) { data: ownProps.groups, removeGroup: ownProps.onGroupRemoved, setNewGroupRole: ownProps.setNewGroupRole, - emptyListTextId: ownProps.isModeSync ? t('admin.team_channel_settings.group_list.no-synced-groups') : t('admin.team_channel_settings.group_list.no-groups'), - emptyListTextDefaultMessage: ownProps.isModeSync ? 'At least one group must be specified' : 'No groups specified yet', total: ownProps.totalGroups, }; } diff --git a/webapp/channels/src/components/admin_console/team_channel_settings/remove_confirm_modal.tsx b/webapp/channels/src/components/admin_console/team_channel_settings/remove_confirm_modal.tsx index 4847685e07..cf23ce5ecd 100644 --- a/webapp/channels/src/components/admin_console/team_channel_settings/remove_confirm_modal.tsx +++ b/webapp/channels/src/components/admin_console/team_channel_settings/remove_confirm_modal.tsx @@ -6,8 +6,6 @@ import {FormattedMessage} from 'react-intl'; import ConfirmModal from 'components/confirm_modal'; -import {t} from 'utils/i18n'; - type Props = { /* @@ -45,17 +43,24 @@ const RemoveConfirmModal = ({show, onConfirm, onCancel, inChannel, amount}: Prop /> ); - const messageId = inChannel ? t('admin.team_channel_settings.removeConfirmModal.messageChannel') : t('admin.team_channel_settings.removeConfirmModal.messageTeam'); - const messageChannel = '{amount, number} {amount, plural, one {user} other {users}} will be removed. They are not in groups linked to this channel. Are you sure you wish to remove {amount, plural, one {this user} other {these users}}?'; - const messageTeam = '{amount, number} {amount, plural, one {user} other {users}} will be removed. They are not in groups linked to this team. Are you sure you wish to remove {amount, plural, one {this user} other {these users}}?'; - - const message = ( - - ); + let message; + if (inChannel) { + message = ( + + ); + } else { + message = ( + + ); + } const buttonClass = 'btn btn-primary'; const button = (