Remove t from system console code (#27054)

* Remove t from components/admin_console/feature_discovery

* Remove t and localizeMessage from components/admin_console/permission_schemes_settings

* Remove t and localizeMessage from components/admin_console/system_user_detail

* Remove t from components/admin_console/team_channel_settins

* Address feedback
Этот коммит содержится в:
Harrison Healey
2024-05-27 15:49:39 -04:00
коммит произвёл GitHub
родитель 1bd7b6f4c2
Коммит 2f7f00b256
29 изменённых файлов: 430 добавлений и 266 удалений

Просмотреть файл

@@ -26,10 +26,14 @@ describe('components/feature_discovery', () => {
<FeatureDiscovery <FeatureDiscovery
featureName='test' featureName='test'
minimumSKURequiredForFeature={LicenseSkus.Professional} minimumSKURequiredForFeature={LicenseSkus.Professional}
titleID='translation.test.title' title={{
titleDefault='Foo' id: 'translation.test.title',
copyID='translation.test.copy' defaultMessage: 'Foo',
copyDefault={'Bar'} }}
copy={{
id: 'translation.test.copy',
defaultMessage: 'Bar',
}}
learnMoreURL='https://test.mattermost.com/secondary/' learnMoreURL='https://test.mattermost.com/secondary/'
featureDiscoveryImage={<SamlSVG/>} featureDiscoveryImage={<SamlSVG/>}
// eslint-disable-next-line @typescript-eslint/naming-convention // eslint-disable-next-line @typescript-eslint/naming-convention
@@ -82,10 +86,14 @@ describe('components/feature_discovery', () => {
<FeatureDiscovery <FeatureDiscovery
featureName='test' featureName='test'
minimumSKURequiredForFeature={LicenseSkus.Professional} minimumSKURequiredForFeature={LicenseSkus.Professional}
titleID='translation.test.title' title={{
titleDefault='Foo' id: 'translation.test.title',
copyID='translation.test.copy' defaultMessage: 'Foo',
copyDefault={'Bar'} }}
copy={{
id: 'translation.test.copy',
defaultMessage: 'Bar',
}}
learnMoreURL='https://test.mattermost.com/secondary/' learnMoreURL='https://test.mattermost.com/secondary/'
featureDiscoveryImage={<SamlSVG/>} featureDiscoveryImage={<SamlSVG/>}
// eslint-disable-next-line @typescript-eslint/naming-convention // eslint-disable-next-line @typescript-eslint/naming-convention
@@ -139,10 +147,14 @@ describe('components/feature_discovery', () => {
<FeatureDiscovery <FeatureDiscovery
featureName='test' featureName='test'
minimumSKURequiredForFeature={LicenseSkus.Professional} minimumSKURequiredForFeature={LicenseSkus.Professional}
titleID='translation.test.title' title={{
titleDefault='Foo' id: 'translation.test.title',
copyID='translation.test.copy' defaultMessage: 'Foo',
copyDefault={'Bar'} }}
copy={{
id: 'translation.test.copy',
defaultMessage: 'Bar',
}}
learnMoreURL='https://test.mattermost.com/secondary/' learnMoreURL='https://test.mattermost.com/secondary/'
featureDiscoveryImage={<SamlSVG/>} featureDiscoveryImage={<SamlSVG/>}
// eslint-disable-next-line @typescript-eslint/naming-convention // eslint-disable-next-line @typescript-eslint/naming-convention

Просмотреть файл

@@ -2,6 +2,7 @@
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import React from 'react'; import React from 'react';
import type {MessageDescriptor} from 'react-intl';
import {FormattedMessage} from 'react-intl'; import {FormattedMessage} from 'react-intl';
import type {AnalyticsState} from '@mattermost/types/admin'; import type {AnalyticsState} from '@mattermost/types/admin';
@@ -30,11 +31,8 @@ type Props = {
featureName: string; featureName: string;
minimumSKURequiredForFeature: LicenseSkus; minimumSKURequiredForFeature: LicenseSkus;
titleID: string; title: MessageDescriptor;
titleDefault: string; copy: MessageDescriptor;
copyID: string;
copyDefault: string;
learnMoreURL: string; learnMoreURL: string;
@@ -230,10 +228,8 @@ export default class FeatureDiscovery extends React.PureComponent<Props, State>
render() { render() {
const { const {
titleID, title,
titleDefault, copy,
copyID,
copyDefault,
learnMoreURL, learnMoreURL,
featureDiscoveryImage, featureDiscoveryImage,
isCloud, isCloud,
@@ -312,14 +308,12 @@ export default class FeatureDiscovery extends React.PureComponent<Props, State>
data-testid='featureDiscovery_title' data-testid='featureDiscovery_title'
> >
<FormattedMessage <FormattedMessage
id={titleID} {...title}
defaultMessage={titleDefault}
/> />
</div> </div>
<div className='FeatureDiscovery_copy'> <div className='FeatureDiscovery_copy'>
<FormattedMessage <FormattedMessage
id={copyID} {...copy}
defaultMessage={copyDefault}
/> />
</div> </div>
{this.props.prevTrialLicense?.IsLicensed === 'true' ? this.renderPostTrialCta() : this.renderStartTrial(learnMoreURL, gettingTrialError)} {this.props.prevTrialLicense?.IsLicensed === 'true' ? this.renderPostTrialCta() : this.renderStartTrial(learnMoreURL, gettingTrialError)}

Просмотреть файл

@@ -2,9 +2,9 @@
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import React from 'react'; import React from 'react';
import {defineMessage} from 'react-intl';
import {LicenseSkus} from 'utils/constants'; import {LicenseSkus} from 'utils/constants';
import {t} from 'utils/i18n';
import AnnouncementBannerSVG from './images/announcement_banner_svg'; import AnnouncementBannerSVG from './images/announcement_banner_svg';
@@ -15,17 +15,18 @@ const AnnouncementBannerFeatureDiscovery: React.FC = () => {
<FeatureDiscovery <FeatureDiscovery
featureName='announcement_banner' featureName='announcement_banner'
minimumSKURequiredForFeature={LicenseSkus.Professional} minimumSKURequiredForFeature={LicenseSkus.Professional}
titleID='admin.announcement_banner_feature_discovery.title' title={defineMessage({
titleDefault='Create custom announcement banners with Mattermost Professional' id: 'admin.announcement_banner_feature_discovery.title',
copyID='admin.announcement_banner_feature_discovery.copy' defaultMessage: 'Create custom announcement banners with Mattermost Professional',
copyDefault={'Create announcement banners to notify all members of important information.'} })}
copy={defineMessage({
id: 'admin.announcement_banner_feature_discovery.copy',
defaultMessage: 'Create announcement banners to notify all members of important information.',
})}
learnMoreURL='https://docs.mattermost.com/administration/announcement-banner.html' learnMoreURL='https://docs.mattermost.com/administration/announcement-banner.html'
featureDiscoveryImage={<AnnouncementBannerSVG/>} featureDiscoveryImage={<AnnouncementBannerSVG/>}
/> />
); );
}; };
t('admin.announcement_banner_feature_discovery.title');
t('admin.announcement_banner_feature_discovery.copy');
export default AnnouncementBannerFeatureDiscovery; export default AnnouncementBannerFeatureDiscovery;

Просмотреть файл

@@ -2,9 +2,9 @@
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import React from 'react'; import React from 'react';
import {defineMessage} from 'react-intl';
import {DocLinks, LicenseSkus} from 'utils/constants'; import {DocLinks, LicenseSkus} from 'utils/constants';
import {t} from 'utils/i18n';
import ComplianceExportSVG from './images/compliance_export_svg'; import ComplianceExportSVG from './images/compliance_export_svg';
@@ -15,17 +15,18 @@ const ComplianceExportFeatureDiscovery: React.FC = () => {
<FeatureDiscovery <FeatureDiscovery
featureName='compliance_export' featureName='compliance_export'
minimumSKURequiredForFeature={LicenseSkus.Enterprise} minimumSKURequiredForFeature={LicenseSkus.Enterprise}
titleID='admin.compliance_export_feature_discovery.title' title={defineMessage({
titleDefault='Run compliance exports with Mattermost Enterprise' id: 'admin.compliance_export_feature_discovery.title',
copyID='admin.compliance_export_feature_discovery.copy' defaultMessage: 'Run compliance exports with Mattermost Enterprise',
copyDefault={'Run daily compliance reports and export them to a variety of formats consumable by third-party integration tools such as Smarsh (Actiance).'} })}
copy={defineMessage({
id: 'admin.compliance_export_feature_discovery.copy',
defaultMessage: 'Run daily compliance reports and export them to a variety of formats consumable by third-party integration tools such as Smarsh (Actiance).',
})}
learnMoreURL={DocLinks.COMPILANCE_EXPORT} learnMoreURL={DocLinks.COMPILANCE_EXPORT}
featureDiscoveryImage={<ComplianceExportSVG/>} featureDiscoveryImage={<ComplianceExportSVG/>}
/> />
); );
}; };
t('admin.compliance_export_feature_discovery.title');
t('admin.compliance_export_feature_discovery.copy');
export default ComplianceExportFeatureDiscovery; export default ComplianceExportFeatureDiscovery;

Просмотреть файл

@@ -2,9 +2,9 @@
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import React from 'react'; import React from 'react';
import {defineMessage} from 'react-intl';
import {LicenseSkus} from 'utils/constants'; import {LicenseSkus} from 'utils/constants';
import {t} from 'utils/i18n';
import CustomTermsOfServiceSVG from './images/custom_terms_of_service_svg'; import CustomTermsOfServiceSVG from './images/custom_terms_of_service_svg';
@@ -15,17 +15,18 @@ const CustomTermsOfServiceFeatureDiscovery: React.FC = () => {
<FeatureDiscovery <FeatureDiscovery
featureName='custom_terms_of_service' featureName='custom_terms_of_service'
minimumSKURequiredForFeature={LicenseSkus.Enterprise} minimumSKURequiredForFeature={LicenseSkus.Enterprise}
titleID='admin.custom_terms_of_service_feature_discovery.title' title={defineMessage({
titleDefault='Create custom terms of service with Mattermost Enterprise' id: 'admin.custom_terms_of_service_feature_discovery.title',
copyID='admin.custom_terms_of_service_feature_discovery.copy' defaultMessage: 'Create custom terms of service with Mattermost Enterprise',
copyDefault={'Create your own terms of service that new users must accept before accessing your Mattermost instance on desktop, web, or mobile.'} })}
copy={defineMessage({
id: 'admin.custom_terms_of_service_feature_discovery.copy',
defaultMessage: 'Create your own terms of service that new users must accept before accessing your Mattermost instance on desktop, web, or mobile.',
})}
learnMoreURL='https://docs.mattermost.com/cloud/cloud-administration/custom-terms-of-service.html' learnMoreURL='https://docs.mattermost.com/cloud/cloud-administration/custom-terms-of-service.html'
featureDiscoveryImage={<CustomTermsOfServiceSVG/>} featureDiscoveryImage={<CustomTermsOfServiceSVG/>}
/> />
); );
}; };
t('admin.custom_terms_of_service_feature_discovery.title');
t('admin.custom_terms_of_service_feature_discovery.copy');
export default CustomTermsOfServiceFeatureDiscovery; export default CustomTermsOfServiceFeatureDiscovery;

Просмотреть файл

@@ -2,9 +2,9 @@
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import React from 'react'; import React from 'react';
import {defineMessage} from 'react-intl';
import {LicenseSkus} from 'utils/constants'; import {LicenseSkus} from 'utils/constants';
import {t} from 'utils/i18n';
import DataRetentionSVG from './images/data_retention_svg'; import DataRetentionSVG from './images/data_retention_svg';
@@ -15,17 +15,18 @@ const DataRetentionFeatureDiscovery: React.FC = () => {
<FeatureDiscovery <FeatureDiscovery
featureName='data_retention' featureName='data_retention'
minimumSKURequiredForFeature={LicenseSkus.Enterprise} minimumSKURequiredForFeature={LicenseSkus.Enterprise}
titleID='admin.data_retention_feature_discovery.title' title={defineMessage({
titleDefault='Create data retention schedules with Mattermost Enterprise' id: 'admin.data_retention_feature_discovery.title',
copyID='admin.data_retention_feature_discovery.copy' defaultMessage: 'Create data retention schedules with Mattermost Enterprise',
copyDefault={'Hold on to your data only as long as you need to. Create data retention jobs for select channels and teams to automatically delete disposable data.'} })}
copy={defineMessage({
id: 'admin.data_retention_feature_discovery.copy',
defaultMessage: 'Hold on to your data only as long as you need to. Create data retention jobs for select channels and teams to automatically delete disposable data.',
})}
learnMoreURL='https://docs.mattermost.com/administration/data-retention.html' learnMoreURL='https://docs.mattermost.com/administration/data-retention.html'
featureDiscoveryImage={<DataRetentionSVG/>} featureDiscoveryImage={<DataRetentionSVG/>}
/> />
); );
}; };
t('admin.data_retention_feature_discovery.title');
t('admin.data_retention_feature_discovery.copy');
export default DataRetentionFeatureDiscovery; export default DataRetentionFeatureDiscovery;

Просмотреть файл

@@ -2,9 +2,9 @@
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import React from 'react'; import React from 'react';
import {defineMessage} from 'react-intl';
import {LicenseSkus} from 'utils/constants'; import {LicenseSkus} from 'utils/constants';
import {t} from 'utils/i18n';
import GroupsSVG from './images/groups_svg'; import GroupsSVG from './images/groups_svg';
@@ -15,17 +15,18 @@ const GroupsFeatureDiscovery: React.FC = () => {
<FeatureDiscovery <FeatureDiscovery
featureName='groups' featureName='groups'
minimumSKURequiredForFeature={LicenseSkus.Enterprise} minimumSKURequiredForFeature={LicenseSkus.Enterprise}
titleID='admin.groups_feature_discovery.title' title={defineMessage({
titleDefault='Synchronize your Active Directory/LDAP groups with Mattermost Enterprise' id: 'admin.groups_feature_discovery.title',
copyID='admin.groups_feature_discovery.copy' defaultMessage: 'Synchronize your Active Directory/LDAP groups with Mattermost Enterprise',
copyDefault={'Use AD/LDAP groups to organize and apply actions to multiple users at once. Manage team and channel memberships, permissions, and more.'} })}
copy={defineMessage({
id: 'admin.groups_feature_discovery.copy',
defaultMessage: 'Use AD/LDAP groups to organize and apply actions to multiple users at once. Manage team and channel memberships, permissions, and more.',
})}
learnMoreURL='https://docs.mattermost.com/deployment/ldap-group-sync.html' learnMoreURL='https://docs.mattermost.com/deployment/ldap-group-sync.html'
featureDiscoveryImage={<GroupsSVG/>} featureDiscoveryImage={<GroupsSVG/>}
/> />
); );
}; };
t('admin.groups_feature_discovery.title');
t('admin.groups_feature_discovery.copy');
export default GroupsFeatureDiscovery; export default GroupsFeatureDiscovery;

Просмотреть файл

@@ -2,9 +2,9 @@
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import React from 'react'; import React from 'react';
import {defineMessage} from 'react-intl';
import {LicenseSkus} from 'utils/constants'; import {LicenseSkus} from 'utils/constants';
import {t} from 'utils/i18n';
import GuestAccessSVG from './images/guest_access_svg'; import GuestAccessSVG from './images/guest_access_svg';
@@ -15,17 +15,18 @@ const GuestAccessFeatureDiscovery: React.FC = () => {
<FeatureDiscovery <FeatureDiscovery
featureName='guest_access' featureName='guest_access'
minimumSKURequiredForFeature={LicenseSkus.Professional} minimumSKURequiredForFeature={LicenseSkus.Professional}
titleID='admin.guest_access_feature_discovery.title' title={defineMessage({
titleDefault='Enable guest accounts with Mattermost Professional' id: 'admin.guest_access_feature_discovery.title',
copyID='admin.guest_access_feature_discovery.copy' defaultMessage: 'Enable guest accounts with Mattermost Professional',
copyDefault={'Collaborate with users outside of your organization while tightly controlling their access channels and team members.'} })}
copy={defineMessage({
id: 'admin.guest_access_feature_discovery.copy',
defaultMessage: 'Collaborate with users outside of your organization while tightly controlling their access channels and team members.',
})}
learnMoreURL='https://docs.mattermost.com/deployment/guest-accounts.html' learnMoreURL='https://docs.mattermost.com/deployment/guest-accounts.html'
featureDiscoveryImage={<GuestAccessSVG/>} featureDiscoveryImage={<GuestAccessSVG/>}
/> />
); );
}; };
t('admin.guest_access_feature_discovery.title');
t('admin.guest_access_feature_discovery.copy');
export default GuestAccessFeatureDiscovery; export default GuestAccessFeatureDiscovery;

Просмотреть файл

@@ -2,9 +2,9 @@
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import React from 'react'; import React from 'react';
import {defineMessage} from 'react-intl';
import {LicenseSkus} from 'utils/constants'; import {LicenseSkus} from 'utils/constants';
import {t} from 'utils/i18n';
import LdapSVG from './images/ldap_svg'; import LdapSVG from './images/ldap_svg';
@@ -15,17 +15,18 @@ const LDAPFeatureDiscovery: React.FC = () => {
<FeatureDiscovery <FeatureDiscovery
featureName='ldap' featureName='ldap'
minimumSKURequiredForFeature={LicenseSkus.Professional} minimumSKURequiredForFeature={LicenseSkus.Professional}
titleID='admin.ldap_feature_discovery.title' title={defineMessage({
titleDefault='Integrate Active Directory/LDAP with Mattermost Professional' id: 'admin.ldap_feature_discovery.title',
copyID='admin.ldap_feature_discovery.copy' defaultMessage: 'Integrate Active Directory/LDAP with Mattermost Professional',
copyDefault={'When you connect Mattermost with your organization\'s Active Directory/LDAP, users can log in without having to create new usernames and passwords.'} })}
copy={defineMessage({
id: 'admin.ldap_feature_discovery.copy',
defaultMessage: 'When you connect Mattermost with your organization\'s Active Directory/LDAP, users can log in without having to create new usernames and passwords.',
})}
learnMoreURL='https://www.mattermost.com/docs-adldap/?utm_medium=product&utm_source=product-feature-discovery&utm_content=adldap' learnMoreURL='https://www.mattermost.com/docs-adldap/?utm_medium=product&utm_source=product-feature-discovery&utm_content=adldap'
featureDiscoveryImage={<LdapSVG/>} featureDiscoveryImage={<LdapSVG/>}
/> />
); );
}; };
t('admin.ldap_feature_discovery.title');
t('admin.ldap_feature_discovery.copy');
export default LDAPFeatureDiscovery; export default LDAPFeatureDiscovery;

Просмотреть файл

@@ -2,9 +2,9 @@
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import React from 'react'; import React from 'react';
import {defineMessage} from 'react-intl';
import {LicenseSkus} from 'utils/constants'; import {LicenseSkus} from 'utils/constants';
import {t} from 'utils/i18n';
import SamlSVG from './images/saml_svg'; import SamlSVG from './images/saml_svg';
@@ -15,17 +15,18 @@ const OpenIDFeatureDiscovery: React.FC = () => {
<FeatureDiscovery <FeatureDiscovery
featureName='openid' featureName='openid'
minimumSKURequiredForFeature={LicenseSkus.Professional} minimumSKURequiredForFeature={LicenseSkus.Professional}
titleID='admin.openid_feature_discovery.title' title={defineMessage({
titleDefault='Integrate OpenID Connect with Mattermost Professional' id: 'admin.openid_feature_discovery.title',
copyID='admin.openid_feature_discovery.copy' defaultMessage: 'Integrate OpenID Connect with Mattermost Professional',
copyDefault={'Use OpenID Connect for authentication and single sign-on (SSO) with any service that supports the OIDC specification such as Google, Office 365, Apple, Okta, OneLogin, and more.'} })}
copy={defineMessage({
id: 'admin.openid_feature_discovery.copy',
defaultMessage: 'Use OpenID Connect for authentication and single sign-on (SSO) with any service that supports the OIDC specification such as Google, Office 365, Apple, Okta, OneLogin, and more.',
})}
learnMoreURL='https://docs.mattermost.com/cloud/cloud-administration/sso-openid-connect.html' learnMoreURL='https://docs.mattermost.com/cloud/cloud-administration/sso-openid-connect.html'
featureDiscoveryImage={<SamlSVG/>} featureDiscoveryImage={<SamlSVG/>}
/> />
); );
}; };
t('admin.openid_feature_discovery.title');
t('admin.openid_feature_discovery.copy');
export default OpenIDFeatureDiscovery; export default OpenIDFeatureDiscovery;

Просмотреть файл

@@ -2,9 +2,9 @@
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import React from 'react'; import React from 'react';
import {defineMessage} from 'react-intl';
import {LicenseSkus} from 'utils/constants'; import {LicenseSkus} from 'utils/constants';
import {t} from 'utils/i18n';
import SamlSVG from './images/saml_svg'; import SamlSVG from './images/saml_svg';
@@ -15,17 +15,18 @@ const OpenIDCustomFeatureDiscovery: React.FC = () => {
<FeatureDiscovery <FeatureDiscovery
featureName='openid' featureName='openid'
minimumSKURequiredForFeature={LicenseSkus.Professional} minimumSKURequiredForFeature={LicenseSkus.Professional}
titleID='admin.openid_custom_feature_discovery.title' title={defineMessage({
titleDefault='Integrate OpenID Connect with Mattermost Professional' id: 'admin.openid_custom_feature_discovery.title',
copyID='admin.openid_custom_feature_discovery.copy' defaultMessage: 'Integrate OpenID Connect with Mattermost Professional',
copyDefault={'Use OpenID Connect for authentication and single sign-on (SSO) with any service that supports the OIDC specification such as Apple, Okta, OneLogin, and more.'} })}
copy={defineMessage({
id: 'admin.openid_custom_feature_discovery.copy',
defaultMessage: 'Use OpenID Connect for authentication and single sign-on (SSO) with any service that supports the OIDC specification such as Apple, Okta, OneLogin, and more.',
})}
learnMoreURL='https://docs.mattermost.com/cloud/cloud-administration/sso-openid-connect.html' learnMoreURL='https://docs.mattermost.com/cloud/cloud-administration/sso-openid-connect.html'
featureDiscoveryImage={<SamlSVG/>} featureDiscoveryImage={<SamlSVG/>}
/> />
); );
}; };
t('admin.openid_custom_feature_discovery.title');
t('admin.openid_custom_feature_discovery.copy');
export default OpenIDCustomFeatureDiscovery; export default OpenIDCustomFeatureDiscovery;

Просмотреть файл

@@ -2,9 +2,9 @@
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import React from 'react'; import React from 'react';
import {defineMessage} from 'react-intl';
import {LicenseSkus} from 'utils/constants'; import {LicenseSkus} from 'utils/constants';
import {t} from 'utils/i18n';
import SamlSVG from './images/saml_svg'; import SamlSVG from './images/saml_svg';
@@ -15,17 +15,18 @@ const SAMLFeatureDiscovery: React.FC = () => {
<FeatureDiscovery <FeatureDiscovery
featureName='saml' featureName='saml'
minimumSKURequiredForFeature={LicenseSkus.Professional} minimumSKURequiredForFeature={LicenseSkus.Professional}
titleID='admin.saml_feature_discovery.title' title={defineMessage({
titleDefault='Integrate SAML 2.0 with Mattermost Professional' id: 'admin.saml_feature_discovery.title',
copyID='admin.saml_feature_discovery.copy' defaultMessage: 'Integrate SAML 2.0 with Mattermost Professional',
copyDefault={'When you connect Mattermost with your organization\'s single sign-on provider, users can access Mattermost without having to re-enter their credentials.'} })}
copyID={defineMessage({
id: 'admin.saml_feature_discovery.copy',
defaultMessage: 'When you connect Mattermost with your organization\'s single sign-on provider, users can access Mattermost without having to re-enter their credentials.',
})}
learnMoreURL='https://www.mattermost.com/docs-saml/?utm_medium=product&utm_source=product-feature-discovery&utm_content=saml' learnMoreURL='https://www.mattermost.com/docs-saml/?utm_medium=product&utm_source=product-feature-discovery&utm_content=saml'
featureDiscoveryImage={<SamlSVG/>} featureDiscoveryImage={<SamlSVG/>}
/> />
); );
}; };
t('admin.saml_feature_discovery.title');
t('admin.saml_feature_discovery.copy');
export default SAMLFeatureDiscovery; export default SAMLFeatureDiscovery;

Просмотреть файл

@@ -2,9 +2,9 @@
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import React from 'react'; import React from 'react';
import {defineMessage} from 'react-intl';
import {LicenseSkus} from 'utils/constants'; import {LicenseSkus} from 'utils/constants';
import {t} from 'utils/i18n';
import SystemRolesSVG from './images/system_roles_svg'; import SystemRolesSVG from './images/system_roles_svg';
@@ -15,17 +15,18 @@ const SystemRolesFeatureDiscovery: React.FC = () => {
<FeatureDiscovery <FeatureDiscovery
featureName='system_roles' featureName='system_roles'
minimumSKURequiredForFeature={LicenseSkus.Enterprise} minimumSKURequiredForFeature={LicenseSkus.Enterprise}
titleID='admin.system_roles_feature_discovery.title' title={defineMessage({
titleDefault='Provide controlled access to the System Console with Mattermost Enterprise' id: 'admin.system_roles_feature_discovery.title',
copyID='admin.system_roles_feature_discovery.copy' defaultMessage: 'Provide controlled access to the System Console with Mattermost Enterprise',
copyDefault={'Use System Roles to give designated users read and/or write access to select sections of System Console.'} })}
copy={defineMessage({
id: 'admin.system_roles_feature_discovery.copy',
defaultMessage: 'Use System Roles to give designated users read and/or write access to select sections of System Console.',
})}
learnMoreURL='https://docs.mattermost.com/deployment/admin-roles.html' learnMoreURL='https://docs.mattermost.com/deployment/admin-roles.html'
featureDiscoveryImage={<SystemRolesSVG/>} featureDiscoveryImage={<SystemRolesSVG/>}
/> />
); );
}; };
t('admin.system_roles_feature_discovery.title');
t('admin.system_roles_feature_discovery.copy');
export default SystemRolesFeatureDiscovery; export default SystemRolesFeatureDiscovery;

Просмотреть файл

@@ -5,21 +5,14 @@ import React from 'react';
import {FormattedMessage} from 'react-intl'; import {FormattedMessage} from 'react-intl';
import {Constants} from 'utils/constants'; import {Constants} from 'utils/constants';
import {t} from 'utils/i18n';
type Props = { type Props = {
timeLimit: number; timeLimit: number;
onClick: () => void; onClick: () => void;
isDisabled: boolean | undefined; 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 ( return (
<button <button
type='button' type='button'
@@ -28,10 +21,18 @@ export default function EditPostTimeLimitButton(props: Props) {
disabled={props.isDisabled} disabled={props.isDisabled}
> >
<i className='fa fa-gear'/> <i className='fa fa-gear'/>
<FormattedMessage {props.timeLimit === Constants.UNSET_POST_EDIT_TIME_LIMIT ? (
id={messageID} <FormattedMessage
values={{n: props.timeLimit}} id='edit_post.time_limit_button.no_limit'
/> defaultMessage='Anytime'
/>
) : (
<FormattedMessage
id='edit_post.time_limit_button.for_n_seconds'
defaultMessage='For {n} seconds'
values={{n: props.timeLimit}}
/>
)}
</button> </button>
); );
} }

Просмотреть файл

@@ -3,7 +3,7 @@
import React, {useState} from 'react'; import React, {useState} from 'react';
import {Modal} from 'react-bootstrap'; 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 {AdminConfig} from '@mattermost/types/config';
import type {DeepPartial} from '@mattermost/types/utilities'; 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 FormattedMarkdownMessage from 'components/formatted_markdown_message';
import {Constants} from 'utils/constants'; import {Constants} from 'utils/constants';
import {t} from 'utils/i18n';
import {localizeMessage} from 'utils/utils';
const INT32_MAX = 2147483647; const INT32_MAX = 2147483647;
@@ -30,6 +28,8 @@ type Props ={
export default function EditPostTimeLimitModal(props: Props) { export default function EditPostTimeLimitModal(props: Props) {
const {ServiceSettings} = props.config; const {ServiceSettings} = props.config;
const intl = useIntl();
const [saving, setSaving] = useState(false); const [saving, setSaving] = useState(false);
const [errorMessage, setErrorMessage] = useState(''); const [errorMessage, setErrorMessage] = useState('');
const [postEditTimeLimit, setPostEditTimeLimit] = useState<number>(ServiceSettings?.PostEditTimeLimit || Constants.UNSET_POST_EDIT_TIME_LIMIT); const [postEditTimeLimit, setPostEditTimeLimit] = useState<number>(ServiceSettings?.PostEditTimeLimit || Constants.UNSET_POST_EDIT_TIME_LIMIT);
@@ -40,7 +40,7 @@ export default function EditPostTimeLimitModal(props: Props) {
setErrorMessage(''); setErrorMessage('');
if (isNaN(postEditTimeLimit) || postEditTimeLimit < 0 || postEditTimeLimit > INT32_MAX) { 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); setSaving(false);
setPostEditTimeLimit(0); setPostEditTimeLimit(0);
return false; return false;
@@ -170,10 +170,17 @@ export default function EditPostTimeLimitModal(props: Props) {
onClick={save} onClick={save}
disabled={saving} disabled={saving}
> >
<FormattedMessage {saving ? (
id={saving ? t('save_button.saving') : t('edit_post.time_limit_modal.save_button')} <FormattedMessage
defaultMessage='Save Edit Time' id='save_button.saving'
/> defaultMessage='Saving'
/>
) : (
<FormattedMessage
id='edit_post.time_limit_modal.save_button'
defaultMessage='Save Edit Time'
/>
)}
</button> </button>
</Modal.Footer> </Modal.Footer>
</Modal> </Modal>

Просмотреть файл

@@ -55,7 +55,10 @@ exports[`admin_console/system_user_detail/team_list/AbstractList should match sn
} }
} }
> >
Name <MemoizedFormattedMessage
defaultMessage="Name"
id="admin.team_settings.team_list.header.name"
/>
</div> </div>
<div <div
className="AbstractList__header-label" className="AbstractList__header-label"
@@ -66,7 +69,10 @@ exports[`admin_console/system_user_detail/team_list/AbstractList should match sn
} }
} }
> >
Type <MemoizedFormattedMessage
defaultMessage="Type"
id="admin.systemUserDetail.teamList.header.type"
/>
</div> </div>
<div <div
className="AbstractList__header-label" className="AbstractList__header-label"
@@ -77,7 +83,10 @@ exports[`admin_console/system_user_detail/team_list/AbstractList should match sn
} }
} }
> >
Role <MemoizedFormattedMessage
defaultMessage="Role"
id="admin.systemUserDetail.teamList.header.role"
/>
</div> </div>
</div> </div>
<div <div
@@ -280,7 +289,10 @@ exports[`admin_console/system_user_detail/team_list/AbstractList should match sn
} }
} }
> >
Name <MemoizedFormattedMessage
defaultMessage="Name"
id="admin.team_settings.team_list.header.name"
/>
</div> </div>
<div <div
className="AbstractList__header-label" className="AbstractList__header-label"
@@ -291,7 +303,10 @@ exports[`admin_console/system_user_detail/team_list/AbstractList should match sn
} }
} }
> >
Type <MemoizedFormattedMessage
defaultMessage="Type"
id="admin.systemUserDetail.teamList.header.type"
/>
</div> </div>
<div <div
className="AbstractList__header-label" className="AbstractList__header-label"
@@ -302,7 +317,10 @@ exports[`admin_console/system_user_detail/team_list/AbstractList should match sn
} }
} }
> >
Role <MemoizedFormattedMessage
defaultMessage="Role"
id="admin.systemUserDetail.teamList.header.role"
/>
</div> </div>
</div> </div>
<div <div
@@ -505,7 +523,10 @@ exports[`admin_console/system_user_detail/team_list/AbstractList should match sn
} }
} }
> >
Name <MemoizedFormattedMessage
defaultMessage="Name"
id="admin.team_settings.team_list.header.name"
/>
</div> </div>
<div <div
className="AbstractList__header-label" className="AbstractList__header-label"
@@ -516,7 +537,10 @@ exports[`admin_console/system_user_detail/team_list/AbstractList should match sn
} }
} }
> >
Type <MemoizedFormattedMessage
defaultMessage="Type"
id="admin.systemUserDetail.teamList.header.type"
/>
</div> </div>
<div <div
className="AbstractList__header-label" className="AbstractList__header-label"
@@ -527,7 +551,10 @@ exports[`admin_console/system_user_detail/team_list/AbstractList should match sn
} }
} }
> >
Role <MemoizedFormattedMessage
defaultMessage="Role"
id="admin.systemUserDetail.teamList.header.role"
/>
</div> </div>
</div> </div>
<div <div

Просмотреть файл

@@ -25,13 +25,19 @@ exports[`admin_console/system_user_detail/team_list/TeamList should match snapsh
} }
} }
data={Array []} data={Array []}
emptyListTextDefaultMessage="No teams found" emptyList={
emptyListTextId="emptyListTextId" Object {
"defaultMessage": "No teams found",
"id": "admin.team_settings.team_list.no_teams_found",
}
}
headerLabels={ headerLabels={
Array [ Array [
Object { Object {
"default": "Name", "label": Object {
"id": "admin.systemUserDetail.teamList.header.name", "defaultMessage": "Name",
"id": "admin.systemUserDetail.teamList.header.name",
},
"style": Object { "style": Object {
"flexGrow": 1, "flexGrow": 1,
"marginLeft": "16px", "marginLeft": "16px",
@@ -39,15 +45,19 @@ exports[`admin_console/system_user_detail/team_list/TeamList should match snapsh
}, },
}, },
Object { Object {
"default": "Type", "label": Object {
"id": "admin.systemUserDetail.teamList.header.type", "defaultMessage": "Type",
"id": "admin.systemUserDetail.teamList.header.type",
},
"style": Object { "style": Object {
"width": "150px", "width": "150px",
}, },
}, },
Object { Object {
"default": "Role", "label": Object {
"id": "admin.systemUserDetail.teamList.header.role", "defaultMessage": "Role",
"id": "admin.systemUserDetail.teamList.header.role",
},
"style": Object { "style": Object {
"width": "150px", "width": "150px",
}, },
@@ -104,13 +114,19 @@ exports[`admin_console/system_user_detail/team_list/TeamList should match snapsh
}, },
] ]
} }
emptyListTextDefaultMessage="No teams found" emptyList={
emptyListTextId="emptyListTextId" Object {
"defaultMessage": "No teams found",
"id": "admin.team_settings.team_list.no_teams_found",
}
}
headerLabels={ headerLabels={
Array [ Array [
Object { Object {
"default": "Name", "label": Object {
"id": "admin.systemUserDetail.teamList.header.name", "defaultMessage": "Name",
"id": "admin.systemUserDetail.teamList.header.name",
},
"style": Object { "style": Object {
"flexGrow": 1, "flexGrow": 1,
"marginLeft": "16px", "marginLeft": "16px",
@@ -118,15 +134,19 @@ exports[`admin_console/system_user_detail/team_list/TeamList should match snapsh
}, },
}, },
Object { Object {
"default": "Type", "label": Object {
"id": "admin.systemUserDetail.teamList.header.type", "defaultMessage": "Type",
"id": "admin.systemUserDetail.teamList.header.type",
},
"style": Object { "style": Object {
"width": "150px", "width": "150px",
}, },
}, },
Object { Object {
"default": "Role", "label": Object {
"id": "admin.systemUserDetail.teamList.header.role", "defaultMessage": "Role",
"id": "admin.systemUserDetail.teamList.header.role",
},
"style": Object { "style": Object {
"width": "150px", "width": "150px",
}, },

Просмотреть файл

@@ -37,8 +37,10 @@ describe('admin_console/system_user_detail/team_list/AbstractList', () => {
const headerLabels = [ const headerLabels = [
{ {
id: 'admin.team_settings.team_list.header.name', label: {
default: 'Name', id: 'admin.team_settings.team_list.header.name',
defaultMessage: 'Name',
},
style: { style: {
flexGrow: 1, flexGrow: 1,
minWidth: '284px', minWidth: '284px',
@@ -46,15 +48,19 @@ describe('admin_console/system_user_detail/team_list/AbstractList', () => {
}, },
}, },
{ {
id: 'admin.systemUserDetail.teamList.header.type', label: {
default: 'Type', id: 'admin.systemUserDetail.teamList.header.type',
defaultMessage: 'Type',
},
style: { style: {
width: '150px', width: '150px',
}, },
}, },
{ {
id: 'admin.systemUserDetail.teamList.header.role', label: {
default: 'Role', id: 'admin.systemUserDetail.teamList.header.role',
defaultMessage: 'Role',
},
style: { style: {
width: '150px', width: '150px',
}, },
@@ -68,8 +74,10 @@ describe('admin_console/system_user_detail/team_list/AbstractList', () => {
total: 0, total: 0,
headerLabels, headerLabels,
renderRow, renderRow,
emptyListTextId: 'admin.team_settings.team_list.no_teams_found', emptyList: {
emptyListTextDefaultMessage: 'No teams found', id: 'admin.team_settings.team_list.no_teams_found',
defaultMessage: 'No teams found',
},
actions: { actions: {
getTeamsData: jest.fn().mockResolvedValue(Promise.resolve([])), getTeamsData: jest.fn().mockResolvedValue(Promise.resolve([])),
removeGroup: jest.fn(), removeGroup: jest.fn(),

Просмотреть файл

@@ -2,6 +2,7 @@
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import React from 'react'; import React from 'react';
import type {MessageDescriptor} from 'react-intl';
import {FormattedMessage} from 'react-intl'; import {FormattedMessage} from 'react-intl';
import type {Team} from '@mattermost/types/teams'; import type {Team} from '@mattermost/types/teams';
@@ -19,13 +20,15 @@ const PAGE_SIZE = 10;
type Props = { type Props = {
userId: string; userId: string;
headerLabels: Array<Record<string, any>>; headerLabels: Array<{
label?: MessageDescriptor;
style: React.CSSProperties;
}>;
data: TeamWithMembership[]; data: TeamWithMembership[];
onPageChangedCallback?: (paging: Paging) => void; onPageChangedCallback?: (paging: Paging) => void;
total: number; total: number;
renderRow: (item: TeamWithMembership) => JSX.Element; renderRow: (item: TeamWithMembership) => JSX.Element;
emptyListTextId: string; emptyList: MessageDescriptor;
emptyListTextDefaultMessage: string;
actions: { actions: {
getTeamsData: (userId: string) => Promise<ActionResult<Team[]>>; getTeamsData: (userId: string) => Promise<ActionResult<Team[]>>;
removeGroup?: () => void; removeGroup?: () => void;
@@ -106,7 +109,9 @@ export default class AbstractList extends React.PureComponent<Props, State> {
key={id} key={id}
className='AbstractList__header-label' className='AbstractList__header-label'
style={headerLabel.style} style={headerLabel.style}
>{headerLabel.default}</div> >
<FormattedMessage {...headerLabel.label}/>
</div>
))} ))}
</div> </div>
); );
@@ -125,10 +130,7 @@ export default class AbstractList extends React.PureComponent<Props, State> {
if (this.props.data.length === 0) { if (this.props.data.length === 0) {
return ( return (
<div className='AbstractList__empty'> <div className='AbstractList__empty'>
<FormattedMessage <FormattedMessage {...this.props.emptyList}/>
id={this.props.emptyListTextId}
defaultMessage={this.props.emptyListTextDefaultMessage}
/>
</div> </div>
); );
} }

Просмотреть файл

@@ -2,12 +2,13 @@
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import React from 'react'; 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 {Team, TeamMembership} from '@mattermost/types/teams';
import type {ActionResult} from 'mattermost-redux/types/actions'; import type {ActionResult} from 'mattermost-redux/types/actions';
import {t} from 'utils/i18n';
import {filterAndSortTeamsByDisplayName} from 'utils/team_utils'; import {filterAndSortTeamsByDisplayName} from 'utils/team_utils';
import AbstractList from './abstract_list'; import AbstractList from './abstract_list';
@@ -16,8 +17,10 @@ import type {TeamWithMembership} from './types';
const headerLabels = [ const headerLabels = [
{ {
id: t('admin.systemUserDetail.teamList.header.name'), label: defineMessage({
default: 'Name', id: 'admin.systemUserDetail.teamList.header.name',
defaultMessage: 'Name',
}),
style: { style: {
flexGrow: 1, flexGrow: 1,
minWidth: '284px', minWidth: '284px',
@@ -25,15 +28,19 @@ const headerLabels = [
}, },
}, },
{ {
id: t('admin.systemUserDetail.teamList.header.type'), label: defineMessage({
default: 'Type', id: 'admin.systemUserDetail.teamList.header.type',
defaultMessage: 'Type',
}),
style: { style: {
width: '150px', width: '150px',
}, },
}, },
{ {
id: t('admin.systemUserDetail.teamList.header.role'), label: defineMessage({
default: 'Role', id: 'admin.systemUserDetail.teamList.header.role',
defaultMessage: 'Role',
}),
style: { style: {
width: '150px', width: '150px',
}, },
@@ -48,8 +55,7 @@ const headerLabels = [
type Props = { type Props = {
userId: string; userId: string;
locale: string; locale: string;
emptyListTextId: string; emptyList: MessageDescriptor;
emptyListTextDefaultMessage: string;
actions: { actions: {
getTeamsData: (userId: string) => Promise<ActionResult<Team[]>>; getTeamsData: (userId: string) => Promise<ActionResult<Team[]>>;
getTeamMembersForUser: (userId: string) => Promise<ActionResult<TeamMembership[]>>; getTeamMembersForUser: (userId: string) => Promise<ActionResult<TeamMembership[]>>;
@@ -68,8 +74,10 @@ type State = {
export default class TeamList extends React.PureComponent<Props, State> { export default class TeamList extends React.PureComponent<Props, State> {
public static defaultProps = { public static defaultProps = {
emptyListTextId: t('admin.team_settings.team_list.no_teams_found'), emptyList: defineMessage({
emptyListTextDefaultMessage: 'No teams found', id: 'admin.team_settings.team_list.no_teams_found',
defaultMessage: 'No teams found',
}),
refreshTeams: false, refreshTeams: false,
}; };
@@ -173,8 +181,7 @@ export default class TeamList extends React.PureComponent<Props, State> {
total={this.state.teamsWithMemberships.length} total={this.state.teamsWithMemberships.length}
data={this.state.teamsWithMemberships} data={this.state.teamsWithMemberships}
actions={this.props.actions} actions={this.props.actions}
emptyListTextId={this.props.emptyListTextId} emptyList={this.props.emptyList}
emptyListTextDefaultMessage={this.props.emptyListTextDefaultMessage}
userId={this.props.userId} userId={this.props.userId}
/> />
</React.Fragment> </React.Fragment>

Просмотреть файл

@@ -55,8 +55,10 @@ describe('admin_console/team_channel_settings/AbstractList', () => {
total={0} total={0}
header={header} header={header}
renderRow={renderRow} renderRow={renderRow}
emptyListTextId={'test'} emptyListText={{
emptyListTextDefaultMessage={'test'} id: 'test',
defaultMessage: 'test',
}}
actions={actions} actions={actions}
/>); />);
@@ -83,8 +85,10 @@ describe('admin_console/team_channel_settings/AbstractList', () => {
total={testTeams.length} total={testTeams.length}
header={header} header={header}
renderRow={renderRow} renderRow={renderRow}
emptyListTextId={'test'} emptyListText={{
emptyListTextDefaultMessage={'test'} id: 'test',
defaultMessage: 'test',
}}
actions={actions} actions={actions}
/>); />);

Просмотреть файл

@@ -4,6 +4,7 @@
import classNames from 'classnames'; import classNames from 'classnames';
import React from 'react'; import React from 'react';
import type {MouseEvent} from 'react'; import type {MouseEvent} from 'react';
import type {MessageDescriptor} from 'react-intl';
import {FormattedMessage} from 'react-intl'; import {FormattedMessage} from 'react-intl';
import type {Group} from '@mattermost/types/groups'; import type {Group} from '@mattermost/types/groups';
@@ -28,8 +29,7 @@ type Props = {
total: number; total: number;
header: JSX.Element; header: JSX.Element;
renderRow: (item: Group | TeamWithMembership) => JSX.Element; renderRow: (item: Group | TeamWithMembership) => JSX.Element;
emptyListTextId: string; emptyListText: MessageDescriptor;
emptyListTextDefaultMessage: string;
actions: { actions: {
getData: (page: number, perPage: number, notAssociatedToGroup?: string, excludeDefaultChannels?: boolean, includeDeleted?: boolean) => Promise<void>; getData: (page: number, perPage: number, notAssociatedToGroup?: string, excludeDefaultChannels?: boolean, includeDeleted?: boolean) => Promise<void>;
}; };
@@ -91,10 +91,7 @@ export default class AbstractList extends React.PureComponent<Props, State> {
if (this.props.data.length === 0) { if (this.props.data.length === 0) {
return ( return (
<div className='groups-list-empty'> <div className='groups-list-empty'>
<FormattedMessage <FormattedMessage {...this.props.emptyListText}/>
id={this.props.emptyListTextId}
defaultMessage={this.props.emptyListTextDefaultMessage}
/>
</div> </div>
); );
} }

Просмотреть файл

@@ -2,13 +2,11 @@
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import React from 'react'; import React from 'react';
import {FormattedMessage} from 'react-intl'; import {FormattedMessage, defineMessages} from 'react-intl';
import ConfirmModal from 'components/confirm_modal'; import ConfirmModal from 'components/confirm_modal';
import FormattedMarkdownMessage from 'components/formatted_markdown_message'; import FormattedMarkdownMessage from 'components/formatted_markdown_message';
import {t} from 'utils/i18n';
type Props = { type Props = {
/* /*
@@ -43,23 +41,23 @@ type Props = {
}; };
const ConvertAndRemoveConfirmModal = ({show, onConfirm, onCancel, displayName, toPublic, removeAmount}: 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?'; let titleMessage;
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?'; let convertMessage;
const convertMessageId = toPublic ? t('admin.team_channel_settings.convertConfirmModal.toPublicMessage') : t('admin.team_channel_settings.convertConfirmModal.toPrivateMessage'); let confirmMessage;
if (toPublic) {
const toPublicTitle = 'Convert channel to public and remove {amount, number} {amount, plural, one {user} other {users}}?'; titleMessage = messages.toPublicTitle;
const toPrivateTitle = 'Convert channel to private and remove {amount, number} {amount, plural, one {user} other {users}}?'; convertMessage = messages.toPublicMessage;
const titleId = toPublic ? t('admin.team_channel_settings.convertAndRemoveConfirmModal.toPublicTitle') : t('admin.team_channel_settings.convertAndRemoveConfirmModal.toPrivateTitle'); confirmMessage = messages.toPublicConfirm;
} else {
const toPublicConfirmMsg = 'Yes, convert channel to public and remove {amount, number} {amount, plural, one {user} other {users}}'; titleMessage = messages.toPrivateTitle;
const toPrivateConfirmMsg = 'Yes, convert channel to private and remove {amount, number} {amount, plural, one {user} other {users}}'; convertMessage = messages.toPrivateMessage;
const confirmMsgId = toPublic ? t('admin.team_channel_settings.convertAndRemoveConfirmModal.toPublicConfirm') : t('admin.team_channel_settings.convertAndRemoveConfirmModal.toPrivateConfirm'); confirmMessage = messages.toPrivateConfirm;
}
const title = ( const title = (
<FormattedMessage <FormattedMessage
id={titleId} {...titleMessage}
defaultMessage={toPublic ? toPublicTitle : toPrivateTitle} values={{amount: removeAmount}}
values={{displayName, amount: removeAmount}}
/> />
); );
@@ -67,8 +65,7 @@ const ConvertAndRemoveConfirmModal = ({show, onConfirm, onCancel, displayName, t
<div> <div>
<p> <p>
<FormattedMarkdownMessage <FormattedMarkdownMessage
id={convertMessageId} {...convertMessage}
defaultMessage={toPublic ? toPublicMsg : toPrivateMsg}
values={{displayName}} values={{displayName}}
/> />
</p> </p>
@@ -84,8 +81,7 @@ const ConvertAndRemoveConfirmModal = ({show, onConfirm, onCancel, displayName, t
const confirmButton = ( const confirmButton = (
<FormattedMessage <FormattedMessage
id={confirmMsgId} {...confirmMessage}
defaultMessage={toPublic ? toPublicConfirmMsg : toPrivateConfirmMsg}
values={{amount: removeAmount}} values={{amount: removeAmount}}
/> />
); );
@@ -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; export default ConvertAndRemoveConfirmModal;

Просмотреть файл

@@ -2,13 +2,11 @@
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import React from 'react'; import React from 'react';
import {FormattedMessage} from 'react-intl'; import {FormattedMessage, defineMessages} from 'react-intl';
import ConfirmModal from 'components/confirm_modal'; import ConfirmModal from 'components/confirm_modal';
import FormattedMarkdownMessage from 'components/formatted_markdown_message'; import FormattedMarkdownMessage from 'components/formatted_markdown_message';
import {t} from 'utils/i18n';
type Props = { type Props = {
/* /*
@@ -38,38 +36,36 @@ type Props = {
}; };
const ConvertConfirmModal = ({show, onConfirm, onCancel, displayName, toPublic}: 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?'; let titleMessage;
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?'; let convertMessage;
const messageId = toPublic ? t('admin.team_channel_settings.convertConfirmModal.toPublicMessage') : t('admin.team_channel_settings.convertConfirmModal.toPrivateMessage'); let confirmMessage;
if (toPublic) {
const toPublicTitle = 'Convert {displayName} to a public channel?'; titleMessage = messages.toPublicTitle;
const toPrivateTitle = 'Convert {displayName} to a private channel?'; convertMessage = messages.toPublicMessage;
const titleId = toPublic ? t('admin.team_channel_settings.convertConfirmModal.toPublicTitle') : t('admin.team_channel_settings.convertConfirmModal.toPrivateTitle'); confirmMessage = messages.toPublicConfirm;
} else {
const toPublicConfirmMsg = 'Yes, convert to public channel'; titleMessage = messages.toPrivateTitle;
const toPrivateConfirmMsg = 'Yes, convert to private channel'; convertMessage = messages.toPrivateMessage;
const confirmMsgId = toPublic ? t('admin.team_channel_settings.convertConfirmModal.toPublicConfirm') : t('admin.team_channel_settings.convertConfirmModal.toPrivateConfirm'); confirmMessage = messages.toPrivateConfirm;
}
const title = ( const title = (
<FormattedMessage <FormattedMessage
id={titleId} {...titleMessage}
defaultMessage={toPublic ? toPublicTitle : toPrivateTitle}
values={{displayName}} values={{displayName}}
/> />
); );
const message = ( const message = (
<FormattedMarkdownMessage <FormattedMarkdownMessage
id={messageId} {...convertMessage}
defaultMessage={toPublic ? toPublicMsg : toPrivateMsg}
values={{displayName}} values={{displayName}}
/> />
); );
const confirmButton = ( const confirmButton = (
<FormattedMessage <FormattedMessage
id={confirmMsgId} {...confirmMessage}
defaultMessage={toPublic ? toPublicConfirmMsg : toPrivateConfirmMsg}
/> />
); );
@@ -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; export default ConvertConfirmModal;

Просмотреть файл

@@ -26,11 +26,14 @@ exports[`admin_console/team_channel_settings/group/GroupList should match snapsh
}, },
] ]
} }
emptyListTextDefaultMessage="test" emptyListText={
emptyListTextId="test" Object {
"defaultMessage": "No groups specified yet",
"id": "admin.team_channel_settings.group_list.no-groups",
}
}
groups={Array []} groups={Array []}
header={<Header />} header={<Header />}
isModeSync={false}
noPadding={false} noPadding={false}
onGroupRemoved={[MockFunction]} onGroupRemoved={[MockFunction]}
onPageChangedCallback={[MockFunction]} onPageChangedCallback={[MockFunction]}
@@ -501,11 +504,14 @@ exports[`admin_console/team_channel_settings/group/GroupList should match snapsh
}, },
] ]
} }
emptyListTextDefaultMessage="test" emptyListText={
emptyListTextId="test" Object {
"defaultMessage": "No groups specified yet",
"id": "admin.team_channel_settings.group_list.no-groups",
}
}
groups={Array []} groups={Array []}
header={<Header />} header={<Header />}
isModeSync={false}
noPadding={false} noPadding={false}
onGroupRemoved={[MockFunction]} onGroupRemoved={[MockFunction]}
onPageChangedCallback={[MockFunction]} onPageChangedCallback={[MockFunction]}

Просмотреть файл

@@ -31,8 +31,6 @@ describe('admin_console/team_channel_settings/group/GroupList', () => {
totalGroups={0} totalGroups={0}
onPageChangedCallback={jest.fn()} onPageChangedCallback={jest.fn()}
total={testGroups.length} total={testGroups.length}
emptyListTextId={'test'}
emptyListTextDefaultMessage={'test'}
actions={actions} actions={actions}
removeGroup={jest.fn()} removeGroup={jest.fn()}
type='team' type='team'
@@ -64,8 +62,6 @@ describe('admin_console/team_channel_settings/group/GroupList', () => {
totalGroups={0} totalGroups={0}
onPageChangedCallback={jest.fn()} onPageChangedCallback={jest.fn()}
total={30} total={30}
emptyListTextId={'test'}
emptyListTextDefaultMessage={'test'}
actions={actions} actions={actions}
type='team' type='team'
removeGroup={jest.fn()} removeGroup={jest.fn()}

Просмотреть файл

@@ -2,7 +2,7 @@
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import React, {memo, useCallback} from 'react'; import React, {memo, useCallback} from 'react';
import {FormattedMessage} from 'react-intl'; import {FormattedMessage, defineMessages} from 'react-intl';
import type {Group} from '@mattermost/types/groups'; import type {Group} from '@mattermost/types/groups';
@@ -47,6 +47,7 @@ const GroupList = ({
setNewGroupRole, setNewGroupRole,
type, type,
isDisabled, isDisabled,
isModeSync,
...restProps ...restProps
}: Props) => { }: Props) => {
const renderRow = useCallback((item: Partial<Group>) => { const renderRow = useCallback((item: Partial<Group>) => {
@@ -66,9 +67,21 @@ const GroupList = ({
<AbstractList <AbstractList
header={<Header/>} header={<Header/>}
renderRow={renderRow} renderRow={renderRow}
emptyListText={isModeSync ? messages.emptyListModeSync : messages.emptyList}
{...restProps} {...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); export default memo(GroupList);

Просмотреть файл

@@ -8,8 +8,6 @@ import type {Channel} from '@mattermost/types/channels';
import type {Group} from '@mattermost/types/groups'; import type {Group} from '@mattermost/types/groups';
import type {Team} from '@mattermost/types/teams'; import type {Team} from '@mattermost/types/teams';
import {t} from 'utils/i18n';
import type {GlobalState} from 'types/store'; import type {GlobalState} from 'types/store';
import GroupList from './group_list'; import GroupList from './group_list';
@@ -32,8 +30,6 @@ function mapStateToProps(state: GlobalState, ownProps: OwnProps) {
data: ownProps.groups, data: ownProps.groups,
removeGroup: ownProps.onGroupRemoved, removeGroup: ownProps.onGroupRemoved,
setNewGroupRole: ownProps.setNewGroupRole, 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, total: ownProps.totalGroups,
}; };
} }

Просмотреть файл

@@ -6,8 +6,6 @@ import {FormattedMessage} from 'react-intl';
import ConfirmModal from 'components/confirm_modal'; import ConfirmModal from 'components/confirm_modal';
import {t} from 'utils/i18n';
type Props = { 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'); let message;
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}}?'; if (inChannel) {
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}}?'; message = (
<FormattedMessage
const message = ( id='admin.team_channel_settings.removeConfirmModal.messageChannel'
<FormattedMessage defaultMessage='{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}}?'
id={messageId} values={{amount}}
defaultMessage={inChannel ? messageChannel : messageTeam} />
values={{amount}} );
/> } else {
); message = (
<FormattedMessage
id='admin.team_channel_settings.removeConfirmModal.messageTeam'
defaultMessage='{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}}?'
values={{amount}}
/>
);
}
const buttonClass = 'btn btn-primary'; const buttonClass = 'btn btn-primary';
const button = ( const button = (