Remove localizeMessage from a bunch of components (#28340)

* Remove localizeMessage usage for passing into LoadingSpinner or LoadingWrapper components

* Allow Input widget to translate its placeholder and remove related usage of localizeMessage

* Allow DropdownInputHybrid to translate its placeholder and remove localizeMessage from related files

* Have Multiselect translate some of its props and remove localizeMessage from the components using it

* Remove unused message prop from StartTrianBtn

* Remove localizeMessage from a bunch of function components

* Remove unused editingPost.title state

* Remove usage of localizeMessage from some random components

* Remove unused DataGrid searchPlaceholder prop

* Add LocalizedPlaceholderInput and LocalizedPlaceholderTextarea

I used these in a bunch of places where we used localizeMessage or in places where we only injected intl just for a placeholder. I didn't really need to remove injectIntl from all these places, but it's been a pet peeve of mine for a while

* Have SearchableChannelList always use its injected intl

* Added changes that VS Code didn't show me in the last commit...
Этот коммит содержится в:
Harrison Healey
2024-10-16 11:22:28 -04:00
коммит произвёл GitHub
родитель 6dc44f2831
Коммит b2fbee1608
158 изменённых файлов: 2442 добавлений и 1196 удалений

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

@@ -272,12 +272,12 @@ describe('Actions.Posts', () => {
test('unsetEditingPost', async () => { test('unsetEditingPost', async () => {
// should allow to edit and should fire an action // should allow to edit and should fire an action
const testStore = mockStore({...initialState}); const testStore = mockStore({...initialState});
const {data: dataSet} = await testStore.dispatch((Actions.setEditingPost as any)('latest_post_id', 'test', 'title')); const {data: dataSet} = await testStore.dispatch((Actions.setEditingPost as any)('latest_post_id', 'test'));
expect(dataSet).toEqual(true); expect(dataSet).toEqual(true);
// matches the action to set editingPost // matches the action to set editingPost
expect(testStore.getActions()).toEqual( expect(testStore.getActions()).toEqual(
[{data: {isRHS: false, postId: 'latest_post_id', refocusId: 'test', title: 'title', show: true}, type: ActionTypes.TOGGLE_EDITING_POST}], [{data: {isRHS: false, postId: 'latest_post_id', refocusId: 'test', show: true}, type: ActionTypes.TOGGLE_EDITING_POST}],
); );
// clear actions // clear actions
@@ -299,11 +299,11 @@ describe('Actions.Posts', () => {
test('setEditingPost', async () => { test('setEditingPost', async () => {
// should allow to edit and should fire an action // should allow to edit and should fire an action
let testStore = mockStore({...initialState}); let testStore = mockStore({...initialState});
const {data} = await testStore.dispatch(Actions.setEditingPost('latest_post_id', 'test', 'title')); const {data} = await testStore.dispatch(Actions.setEditingPost('latest_post_id', 'test'));
expect(data).toEqual(true); expect(data).toEqual(true);
expect(testStore.getActions()).toEqual( expect(testStore.getActions()).toEqual(
[{data: {isRHS: false, postId: 'latest_post_id', refocusId: 'test', title: 'title', show: true}, type: ActionTypes.TOGGLE_EDITING_POST}], [{data: {isRHS: false, postId: 'latest_post_id', refocusId: 'test', show: true}, type: ActionTypes.TOGGLE_EDITING_POST}],
); );
const general = { const general = {
@@ -319,10 +319,10 @@ describe('Actions.Posts', () => {
testStore = mockStore(withLicenseState); testStore = mockStore(withLicenseState);
const {data: withLicenseData} = await testStore.dispatch(Actions.setEditingPost('latest_post_id', 'test', 'title')); const {data: withLicenseData} = await testStore.dispatch(Actions.setEditingPost('latest_post_id', 'test'));
expect(withLicenseData).toEqual(true); expect(withLicenseData).toEqual(true);
expect(testStore.getActions()).toEqual( expect(testStore.getActions()).toEqual(
[{data: {isRHS: false, postId: 'latest_post_id', refocusId: 'test', title: 'title', show: true}, type: ActionTypes.TOGGLE_EDITING_POST}], [{data: {isRHS: false, postId: 'latest_post_id', refocusId: 'test', show: true}, type: ActionTypes.TOGGLE_EDITING_POST}],
); );
// should not allow edit for pending post // should not allow edit for pending post
@@ -332,7 +332,7 @@ describe('Actions.Posts', () => {
testStore = mockStore(withPendingPostState); testStore = mockStore(withPendingPostState);
const {data: withPendingPostData} = await testStore.dispatch(Actions.setEditingPost('latest_post_id', 'test', 'title')); const {data: withPendingPostData} = await testStore.dispatch(Actions.setEditingPost('latest_post_id', 'test'));
expect(withPendingPostData).toEqual(false); expect(withPendingPostData).toEqual(false);
expect(testStore.getActions()).toEqual([]); expect(testStore.getActions()).toEqual([]);
}); });

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

@@ -278,7 +278,7 @@ export function unpinPost(postId: string): ActionFuncAsync<boolean, GlobalState>
}; };
} }
export function setEditingPost(postId = '', refocusId = '', title = '', isRHS = false): ActionFunc<boolean> { export function setEditingPost(postId = '', refocusId = '', isRHS = false): ActionFunc<boolean> {
return (dispatch, getState) => { return (dispatch, getState) => {
const state = getState(); const state = getState();
const post = PostSelectors.getPost(state, postId); const post = PostSelectors.getPost(state, postId);
@@ -300,7 +300,7 @@ export function setEditingPost(postId = '', refocusId = '', title = '', isRHS =
if (canEditNow) { if (canEditNow) {
dispatch({ dispatch({
type: ActionTypes.TOGGLE_EDITING_POST, type: ActionTypes.TOGGLE_EDITING_POST,
data: {postId, refocusId, title, isRHS, show: true}, data: {postId, refocusId, isRHS, show: true},
}); });
} }

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

@@ -181,7 +181,6 @@ export function editLatestPost(channelId: string, rootId = ''): ActionFunc<boole
return dispatch(PostActions.setEditingPost( return dispatch(PostActions.setEditingPost(
lastPostId, lastPostId,
rootId ? 'reply_textbox' : 'post_textbox', rootId ? 'reply_textbox' : 'post_textbox',
'', // title is no longer used
Boolean(rootId), Boolean(rootId),
)); ));
}; };

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

@@ -8,7 +8,8 @@ exports[`components/LoadingImagePreview should match snapshot 1`] = `
<span <span
className="loader-percent" className="loader-percent"
> >
Loading 50% Loading
50%
</span> </span>
</div> </div>
`; `;
@@ -21,7 +22,8 @@ exports[`components/LoadingImagePreview should match snapshot 2`] = `
<span <span
className="loader-percent" className="loader-percent"
> >
Loading 90% Loading
90%
</span> </span>
</div> </div>
`; `;

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

@@ -22,6 +22,7 @@ exports[`components/SearchableChannelList should match init snapshot 1`] = `
id="searchChannelsTextbox" id="searchChannelsTextbox"
onClear={[Function]} onClear={[Function]}
onInput={[Function]} onInput={[Function]}
placeholder="Search channels"
value="" value=""
/> />
</div> </div>

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

@@ -88,7 +88,12 @@ exports[`components/SettingItemMin should match snapshot with active Save button
> >
<Memo(LoadingWrapper) <Memo(LoadingWrapper)
loading={false} loading={false}
text="Uploading..." text={
Object {
"defaultMessage": "Uploading...",
"id": "setting_picture.uploading",
}
}
> >
<MemoizedFormattedMessage <MemoizedFormattedMessage
defaultMessage="Save" defaultMessage="Save"
@@ -192,7 +197,12 @@ exports[`components/SettingItemMin should match snapshot with active Save button
> >
<Memo(LoadingWrapper) <Memo(LoadingWrapper)
loading={false} loading={false}
text="Uploading..." text={
Object {
"defaultMessage": "Uploading...",
"id": "setting_picture.uploading",
}
}
> >
<MemoizedFormattedMessage <MemoizedFormattedMessage
defaultMessage="Save" defaultMessage="Save"
@@ -306,7 +316,12 @@ exports[`components/SettingItemMin should match snapshot, on loading picture 1`]
> >
<Memo(LoadingWrapper) <Memo(LoadingWrapper)
loading={true} loading={true}
text="Uploading..." text={
Object {
"defaultMessage": "Uploading...",
"id": "setting_picture.uploading",
}
}
> >
<MemoizedFormattedMessage <MemoizedFormattedMessage
defaultMessage="Save" defaultMessage="Save"
@@ -432,7 +447,12 @@ exports[`components/SettingItemMin should match snapshot, profile picture on fil
> >
<Memo(LoadingWrapper) <Memo(LoadingWrapper)
loading={false} loading={false}
text="Uploading..." text={
Object {
"defaultMessage": "Uploading...",
"id": "setting_picture.uploading",
}
}
> >
<MemoizedFormattedMessage <MemoizedFormattedMessage
defaultMessage="Save" defaultMessage="Save"
@@ -546,7 +566,12 @@ exports[`components/SettingItemMin should match snapshot, profile picture on sou
> >
<Memo(LoadingWrapper) <Memo(LoadingWrapper)
loading={false} loading={false}
text="Uploading..." text={
Object {
"defaultMessage": "Uploading...",
"id": "setting_picture.uploading",
}
}
> >
<MemoizedFormattedMessage <MemoizedFormattedMessage
defaultMessage="Save" defaultMessage="Save"
@@ -672,7 +697,12 @@ exports[`components/SettingItemMin should match snapshot, team icon on file 1`]
> >
<Memo(LoadingWrapper) <Memo(LoadingWrapper)
loading={false} loading={false}
text="Uploading..." text={
Object {
"defaultMessage": "Uploading...",
"id": "setting_picture.uploading",
}
}
> >
<MemoizedFormattedMessage <MemoizedFormattedMessage
defaultMessage="Save" defaultMessage="Save"
@@ -826,7 +856,12 @@ exports[`components/SettingItemMin should match snapshot, team icon on source 1`
> >
<Memo(LoadingWrapper) <Memo(LoadingWrapper)
loading={false} loading={false}
text="Uploading..." text={
Object {
"defaultMessage": "Uploading...",
"id": "setting_picture.uploading",
}
}
> >
<MemoizedFormattedMessage <MemoizedFormattedMessage
defaultMessage="Save" defaultMessage="Save"
@@ -980,7 +1015,12 @@ exports[`components/SettingItemMin should match snapshot, user icon on source 1`
> >
<Memo(LoadingWrapper) <Memo(LoadingWrapper)
loading={false} loading={false}
text="Uploading..." text={
Object {
"defaultMessage": "Uploading...",
"id": "setting_picture.uploading",
}
}
> >
<MemoizedFormattedMessage <MemoizedFormattedMessage
defaultMessage="Save" defaultMessage="Save"

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

@@ -5,7 +5,7 @@ import React from 'react';
import type {MessageDescriptor} from 'react-intl'; import type {MessageDescriptor} from 'react-intl';
import {useIntl} from 'react-intl'; import {useIntl} from 'react-intl';
import {isMessageDescriptor} from 'utils/i18n'; import {formatAsString} from 'utils/i18n';
type Props = { type Props = {
devicePicture?: string; devicePicture?: string;
@@ -15,17 +15,10 @@ type Props = {
export default function DeviceIcon(props: Props) { export default function DeviceIcon(props: Props) {
const intl = useIntl(); const intl = useIntl();
let title;
if (isMessageDescriptor(props.deviceTitle)) {
title = intl.formatMessage(props.deviceTitle);
} else {
title = props.deviceTitle;
}
return ( return (
<i <i
className={props.devicePicture} className={props.devicePicture}
title={title} title={formatAsString(intl.formatMessage, props.deviceTitle)}
/> />
); );
} }

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

@@ -57,8 +57,18 @@ exports[`components/AddGroupsToChannelModal should match snapshot 1`] = `
> >
<MultiSelect <MultiSelect
ariaLabelRenderer={[Function]} ariaLabelRenderer={[Function]}
buttonSubmitLoadingText="Adding..." buttonSubmitLoadingText={
buttonSubmitText="Add" Object {
"defaultMessage": "Adding...",
"id": "multiselect.adding",
}
}
buttonSubmitText={
Object {
"defaultMessage": "Add",
"id": "multiselect.add",
}
}
focusOnLoad={true} focusOnLoad={true}
handleAdd={[Function]} handleAdd={[Function]}
handleDelete={[Function]} handleDelete={[Function]}
@@ -87,7 +97,12 @@ exports[`components/AddGroupsToChannelModal should match snapshot 1`] = `
optionRenderer={[Function]} optionRenderer={[Function]}
options={Array []} options={Array []}
perPage={50} perPage={50}
placeholderText="Search and add groups" placeholderText={
Object {
"defaultMessage": "Search and add groups",
"id": "multiselect.addGroupsPlaceholder",
}
}
saveButtonPosition="top" saveButtonPosition="top"
saving={false} saving={false}
savingEnabled={true} savingEnabled={true}

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

@@ -4,7 +4,7 @@
import React from 'react'; import React from 'react';
import {Modal} from 'react-bootstrap'; import {Modal} from 'react-bootstrap';
import type {IntlShape} from 'react-intl'; import type {IntlShape} from 'react-intl';
import {injectIntl, FormattedMessage} from 'react-intl'; import {injectIntl, FormattedMessage, defineMessage} from 'react-intl';
import type {ServerError} from '@mattermost/types/errors'; import type {ServerError} from '@mattermost/types/errors';
import type {Group, SyncablePatch} from '@mattermost/types/groups'; import type {Group, SyncablePatch} from '@mattermost/types/groups';
@@ -17,7 +17,6 @@ import type {Value} from 'components/multiselect/multiselect';
import groupsAvatar from 'images/groups-avatar.png'; import groupsAvatar from 'images/groups-avatar.png';
import Constants from 'utils/constants'; import Constants from 'utils/constants';
import {localizeMessage} from 'utils/utils';
const GROUPS_PER_PAGE = 50; const GROUPS_PER_PAGE = 50;
const MAX_SELECTABLE_VALUES = 10; const MAX_SELECTABLE_VALUES = 10;
@@ -242,8 +241,8 @@ export class AddGroupsToChannelModal extends React.PureComponent<Props, State> {
</div> </div>
); );
const buttonSubmitText = localizeMessage({id: 'multiselect.add', defaultMessage: 'Add'}); const buttonSubmitText = defineMessage({id: 'multiselect.add', defaultMessage: 'Add'});
const buttonSubmitLoadingText = localizeMessage({id: 'multiselect.adding', defaultMessage: 'Adding...'}); const buttonSubmitLoadingText = defineMessage({id: 'multiselect.adding', defaultMessage: 'Adding...'});
let addError = null; let addError = null;
if (this.state.addError) { if (this.state.addError) {
@@ -305,7 +304,7 @@ export class AddGroupsToChannelModal extends React.PureComponent<Props, State> {
buttonSubmitLoadingText={buttonSubmitLoadingText} buttonSubmitLoadingText={buttonSubmitLoadingText}
saving={this.state.saving} saving={this.state.saving}
loading={this.state.loadingGroups} loading={this.state.loadingGroups}
placeholderText={localizeMessage({id: 'multiselect.addGroupsPlaceholder', defaultMessage: 'Search and add groups'})} placeholderText={defineMessage({id: 'multiselect.addGroupsPlaceholder', defaultMessage: 'Search and add groups'})}
/> />
</Modal.Body> </Modal.Body>
</Modal> </Modal>

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

@@ -57,8 +57,18 @@ exports[`components/AddGroupsToTeamModal should match snapshot 1`] = `
> >
<MultiSelect <MultiSelect
ariaLabelRenderer={[Function]} ariaLabelRenderer={[Function]}
buttonSubmitLoadingText="Adding..." buttonSubmitLoadingText={
buttonSubmitText="Add" Object {
"defaultMessage": "Adding...",
"id": "multiselect.adding",
}
}
buttonSubmitText={
Object {
"defaultMessage": "Add",
"id": "multiselect.add",
}
}
focusOnLoad={true} focusOnLoad={true}
handleAdd={[Function]} handleAdd={[Function]}
handleDelete={[Function]} handleDelete={[Function]}
@@ -124,7 +134,12 @@ exports[`components/AddGroupsToTeamModal should match snapshot 1`] = `
optionRenderer={[Function]} optionRenderer={[Function]}
options={Array []} options={Array []}
perPage={50} perPage={50}
placeholderText="Search and add groups" placeholderText={
Object {
"defaultMessage": "Search and add groups",
"id": "multiselect.addGroupsPlaceholder",
}
}
saveButtonPosition="top" saveButtonPosition="top"
saving={false} saving={false}
savingEnabled={true} savingEnabled={true}

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

@@ -5,7 +5,7 @@ import React from 'react';
import type {RefObject} from 'react'; import type {RefObject} from 'react';
import {Modal} from 'react-bootstrap'; import {Modal} from 'react-bootstrap';
import type {IntlShape} from 'react-intl'; import type {IntlShape} from 'react-intl';
import {injectIntl, FormattedMessage} from 'react-intl'; import {injectIntl, FormattedMessage, defineMessage} from 'react-intl';
import type {Group, SyncablePatch} from '@mattermost/types/groups'; import type {Group, SyncablePatch} from '@mattermost/types/groups';
import {SyncableType} from '@mattermost/types/groups'; import {SyncableType} from '@mattermost/types/groups';
@@ -18,7 +18,6 @@ import type {Value} from 'components/multiselect/multiselect';
import groupsAvatar from 'images/groups-avatar.png'; import groupsAvatar from 'images/groups-avatar.png';
import Constants from 'utils/constants'; import Constants from 'utils/constants';
import {localizeMessage} from 'utils/utils';
const GROUPS_PER_PAGE = 50; const GROUPS_PER_PAGE = 50;
const MAX_SELECTABLE_VALUES = 10; const MAX_SELECTABLE_VALUES = 10;
@@ -248,8 +247,8 @@ export class AddGroupsToTeamModal extends React.PureComponent<Props, State> {
</div> </div>
); );
const buttonSubmitText = localizeMessage({id: 'multiselect.add', defaultMessage: 'Add'}); const buttonSubmitText = defineMessage({id: 'multiselect.add', defaultMessage: 'Add'});
const buttonSubmitLoadingText = localizeMessage({id: 'multiselect.adding', defaultMessage: 'Adding...'}); const buttonSubmitLoadingText = defineMessage({id: 'multiselect.adding', defaultMessage: 'Adding...'});
let addError = null; let addError = null;
if (this.state.addError) { if (this.state.addError) {
@@ -319,11 +318,12 @@ export class AddGroupsToTeamModal extends React.PureComponent<Props, State> {
buttonSubmitLoadingText={buttonSubmitLoadingText} buttonSubmitLoadingText={buttonSubmitLoadingText}
saving={this.state.saving} saving={this.state.saving}
loading={this.state.loadingGroups} loading={this.state.loadingGroups}
placeholderText={localizeMessage({id: 'multiselect.addGroupsPlaceholder', defaultMessage: 'Search and add groups'})} placeholderText={defineMessage({id: 'multiselect.addGroupsPlaceholder', defaultMessage: 'Search and add groups'})}
/> />
</Modal.Body> </Modal.Body>
</Modal> </Modal>
); );
} }
} }
export default injectIntl(AddGroupsToTeamModal); export default injectIntl(AddGroupsToTeamModal);

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

@@ -70,7 +70,12 @@ exports[`component/add_user_to_group_multiselect should match snapshot with diff
] ]
} }
perPage={50} perPage={50}
placeholderText="Search for people" placeholderText={
Object {
"defaultMessage": "Search for people",
"id": "multiselect.placeholder",
}
}
saveButtonPosition="bottom" saveButtonPosition="bottom"
saving={false} saving={false}
savingEnabled={false} savingEnabled={false}
@@ -87,8 +92,18 @@ exports[`component/add_user_to_group_multiselect should match snapshot with diff
exports[`component/add_user_to_group_multiselect should match snapshot with profiles 1`] = ` exports[`component/add_user_to_group_multiselect should match snapshot with profiles 1`] = `
<MultiSelect <MultiSelect
ariaLabelRenderer={[Function]} ariaLabelRenderer={[Function]}
buttonSubmitLoadingText="Creating..." buttonSubmitLoadingText={
buttonSubmitText="Create Group" Object {
"defaultMessage": "Creating...",
"id": "multiselect.creating",
}
}
buttonSubmitText={
Object {
"defaultMessage": "Create Group",
"id": "multiselect.createGroup",
}
}
focusOnLoad={false} focusOnLoad={false}
handleAdd={[Function]} handleAdd={[Function]}
handleDelete={[Function]} handleDelete={[Function]}
@@ -154,7 +169,12 @@ exports[`component/add_user_to_group_multiselect should match snapshot with prof
] ]
} }
perPage={50} perPage={50}
placeholderText="Search for people" placeholderText={
Object {
"defaultMessage": "Search for people",
"id": "multiselect.placeholder",
}
}
saveButtonPosition="bottom" saveButtonPosition="bottom"
saving={false} saving={false}
savingEnabled={false} savingEnabled={false}
@@ -171,8 +191,18 @@ exports[`component/add_user_to_group_multiselect should match snapshot with prof
exports[`component/add_user_to_group_multiselect should match snapshot without any profiles 1`] = ` exports[`component/add_user_to_group_multiselect should match snapshot without any profiles 1`] = `
<MultiSelect <MultiSelect
ariaLabelRenderer={[Function]} ariaLabelRenderer={[Function]}
buttonSubmitLoadingText="Creating..." buttonSubmitLoadingText={
buttonSubmitText="Create Group" Object {
"defaultMessage": "Creating...",
"id": "multiselect.creating",
}
}
buttonSubmitText={
Object {
"defaultMessage": "Create Group",
"id": "multiselect.createGroup",
}
}
focusOnLoad={false} focusOnLoad={false}
handleAdd={[Function]} handleAdd={[Function]}
handleDelete={[Function]} handleDelete={[Function]}
@@ -223,7 +253,12 @@ exports[`component/add_user_to_group_multiselect should match snapshot without a
optionRenderer={[Function]} optionRenderer={[Function]}
options={Array []} options={Array []}
perPage={50} perPage={50}
placeholderText="Search for people" placeholderText={
Object {
"defaultMessage": "Search for people",
"id": "multiselect.placeholder",
}
}
saveButtonPosition="bottom" saveButtonPosition="bottom"
saving={false} saving={false}
savingEnabled={false} savingEnabled={false}

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

@@ -2,8 +2,8 @@
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import React from 'react'; import React from 'react';
import type {IntlShape} from 'react-intl'; import type {IntlShape, MessageDescriptor} from 'react-intl';
import {injectIntl} from 'react-intl'; import {defineMessage, injectIntl} from 'react-intl';
import type {UserProfile} from '@mattermost/types/users'; import type {UserProfile} from '@mattermost/types/users';
import type {RelationOneToOne} from '@mattermost/types/utilities'; import type {RelationOneToOne} from '@mattermost/types/utilities';
@@ -15,7 +15,6 @@ import MultiSelect from 'components/multiselect/multiselect';
import type {Value} from 'components/multiselect/multiselect'; import type {Value} from 'components/multiselect/multiselect';
import Constants from 'utils/constants'; import Constants from 'utils/constants';
import {localizeMessage} from 'utils/utils';
import MultiSelectOption from './multiselect_option/multiselect_option'; import MultiSelectOption from './multiselect_option/multiselect_option';
@@ -50,11 +49,11 @@ export type Props = {
savingEnabled: boolean; savingEnabled: boolean;
saving: boolean; saving: boolean;
buttonSubmitText?: string; buttonSubmitText?: string | MessageDescriptor;
buttonSubmitLoadingText?: string; buttonSubmitLoadingText?: string | MessageDescriptor;
backButtonClick?: () => void; backButtonClick?: () => void;
backButtonClass?: string; backButtonClass?: string;
backButtonText?: string; backButtonText?: string | MessageDescriptor;
actions: { actions: {
getProfiles: (page?: number, perPage?: number) => Promise<ActionResult>; getProfiles: (page?: number, perPage?: number) => Promise<ActionResult>;
@@ -196,8 +195,8 @@ export class AddUserToGroupMultiSelect extends React.PureComponent<Props, State>
}; };
public render = (): JSX.Element => { public render = (): JSX.Element => {
const buttonSubmitText = this.props.buttonSubmitText || localizeMessage({id: 'multiselect.createGroup', defaultMessage: 'Create Group'}); const buttonSubmitText = this.props.buttonSubmitText || defineMessage({id: 'multiselect.createGroup', defaultMessage: 'Create Group'});
const buttonSubmitLoadingText = this.props.buttonSubmitLoadingText || localizeMessage({id: 'multiselect.creating', defaultMessage: 'Creating...'}); const buttonSubmitLoadingText = this.props.buttonSubmitLoadingText || defineMessage({id: 'multiselect.creating', defaultMessage: 'Creating...'});
let users = filterProfilesStartingWithTerm(this.props.profiles, this.state.term).filter((user) => { let users = filterProfilesStartingWithTerm(this.props.profiles, this.state.term).filter((user) => {
return user.delete_at === 0 && return user.delete_at === 0 &&
@@ -214,7 +213,7 @@ export class AddUserToGroupMultiSelect extends React.PureComponent<Props, State>
if (this.state.values.length >= MAX_SELECTABLE_VALUES) { if (this.state.values.length >= MAX_SELECTABLE_VALUES) {
maxValues = MAX_SELECTABLE_VALUES; maxValues = MAX_SELECTABLE_VALUES;
numRemainingText = localizeMessage({id: 'multiselect.maxGroupMembers', defaultMessage: 'No more than 256 members can be added to a group at once.'}); numRemainingText = defineMessage({id: 'multiselect.maxGroupMembers', defaultMessage: 'No more than 256 members can be added to a group at once.'});
} }
return ( return (
@@ -237,7 +236,7 @@ export class AddUserToGroupMultiSelect extends React.PureComponent<Props, State>
buttonSubmitLoadingText={buttonSubmitLoadingText} buttonSubmitLoadingText={buttonSubmitLoadingText}
saving={this.props.saving} saving={this.props.saving}
loading={this.state.loadingUsers} loading={this.state.loadingUsers}
placeholderText={localizeMessage({id: 'multiselect.placeholder', defaultMessage: 'Search for people'})} placeholderText={defineMessage({id: 'multiselect.placeholder', defaultMessage: 'Search for people'})}
valueWithImage={true} valueWithImage={true}
focusOnLoad={this.props.focusOnLoad} focusOnLoad={this.props.focusOnLoad}
savingEnabled={this.props.savingEnabled} savingEnabled={this.props.savingEnabled}

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

@@ -84,8 +84,18 @@ exports[`component/add_users_to_group_modal should match snapshot 1`] = `
addUserCallback={[Function]} addUserCallback={[Function]}
backButtonClass="multiselect-back" backButtonClass="multiselect-back"
backButtonClick={[Function]} backButtonClick={[Function]}
buttonSubmitLoadingText="Adding..." buttonSubmitLoadingText={
buttonSubmitText="Add People" Object {
"defaultMessage": "Adding...",
"id": "multiselect.adding",
}
}
buttonSubmitText={
Object {
"defaultMessage": "Add People",
"id": "multiselect.addPeopleToGroup",
}
}
deleteUserCallback={[Function]} deleteUserCallback={[Function]}
focusOnLoad={false} focusOnLoad={false}
groupId="groupid123" groupId="groupid123"

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

@@ -3,7 +3,7 @@
import React, {useState, useCallback, useMemo} from 'react'; import React, {useState, useCallback, useMemo} from 'react';
import {Modal} from 'react-bootstrap'; import {Modal} from 'react-bootstrap';
import {FormattedMessage, useIntl} from 'react-intl'; import {defineMessage, FormattedMessage, useIntl} from 'react-intl';
import type {Group} from '@mattermost/types/groups'; import type {Group} from '@mattermost/types/groups';
import type {UserProfile} from '@mattermost/types/users'; import type {UserProfile} from '@mattermost/types/users';
@@ -12,8 +12,6 @@ import type {ActionResult} from 'mattermost-redux/types/actions';
import AddUserToGroupMultiSelect from 'components/add_user_to_group_multiselect'; import AddUserToGroupMultiSelect from 'components/add_user_to_group_multiselect';
import {localizeMessage} from 'utils/utils';
import type {ModalData} from 'types/actions'; import type {ModalData} from 'types/actions';
import 'components/user_groups_modal/user_groups_modal.scss'; import 'components/user_groups_modal/user_groups_modal.scss';
@@ -136,8 +134,8 @@ const AddUsersToGroupModal = (props: Props) => {
deleteUserCallback={deleteUserCallback} deleteUserCallback={deleteUserCallback}
groupId={props.groupId} groupId={props.groupId}
searchOptions={searchOptions} searchOptions={searchOptions}
buttonSubmitText={localizeMessage({id: 'multiselect.addPeopleToGroup', defaultMessage: 'Add People'})} buttonSubmitText={defineMessage({id: 'multiselect.addPeopleToGroup', defaultMessage: 'Add People'})}
buttonSubmitLoadingText={localizeMessage({id: 'multiselect.adding', defaultMessage: 'Adding...'})} buttonSubmitLoadingText={defineMessage({id: 'multiselect.adding', defaultMessage: 'Adding...'})}
backButtonClick={goBack} backButtonClick={goBack}
backButtonClass={'multiselect-back'} backButtonClass={'multiselect-back'}
saving={saving} saving={saving}

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

@@ -57,8 +57,18 @@ exports[`components/admin_console/add_users_to_team_modal/AddUsersToTeamModal sh
> >
<MultiSelect <MultiSelect
ariaLabelRenderer={[Function]} ariaLabelRenderer={[Function]}
buttonSubmitLoadingText="Adding..." buttonSubmitLoadingText={
buttonSubmitText="Add" Object {
"defaultMessage": "Adding...",
"id": "multiselect.adding",
}
}
buttonSubmitText={
Object {
"defaultMessage": "Add",
"id": "multiselect.add",
}
}
focusOnLoad={true} focusOnLoad={true}
handleAdd={[Function]} handleAdd={[Function]}
handleDelete={[Function]} handleDelete={[Function]}
@@ -209,7 +219,12 @@ exports[`components/admin_console/add_users_to_team_modal/AddUsersToTeamModal sh
] ]
} }
perPage={50} perPage={50}
placeholderText="Search and add members" placeholderText={
Object {
"defaultMessage": "Search and add members",
"id": "multiselect.placeholder",
}
}
saveButtonPosition="top" saveButtonPosition="top"
saving={false} saving={false}
savingEnabled={true} savingEnabled={true}
@@ -283,8 +298,18 @@ exports[`components/admin_console/add_users_to_team_modal/AddUsersToTeamModal sh
> >
<MultiSelect <MultiSelect
ariaLabelRenderer={[Function]} ariaLabelRenderer={[Function]}
buttonSubmitLoadingText="Adding..." buttonSubmitLoadingText={
buttonSubmitText="Add" Object {
"defaultMessage": "Adding...",
"id": "multiselect.adding",
}
}
buttonSubmitText={
Object {
"defaultMessage": "Add",
"id": "multiselect.add",
}
}
focusOnLoad={true} focusOnLoad={true}
handleAdd={[Function]} handleAdd={[Function]}
handleDelete={[Function]} handleDelete={[Function]}
@@ -435,7 +460,12 @@ exports[`components/admin_console/add_users_to_team_modal/AddUsersToTeamModal sh
] ]
} }
perPage={50} perPage={50}
placeholderText="Search and add members" placeholderText={
Object {
"defaultMessage": "Search and add members",
"id": "multiselect.placeholder",
}
}
saveButtonPosition="top" saveButtonPosition="top"
saving={false} saving={false}
savingEnabled={true} savingEnabled={true}

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

@@ -4,7 +4,7 @@
import React from 'react'; import React from 'react';
import {Modal} from 'react-bootstrap'; import {Modal} from 'react-bootstrap';
import type {IntlShape} from 'react-intl'; import type {IntlShape} from 'react-intl';
import {injectIntl, FormattedMessage} from 'react-intl'; import {injectIntl, FormattedMessage, defineMessage} from 'react-intl';
import type {Team} from '@mattermost/types/teams'; import type {Team} from '@mattermost/types/teams';
import type {UserProfile} from '@mattermost/types/users'; import type {UserProfile} from '@mattermost/types/users';
@@ -19,7 +19,7 @@ import ProfilePicture from 'components/profile_picture';
import BotTag from 'components/widgets/tag/bot_tag'; import BotTag from 'components/widgets/tag/bot_tag';
import GuestTag from 'components/widgets/tag/guest_tag'; import GuestTag from 'components/widgets/tag/guest_tag';
import {displayEntireNameForUser, localizeMessage} from 'utils/utils'; import {displayEntireNameForUser} from 'utils/utils';
const USERS_PER_PAGE = 50; const USERS_PER_PAGE = 50;
const MAX_SELECTABLE_VALUES = 20; const MAX_SELECTABLE_VALUES = 20;
@@ -192,8 +192,8 @@ export class AddUsersToTeamModal extends React.PureComponent<Props, State> {
</div> </div>
); );
const buttonSubmitText = localizeMessage({id: 'multiselect.add', defaultMessage: 'Add'}); const buttonSubmitText = defineMessage({id: 'multiselect.add', defaultMessage: 'Add'});
const buttonSubmitLoadingText = localizeMessage({id: 'multiselect.adding', defaultMessage: 'Adding...'}); const buttonSubmitLoadingText = defineMessage({id: 'multiselect.adding', defaultMessage: 'Adding...'});
let addError = null; let addError = null;
if (this.state.addError) { if (this.state.addError) {
@@ -259,7 +259,7 @@ export class AddUsersToTeamModal extends React.PureComponent<Props, State> {
buttonSubmitLoadingText={buttonSubmitLoadingText} buttonSubmitLoadingText={buttonSubmitLoadingText}
saving={this.state.saving} saving={this.state.saving}
loading={this.state.loading} loading={this.state.loading}
placeholderText={localizeMessage({id: 'multiselect.placeholder', defaultMessage: 'Search and add members'})} placeholderText={defineMessage({id: 'multiselect.placeholder', defaultMessage: 'Search and add members'})}
/> />
</Modal.Body> </Modal.Body>
</Modal> </Modal>

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

@@ -4,44 +4,6 @@ exports[`components/AdminConsole/CustomUrlSchemeSetting initial state with multi
<CustomURLSchemesSetting <CustomURLSchemesSetting
disabled={false} disabled={false}
id="MySetting" id="MySetting"
intl={
Object {
"$t": [Function],
"defaultFormats": Object {},
"defaultLocale": "en",
"defaultRichTextElements": undefined,
"fallbackOnEmptyString": true,
"formatDate": [Function],
"formatDateTimeRange": [Function],
"formatDateToParts": [Function],
"formatDisplayName": [Function],
"formatList": [Function],
"formatListToParts": [Function],
"formatMessage": [Function],
"formatNumber": [Function],
"formatNumberToParts": [Function],
"formatPlural": [Function],
"formatRelativeTime": [Function],
"formatTime": [Function],
"formatTimeToParts": [Function],
"formats": Object {},
"formatters": Object {
"getDateTimeFormat": [Function],
"getDisplayNames": [Function],
"getListFormat": [Function],
"getMessageFormat": [Function],
"getNumberFormat": [Function],
"getPluralRules": [Function],
"getRelativeTimeFormat": [Function],
},
"locale": "en",
"messages": Object {},
"onError": [Function],
"onWarn": [Function],
"textComponent": "span",
"timeZone": "Etc/UTC",
}
}
onChange={[MockFunction]} onChange={[MockFunction]}
setByEnv={false} setByEnv={false}
value={ value={
@@ -53,9 +15,19 @@ exports[`components/AdminConsole/CustomUrlSchemeSetting initial state with multi
} }
> >
<Memo(Settings) <Memo(Settings)
helpText="Allows message text to link if it begins with any of the comma-separated URL schemes listed. By default, the following schemes will create links: \\"http\\", \\"https\\", \\"ftp\\", \\"tel\\", and \\"mailto\\"." helpText={
<Memo(MemoizedFormattedMessage)
defaultMessage="Allows message text to link if it begins with any of the comma-separated URL schemes listed. By default, the following schemes will create links: \\"http\\", \\"https\\", \\"ftp\\", \\"tel\\", and \\"mailto\\"."
id="admin.customization.customUrlSchemesDesc"
/>
}
inputId="MySetting" inputId="MySetting"
label="Custom URL Schemes:" label={
<Memo(MemoizedFormattedMessage)
defaultMessage="Custom URL Schemes:"
id="admin.customization.customUrlSchemes"
/>
}
setByEnv={false} setByEnv={false}
> >
<div <div
@@ -66,25 +38,54 @@ exports[`components/AdminConsole/CustomUrlSchemeSetting initial state with multi
className="control-label col-sm-4" className="control-label col-sm-4"
htmlFor="MySetting" htmlFor="MySetting"
> >
Custom URL Schemes: <FormattedMessage
defaultMessage="Custom URL Schemes:"
id="admin.customization.customUrlSchemes"
>
<span>
Custom URL Schemes:
</span>
</FormattedMessage>
</label> </label>
<div <div
className="col-sm-8" className="col-sm-8"
> >
<input <LocalizedPlaceholderInput
className="form-control" className="form-control"
disabled={false} disabled={false}
id="MySetting" id="MySetting"
onChange={[Function]} onChange={[Function]}
placeholder="E.g.: \\"git,smtp\\"" placeholder={
Object {
"defaultMessage": "E.g.: \\"git,smtp\\"",
"id": "admin.customization.customUrlSchemesPlaceholder",
}
}
type="text" type="text"
value="git,smtp,steam" value="git,smtp,steam"
/> >
<input
className="form-control"
disabled={false}
id="MySetting"
onChange={[Function]}
placeholder="E.g.: \\"git,smtp\\""
type="text"
value="git,smtp,steam"
/>
</LocalizedPlaceholderInput>
<div <div
className="help-text" className="help-text"
data-testid="MySettinghelp-text" data-testid="MySettinghelp-text"
> >
Allows message text to link if it begins with any of the comma-separated URL schemes listed. By default, the following schemes will create links: "http", "https", "ftp", "tel", and "mailto". <FormattedMessage
defaultMessage="Allows message text to link if it begins with any of the comma-separated URL schemes listed. By default, the following schemes will create links: \\"http\\", \\"https\\", \\"ftp\\", \\"tel\\", and \\"mailto\\"."
id="admin.customization.customUrlSchemesDesc"
>
<span>
Allows message text to link if it begins with any of the comma-separated URL schemes listed. By default, the following schemes will create links: "http", "https", "ftp", "tel", and "mailto".
</span>
</FormattedMessage>
</div> </div>
</div> </div>
</div> </div>
@@ -96,52 +97,24 @@ exports[`components/AdminConsole/CustomUrlSchemeSetting initial state with no it
<CustomURLSchemesSetting <CustomURLSchemesSetting
disabled={false} disabled={false}
id="MySetting" id="MySetting"
intl={
Object {
"$t": [Function],
"defaultFormats": Object {},
"defaultLocale": "en",
"defaultRichTextElements": undefined,
"fallbackOnEmptyString": true,
"formatDate": [Function],
"formatDateTimeRange": [Function],
"formatDateToParts": [Function],
"formatDisplayName": [Function],
"formatList": [Function],
"formatListToParts": [Function],
"formatMessage": [Function],
"formatNumber": [Function],
"formatNumberToParts": [Function],
"formatPlural": [Function],
"formatRelativeTime": [Function],
"formatTime": [Function],
"formatTimeToParts": [Function],
"formats": Object {},
"formatters": Object {
"getDateTimeFormat": [Function],
"getDisplayNames": [Function],
"getListFormat": [Function],
"getMessageFormat": [Function],
"getNumberFormat": [Function],
"getPluralRules": [Function],
"getRelativeTimeFormat": [Function],
},
"locale": "en",
"messages": Object {},
"onError": [Function],
"onWarn": [Function],
"textComponent": "span",
"timeZone": "Etc/UTC",
}
}
onChange={[MockFunction]} onChange={[MockFunction]}
setByEnv={false} setByEnv={false}
value={Array []} value={Array []}
> >
<Memo(Settings) <Memo(Settings)
helpText="Allows message text to link if it begins with any of the comma-separated URL schemes listed. By default, the following schemes will create links: \\"http\\", \\"https\\", \\"ftp\\", \\"tel\\", and \\"mailto\\"." helpText={
<Memo(MemoizedFormattedMessage)
defaultMessage="Allows message text to link if it begins with any of the comma-separated URL schemes listed. By default, the following schemes will create links: \\"http\\", \\"https\\", \\"ftp\\", \\"tel\\", and \\"mailto\\"."
id="admin.customization.customUrlSchemesDesc"
/>
}
inputId="MySetting" inputId="MySetting"
label="Custom URL Schemes:" label={
<Memo(MemoizedFormattedMessage)
defaultMessage="Custom URL Schemes:"
id="admin.customization.customUrlSchemes"
/>
}
setByEnv={false} setByEnv={false}
> >
<div <div
@@ -152,25 +125,54 @@ exports[`components/AdminConsole/CustomUrlSchemeSetting initial state with no it
className="control-label col-sm-4" className="control-label col-sm-4"
htmlFor="MySetting" htmlFor="MySetting"
> >
Custom URL Schemes: <FormattedMessage
defaultMessage="Custom URL Schemes:"
id="admin.customization.customUrlSchemes"
>
<span>
Custom URL Schemes:
</span>
</FormattedMessage>
</label> </label>
<div <div
className="col-sm-8" className="col-sm-8"
> >
<input <LocalizedPlaceholderInput
className="form-control" className="form-control"
disabled={false} disabled={false}
id="MySetting" id="MySetting"
onChange={[Function]} onChange={[Function]}
placeholder="E.g.: \\"git,smtp\\"" placeholder={
Object {
"defaultMessage": "E.g.: \\"git,smtp\\"",
"id": "admin.customization.customUrlSchemesPlaceholder",
}
}
type="text" type="text"
value="" value=""
/> >
<input
className="form-control"
disabled={false}
id="MySetting"
onChange={[Function]}
placeholder="E.g.: \\"git,smtp\\""
type="text"
value=""
/>
</LocalizedPlaceholderInput>
<div <div
className="help-text" className="help-text"
data-testid="MySettinghelp-text" data-testid="MySettinghelp-text"
> >
Allows message text to link if it begins with any of the comma-separated URL schemes listed. By default, the following schemes will create links: "http", "https", "ftp", "tel", and "mailto". <FormattedMessage
defaultMessage="Allows message text to link if it begins with any of the comma-separated URL schemes listed. By default, the following schemes will create links: \\"http\\", \\"https\\", \\"ftp\\", \\"tel\\", and \\"mailto\\"."
id="admin.customization.customUrlSchemesDesc"
>
<span>
Allows message text to link if it begins with any of the comma-separated URL schemes listed. By default, the following schemes will create links: "http", "https", "ftp", "tel", and "mailto".
</span>
</FormattedMessage>
</div> </div>
</div> </div>
</div> </div>
@@ -182,44 +184,6 @@ exports[`components/AdminConsole/CustomUrlSchemeSetting initial state with one i
<CustomURLSchemesSetting <CustomURLSchemesSetting
disabled={false} disabled={false}
id="MySetting" id="MySetting"
intl={
Object {
"$t": [Function],
"defaultFormats": Object {},
"defaultLocale": "en",
"defaultRichTextElements": undefined,
"fallbackOnEmptyString": true,
"formatDate": [Function],
"formatDateTimeRange": [Function],
"formatDateToParts": [Function],
"formatDisplayName": [Function],
"formatList": [Function],
"formatListToParts": [Function],
"formatMessage": [Function],
"formatNumber": [Function],
"formatNumberToParts": [Function],
"formatPlural": [Function],
"formatRelativeTime": [Function],
"formatTime": [Function],
"formatTimeToParts": [Function],
"formats": Object {},
"formatters": Object {
"getDateTimeFormat": [Function],
"getDisplayNames": [Function],
"getListFormat": [Function],
"getMessageFormat": [Function],
"getNumberFormat": [Function],
"getPluralRules": [Function],
"getRelativeTimeFormat": [Function],
},
"locale": "en",
"messages": Object {},
"onError": [Function],
"onWarn": [Function],
"textComponent": "span",
"timeZone": "Etc/UTC",
}
}
onChange={[MockFunction]} onChange={[MockFunction]}
setByEnv={false} setByEnv={false}
value={ value={
@@ -229,9 +193,19 @@ exports[`components/AdminConsole/CustomUrlSchemeSetting initial state with one i
} }
> >
<Memo(Settings) <Memo(Settings)
helpText="Allows message text to link if it begins with any of the comma-separated URL schemes listed. By default, the following schemes will create links: \\"http\\", \\"https\\", \\"ftp\\", \\"tel\\", and \\"mailto\\"." helpText={
<Memo(MemoizedFormattedMessage)
defaultMessage="Allows message text to link if it begins with any of the comma-separated URL schemes listed. By default, the following schemes will create links: \\"http\\", \\"https\\", \\"ftp\\", \\"tel\\", and \\"mailto\\"."
id="admin.customization.customUrlSchemesDesc"
/>
}
inputId="MySetting" inputId="MySetting"
label="Custom URL Schemes:" label={
<Memo(MemoizedFormattedMessage)
defaultMessage="Custom URL Schemes:"
id="admin.customization.customUrlSchemes"
/>
}
setByEnv={false} setByEnv={false}
> >
<div <div
@@ -242,25 +216,54 @@ exports[`components/AdminConsole/CustomUrlSchemeSetting initial state with one i
className="control-label col-sm-4" className="control-label col-sm-4"
htmlFor="MySetting" htmlFor="MySetting"
> >
Custom URL Schemes: <FormattedMessage
defaultMessage="Custom URL Schemes:"
id="admin.customization.customUrlSchemes"
>
<span>
Custom URL Schemes:
</span>
</FormattedMessage>
</label> </label>
<div <div
className="col-sm-8" className="col-sm-8"
> >
<input <LocalizedPlaceholderInput
className="form-control" className="form-control"
disabled={false} disabled={false}
id="MySetting" id="MySetting"
onChange={[Function]} onChange={[Function]}
placeholder="E.g.: \\"git,smtp\\"" placeholder={
Object {
"defaultMessage": "E.g.: \\"git,smtp\\"",
"id": "admin.customization.customUrlSchemesPlaceholder",
}
}
type="text" type="text"
value="git" value="git"
/> >
<input
className="form-control"
disabled={false}
id="MySetting"
onChange={[Function]}
placeholder="E.g.: \\"git,smtp\\""
type="text"
value="git"
/>
</LocalizedPlaceholderInput>
<div <div
className="help-text" className="help-text"
data-testid="MySettinghelp-text" data-testid="MySettinghelp-text"
> >
Allows message text to link if it begins with any of the comma-separated URL schemes listed. By default, the following schemes will create links: "http", "https", "ftp", "tel", and "mailto". <FormattedMessage
defaultMessage="Allows message text to link if it begins with any of the comma-separated URL schemes listed. By default, the following schemes will create links: \\"http\\", \\"https\\", \\"ftp\\", \\"tel\\", and \\"mailto\\"."
id="admin.customization.customUrlSchemesDesc"
>
<span>
Allows message text to link if it begins with any of the comma-separated URL schemes listed. By default, the following schemes will create links: "http", "https", "ftp", "tel", and "mailto".
</span>
</FormattedMessage>
</div> </div>
</div> </div>
</div> </div>
@@ -272,44 +275,6 @@ exports[`components/AdminConsole/CustomUrlSchemeSetting renders properly when di
<CustomURLSchemesSetting <CustomURLSchemesSetting
disabled={true} disabled={true}
id="MySetting" id="MySetting"
intl={
Object {
"$t": [Function],
"defaultFormats": Object {},
"defaultLocale": "en",
"defaultRichTextElements": undefined,
"fallbackOnEmptyString": true,
"formatDate": [Function],
"formatDateTimeRange": [Function],
"formatDateToParts": [Function],
"formatDisplayName": [Function],
"formatList": [Function],
"formatListToParts": [Function],
"formatMessage": [Function],
"formatNumber": [Function],
"formatNumberToParts": [Function],
"formatPlural": [Function],
"formatRelativeTime": [Function],
"formatTime": [Function],
"formatTimeToParts": [Function],
"formats": Object {},
"formatters": Object {
"getDateTimeFormat": [Function],
"getDisplayNames": [Function],
"getListFormat": [Function],
"getMessageFormat": [Function],
"getNumberFormat": [Function],
"getPluralRules": [Function],
"getRelativeTimeFormat": [Function],
},
"locale": "en",
"messages": Object {},
"onError": [Function],
"onWarn": [Function],
"textComponent": "span",
"timeZone": "Etc/UTC",
}
}
onChange={[MockFunction]} onChange={[MockFunction]}
setByEnv={false} setByEnv={false}
value={ value={
@@ -320,9 +285,19 @@ exports[`components/AdminConsole/CustomUrlSchemeSetting renders properly when di
} }
> >
<Memo(Settings) <Memo(Settings)
helpText="Allows message text to link if it begins with any of the comma-separated URL schemes listed. By default, the following schemes will create links: \\"http\\", \\"https\\", \\"ftp\\", \\"tel\\", and \\"mailto\\"." helpText={
<Memo(MemoizedFormattedMessage)
defaultMessage="Allows message text to link if it begins with any of the comma-separated URL schemes listed. By default, the following schemes will create links: \\"http\\", \\"https\\", \\"ftp\\", \\"tel\\", and \\"mailto\\"."
id="admin.customization.customUrlSchemesDesc"
/>
}
inputId="MySetting" inputId="MySetting"
label="Custom URL Schemes:" label={
<Memo(MemoizedFormattedMessage)
defaultMessage="Custom URL Schemes:"
id="admin.customization.customUrlSchemes"
/>
}
setByEnv={false} setByEnv={false}
> >
<div <div
@@ -333,25 +308,54 @@ exports[`components/AdminConsole/CustomUrlSchemeSetting renders properly when di
className="control-label col-sm-4" className="control-label col-sm-4"
htmlFor="MySetting" htmlFor="MySetting"
> >
Custom URL Schemes: <FormattedMessage
defaultMessage="Custom URL Schemes:"
id="admin.customization.customUrlSchemes"
>
<span>
Custom URL Schemes:
</span>
</FormattedMessage>
</label> </label>
<div <div
className="col-sm-8" className="col-sm-8"
> >
<input <LocalizedPlaceholderInput
className="form-control" className="form-control"
disabled={true} disabled={true}
id="MySetting" id="MySetting"
onChange={[Function]} onChange={[Function]}
placeholder="E.g.: \\"git,smtp\\"" placeholder={
Object {
"defaultMessage": "E.g.: \\"git,smtp\\"",
"id": "admin.customization.customUrlSchemesPlaceholder",
}
}
type="text" type="text"
value="git,smtp" value="git,smtp"
/> >
<input
className="form-control"
disabled={true}
id="MySetting"
onChange={[Function]}
placeholder="E.g.: \\"git,smtp\\""
type="text"
value="git,smtp"
/>
</LocalizedPlaceholderInput>
<div <div
className="help-text" className="help-text"
data-testid="MySettinghelp-text" data-testid="MySettinghelp-text"
> >
Allows message text to link if it begins with any of the comma-separated URL schemes listed. By default, the following schemes will create links: "http", "https", "ftp", "tel", and "mailto". <FormattedMessage
defaultMessage="Allows message text to link if it begins with any of the comma-separated URL schemes listed. By default, the following schemes will create links: \\"http\\", \\"https\\", \\"ftp\\", \\"tel\\", and \\"mailto\\"."
id="admin.customization.customUrlSchemesDesc"
>
<span>
Allows message text to link if it begins with any of the comma-separated URL schemes listed. By default, the following schemes will create links: "http", "https", "ftp", "tel", and "mailto".
</span>
</FormattedMessage>
</div> </div>
</div> </div>
</div> </div>
@@ -363,44 +367,6 @@ exports[`components/AdminConsole/CustomUrlSchemeSetting renders properly when se
<CustomURLSchemesSetting <CustomURLSchemesSetting
disabled={false} disabled={false}
id="MySetting" id="MySetting"
intl={
Object {
"$t": [Function],
"defaultFormats": Object {},
"defaultLocale": "en",
"defaultRichTextElements": undefined,
"fallbackOnEmptyString": true,
"formatDate": [Function],
"formatDateTimeRange": [Function],
"formatDateToParts": [Function],
"formatDisplayName": [Function],
"formatList": [Function],
"formatListToParts": [Function],
"formatMessage": [Function],
"formatNumber": [Function],
"formatNumberToParts": [Function],
"formatPlural": [Function],
"formatRelativeTime": [Function],
"formatTime": [Function],
"formatTimeToParts": [Function],
"formats": Object {},
"formatters": Object {
"getDateTimeFormat": [Function],
"getDisplayNames": [Function],
"getListFormat": [Function],
"getMessageFormat": [Function],
"getNumberFormat": [Function],
"getPluralRules": [Function],
"getRelativeTimeFormat": [Function],
},
"locale": "en",
"messages": Object {},
"onError": [Function],
"onWarn": [Function],
"textComponent": "span",
"timeZone": "Etc/UTC",
}
}
onChange={[MockFunction]} onChange={[MockFunction]}
setByEnv={true} setByEnv={true}
value={ value={
@@ -411,9 +377,19 @@ exports[`components/AdminConsole/CustomUrlSchemeSetting renders properly when se
} }
> >
<Memo(Settings) <Memo(Settings)
helpText="Allows message text to link if it begins with any of the comma-separated URL schemes listed. By default, the following schemes will create links: \\"http\\", \\"https\\", \\"ftp\\", \\"tel\\", and \\"mailto\\"." helpText={
<Memo(MemoizedFormattedMessage)
defaultMessage="Allows message text to link if it begins with any of the comma-separated URL schemes listed. By default, the following schemes will create links: \\"http\\", \\"https\\", \\"ftp\\", \\"tel\\", and \\"mailto\\"."
id="admin.customization.customUrlSchemesDesc"
/>
}
inputId="MySetting" inputId="MySetting"
label="Custom URL Schemes:" label={
<Memo(MemoizedFormattedMessage)
defaultMessage="Custom URL Schemes:"
id="admin.customization.customUrlSchemes"
/>
}
setByEnv={true} setByEnv={true}
> >
<div <div
@@ -424,25 +400,54 @@ exports[`components/AdminConsole/CustomUrlSchemeSetting renders properly when se
className="control-label col-sm-4" className="control-label col-sm-4"
htmlFor="MySetting" htmlFor="MySetting"
> >
Custom URL Schemes: <FormattedMessage
defaultMessage="Custom URL Schemes:"
id="admin.customization.customUrlSchemes"
>
<span>
Custom URL Schemes:
</span>
</FormattedMessage>
</label> </label>
<div <div
className="col-sm-8" className="col-sm-8"
> >
<input <LocalizedPlaceholderInput
className="form-control" className="form-control"
disabled={true} disabled={true}
id="MySetting" id="MySetting"
onChange={[Function]} onChange={[Function]}
placeholder="E.g.: \\"git,smtp\\"" placeholder={
Object {
"defaultMessage": "E.g.: \\"git,smtp\\"",
"id": "admin.customization.customUrlSchemesPlaceholder",
}
}
type="text" type="text"
value="git,smtp" value="git,smtp"
/> >
<input
className="form-control"
disabled={true}
id="MySetting"
onChange={[Function]}
placeholder="E.g.: \\"git,smtp\\""
type="text"
value="git,smtp"
/>
</LocalizedPlaceholderInput>
<div <div
className="help-text" className="help-text"
data-testid="MySettinghelp-text" data-testid="MySettinghelp-text"
> >
Allows message text to link if it begins with any of the comma-separated URL schemes listed. By default, the following schemes will create links: "http", "https", "ftp", "tel", and "mailto". <FormattedMessage
defaultMessage="Allows message text to link if it begins with any of the comma-separated URL schemes listed. By default, the following schemes will create links: \\"http\\", \\"https\\", \\"ftp\\", \\"tel\\", and \\"mailto\\"."
id="admin.customization.customUrlSchemesDesc"
>
<span>
Allows message text to link if it begins with any of the comma-separated URL schemes listed. By default, the following schemes will create links: "http", "https", "ftp", "tel", and "mailto".
</span>
</FormattedMessage>
</div> </div>
<SetByEnv> <SetByEnv>
<div <div

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

@@ -3,7 +3,7 @@
import {getName} from 'country-list'; import {getName} from 'country-list';
import React, {useCallback, useEffect, useState} from 'react'; import React, {useCallback, useEffect, useState} from 'react';
import {FormattedMessage} from 'react-intl'; import {defineMessage, FormattedMessage} from 'react-intl';
import {useDispatch, useSelector} from 'react-redux'; import {useDispatch, useSelector} from 'react-redux';
import {useHistory} from 'react-router-dom'; import {useHistory} from 'react-router-dom';
@@ -18,8 +18,6 @@ import SaveButton from 'components/save_button';
import AdminHeader from 'components/widgets/admin_console/admin_header'; import AdminHeader from 'components/widgets/admin_console/admin_header';
import Input from 'components/widgets/inputs/input/input'; import Input from 'components/widgets/inputs/input/input';
import * as Utils from 'utils/utils';
import type {GlobalState} from 'types/store'; import type {GlobalState} from 'types/store';
import './company_info_edit.scss'; import './company_info_edit.scss';
@@ -150,7 +148,7 @@ const CompanyInfoEdit: React.FC<Props> = () => {
type='text' type='text'
value={address} value={address}
onChange={updateState(setAddress)} onChange={updateState(setAddress)}
placeholder={Utils.localizeMessage({id: 'admin.billing.company_info.address', defaultMessage: 'Address'})} placeholder={defineMessage({id: 'admin.billing.company_info.address', defaultMessage: 'Address'})}
required={true} required={true}
/> />
</div> </div>
@@ -160,7 +158,7 @@ const CompanyInfoEdit: React.FC<Props> = () => {
type='text' type='text'
value={address2} value={address2}
onChange={updateState(setAddress2)} onChange={updateState(setAddress2)}
placeholder={Utils.localizeMessage({id: 'admin.billing.company_info.address_2', defaultMessage: 'Address 2'})} placeholder={defineMessage({id: 'admin.billing.company_info.address_2', defaultMessage: 'Address 2'})}
/> />
</div> </div>
<div className='form-row'> <div className='form-row'>
@@ -169,7 +167,7 @@ const CompanyInfoEdit: React.FC<Props> = () => {
type='text' type='text'
value={city} value={city}
onChange={updateState(setCity)} onChange={updateState(setCity)}
placeholder={Utils.localizeMessage({id: 'admin.billing.company_info.city', defaultMessage: 'City'})} placeholder={defineMessage({id: 'admin.billing.company_info.city', defaultMessage: 'City'})}
required={true} required={true}
/> />
</div> </div>
@@ -190,7 +188,10 @@ const CompanyInfoEdit: React.FC<Props> = () => {
type='text' type='text'
value={postalCode} value={postalCode}
onChange={updateState(setPostalCode)} onChange={updateState(setPostalCode)}
placeholder={Utils.localizeMessage({id: 'admin.billing.company_info.zipcode', defaultMessage: 'Zip/Postal Code'})} placeholder={defineMessage({
id: 'admin.billing.company_info.zipcode',
defaultMessage: 'Zip/Postal Code',
})}
required={true} required={true}
/> />
</div> </div>
@@ -228,7 +229,7 @@ const CompanyInfoEdit: React.FC<Props> = () => {
type='text' type='text'
value={companyName} value={companyName}
onChange={updateState(setCompanyName)} onChange={updateState(setCompanyName)}
placeholder={Utils.localizeMessage({id: 'admin.billing.company_info.companyName', defaultMessage: 'Company name'})} placeholder={defineMessage({id: 'admin.billing.company_info.companyName', defaultMessage: 'Company name'})}
required={true} required={true}
/> />
</div> </div>
@@ -238,7 +239,7 @@ const CompanyInfoEdit: React.FC<Props> = () => {
type='number' type='number'
value={numEmployees} value={numEmployees}
onChange={updateNumEmployees} onChange={updateNumEmployees}
placeholder={Utils.localizeMessage({id: 'admin.billing.company_info.numEmployees', defaultMessage: 'Number of employees (optional)'})} placeholder={defineMessage({id: 'admin.billing.company_info.numEmployees', defaultMessage: 'Number of employees (optional)'})}
/> />
</div> </div>
<div className='section-title'> <div className='section-title'>

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

@@ -10,7 +10,6 @@ import WarningIcon from 'components/widgets/icons/fa_warning_icon';
import statusGreen from 'images/status_green.png'; import statusGreen from 'images/status_green.png';
import statusYellow from 'images/status_yellow.png'; import statusYellow from 'images/status_yellow.png';
import * as Utils from 'utils/utils';
type Props = { type Props = {
clusterInfos: Array<{ clusterInfos: Array<{
@@ -97,16 +96,34 @@ export default class ClusterTable extends PureComponent<Props> {
const items = this.props.clusterInfos.map((clusterInfo) => { const items = this.props.clusterInfos.map((clusterInfo) => {
let status = null; let status = null;
if (clusterInfo.hostname === '') { let hostname: React.ReactNode = clusterInfo.hostname;
clusterInfo.hostname = Utils.localizeMessage({id: 'admin.cluster.unknown', defaultMessage: 'unknown'}); if (hostname === '') {
hostname = (
<FormattedMessage
id='admin.cluster.unknown'
defaultMessage='unknown'
/>
);
} }
if (clusterInfo.version === '') { let version: React.ReactNode = clusterInfo.version;
clusterInfo.version = Utils.localizeMessage({id: 'admin.cluster.unknown', defaultMessage: 'unknown'}); if (version === '') {
version = (
<FormattedMessage
id='admin.cluster.unknown'
defaultMessage='unknown'
/>
);
} }
if (clusterInfo.config_hash === '') { let configHash: React.ReactNode = clusterInfo.config_hash;
clusterInfo.config_hash = Utils.localizeMessage({id: 'admin.cluster.unknown', defaultMessage: 'unknown'}); if (configHash === '') {
configHash = (
<FormattedMessage
id='admin.cluster.unknown'
defaultMessage='unknown'
/>
);
} }
if (singleItem) { if (singleItem) {
@@ -130,9 +147,9 @@ export default class ClusterTable extends PureComponent<Props> {
return ( return (
<tr key={clusterInfo.ipaddress}> <tr key={clusterInfo.ipaddress}>
<td style={style.clusterCell}>{status}</td> <td style={style.clusterCell}>{status}</td>
<td style={style.clusterCell}>{clusterInfo.hostname}</td> <td style={style.clusterCell}>{hostname}</td>
<td style={style.clusterCell}>{versionMismatch} {clusterInfo.version}</td> <td style={style.clusterCell}>{versionMismatch} {version}</td>
<td style={style.clusterCell}><div className='config-hash'>{configMismatch} {clusterInfo.config_hash}</div></td> <td style={style.clusterCell}><div className='config-hash'>{configMismatch} {configHash}</div></td>
<td style={style.clusterCell}>{clusterInfo.ipaddress}</td> <td style={style.clusterCell}>{clusterInfo.ipaddress}</td>
<td style={style.clusterCell}>{clusterInfo.schema_version}</td> <td style={style.clusterCell}>{clusterInfo.schema_version}</td>
</tr> </tr>

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

@@ -2,7 +2,7 @@
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import React from 'react'; import React from 'react';
import {FormattedDate, FormattedMessage, FormattedTime, type IntlShape, injectIntl} from 'react-intl'; import {FormattedDate, FormattedMessage, FormattedTime, defineMessage} from 'react-intl';
import type {Compliance} from '@mattermost/types/compliance'; import type {Compliance} from '@mattermost/types/compliance';
import type {UserProfile} from '@mattermost/types/users'; import type {UserProfile} from '@mattermost/types/users';
@@ -11,6 +11,7 @@ import {Client4} from 'mattermost-redux/client';
import type {ActionResult} from 'mattermost-redux/types/actions'; import type {ActionResult} from 'mattermost-redux/types/actions';
import LoadingScreen from 'components/loading_screen'; import LoadingScreen from 'components/loading_screen';
import LocalizedPlaceholderInput from 'components/localized_placeholder_input';
import ReloadIcon from 'components/widgets/icons/fa_reload_icon'; import ReloadIcon from 'components/widgets/icons/fa_reload_icon';
type Props = { type Props = {
@@ -38,8 +39,6 @@ type Props = {
readOnly?: boolean; readOnly?: boolean;
intl: IntlShape;
actions: { actions: {
/* /*
@@ -59,7 +58,7 @@ type State = {
runningReport?: boolean; runningReport?: boolean;
} }
class ComplianceReports extends React.PureComponent<Props, State> { export default class ComplianceReports extends React.PureComponent<Props, State> {
private descInput: React.RefObject<HTMLInputElement>; private descInput: React.RefObject<HTMLInputElement>;
private emailsInput: React.RefObject<HTMLInputElement>; private emailsInput: React.RefObject<HTMLInputElement>;
private fromInput: React.RefObject<HTMLInputElement>; private fromInput: React.RefObject<HTMLInputElement>;
@@ -345,12 +344,12 @@ class ComplianceReports extends React.PureComponent<Props, State> {
defaultMessage='Job Name:' defaultMessage='Job Name:'
/> />
</label> </label>
<input <LocalizedPlaceholderInput
type='text' type='text'
className='form-control' className='form-control'
id='desc' id='desc'
ref={this.descInput} ref={this.descInput}
placeholder={this.props.intl.formatMessage({id: 'admin.compliance_reports.desc_placeholder', defaultMessage: 'E.g. "Audit 445 for HR"'})} placeholder={defineMessage({id: 'admin.compliance_reports.desc_placeholder', defaultMessage: 'E.g. "Audit 445 for HR"'})}
disabled={this.props.readOnly} disabled={this.props.readOnly}
/> />
</div> </div>
@@ -361,12 +360,12 @@ class ComplianceReports extends React.PureComponent<Props, State> {
defaultMessage='From:' defaultMessage='From:'
/> />
</label> </label>
<input <LocalizedPlaceholderInput
type='text' type='text'
className='form-control' className='form-control'
id='from' id='from'
ref={this.fromInput} ref={this.fromInput}
placeholder={this.props.intl.formatMessage({id: 'admin.compliance_reports.from_placeholder', defaultMessage: 'E.g. "2016-03-11"'})} placeholder={defineMessage({id: 'admin.compliance_reports.from_placeholder', defaultMessage: 'E.g. "2016-03-11"'})}
disabled={this.props.readOnly} disabled={this.props.readOnly}
/> />
</div> </div>
@@ -377,12 +376,12 @@ class ComplianceReports extends React.PureComponent<Props, State> {
defaultMessage='To:' defaultMessage='To:'
/> />
</label> </label>
<input <LocalizedPlaceholderInput
type='text' type='text'
className='form-control' className='form-control'
id='to' id='to'
ref={this.toInput} ref={this.toInput}
placeholder={this.props.intl.formatMessage({id: 'admin.compliance_reports.to_placeholder', defaultMessage: 'E.g. "2016-03-15"'})} placeholder={defineMessage({id: 'admin.compliance_reports.to_placeholder', defaultMessage: 'E.g. "2016-03-15"'})}
disabled={this.props.readOnly} disabled={this.props.readOnly}
/> />
</div> </div>
@@ -395,12 +394,12 @@ class ComplianceReports extends React.PureComponent<Props, State> {
defaultMessage='Emails:' defaultMessage='Emails:'
/> />
</label> </label>
<input <LocalizedPlaceholderInput
type='text' type='text'
className='form-control' className='form-control'
id='emails' id='emails'
ref={this.emailsInput} ref={this.emailsInput}
placeholder={this.props.intl.formatMessage({id: 'admin.compliance_reports.emails_placeholder', defaultMessage: 'E.g. "bill@example.com, bob@example.com"'})} placeholder={defineMessage({id: 'admin.compliance_reports.emails_placeholder', defaultMessage: 'E.g. "bill@example.com, bob@example.com"'})}
disabled={this.props.readOnly} disabled={this.props.readOnly}
/> />
</div> </div>
@@ -411,12 +410,12 @@ class ComplianceReports extends React.PureComponent<Props, State> {
defaultMessage='Keywords:' defaultMessage='Keywords:'
/> />
</label> </label>
<input <LocalizedPlaceholderInput
type='text' type='text'
className='form-control' className='form-control'
id='keywords' id='keywords'
ref={this.keywordsInput} ref={this.keywordsInput}
placeholder={this.props.intl.formatMessage({id: 'admin.compliance_reports.keywords_placeholder', defaultMessage: 'E.g. "shorting stock"'})} placeholder={defineMessage({id: 'admin.compliance_reports.keywords_placeholder', defaultMessage: 'E.g. "shorting stock"'})}
disabled={this.props.readOnly} disabled={this.props.readOnly}
/> />
</div> </div>
@@ -466,5 +465,3 @@ const style: Record<string, React.CSSProperties> = {
date: {whiteSpace: 'nowrap'}, date: {whiteSpace: 'nowrap'},
serverError: {marginTop: '10px'}, serverError: {marginTop: '10px'},
}; };
export default injectIntl(ComplianceReports);

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

@@ -3,10 +3,10 @@
import React from 'react'; import React from 'react';
import CustomURLSchemesSetting from 'components/admin_console/custom_url_schemes_setting';
import {mountWithIntl} from 'tests/helpers/intl-test-helper'; import {mountWithIntl} from 'tests/helpers/intl-test-helper';
import CustomURLSchemesSetting from './custom_url_schemes_setting';
describe('components/AdminConsole/CustomUrlSchemeSetting', () => { describe('components/AdminConsole/CustomUrlSchemeSetting', () => {
const baseProps = { const baseProps = {
id: 'MySetting', id: 'MySetting',

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

@@ -3,7 +3,9 @@
import React, {PureComponent} from 'react'; import React, {PureComponent} from 'react';
import type {ChangeEvent} from 'react'; import type {ChangeEvent} from 'react';
import {injectIntl, type IntlShape} from 'react-intl'; import {defineMessage, FormattedMessage} from 'react-intl';
import LocalizedPlaceholderInput from 'components/localized_placeholder_input';
import Setting from './setting'; import Setting from './setting';
@@ -13,15 +15,13 @@ type Props = {
onChange: (id: string, valueAsArray: string[]) => void; onChange: (id: string, valueAsArray: string[]) => void;
disabled: boolean; disabled: boolean;
setByEnv: boolean; setByEnv: boolean;
intl: IntlShape;
} }
type State = { type State = {
value: string; value: string;
} }
class CustomURLSchemesSetting extends export default class CustomURLSchemesSetting extends PureComponent<Props, State> {
PureComponent<Props, State> {
constructor(props: Props) { constructor(props: Props) {
super(props); super(props);
@@ -51,22 +51,26 @@ class CustomURLSchemesSetting extends
render() { render() {
return ( return (
<Setting <Setting
label={this.props.intl.formatMessage({ label={
id: 'admin.customization.customUrlSchemes', <FormattedMessage
defaultMessage: 'Custom URL Schemes:', id='admin.customization.customUrlSchemes'
})} defaultMessage='Custom URL Schemes:'
helpText={this.props.intl.formatMessage({ />
id: 'admin.customization.customUrlSchemesDesc', }
defaultMessage: 'Allows message text to link if it begins with any of the comma-separated URL schemes listed. By default, the following schemes will create links: "http", "https", "ftp", "tel", and "mailto".', helpText={
})} <FormattedMessage
id='admin.customization.customUrlSchemesDesc'
defaultMessage='Allows message text to link if it begins with any of the comma-separated URL schemes listed. By default, the following schemes will create links: "http", "https", "ftp", "tel", and "mailto".'
/>
}
inputId={this.props.id} inputId={this.props.id}
setByEnv={this.props.setByEnv} setByEnv={this.props.setByEnv}
> >
<input <LocalizedPlaceholderInput
id={this.props.id} id={this.props.id}
className='form-control' className='form-control'
type='text' type='text'
placeholder={this.props.intl.formatMessage({id: 'admin.customization.customUrlSchemesPlaceholder', defaultMessage: 'E.g.: "git,smtp"'})} placeholder={defineMessage({id: 'admin.customization.customUrlSchemesPlaceholder', defaultMessage: 'E.g.: "git,smtp"'})}
value={this.state.value} value={this.state.value}
onChange={this.handleChange} onChange={this.handleChange}
disabled={this.props.disabled || this.props.setByEnv} disabled={this.props.disabled || this.props.setByEnv}
@@ -75,5 +79,3 @@ class CustomURLSchemesSetting extends
); );
} }
} }
export default injectIntl(CustomURLSchemesSetting);

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

@@ -6,7 +6,6 @@ exports[`components/admin_console/data_grid/DataGrid should match snapshot while
> >
<DataGridSearch <DataGridSearch
onSearch={[Function]} onSearch={[Function]}
placeholder=""
term="" term=""
/> />
<DataGridHeader <DataGridHeader
@@ -35,7 +34,6 @@ exports[`components/admin_console/data_grid/DataGrid should match snapshot with
> >
<DataGridSearch <DataGridSearch
onSearch={[Function]} onSearch={[Function]}
placeholder=""
term="" term=""
/> />
<DataGridHeader <DataGridHeader
@@ -147,7 +145,6 @@ exports[`components/admin_console/data_grid/DataGrid should match snapshot with
> >
<DataGridSearch <DataGridSearch
onSearch={[Function]} onSearch={[Function]}
placeholder=""
term="" term=""
/> />
<DataGridHeader <DataGridHeader
@@ -247,7 +244,6 @@ exports[`components/admin_console/data_grid/DataGrid should match snapshot with
> >
<DataGridSearch <DataGridSearch
onSearch={[Function]} onSearch={[Function]}
placeholder=""
term="" term=""
/> />
<DataGridHeader <DataGridHeader

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

@@ -57,7 +57,6 @@ type Props = {
onSearch?: (term: string) => void; onSearch?: (term: string) => void;
term?: string; term?: string;
searchPlaceholder?: string;
extraComponent?: JSX.Element; extraComponent?: JSX.Element;
filterProps?: { filterProps?: {
options: FilterOptions; options: FilterOptions;
@@ -82,7 +81,6 @@ class DataGrid extends React.PureComponent<Props, State> {
static defaultProps = { static defaultProps = {
term: '', term: '',
searchPlaceholder: '',
}; };
public constructor(props: Props) { public constructor(props: Props) {
@@ -206,7 +204,6 @@ class DataGrid extends React.PureComponent<Props, State> {
return ( return (
<DataGridSearch <DataGridSearch
onSearch={this.search} onSearch={this.search}
placeholder={this.props.searchPlaceholder}
term={this.props.term} term={this.props.term}
filterProps={this.props.filterProps} filterProps={this.props.filterProps}
extraComponent={this.props.extraComponent} extraComponent={this.props.extraComponent}

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

@@ -2,18 +2,17 @@
// 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 Filter from 'components/admin_console/filter/filter'; import Filter from 'components/admin_console/filter/filter';
import type {FilterOptions} from 'components/admin_console/filter/filter'; import type {FilterOptions} from 'components/admin_console/filter/filter';
import LocalizedPlaceholderInput from 'components/localized_placeholder_input';
import FaSearchIcon from 'components/widgets/icons/fa_search_icon'; import FaSearchIcon from 'components/widgets/icons/fa_search_icon';
import * as Utils from 'utils/utils';
import './data_grid.scss'; import './data_grid.scss';
type Props = { type Props = {
onSearch: (term: string) => void; onSearch: (term: string) => void;
placeholder?: string;
term: string; term: string;
extraComponent?: JSX.Element; extraComponent?: JSX.Element;
@@ -30,7 +29,6 @@ type State = {
class DataGridSearch extends React.PureComponent<Props, State> { class DataGridSearch extends React.PureComponent<Props, State> {
static defaultProps = { static defaultProps = {
placeholder: '',
term: '', term: '',
}; };
@@ -59,11 +57,6 @@ class DataGridSearch extends React.PureComponent<Props, State> {
render() { render() {
const {filterProps} = this.props; const {filterProps} = this.props;
let {placeholder} = this.props;
if (!placeholder) {
placeholder = Utils.localizeMessage({id: 'search_bar.search', defaultMessage: 'Search'});
}
let filter; let filter;
if (filterProps) { if (filterProps) {
filter = <Filter {...filterProps}/>; filter = <Filter {...filterProps}/>;
@@ -79,9 +72,9 @@ class DataGridSearch extends React.PureComponent<Props, State> {
<FaSearchIcon/> <FaSearchIcon/>
</span> </span>
<input <LocalizedPlaceholderInput
type='text' type='text'
placeholder={Utils.localizeMessage({id: 'search_bar.search', defaultMessage: 'Search'})} placeholder={defineMessage({id: 'search_bar.search', defaultMessage: 'Search'})}
onChange={this.handleSearch} onChange={this.handleSearch}
value={this.props.term} value={this.props.term}
data-testid='searchInput' data-testid='searchInput'

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

@@ -134,7 +134,6 @@ exports[`components/admin_console/data_retention_settings/data_retention_setting
}, },
] ]
} }
searchPlaceholder=""
startCount={1} startCount={1}
term="" term=""
total={0} total={0}
@@ -283,7 +282,6 @@ exports[`components/admin_console/data_retention_settings/data_retention_setting
}, },
] ]
} }
searchPlaceholder=""
startCount={1} startCount={1}
term="" term=""
total={1} total={1}
@@ -514,7 +512,6 @@ exports[`components/admin_console/data_retention_settings/data_retention_setting
}, },
] ]
} }
searchPlaceholder=""
startCount={1} startCount={1}
term="" term=""
total={0} total={0}
@@ -668,7 +665,6 @@ exports[`components/admin_console/data_retention_settings/data_retention_setting
}, },
] ]
} }
searchPlaceholder=""
startCount={1} startCount={1}
term="" term=""
total={1} total={1}
@@ -899,7 +895,6 @@ exports[`components/admin_console/data_retention_settings/data_retention_setting
}, },
] ]
} }
searchPlaceholder=""
startCount={1} startCount={1}
term="" term=""
total={0} total={0}
@@ -1048,7 +1043,6 @@ exports[`components/admin_console/data_retention_settings/data_retention_setting
}, },
] ]
} }
searchPlaceholder=""
startCount={1} startCount={1}
term="" term=""
total={1} total={1}
@@ -1279,7 +1273,6 @@ exports[`components/admin_console/data_retention_settings/data_retention_setting
}, },
] ]
} }
searchPlaceholder=""
startCount={1} startCount={1}
term="" term=""
total={0} total={0}
@@ -1358,7 +1351,6 @@ exports[`components/admin_console/data_retention_settings/data_retention_setting
page={0} page={0}
previousPage={[Function]} previousPage={[Function]}
rows={Array []} rows={Array []}
searchPlaceholder=""
startCount={1} startCount={1}
term="" term=""
total={0} total={0}

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

@@ -139,7 +139,6 @@ exports[`components/admin_console/data_retention_settings/channel_list should ma
}, },
] ]
} }
searchPlaceholder=""
startCount={1} startCount={1}
term="" term=""
total={1} total={1}
@@ -592,7 +591,6 @@ exports[`components/admin_console/data_retention_settings/channel_list should ma
}, },
] ]
} }
searchPlaceholder=""
startCount={1} startCount={1}
term="" term=""
total={30} total={30}

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

@@ -60,7 +60,12 @@ exports[`components/admin_console/data_retention_settings/custom_policy_form sho
} }
name="policyName" name="policyName"
onChange={[Function]} onChange={[Function]}
placeholder="Policy name" placeholder={
Object {
"defaultMessage": "Policy name",
"id": "admin.data_retention.custom_policy.form.input",
}
}
type="text" type="text"
value="" value=""
/> />
@@ -89,7 +94,12 @@ exports[`components/admin_console/data_retention_settings/custom_policy_form sho
inputId="message_retention_input" inputId="message_retention_input"
inputType="number" inputType="number"
inputValue="" inputValue=""
legend="Channel & direct message retention" legend={
Object {
"defaultMessage": "Channel & direct message retention",
"id": "admin.data_retention.form.channelAndDirectMessageRetention",
}
}
name="message_retention" name="message_retention"
onDropdownChange={[Function]} onDropdownChange={[Function]}
onInputChange={[Function]} onInputChange={[Function]}
@@ -126,7 +136,12 @@ exports[`components/admin_console/data_retention_settings/custom_policy_form sho
}, },
] ]
} }
placeholder="Channel & direct message retention" placeholder={
Object {
"defaultMessage": "Channel & direct message retention",
"id": "admin.data_retention.form.channelAndDirectMessageRetention",
}
}
value={ value={
Object { Object {
"label": <div> "label": <div>
@@ -312,7 +327,12 @@ exports[`components/admin_console/data_retention_settings/custom_policy_form sho
} }
name="policyName" name="policyName"
onChange={[Function]} onChange={[Function]}
placeholder="Policy name" placeholder={
Object {
"defaultMessage": "Policy name",
"id": "admin.data_retention.custom_policy.form.input",
}
}
type="text" type="text"
value="" value=""
/> />
@@ -341,7 +361,12 @@ exports[`components/admin_console/data_retention_settings/custom_policy_form sho
inputId="message_retention_input" inputId="message_retention_input"
inputType="number" inputType="number"
inputValue="22" inputValue="22"
legend="Channel & direct message retention" legend={
Object {
"defaultMessage": "Channel & direct message retention",
"id": "admin.data_retention.form.channelAndDirectMessageRetention",
}
}
name="message_retention" name="message_retention"
onDropdownChange={[Function]} onDropdownChange={[Function]}
onInputChange={[Function]} onInputChange={[Function]}
@@ -378,7 +403,12 @@ exports[`components/admin_console/data_retention_settings/custom_policy_form sho
}, },
] ]
} }
placeholder="Channel & direct message retention" placeholder={
Object {
"defaultMessage": "Channel & direct message retention",
"id": "admin.data_retention.form.channelAndDirectMessageRetention",
}
}
value={ value={
Object { Object {
"label": <span "label": <span

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

@@ -2,7 +2,7 @@
// 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 {defineMessages, FormattedMessage} from 'react-intl';
import type {ChannelWithTeamData} from '@mattermost/types/channels'; import type {ChannelWithTeamData} from '@mattermost/types/channels';
import type { import type {
@@ -30,7 +30,6 @@ import Input from 'components/widgets/inputs/input/input';
import {getHistory} from 'utils/browser_history'; import {getHistory} from 'utils/browser_history';
import {ItemStatus} from 'utils/constants'; import {ItemStatus} from 'utils/constants';
import * as Utils from 'utils/utils';
import './custom_policy_form.scss'; import './custom_policy_form.scss';
@@ -66,8 +65,8 @@ type State = {
saveNeeded: boolean; saveNeeded: boolean;
saving: boolean; saving: boolean;
serverError: boolean; serverError: boolean;
inputErrorText: string; inputErrorText: React.ReactNode;
formErrorText: string; formErrorText: React.ReactNode;
} }
export default class CustomPolicyForm extends React.PureComponent<Props, State> { export default class CustomPolicyForm extends React.PureComponent<Props, State> {
@@ -235,7 +234,15 @@ export default class CustomPolicyForm extends React.PureComponent<Props, State>
let postDuration = parseInt(messageRetentionInputValue, 10); let postDuration = parseInt(messageRetentionInputValue, 10);
if (postDuration <= 0) { if (postDuration <= 0) {
this.setState({formErrorText: Utils.localizeMessage({id: 'admin.data_retention.custom_policy.form.durationInput.error', defaultMessage: 'Error parsing message retention.'}), saving: false}); this.setState({
formErrorText: (
<FormattedMessage
id='admin.data_retention.custom_policy.form.durationInput.error'
defaultMessage='Error parsing message retention.'
/>
),
saving: false,
});
return; return;
} }
if (messageRetentionDropdownValue.value === FOREVER) { if (messageRetentionDropdownValue.value === FOREVER) {
@@ -245,7 +252,15 @@ export default class CustomPolicyForm extends React.PureComponent<Props, State>
} }
if (!policyName?.trim()) { if (!policyName?.trim()) {
this.setState({inputErrorText: Utils.localizeMessage({id: 'admin.data_retention.custom_policy.form.input.error', defaultMessage: 'Policy name can\'t be blank.'}), saving: false}); this.setState({
inputErrorText: (
<FormattedMessage
id='admin.data_retention.custom_policy.form.input.error'
defaultMessage="Policy name can't be blank."
/>
),
saving: false,
});
return; return;
} }
@@ -256,7 +271,15 @@ export default class CustomPolicyForm extends React.PureComponent<Props, State>
}; };
if (((policy?.team_count + teamsToAdd.length) - teamsToRemove.length) === 0 && ((policy?.channel_count + channelsToAdd.length) - channelsToRemove.length) === 0) { if (((policy?.team_count + teamsToAdd.length) - teamsToRemove.length) === 0 && ((policy?.channel_count + channelsToAdd.length) - channelsToRemove.length) === 0) {
this.setState({formErrorText: Utils.localizeMessage({id: 'admin.data_retention.custom_policy.form.teamsError', defaultMessage: 'You must add a team or a channel to the policy.'}), saving: false}); this.setState({
formErrorText: (
<FormattedMessage
id='admin.data_retention.custom_policy.form.teamsError'
defaultMessage='You must add a team or a channel to the policy.'
/>
),
saving: false,
});
return; return;
} }
@@ -282,7 +305,15 @@ export default class CustomPolicyForm extends React.PureComponent<Props, State>
} }
} else { } else {
if (teamsToAdd.length < 1 && channelsToAdd.length < 1) { if (teamsToAdd.length < 1 && channelsToAdd.length < 1) {
this.setState({formErrorText: Utils.localizeMessage({id: 'admin.data_retention.custom_policy.form.teamsError', defaultMessage: 'You must add a team or a channel to the policy.'}), saving: false}); this.setState({
formErrorText: (
<FormattedMessage
id='admin.data_retention.custom_policy.form.teamsError'
defaultMessage='You must add a team or a channel to the policy.'
/>
),
saving: false,
});
return; return;
} }
const newPolicy = { const newPolicy = {
@@ -359,7 +390,7 @@ export default class CustomPolicyForm extends React.PureComponent<Props, State>
this.setState({policyName: e.target.value, saveNeeded: true}); this.setState({policyName: e.target.value, saveNeeded: true});
this.props.actions.setNavigationBlocked(true); this.props.actions.setNavigationBlocked(true);
}} }}
placeholder={Utils.localizeMessage({id: 'admin.data_retention.custom_policy.form.input', defaultMessage: 'Policy name'})} placeholder={messages.policyName}
customMessage={{type: ItemStatus.ERROR, value: this.state.inputErrorText}} customMessage={{type: ItemStatus.ERROR, value: this.state.inputErrorText}}
/> />
<DropdownInputHybrid <DropdownInputHybrid
@@ -379,8 +410,8 @@ export default class CustomPolicyForm extends React.PureComponent<Props, State>
exceptionToInput={[FOREVER]} exceptionToInput={[FOREVER]}
defaultValue={keepForeverOption()} defaultValue={keepForeverOption()}
options={[daysOption(), yearsOption(), keepForeverOption()]} options={[daysOption(), yearsOption(), keepForeverOption()]}
legend={Utils.localizeMessage({id: 'admin.data_retention.form.channelAndDirectMessageRetention', defaultMessage: 'Channel & direct message retention'})} legend={messages.channelAndDirectMessageRetention}
placeholder={Utils.localizeMessage({id: 'admin.data_retention.form.channelAndDirectMessageRetention', defaultMessage: 'Channel & direct message retention'})} placeholder={messages.channelAndDirectMessageRetention}
inputType={'number'} inputType={'number'}
name={'message_retention'} name={'message_retention'}
dropdownClassNamePrefix={'message_retention'} dropdownClassNamePrefix={'message_retention'}
@@ -535,3 +566,14 @@ export default class CustomPolicyForm extends React.PureComponent<Props, State>
); );
}; };
} }
const messages = defineMessages({
channelAndDirectMessageRetention: {
id: 'admin.data_retention.form.channelAndDirectMessageRetention',
defaultMessage: 'Channel & direct message retention',
},
policyName: {
id: 'admin.data_retention.custom_policy.form.input',
defaultMessage: 'Policy name',
},
});

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

@@ -33,7 +33,10 @@ exports[`components/PluginManagement should match snapshot 1`] = `
className="global_policy" className="global_policy"
> >
<p> <p>
Applies to all teams and channels, but does not apply to custom retention policies. <MemoizedFormattedMessage
defaultMessage="Applies to all teams and channels, but does not apply to custom retention policies."
id="admin.data_retention.form.text"
/>
</p> </p>
<div <div
id="global_direct_message_dropdown" id="global_direct_message_dropdown"
@@ -63,7 +66,12 @@ exports[`components/PluginManagement should match snapshot 1`] = `
inputId="channel_message_retention_input" inputId="channel_message_retention_input"
inputType="number" inputType="number"
inputValue="100" inputValue="100"
legend="Channel & direct message retention" legend={
Object {
"defaultMessage": "Channel & direct message retention",
"id": "admin.data_retention.form.channelAndDirectMessageRetention",
}
}
name="channel_message_retention" name="channel_message_retention"
onDropdownChange={[Function]} onDropdownChange={[Function]}
onInputChange={[Function]} onInputChange={[Function]}
@@ -108,7 +116,12 @@ exports[`components/PluginManagement should match snapshot 1`] = `
}, },
] ]
} }
placeholder="Channel & direct message retention" placeholder={
Object {
"defaultMessage": "Channel & direct message retention",
"id": "admin.data_retention.form.channelAndDirectMessageRetention",
}
}
value={ value={
Object { Object {
"label": <span "label": <span
@@ -150,7 +163,12 @@ exports[`components/PluginManagement should match snapshot 1`] = `
inputId="file_retention_input" inputId="file_retention_input"
inputType="number" inputType="number"
inputValue="100" inputValue="100"
legend="File retention" legend={
Object {
"defaultMessage": "File retention",
"id": "admin.data_retention.form.fileRetention",
}
}
name="file_retention" name="file_retention"
onDropdownChange={[Function]} onDropdownChange={[Function]}
onInputChange={[Function]} onInputChange={[Function]}
@@ -195,7 +213,12 @@ exports[`components/PluginManagement should match snapshot 1`] = `
}, },
] ]
} }
placeholder="File retention" placeholder={
Object {
"defaultMessage": "File retention",
"id": "admin.data_retention.form.fileRetention",
}
}
value={ value={
Object { Object {
"label": <span "label": <span

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

@@ -2,7 +2,7 @@
// 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 {defineMessages, FormattedMessage} from 'react-intl';
import type {AdminConfig, EnvironmentConfig} from '@mattermost/types/config'; import type {AdminConfig, EnvironmentConfig} from '@mattermost/types/config';
import type {DeepPartial} from '@mattermost/types/utilities'; import type {DeepPartial} from '@mattermost/types/utilities';
@@ -18,7 +18,6 @@ import AdminHeader from 'components/widgets/admin_console/admin_header';
import DropdownInputHybrid from 'components/widgets/inputs/dropdown_input_hybrid'; import DropdownInputHybrid from 'components/widgets/inputs/dropdown_input_hybrid';
import {getHistory} from 'utils/browser_history'; import {getHistory} from 'utils/browser_history';
import * as Utils from 'utils/utils';
import './global_policy_form.scss'; import './global_policy_form.scss';
@@ -43,8 +42,8 @@ type State = {
fileRetentionInputValue: string; fileRetentionInputValue: string;
saveNeeded: boolean; saveNeeded: boolean;
saving: boolean; saving: boolean;
serverError: JSX.Element | string | null; serverError: React.ReactNode;
formErrorText: string; formErrorText: React.ReactNode;
} }
export default class GlobalPolicyForm extends React.PureComponent<Props, State> { export default class GlobalPolicyForm extends React.PureComponent<Props, State> {
@@ -103,7 +102,15 @@ export default class GlobalPolicyForm extends React.PureComponent<Props, State>
this.setState({saving: true}); this.setState({saving: true});
if ((messageRetentionDropdownValue.value !== FOREVER && parseInt(messageRetentionInputValue, 10) < 1) || (fileRetentionDropdownValue.value !== FOREVER && parseInt(fileRetentionInputValue, 10) < 1)) { if ((messageRetentionDropdownValue.value !== FOREVER && parseInt(messageRetentionInputValue, 10) < 1) || (fileRetentionDropdownValue.value !== FOREVER && parseInt(fileRetentionInputValue, 10) < 1)) {
this.setState({formErrorText: Utils.localizeMessage({id: 'admin.data_retention.global_policy.form.numberError', defaultMessage: 'You must add a number greater than or equal to 1.'}), saving: false}); this.setState({
formErrorText: (
<FormattedMessage
id='admin.data_retention.global_policy.form.numberError'
defaultMessage='You must add a number greater than or equal to 1.'
/>
),
saving: false,
});
return; return;
} }
@@ -185,7 +192,12 @@ export default class GlobalPolicyForm extends React.PureComponent<Props, State>
<div <div
className='global_policy' className='global_policy'
> >
<p>{Utils.localizeMessage({id: 'admin.data_retention.form.text', defaultMessage: 'Applies to all teams and channels, but does not apply to custom retention policies.'})}</p> <p>
<FormattedMessage
id='admin.data_retention.form.text'
defaultMessage='Applies to all teams and channels, but does not apply to custom retention policies.'
/>
</p>
<div id='global_direct_message_dropdown'> <div id='global_direct_message_dropdown'>
<DropdownInputHybrid <DropdownInputHybrid
onDropdownChange={(value) => { onDropdownChange={(value) => {
@@ -205,8 +217,8 @@ export default class GlobalPolicyForm extends React.PureComponent<Props, State>
disabled={this.isMessageRetentionSetByEnv()} disabled={this.isMessageRetentionSetByEnv()}
defaultValue={keepForeverOption()} defaultValue={keepForeverOption()}
options={[hoursOption(), daysOption(), yearsOption(), keepForeverOption()]} options={[hoursOption(), daysOption(), yearsOption(), keepForeverOption()]}
legend={Utils.localizeMessage({id: 'admin.data_retention.form.channelAndDirectMessageRetention', defaultMessage: 'Channel & direct message retention'})} legend={messages.channelAndMessageRetention}
placeholder={Utils.localizeMessage({id: 'admin.data_retention.form.channelAndDirectMessageRetention', defaultMessage: 'Channel & direct message retention'})} placeholder={messages.channelAndMessageRetention}
name={'channel_message_retention'} name={'channel_message_retention'}
inputType={'number'} inputType={'number'}
dropdownClassNamePrefix={'channel_message_retention_dropdown'} dropdownClassNamePrefix={'channel_message_retention_dropdown'}
@@ -233,8 +245,8 @@ export default class GlobalPolicyForm extends React.PureComponent<Props, State>
disabled={this.isFileRetentionSetByEnv()} disabled={this.isFileRetentionSetByEnv()}
defaultValue={keepForeverOption()} defaultValue={keepForeverOption()}
options={[hoursOption(), daysOption(), yearsOption(), keepForeverOption()]} options={[hoursOption(), daysOption(), yearsOption(), keepForeverOption()]}
legend={Utils.localizeMessage({id: 'admin.data_retention.form.fileRetention', defaultMessage: 'File retention'})} legend={messages.fileRetention}
placeholder={Utils.localizeMessage({id: 'admin.data_retention.form.fileRetention', defaultMessage: 'File retention'})} placeholder={messages.fileRetention}
name={'file_retention'} name={'file_retention'}
inputType={'number'} inputType={'number'}
dropdownClassNamePrefix={'file_retention_dropdown'} dropdownClassNamePrefix={'file_retention_dropdown'}
@@ -287,3 +299,14 @@ export default class GlobalPolicyForm extends React.PureComponent<Props, State>
); );
}; };
} }
const messages = defineMessages({
channelAndMessageRetention: {
id: 'admin.data_retention.form.channelAndDirectMessageRetention',
defaultMessage: 'Channel & direct message retention',
},
fileRetention: {
id: 'admin.data_retention.form.fileRetention',
defaultMessage: 'File retention',
},
});

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

@@ -65,13 +65,15 @@ exports[`components/admin_console/data_retention_settings/team_list should match
id="remove-team-team-1" id="remove-team-team-1"
onClick={[Function]} onClick={[Function]}
> >
Remove <Memo(MemoizedFormattedMessage)
defaultMessage="Remove"
id="admin.data_retention.custom_policy.teams.remove"
/>
</a>, </a>,
}, },
}, },
] ]
} }
searchPlaceholder=""
startCount={1} startCount={1}
term="" term=""
total={1} total={1}
@@ -144,7 +146,10 @@ exports[`components/admin_console/data_retention_settings/team_list should match
id="remove-team-id0" id="remove-team-id0"
onClick={[Function]} onClick={[Function]}
> >
Remove <Memo(MemoizedFormattedMessage)
defaultMessage="Remove"
id="admin.data_retention.custom_policy.teams.remove"
/>
</a>, </a>,
}, },
}, },
@@ -180,7 +185,10 @@ exports[`components/admin_console/data_retention_settings/team_list should match
id="remove-team-id1" id="remove-team-id1"
onClick={[Function]} onClick={[Function]}
> >
Remove <Memo(MemoizedFormattedMessage)
defaultMessage="Remove"
id="admin.data_retention.custom_policy.teams.remove"
/>
</a>, </a>,
}, },
}, },
@@ -216,7 +224,10 @@ exports[`components/admin_console/data_retention_settings/team_list should match
id="remove-team-id2" id="remove-team-id2"
onClick={[Function]} onClick={[Function]}
> >
Remove <Memo(MemoizedFormattedMessage)
defaultMessage="Remove"
id="admin.data_retention.custom_policy.teams.remove"
/>
</a>, </a>,
}, },
}, },
@@ -252,7 +263,10 @@ exports[`components/admin_console/data_retention_settings/team_list should match
id="remove-team-id3" id="remove-team-id3"
onClick={[Function]} onClick={[Function]}
> >
Remove <Memo(MemoizedFormattedMessage)
defaultMessage="Remove"
id="admin.data_retention.custom_policy.teams.remove"
/>
</a>, </a>,
}, },
}, },
@@ -288,7 +302,10 @@ exports[`components/admin_console/data_retention_settings/team_list should match
id="remove-team-id4" id="remove-team-id4"
onClick={[Function]} onClick={[Function]}
> >
Remove <Memo(MemoizedFormattedMessage)
defaultMessage="Remove"
id="admin.data_retention.custom_policy.teams.remove"
/>
</a>, </a>,
}, },
}, },
@@ -324,7 +341,10 @@ exports[`components/admin_console/data_retention_settings/team_list should match
id="remove-team-id5" id="remove-team-id5"
onClick={[Function]} onClick={[Function]}
> >
Remove <Memo(MemoizedFormattedMessage)
defaultMessage="Remove"
id="admin.data_retention.custom_policy.teams.remove"
/>
</a>, </a>,
}, },
}, },
@@ -360,7 +380,10 @@ exports[`components/admin_console/data_retention_settings/team_list should match
id="remove-team-id6" id="remove-team-id6"
onClick={[Function]} onClick={[Function]}
> >
Remove <Memo(MemoizedFormattedMessage)
defaultMessage="Remove"
id="admin.data_retention.custom_policy.teams.remove"
/>
</a>, </a>,
}, },
}, },
@@ -396,7 +419,10 @@ exports[`components/admin_console/data_retention_settings/team_list should match
id="remove-team-id7" id="remove-team-id7"
onClick={[Function]} onClick={[Function]}
> >
Remove <Memo(MemoizedFormattedMessage)
defaultMessage="Remove"
id="admin.data_retention.custom_policy.teams.remove"
/>
</a>, </a>,
}, },
}, },
@@ -432,7 +458,10 @@ exports[`components/admin_console/data_retention_settings/team_list should match
id="remove-team-id8" id="remove-team-id8"
onClick={[Function]} onClick={[Function]}
> >
Remove <Memo(MemoizedFormattedMessage)
defaultMessage="Remove"
id="admin.data_retention.custom_policy.teams.remove"
/>
</a>, </a>,
}, },
}, },
@@ -468,13 +497,15 @@ exports[`components/admin_console/data_retention_settings/team_list should match
id="remove-team-id9" id="remove-team-id9"
onClick={[Function]} onClick={[Function]}
> >
Remove <Memo(MemoizedFormattedMessage)
defaultMessage="Remove"
id="admin.data_retention.custom_policy.teams.remove"
/>
</a>, </a>,
}, },
}, },
] ]
} }
searchPlaceholder=""
startCount={1} startCount={1}
term="" term=""
total={30} total={30}

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

@@ -199,7 +199,10 @@ export default class TeamList extends React.PureComponent<Props, State> {
}} }}
href='#' href='#'
> >
{Utils.localizeMessage({id: 'admin.data_retention.custom_policy.teams.remove', defaultMessage: 'Remove'})} <FormattedMessage
id='admin.data_retention.custom_policy.teams.remove'
defaultMessage='Remove'
/>
</a> </a>
), ),
}, },

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

@@ -20,7 +20,6 @@ import LoadingSpinner from 'components/widgets/loading/loading_spinner';
import {TELEMETRY_CATEGORIES, AboutLinks, LicenseLinks, LicenseSkus} from 'utils/constants'; import {TELEMETRY_CATEGORIES, AboutLinks, LicenseLinks, LicenseSkus} from 'utils/constants';
import {goToMattermostContactSalesForm} from 'utils/contact_support_sales'; import {goToMattermostContactSalesForm} from 'utils/contact_support_sales';
import * as Utils from 'utils/utils';
import type {ModalData} from 'types/actions'; import type {ModalData} from 'types/actions';
@@ -146,10 +145,6 @@ export default class FeatureDiscovery extends React.PureComponent<Props, State>
// by default we assume is not cloud, so the cta button is Start Trial (which will request a trial license) // by default we assume is not cloud, so the cta button is Start Trial (which will request a trial license)
let ctaPrimaryButton = ( let ctaPrimaryButton = (
<StartTrialBtn <StartTrialBtn
message={Utils.localizeMessage({
id: 'admin.ldap_feature_discovery.call_to_action.primary',
defaultMessage: 'Start trial',
})}
telemetryId={`start_self_hosted_trial_from_${this.props.featureName}`} telemetryId={`start_self_hosted_trial_from_${this.props.featureName}`}
btnClass='btn btn-primary' btnClass='btn btn-primary'
renderAsButton={true} renderAsButton={true}

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

@@ -10,10 +10,15 @@ exports[`components/admin_console/group_settings/GroupsList.tsx should match sna
<div <div
className="group-list-search" className="group-list-search"
> >
<input <LocalizedPlaceholderInput
onChange={[Function]} onChange={[Function]}
onKeyUp={[Function]} onKeyUp={[Function]}
placeholder="Search" placeholder={
Object {
"defaultMessage": "Search",
"id": "search_bar.search",
}
}
type="text" type="text"
value="" value=""
/> />
@@ -72,10 +77,15 @@ exports[`components/admin_console/group_settings/GroupsList.tsx should match sna
<div <div
className="group-list-search" className="group-list-search"
> >
<input <LocalizedPlaceholderInput
onChange={[Function]} onChange={[Function]}
onKeyUp={[Function]} onKeyUp={[Function]}
placeholder="Search" placeholder={
Object {
"defaultMessage": "Search",
"id": "search_bar.search",
}
}
type="text" type="text"
value="" value=""
/> />
@@ -209,10 +219,15 @@ exports[`components/admin_console/group_settings/GroupsList.tsx should match sna
<div <div
className="group-list-search" className="group-list-search"
> >
<input <LocalizedPlaceholderInput
onChange={[Function]} onChange={[Function]}
onKeyUp={[Function]} onKeyUp={[Function]}
placeholder="Search" placeholder={
Object {
"defaultMessage": "Search",
"id": "search_bar.search",
}
}
type="text" type="text"
value="" value=""
/> />
@@ -334,10 +349,15 @@ exports[`components/admin_console/group_settings/GroupsList.tsx should match sna
<div <div
className="group-list-search" className="group-list-search"
> >
<input <LocalizedPlaceholderInput
onChange={[Function]} onChange={[Function]}
onKeyUp={[Function]} onKeyUp={[Function]}
placeholder="Search" placeholder={
Object {
"defaultMessage": "Search",
"id": "search_bar.search",
}
}
type="text" type="text"
value="" value=""
/> />
@@ -459,10 +479,15 @@ exports[`components/admin_console/group_settings/GroupsList.tsx should match sna
<div <div
className="group-list-search" className="group-list-search"
> >
<input <LocalizedPlaceholderInput
onChange={[Function]} onChange={[Function]}
onKeyUp={[Function]} onKeyUp={[Function]}
placeholder="Search" placeholder={
Object {
"defaultMessage": "Search",
"id": "search_bar.search",
}
}
type="text" type="text"
value="" value=""
/> />
@@ -584,10 +609,15 @@ exports[`components/admin_console/group_settings/GroupsList.tsx should match sna
<div <div
className="group-list-search" className="group-list-search"
> >
<input <LocalizedPlaceholderInput
onChange={[Function]} onChange={[Function]}
onKeyUp={[Function]} onKeyUp={[Function]}
placeholder="Search" placeholder={
Object {
"defaultMessage": "Search",
"id": "search_bar.search",
}
}
type="text" type="text"
value="" value=""
/> />
@@ -744,10 +774,15 @@ exports[`components/admin_console/group_settings/GroupsList.tsx should match sna
<div <div
className="group-list-search" className="group-list-search"
> >
<input <LocalizedPlaceholderInput
onChange={[Function]} onChange={[Function]}
onKeyUp={[Function]} onKeyUp={[Function]}
placeholder="Search" placeholder={
Object {
"defaultMessage": "Search",
"id": "search_bar.search",
}
}
type="text" type="text"
value="" value=""
/> />
@@ -995,10 +1030,15 @@ exports[`components/admin_console/group_settings/GroupsList.tsx should match sna
<div <div
className="group-list-search" className="group-list-search"
> >
<input <LocalizedPlaceholderInput
onChange={[Function]} onChange={[Function]}
onKeyUp={[Function]} onKeyUp={[Function]}
placeholder="Search" placeholder={
Object {
"defaultMessage": "Search",
"id": "search_bar.search",
}
}
type="text" type="text"
value="" value=""
/> />
@@ -1246,10 +1286,15 @@ exports[`components/admin_console/group_settings/GroupsList.tsx should match sna
<div <div
className="group-list-search" className="group-list-search"
> >
<input <LocalizedPlaceholderInput
onChange={[Function]} onChange={[Function]}
onKeyUp={[Function]} onKeyUp={[Function]}
placeholder="Search" placeholder={
Object {
"defaultMessage": "Search",
"id": "search_bar.search",
}
}
type="text" type="text"
value="" value=""
/> />
@@ -1406,10 +1451,15 @@ exports[`components/admin_console/group_settings/GroupsList.tsx should match sna
<div <div
className="group-list-search" className="group-list-search"
> >
<input <LocalizedPlaceholderInput
onChange={[Function]} onChange={[Function]}
onKeyUp={[Function]} onKeyUp={[Function]}
placeholder="Search" placeholder={
Object {
"defaultMessage": "Search",
"id": "search_bar.search",
}
}
type="text" type="text"
value="" value=""
/> />
@@ -1469,10 +1519,15 @@ exports[`components/admin_console/group_settings/GroupsList.tsx should match sna
<div <div
className="group-list-search" className="group-list-search"
> >
<input <LocalizedPlaceholderInput
onChange={[Function]} onChange={[Function]}
onKeyUp={[Function]} onKeyUp={[Function]}
placeholder="Search" placeholder={
Object {
"defaultMessage": "Search",
"id": "search_bar.search",
}
}
type="text" type="text"
value="" value=""
/> />

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

@@ -2,20 +2,20 @@
// 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 {defineMessage, FormattedMessage} from 'react-intl';
import type {GroupSearchOpts, MixedUnlinkedGroupRedux} from '@mattermost/types/groups'; import type {GroupSearchOpts, MixedUnlinkedGroupRedux} from '@mattermost/types/groups';
import type {ActionResult} from 'mattermost-redux/types/actions'; import type {ActionResult} from 'mattermost-redux/types/actions';
import GroupRow from 'components/admin_console/group_settings/group_row'; import GroupRow from 'components/admin_console/group_settings/group_row';
import LocalizedPlaceholderInput from 'components/localized_placeholder_input';
import CheckboxCheckedIcon from 'components/widgets/icons/checkbox_checked_icon'; import CheckboxCheckedIcon from 'components/widgets/icons/checkbox_checked_icon';
import NextIcon from 'components/widgets/icons/fa_next_icon'; import NextIcon from 'components/widgets/icons/fa_next_icon';
import PreviousIcon from 'components/widgets/icons/fa_previous_icon'; import PreviousIcon from 'components/widgets/icons/fa_previous_icon';
import SearchIcon from 'components/widgets/icons/search_icon'; import SearchIcon from 'components/widgets/icons/search_icon';
import {Constants} from 'utils/constants'; import {Constants} from 'utils/constants';
import * as Utils from 'utils/utils';
const LDAP_GROUPS_PAGE_SIZE = 200; const LDAP_GROUPS_PAGE_SIZE = 200;
@@ -469,9 +469,9 @@ export default class GroupsList extends React.PureComponent<Props, State> {
<div className='groups-list'> <div className='groups-list'>
<div className='groups-list--global-actions'> <div className='groups-list--global-actions'>
<div className='group-list-search'> <div className='group-list-search'>
<input <LocalizedPlaceholderInput
type='text' type='text'
placeholder={Utils.localizeMessage({id: 'search_bar.search', defaultMessage: 'Search'})} placeholder={defineMessage({id: 'search_bar.search', defaultMessage: 'Search'})}
onKeyUp={(e: any) => this.handleGroupSearchKeyUp(e)} onKeyUp={(e: any) => this.handleGroupSearchKeyUp(e)}
onChange={(e) => this.setState({searchString: e.target.value})} onChange={(e) => this.setState({searchString: e.target.value})}
value={this.state.searchString} value={this.state.searchString}

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

@@ -3,7 +3,7 @@
import marked from 'marked'; import marked from 'marked';
import React, {useRef} from 'react'; import React, {useRef} from 'react';
import {FormattedDate, FormattedMessage} from 'react-intl'; import {defineMessage, FormattedDate, FormattedMessage} from 'react-intl';
import {useSelector, useDispatch} from 'react-redux'; import {useSelector, useDispatch} from 'react-redux';
import {GenericModal} from '@mattermost/components'; import {GenericModal} from '@mattermost/components';
@@ -25,7 +25,7 @@ import LoadingWrapper from 'components/widgets/loading/loading_wrapper';
import {FileTypes, ModalIdentifiers} from 'utils/constants'; import {FileTypes, ModalIdentifiers} from 'utils/constants';
import {getMonthLong} from 'utils/i18n'; import {getMonthLong} from 'utils/i18n';
import {getSkuDisplayName} from 'utils/subscription'; import {getSkuDisplayName} from 'utils/subscription';
import {fileSizeToString, localizeMessage} from 'utils/utils'; import {fileSizeToString} from 'utils/utils';
import type {GlobalState} from 'types/store'; import type {GlobalState} from 'types/store';
@@ -205,7 +205,7 @@ const UploadLicenseModal = (props: Props): JSX.Element | null => {
> >
<LoadingWrapper <LoadingWrapper
loading={Boolean(isUploading)} loading={Boolean(isUploading)}
text={localizeMessage({id: 'admin.license.modal.uploading', defaultMessage: 'Uploading'})} text={defineMessage({id: 'admin.license.modal.uploading', defaultMessage: 'Uploading'})}
> >
<FormattedMessage <FormattedMessage
id='admin.license.modal.upload' id='admin.license.modal.upload'

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

@@ -2,7 +2,7 @@
// 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, useIntl} from 'react-intl';
import type {Team, TeamMembership} from '@mattermost/types/teams'; import type {Team, TeamMembership} from '@mattermost/types/teams';
import type {UserProfile} from '@mattermost/types/users'; import type {UserProfile} from '@mattermost/types/users';
@@ -13,8 +13,6 @@ import {isAdmin, isSystemAdmin, isGuest} from 'mattermost-redux/utils/user_utils
import Menu from 'components/widgets/menu/menu'; import Menu from 'components/widgets/menu/menu';
import MenuWrapper from 'components/widgets/menu/menu_wrapper'; import MenuWrapper from 'components/widgets/menu/menu_wrapper';
import {localizeMessage} from 'utils/utils';
type Props = { type Props = {
team: Team; team: Team;
user: UserProfile; user: UserProfile;
@@ -26,6 +24,8 @@ type Props = {
} }
const ManageTeamsDropdown = (props: Props) => { const ManageTeamsDropdown = (props: Props) => {
const {formatMessage} = useIntl();
const makeTeamAdmin = async () => { const makeTeamAdmin = async () => {
const {error} = await props.updateTeamMemberSchemeRoles(props.teamMember.team_id, props.user.id, true, true); const {error} = await props.updateTeamMemberSchemeRoles(props.teamMember.team_id, props.user.id, true, true);
if (error) { if (error) {
@@ -62,13 +62,13 @@ const ManageTeamsDropdown = (props: Props) => {
const {team} = props; const {team} = props;
let title; let title;
if (isSysAdmin) { if (isSysAdmin) {
title = localizeMessage({id: 'admin.user_item.sysAdmin', defaultMessage: 'System Admin'}); title = formatMessage({id: 'admin.user_item.sysAdmin', defaultMessage: 'System Admin'});
} else if (isTeamAdmin) { } else if (isTeamAdmin) {
title = localizeMessage({id: 'admin.user_item.teamAdmin', defaultMessage: 'Team Admin'}); title = formatMessage({id: 'admin.user_item.teamAdmin', defaultMessage: 'Team Admin'});
} else if (isGuestUser) { } else if (isGuestUser) {
title = localizeMessage({id: 'admin.user_item.guest', defaultMessage: 'Guest'}); title = formatMessage({id: 'admin.user_item.guest', defaultMessage: 'Guest'});
} else { } else {
title = localizeMessage({id: 'admin.user_item.teamMember', defaultMessage: 'Team Member'}); title = formatMessage({id: 'admin.user_item.teamMember', defaultMessage: 'Team Member'});
} }
return ( return (
@@ -79,22 +79,22 @@ const ManageTeamsDropdown = (props: Props) => {
</a> </a>
<Menu <Menu
openLeft={true} openLeft={true}
ariaLabel={localizeMessage({id: 'team_members_dropdown.menuAriaLabel', defaultMessage: 'Change the role of a team member'})} ariaLabel={formatMessage({id: 'team_members_dropdown.menuAriaLabel', defaultMessage: 'Change the role of a team member'})}
> >
<Menu.ItemAction <Menu.ItemAction
show={!isTeamAdmin && !isGuestUser} show={!isTeamAdmin && !isGuestUser}
onClick={makeTeamAdmin} onClick={makeTeamAdmin}
text={localizeMessage({id: 'admin.user_item.makeTeamAdmin', defaultMessage: 'Make Team Admin'})} text={formatMessage({id: 'admin.user_item.makeTeamAdmin', defaultMessage: 'Make Team Admin'})}
/> />
<Menu.ItemAction <Menu.ItemAction
show={isTeamAdmin} show={isTeamAdmin}
onClick={makeMember} onClick={makeMember}
text={localizeMessage({id: 'admin.user_item.makeMember', defaultMessage: 'Make Team Member'})} text={formatMessage({id: 'admin.user_item.makeMember', defaultMessage: 'Make Team Member'})}
/> />
<Menu.ItemAction <Menu.ItemAction
show={!team.group_constrained} show={!team.group_constrained}
onClick={removeFromTeam} onClick={removeFromTeam}
text={localizeMessage({id: 'team_members_dropdown.leave_team', defaultMessage: 'Remove from Team'})} text={formatMessage({id: 'team_members_dropdown.leave_team', defaultMessage: 'Remove from Team'})}
/> />
</Menu> </Menu>
</MenuWrapper> </MenuWrapper>

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

@@ -512,7 +512,6 @@ exports[`admin_console/team_channel_settings/group/GroupList should match snapsh
}, },
] ]
} }
searchPlaceholder=""
startCount={1} startCount={1}
term="" term=""
total={15} total={15}
@@ -549,7 +548,6 @@ exports[`admin_console/team_channel_settings/group/GroupList should match snapsh
} }
previousPage={[Function]} previousPage={[Function]}
rows={Array []} rows={Array []}
searchPlaceholder=""
startCount={1} startCount={1}
term="" term=""
total={0} total={0}

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

@@ -1,6 +1,7 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import {shallow} from 'enzyme';
import React from 'react'; import React from 'react';
import type {ComponentProps} from 'react'; import type {ComponentProps} from 'react';
import type {RouteComponentProps} from 'react-router-dom'; import type {RouteComponentProps} from 'react-router-dom';
@@ -9,8 +10,6 @@ import type {Scheme} from '@mattermost/types/schemes';
import PermissionSchemesSettings from 'components/admin_console/permission_schemes_settings/permission_schemes_settings'; import PermissionSchemesSettings from 'components/admin_console/permission_schemes_settings/permission_schemes_settings';
import {shallowWithIntl} from 'tests/helpers/intl-test-helper';
describe('components/admin_console/permission_schemes_settings/permission_schemes_settings', () => { describe('components/admin_console/permission_schemes_settings/permission_schemes_settings', () => {
const defaultProps: ComponentProps<typeof PermissionSchemesSettings> = { const defaultProps: ComponentProps<typeof PermissionSchemesSettings> = {
schemes: { schemes: {
@@ -32,14 +31,14 @@ describe('components/admin_console/permission_schemes_settings/permission_scheme
}; };
test('should match snapshot loading', () => { test('should match snapshot loading', () => {
const wrapper = shallowWithIntl( const wrapper = shallow(
<PermissionSchemesSettings {...defaultProps}/>, <PermissionSchemesSettings {...defaultProps}/>,
); );
expect(wrapper).toMatchSnapshot(); expect(wrapper).toMatchSnapshot();
}); });
test('should match snapshot without schemes', () => { test('should match snapshot without schemes', () => {
const wrapper = shallowWithIntl( const wrapper = shallow(
<PermissionSchemesSettings <PermissionSchemesSettings
{...defaultProps} {...defaultProps}
schemes={{}} schemes={{}}
@@ -50,7 +49,7 @@ describe('components/admin_console/permission_schemes_settings/permission_scheme
}); });
test('should match snapshot with schemes', () => { test('should match snapshot with schemes', () => {
const wrapper = shallowWithIntl( const wrapper = shallow(
<PermissionSchemesSettings {...defaultProps}/>, <PermissionSchemesSettings {...defaultProps}/>,
); );
wrapper.setState({loading: false, phase2MigrationIsComplete: true}); wrapper.setState({loading: false, phase2MigrationIsComplete: true});
@@ -58,7 +57,7 @@ describe('components/admin_console/permission_schemes_settings/permission_scheme
}); });
test('should show migration in-progress view', () => { test('should show migration in-progress view', () => {
const wrapper = shallowWithIntl( const wrapper = shallow(
<PermissionSchemesSettings {...defaultProps}/>, <PermissionSchemesSettings {...defaultProps}/>,
); );
wrapper.setState({loading: false, phase2MigrationIsComplete: false}); wrapper.setState({loading: false, phase2MigrationIsComplete: false});
@@ -68,7 +67,7 @@ describe('components/admin_console/permission_schemes_settings/permission_scheme
test('should show migration on hold view', () => { test('should show migration on hold view', () => {
const testProps = {...defaultProps}; const testProps = {...defaultProps};
testProps.jobsAreEnabled = false; testProps.jobsAreEnabled = false;
const wrapper = shallowWithIntl( const wrapper = shallow(
<PermissionSchemesSettings {...testProps}/>, <PermissionSchemesSettings {...testProps}/>,
); );
wrapper.setState({loading: false, phase2MigrationIsComplete: false}); wrapper.setState({loading: false, phase2MigrationIsComplete: false});
@@ -78,7 +77,7 @@ describe('components/admin_console/permission_schemes_settings/permission_scheme
test('should show normal view (jobs disabled after migration)', () => { test('should show normal view (jobs disabled after migration)', () => {
const testProps = {...defaultProps}; const testProps = {...defaultProps};
testProps.jobsAreEnabled = false; testProps.jobsAreEnabled = false;
const wrapper = shallowWithIntl( const wrapper = shallow(
<PermissionSchemesSettings {...testProps}/>, <PermissionSchemesSettings {...testProps}/>,
); );
wrapper.setState({loading: false, phase2MigrationIsComplete: true}); wrapper.setState({loading: false, phase2MigrationIsComplete: true});

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

@@ -2,7 +2,7 @@
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import React from 'react'; import React from 'react';
import {injectIntl, type MessageDescriptor, type WrappedComponentProps} from 'react-intl'; import {type MessageDescriptor} from 'react-intl';
import {FormattedMessage, defineMessage, defineMessages} from 'react-intl'; import {FormattedMessage, defineMessage, defineMessages} from 'react-intl';
import type {RouteComponentProps} from 'react-router-dom'; import type {RouteComponentProps} from 'react-router-dom';
@@ -36,7 +36,7 @@ export type Props = {
loadSchemeTeams: (id: string) => Promise<ActionResult>; loadSchemeTeams: (id: string) => Promise<ActionResult>;
}; };
isDisabled?: boolean; isDisabled?: boolean;
} & WrappedComponentProps; };
type State = { type State = {
loading: boolean; loading: boolean;
@@ -69,7 +69,7 @@ export const searchableStrings = [
messages.teamOverrideSchemesNewButton, messages.teamOverrideSchemesNewButton,
]; ];
class PermissionSchemesSettings extends React.PureComponent<Props & RouteComponentProps, State> { export default class PermissionSchemesSettings extends React.PureComponent<Props & RouteComponentProps, State> {
constructor(props: Props & RouteComponentProps) { constructor(props: Props & RouteComponentProps) {
super(props); super(props);
this.state = { this.state = {
@@ -213,7 +213,7 @@ class PermissionSchemesSettings extends React.PureComponent<Props & RouteCompone
> >
<LoadingWrapper <LoadingWrapper
loading={this.state.loadingMore} loading={this.state.loadingMore}
text={this.props.intl.formatMessage({id: 'admin.permissions.loadingMoreSchemes', defaultMessage: 'Loading...'})} text={defineMessage({id: 'admin.permissions.loadingMoreSchemes', defaultMessage: 'Loading...'})}
> >
<FormattedMessage {...messages.loadMoreSchemes}/> <FormattedMessage {...messages.loadMoreSchemes}/>
</LoadingWrapper> </LoadingWrapper>
@@ -287,5 +287,3 @@ class PermissionSchemesSettings extends React.PureComponent<Props & RouteCompone
); );
}; };
} }
export default injectIntl(PermissionSchemesSettings);

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

@@ -99,11 +99,17 @@ exports[`components/admin_console/permission_schemes_settings/permission_team_sc
id="admin.permissions.teamScheme.schemeNameLabel" id="admin.permissions.teamScheme.schemeNameLabel"
/> />
</label> </label>
<input <LocalizedPlaceholderInput
className="form-control" className="form-control"
disabled={false} disabled={false}
id="scheme-name" id="scheme-name"
onChange={[Function]} onChange={[Function]}
placeholder={
Object {
"defaultMessage": "Scheme Name",
"id": "admin.permissions.teamScheme.schemeNamePlaceholder",
}
}
type="text" type="text"
value="Test scheme" value="Test scheme"
/> />
@@ -120,11 +126,17 @@ exports[`components/admin_console/permission_schemes_settings/permission_team_sc
id="admin.permissions.teamScheme.schemeDescriptionLabel" id="admin.permissions.teamScheme.schemeDescriptionLabel"
/> />
</label> </label>
<textarea <LocalizedPlaceholderTextarea
className="form-control" className="form-control"
disabled={false} disabled={false}
id="scheme-description" id="scheme-description"
onChange={[Function]} onChange={[Function]}
placeholder={
Object {
"defaultMessage": "Scheme Description",
"id": "admin.permissions.teamScheme.schemeDescriptionPlaceholder",
}
}
rows={5} rows={5}
value="Test scheme description" value="Test scheme description"
/> />
@@ -323,6 +335,12 @@ exports[`components/admin_console/permission_schemes_settings/permission_team_sc
disabled={true} disabled={true}
onClick={[Function]} onClick={[Function]}
saving={false} saving={false}
savingMessage={
<Memo(MemoizedFormattedMessage)
defaultMessage="Saving Config..."
id="admin.saving"
/>
}
/> />
<Connect(Component) <Connect(Component)
className="cancel-button" className="cancel-button"
@@ -459,11 +477,17 @@ exports[`components/admin_console/permission_schemes_settings/permission_team_sc
id="admin.permissions.teamScheme.schemeNameLabel" id="admin.permissions.teamScheme.schemeNameLabel"
/> />
</label> </label>
<input <LocalizedPlaceholderInput
className="form-control" className="form-control"
disabled={false} disabled={false}
id="scheme-name" id="scheme-name"
onChange={[Function]} onChange={[Function]}
placeholder={
Object {
"defaultMessage": "Scheme Name",
"id": "admin.permissions.teamScheme.schemeNamePlaceholder",
}
}
type="text" type="text"
value="Test scheme" value="Test scheme"
/> />
@@ -480,11 +504,17 @@ exports[`components/admin_console/permission_schemes_settings/permission_team_sc
id="admin.permissions.teamScheme.schemeDescriptionLabel" id="admin.permissions.teamScheme.schemeDescriptionLabel"
/> />
</label> </label>
<textarea <LocalizedPlaceholderTextarea
className="form-control" className="form-control"
disabled={false} disabled={false}
id="scheme-description" id="scheme-description"
onChange={[Function]} onChange={[Function]}
placeholder={
Object {
"defaultMessage": "Scheme Description",
"id": "admin.permissions.teamScheme.schemeDescriptionPlaceholder",
}
}
rows={5} rows={5}
value="Test scheme description" value="Test scheme description"
/> />
@@ -713,6 +743,12 @@ exports[`components/admin_console/permission_schemes_settings/permission_team_sc
disabled={true} disabled={true}
onClick={[Function]} onClick={[Function]}
saving={false} saving={false}
savingMessage={
<Memo(MemoizedFormattedMessage)
defaultMessage="Saving Config..."
id="admin.saving"
/>
}
/> />
<Connect(Component) <Connect(Component)
className="cancel-button" className="cancel-button"
@@ -849,11 +885,17 @@ exports[`components/admin_console/permission_schemes_settings/permission_team_sc
id="admin.permissions.teamScheme.schemeNameLabel" id="admin.permissions.teamScheme.schemeNameLabel"
/> />
</label> </label>
<input <LocalizedPlaceholderInput
className="form-control" className="form-control"
disabled={false} disabled={false}
id="scheme-name" id="scheme-name"
onChange={[Function]} onChange={[Function]}
placeholder={
Object {
"defaultMessage": "Scheme Name",
"id": "admin.permissions.teamScheme.schemeNamePlaceholder",
}
}
type="text" type="text"
value="Test scheme" value="Test scheme"
/> />
@@ -870,11 +912,17 @@ exports[`components/admin_console/permission_schemes_settings/permission_team_sc
id="admin.permissions.teamScheme.schemeDescriptionLabel" id="admin.permissions.teamScheme.schemeDescriptionLabel"
/> />
</label> </label>
<textarea <LocalizedPlaceholderTextarea
className="form-control" className="form-control"
disabled={false} disabled={false}
id="scheme-description" id="scheme-description"
onChange={[Function]} onChange={[Function]}
placeholder={
Object {
"defaultMessage": "Scheme Description",
"id": "admin.permissions.teamScheme.schemeDescriptionPlaceholder",
}
}
rows={5} rows={5}
value="Test scheme description" value="Test scheme description"
/> />
@@ -1105,6 +1153,12 @@ exports[`components/admin_console/permission_schemes_settings/permission_team_sc
disabled={true} disabled={true}
onClick={[Function]} onClick={[Function]}
saving={false} saving={false}
savingMessage={
<Memo(MemoizedFormattedMessage)
defaultMessage="Saving Config..."
id="admin.saving"
/>
}
/> />
<Connect(Component) <Connect(Component)
className="cancel-button" className="cancel-button"
@@ -1307,11 +1361,17 @@ exports[`components/admin_console/permission_schemes_settings/permission_team_sc
id="admin.permissions.teamScheme.schemeNameLabel" id="admin.permissions.teamScheme.schemeNameLabel"
/> />
</label> </label>
<input <LocalizedPlaceholderInput
className="form-control" className="form-control"
disabled={false} disabled={false}
id="scheme-name" id="scheme-name"
onChange={[Function]} onChange={[Function]}
placeholder={
Object {
"defaultMessage": "Scheme Name",
"id": "admin.permissions.teamScheme.schemeNamePlaceholder",
}
}
type="text" type="text"
value="" value=""
/> />
@@ -1328,11 +1388,17 @@ exports[`components/admin_console/permission_schemes_settings/permission_team_sc
id="admin.permissions.teamScheme.schemeDescriptionLabel" id="admin.permissions.teamScheme.schemeDescriptionLabel"
/> />
</label> </label>
<textarea <LocalizedPlaceholderTextarea
className="form-control" className="form-control"
disabled={false} disabled={false}
id="scheme-description" id="scheme-description"
onChange={[Function]} onChange={[Function]}
placeholder={
Object {
"defaultMessage": "Scheme Description",
"id": "admin.permissions.teamScheme.schemeDescriptionPlaceholder",
}
}
rows={5} rows={5}
value="" value=""
/> />
@@ -1563,6 +1629,12 @@ exports[`components/admin_console/permission_schemes_settings/permission_team_sc
disabled={true} disabled={true}
onClick={[Function]} onClick={[Function]}
saving={false} saving={false}
savingMessage={
<Memo(MemoizedFormattedMessage)
defaultMessage="Saving Config..."
id="admin.saving"
/>
}
/> />
<Connect(Component) <Connect(Component)
className="cancel-button" className="cancel-button"

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

@@ -1,13 +1,12 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import {shallow} from 'enzyme';
import React from 'react'; import React from 'react';
import Permissions from 'mattermost-redux/constants/permissions'; import Permissions from 'mattermost-redux/constants/permissions';
import PermissionTeamSchemeSettings from 'components/admin_console/permission_schemes_settings/permission_team_scheme_settings/permission_team_scheme_settings'; import PermissionTeamSchemeSettings from './permission_team_scheme_settings';
import {shallowWithIntl} from 'tests/helpers/intl-test-helper';
function getAnyInstance(wrapper: any) { function getAnyInstance(wrapper: any) {
return wrapper.instance() as any; return wrapper.instance() as any;
@@ -120,7 +119,7 @@ describe('components/admin_console/permission_schemes_settings/permission_team_s
} as any; } as any;
test('should match snapshot on new with default roles without permissions', (done) => { test('should match snapshot on new with default roles without permissions', (done) => {
const wrapper = shallowWithIntl( const wrapper = shallow(
<PermissionTeamSchemeSettings {...defaultProps}/>, <PermissionTeamSchemeSettings {...defaultProps}/>,
); );
defaultProps.actions.loadRolesIfNeeded().then(() => { defaultProps.actions.loadRolesIfNeeded().then(() => {
@@ -159,7 +158,7 @@ describe('components/admin_console/permission_schemes_settings/permission_team_s
permissions: ['delete_post'], permissions: ['delete_post'],
}, },
}; };
const wrapper = shallowWithIntl( const wrapper = shallow(
<PermissionTeamSchemeSettings <PermissionTeamSchemeSettings
{...defaultProps} {...defaultProps}
roles={roles} roles={roles}
@@ -191,7 +190,7 @@ describe('components/admin_console/permission_schemes_settings/permission_team_s
}, },
})); }));
const updateTeamScheme = jest.fn().mockImplementation(() => Promise.resolve({})); const updateTeamScheme = jest.fn().mockImplementation(() => Promise.resolve({}));
const wrapper = shallowWithIntl( const wrapper = shallow(
<PermissionTeamSchemeSettings <PermissionTeamSchemeSettings
{...defaultProps} {...defaultProps}
actions={{...defaultProps.actions, editRole, createScheme, updateTeamScheme}} actions={{...defaultProps.actions, editRole, createScheme, updateTeamScheme}}
@@ -207,7 +206,7 @@ describe('components/admin_console/permission_schemes_settings/permission_team_s
const editRole = jest.fn().mockImplementation(() => Promise.resolve({})); const editRole = jest.fn().mockImplementation(() => Promise.resolve({}));
const createScheme = jest.fn().mockImplementation(() => Promise.resolve({error: {message: 'test error'}})); const createScheme = jest.fn().mockImplementation(() => Promise.resolve({error: {message: 'test error'}}));
const updateTeamScheme = jest.fn().mockImplementation(() => Promise.resolve({})); const updateTeamScheme = jest.fn().mockImplementation(() => Promise.resolve({}));
const wrapper = shallowWithIntl( const wrapper = shallow(
<PermissionTeamSchemeSettings <PermissionTeamSchemeSettings
{...defaultProps} {...defaultProps}
actions={{...defaultProps.actions, editRole, createScheme, updateTeamScheme}} actions={{...defaultProps.actions, editRole, createScheme, updateTeamScheme}}
@@ -236,7 +235,7 @@ describe('components/admin_console/permission_schemes_settings/permission_team_s
}, },
})); }));
const updateTeamScheme = jest.fn().mockImplementation(() => Promise.resolve({})); const updateTeamScheme = jest.fn().mockImplementation(() => Promise.resolve({}));
const wrapper = shallowWithIntl( const wrapper = shallow(
<PermissionTeamSchemeSettings <PermissionTeamSchemeSettings
{...defaultProps} {...defaultProps}
actions={{...defaultProps.actions, editRole, createScheme, updateTeamScheme}} actions={{...defaultProps.actions, editRole, createScheme, updateTeamScheme}}
@@ -248,7 +247,7 @@ describe('components/admin_console/permission_schemes_settings/permission_team_s
}); });
test('should open and close correctly roles blocks', () => { test('should open and close correctly roles blocks', () => {
const wrapper = shallowWithIntl( const wrapper = shallow(
<PermissionTeamSchemeSettings {...defaultProps}/>, <PermissionTeamSchemeSettings {...defaultProps}/>,
); );
const instance = getAnyInstance(wrapper); const instance = getAnyInstance(wrapper);
@@ -299,7 +298,7 @@ describe('components/admin_console/permission_schemes_settings/permission_team_s
}, },
}; };
const wrapper = shallowWithIntl( const wrapper = shallow(
<PermissionTeamSchemeSettings {...props}/>, <PermissionTeamSchemeSettings {...props}/>,
); );
expect(wrapper).toMatchSnapshot(); expect(wrapper).toMatchSnapshot();
@@ -354,7 +353,7 @@ describe('components/admin_console/permission_schemes_settings/permission_team_s
}, },
}; };
const wrapper = shallowWithIntl( const wrapper = shallow(
<PermissionTeamSchemeSettings {...props}/>, <PermissionTeamSchemeSettings {...props}/>,
); );
expect(wrapper).toMatchSnapshot(); expect(wrapper).toMatchSnapshot();
@@ -389,7 +388,7 @@ describe('components/admin_console/permission_schemes_settings/permission_team_s
}, },
}; };
const wrapper = shallowWithIntl( const wrapper = shallow(
<PermissionTeamSchemeSettings {...props}/>, <PermissionTeamSchemeSettings {...props}/>,
); );
expect(wrapper).toMatchSnapshot(); expect(wrapper).toMatchSnapshot();
@@ -424,7 +423,7 @@ describe('components/admin_console/permission_schemes_settings/permission_team_s
}, },
}; };
const wrapper = shallowWithIntl( const wrapper = shallow(
<PermissionTeamSchemeSettings {...props}/>, <PermissionTeamSchemeSettings {...props}/>,
); );
expect(wrapper).toMatchSnapshot(); expect(wrapper).toMatchSnapshot();
@@ -435,7 +434,7 @@ describe('components/admin_console/permission_schemes_settings/permission_team_s
}); });
test('should set moderated permissions on team/channel admins', () => { test('should set moderated permissions on team/channel admins', () => {
const wrapper = shallowWithIntl( const wrapper = shallow(
<PermissionTeamSchemeSettings {...defaultProps}/>, <PermissionTeamSchemeSettings {...defaultProps}/>,
); );
const instance = getAnyInstance(wrapper); const instance = getAnyInstance(wrapper);

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

@@ -2,7 +2,7 @@
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import React from 'react'; import React from 'react';
import {defineMessage, FormattedMessage, injectIntl} from 'react-intl'; import {defineMessage, FormattedMessage} from 'react-intl';
import type {WrappedComponentProps} from 'react-intl'; import type {WrappedComponentProps} from 'react-intl';
import type {RouteComponentProps} from 'react-router-dom'; import type {RouteComponentProps} from 'react-router-dom';
@@ -18,6 +18,8 @@ import BlockableLink from 'components/admin_console/blockable_link';
import ExternalLink from 'components/external_link'; import ExternalLink from 'components/external_link';
import FormError from 'components/form_error'; import FormError from 'components/form_error';
import LoadingScreen from 'components/loading_screen'; import LoadingScreen from 'components/loading_screen';
import LocalizedPlaceholderInput from 'components/localized_placeholder_input';
import LocalizedPlaceholderTextarea from 'components/localized_placeholder_textarea';
import SaveButton from 'components/save_button'; import SaveButton from 'components/save_button';
import TeamSelectorModal from 'components/team_selector_modal'; import TeamSelectorModal from 'components/team_selector_modal';
import AdminHeader from 'components/widgets/admin_console/admin_header'; import AdminHeader from 'components/widgets/admin_console/admin_header';
@@ -79,7 +81,7 @@ type State = {
schemeDescription: string | undefined; schemeDescription: string | undefined;
}; };
class PermissionTeamSchemeSettings extends React.PureComponent<Props & RouteComponentProps, State> { export default class PermissionTeamSchemeSettings extends React.PureComponent<Props & RouteComponentProps, State> {
constructor(props: Props & RouteComponentProps) { constructor(props: Props & RouteComponentProps) {
super(props); super(props);
this.state = { this.state = {
@@ -642,11 +644,11 @@ class PermissionTeamSchemeSettings extends React.PureComponent<Props & RouteComp
defaultMessage='Scheme Name:' defaultMessage='Scheme Name:'
/> />
</label> </label>
<input <LocalizedPlaceholderInput
className='form-control' className='form-control'
disabled={this.props.isDisabled} disabled={this.props.isDisabled}
id='scheme-name' id='scheme-name'
placeholder={this.props.intl.formatMessage({id: 'admin.permissions.teamScheme.schemeNamePlaceholder', defaultMessage: 'Scheme Name'})} placeholder={defineMessage({id: 'admin.permissions.teamScheme.schemeNamePlaceholder', defaultMessage: 'Scheme Name'})}
type='text' type='text'
value={schemeName} value={schemeName}
onChange={this.handleNameChange} onChange={this.handleNameChange}
@@ -662,12 +664,12 @@ class PermissionTeamSchemeSettings extends React.PureComponent<Props & RouteComp
defaultMessage='Scheme Description:' defaultMessage='Scheme Description:'
/> />
</label> </label>
<textarea <LocalizedPlaceholderTextarea
id='scheme-description' id='scheme-description'
className='form-control' className='form-control'
rows={5} rows={5}
value={schemeDescription} value={schemeDescription}
placeholder={this.props.intl.formatMessage({id: 'admin.permissions.teamScheme.schemeDescriptionPlaceholder', defaultMessage: 'Scheme Description'})} placeholder={defineMessage({id: 'admin.permissions.teamScheme.schemeDescriptionPlaceholder', defaultMessage: 'Scheme Description'})}
onChange={this.handleDescriptionChange} onChange={this.handleDescriptionChange}
disabled={this.props.isDisabled} disabled={this.props.isDisabled}
/> />
@@ -799,7 +801,12 @@ class PermissionTeamSchemeSettings extends React.PureComponent<Props & RouteComp
saving={this.state.saving} saving={this.state.saving}
disabled={this.props.isDisabled || !this.state.saveNeeded} disabled={this.props.isDisabled || !this.state.saveNeeded}
onClick={this.handleSubmit} onClick={this.handleSubmit}
savingMessage={this.props.intl.formatMessage({id: 'admin.saving', defaultMessage: 'Saving Config...'})} savingMessage={
<FormattedMessage
id='admin.saving'
defaultMessage='Saving Config...'
/>
}
/> />
<BlockableLink <BlockableLink
className='cancel-button' className='cancel-button'
@@ -818,5 +825,3 @@ class PermissionTeamSchemeSettings extends React.PureComponent<Props & RouteComp
); );
}; };
} }
export default injectIntl(PermissionTeamSchemeSettings);

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

@@ -14,7 +14,12 @@ exports[`components/admin_console/permission_schemes_settings/permissions_scheme
confirmButtonText={ confirmButtonText={
<Memo(LoadingWrapper) <Memo(LoadingWrapper)
loading={false} loading={false}
text="Deleting..." text={
Object {
"defaultMessage": "Deleting...",
"id": "admin.permissions.permissionsSchemeSummary.deleting",
}
}
> >
<Memo(MemoizedFormattedMessage) <Memo(MemoizedFormattedMessage)
defaultMessage="Yes, Delete" defaultMessage="Yes, Delete"
@@ -132,7 +137,12 @@ exports[`components/admin_console/permission_schemes_settings/permissions_scheme
confirmButtonText={ confirmButtonText={
<Memo(LoadingWrapper) <Memo(LoadingWrapper)
loading={false} loading={false}
text="Deleting..." text={
Object {
"defaultMessage": "Deleting...",
"id": "admin.permissions.permissionsSchemeSummary.deleting",
}
}
> >
<Memo(MemoizedFormattedMessage) <Memo(MemoizedFormattedMessage)
defaultMessage="Yes, Delete" defaultMessage="Yes, Delete"
@@ -300,7 +310,12 @@ exports[`components/admin_console/permission_schemes_settings/permissions_scheme
confirmButtonText={ confirmButtonText={
<Memo(LoadingWrapper) <Memo(LoadingWrapper)
loading={false} loading={false}
text="Deleting..." text={
Object {
"defaultMessage": "Deleting...",
"id": "admin.permissions.permissionsSchemeSummary.deleting",
}
}
> >
<Memo(MemoizedFormattedMessage) <Memo(MemoizedFormattedMessage)
defaultMessage="Yes, Delete" defaultMessage="Yes, Delete"

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

@@ -2,7 +2,7 @@
// 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 {defineMessage, FormattedMessage} from 'react-intl';
import {Link} from 'react-router-dom'; import {Link} from 'react-router-dom';
import type {RouteComponentProps} from 'react-router-dom'; import type {RouteComponentProps} from 'react-router-dom';
@@ -15,8 +15,6 @@ import ConfirmModal from 'components/confirm_modal';
import LoadingWrapper from 'components/widgets/loading/loading_wrapper'; import LoadingWrapper from 'components/widgets/loading/loading_wrapper';
import WithTooltip from 'components/with_tooltip'; import WithTooltip from 'components/with_tooltip';
import * as Utils from 'utils/utils';
const MAX_TEAMS_PER_SCHEME_SUMMARY = 8; const MAX_TEAMS_PER_SCHEME_SUMMARY = 8;
export type Props = { export type Props = {
@@ -78,7 +76,7 @@ export default class PermissionsSchemeSummary extends React.PureComponent<Props
const confirmButton = ( const confirmButton = (
<LoadingWrapper <LoadingWrapper
loading={this.state.deleting} loading={this.state.deleting}
text={Utils.localizeMessage({id: 'admin.permissions.permissionsSchemeSummary.deleting', defaultMessage: 'Deleting...'})} text={defineMessage({id: 'admin.permissions.permissionsSchemeSummary.deleting', defaultMessage: 'Deleting...'})}
> >
<FormattedMessage <FormattedMessage
id='admin.permissions.permissionsSchemeSummary.deleteConfirmButton' id='admin.permissions.permissionsSchemeSummary.deleteConfirmButton'

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

@@ -99,7 +99,6 @@ exports[`admin_console/system_roles should match snapshot 1`] = `
}, },
] ]
} }
searchPlaceholder=""
startCount={0} startCount={0}
term="" term=""
/> />

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

@@ -57,8 +57,18 @@ exports[`admin_console/add_users_to_role_modal search should not include bot use
> >
<MultiSelect <MultiSelect
ariaLabelRenderer={[Function]} ariaLabelRenderer={[Function]}
buttonSubmitLoadingText="Adding..." buttonSubmitLoadingText={
buttonSubmitText="Add" Object {
"defaultMessage": "Adding...",
"id": "multiselect.adding",
}
}
buttonSubmitText={
Object {
"defaultMessage": "Add",
"id": "multiselect.add",
}
}
focusOnLoad={true} focusOnLoad={true}
handleAdd={[Function]} handleAdd={[Function]}
handleDelete={[Function]} handleDelete={[Function]}
@@ -168,7 +178,12 @@ exports[`admin_console/add_users_to_role_modal search should not include bot use
] ]
} }
perPage={50} perPage={50}
placeholderText="Search and add members" placeholderText={
Object {
"defaultMessage": "Search and add members",
"id": "multiselect.placeholder",
}
}
saveButtonPosition="top" saveButtonPosition="top"
saving={false} saving={false}
savingEnabled={true} savingEnabled={true}
@@ -237,8 +252,18 @@ exports[`admin_console/add_users_to_role_modal should exclude user 1`] = `
> >
<MultiSelect <MultiSelect
ariaLabelRenderer={[Function]} ariaLabelRenderer={[Function]}
buttonSubmitLoadingText="Adding..." buttonSubmitLoadingText={
buttonSubmitText="Add" Object {
"defaultMessage": "Adding...",
"id": "multiselect.adding",
}
}
buttonSubmitText={
Object {
"defaultMessage": "Add",
"id": "multiselect.add",
}
}
focusOnLoad={true} focusOnLoad={true}
handleAdd={[Function]} handleAdd={[Function]}
handleDelete={[Function]} handleDelete={[Function]}
@@ -304,7 +329,12 @@ exports[`admin_console/add_users_to_role_modal should exclude user 1`] = `
optionRenderer={[Function]} optionRenderer={[Function]}
options={Array []} options={Array []}
perPage={50} perPage={50}
placeholderText="Search and add members" placeholderText={
Object {
"defaultMessage": "Search and add members",
"id": "multiselect.placeholder",
}
}
saveButtonPosition="top" saveButtonPosition="top"
saving={false} saving={false}
savingEnabled={true} savingEnabled={true}
@@ -373,8 +403,18 @@ exports[`admin_console/add_users_to_role_modal should have single passed value 1
> >
<MultiSelect <MultiSelect
ariaLabelRenderer={[Function]} ariaLabelRenderer={[Function]}
buttonSubmitLoadingText="Adding..." buttonSubmitLoadingText={
buttonSubmitText="Add" Object {
"defaultMessage": "Adding...",
"id": "multiselect.adding",
}
}
buttonSubmitText={
Object {
"defaultMessage": "Add",
"id": "multiselect.add",
}
}
focusOnLoad={true} focusOnLoad={true}
handleAdd={[Function]} handleAdd={[Function]}
handleDelete={[Function]} handleDelete={[Function]}
@@ -484,7 +524,12 @@ exports[`admin_console/add_users_to_role_modal should have single passed value 1
] ]
} }
perPage={50} perPage={50}
placeholderText="Search and add members" placeholderText={
Object {
"defaultMessage": "Search and add members",
"id": "multiselect.placeholder",
}
}
saveButtonPosition="top" saveButtonPosition="top"
saving={false} saving={false}
savingEnabled={true} savingEnabled={true}
@@ -553,8 +598,18 @@ exports[`admin_console/add_users_to_role_modal should include additional user 1`
> >
<MultiSelect <MultiSelect
ariaLabelRenderer={[Function]} ariaLabelRenderer={[Function]}
buttonSubmitLoadingText="Adding..." buttonSubmitLoadingText={
buttonSubmitText="Add" Object {
"defaultMessage": "Adding...",
"id": "multiselect.adding",
}
}
buttonSubmitText={
Object {
"defaultMessage": "Add",
"id": "multiselect.add",
}
}
focusOnLoad={true} focusOnLoad={true}
handleAdd={[Function]} handleAdd={[Function]}
handleDelete={[Function]} handleDelete={[Function]}
@@ -705,7 +760,12 @@ exports[`admin_console/add_users_to_role_modal should include additional user 1`
] ]
} }
perPage={50} perPage={50}
placeholderText="Search and add members" placeholderText={
Object {
"defaultMessage": "Search and add members",
"id": "multiselect.placeholder",
}
}
saveButtonPosition="top" saveButtonPosition="top"
saving={false} saving={false}
savingEnabled={true} savingEnabled={true}
@@ -774,8 +834,18 @@ exports[`admin_console/add_users_to_role_modal should include additional user 2`
> >
<MultiSelect <MultiSelect
ariaLabelRenderer={[Function]} ariaLabelRenderer={[Function]}
buttonSubmitLoadingText="Adding..." buttonSubmitLoadingText={
buttonSubmitText="Add" Object {
"defaultMessage": "Adding...",
"id": "multiselect.adding",
}
}
buttonSubmitText={
Object {
"defaultMessage": "Add",
"id": "multiselect.add",
}
}
focusOnLoad={true} focusOnLoad={true}
handleAdd={[Function]} handleAdd={[Function]}
handleDelete={[Function]} handleDelete={[Function]}
@@ -926,7 +996,12 @@ exports[`admin_console/add_users_to_role_modal should include additional user 2`
] ]
} }
perPage={50} perPage={50}
placeholderText="Search and add members" placeholderText={
Object {
"defaultMessage": "Search and add members",
"id": "multiselect.placeholder",
}
}
saveButtonPosition="top" saveButtonPosition="top"
saving={false} saving={false}
savingEnabled={true} savingEnabled={true}
@@ -995,8 +1070,18 @@ exports[`admin_console/add_users_to_role_modal should not include bot user 1`] =
> >
<MultiSelect <MultiSelect
ariaLabelRenderer={[Function]} ariaLabelRenderer={[Function]}
buttonSubmitLoadingText="Adding..." buttonSubmitLoadingText={
buttonSubmitText="Add" Object {
"defaultMessage": "Adding...",
"id": "multiselect.adding",
}
}
buttonSubmitText={
Object {
"defaultMessage": "Add",
"id": "multiselect.add",
}
}
focusOnLoad={true} focusOnLoad={true}
handleAdd={[Function]} handleAdd={[Function]}
handleDelete={[Function]} handleDelete={[Function]}
@@ -1106,7 +1191,12 @@ exports[`admin_console/add_users_to_role_modal should not include bot user 1`] =
] ]
} }
perPage={50} perPage={50}
placeholderText="Search and add members" placeholderText={
Object {
"defaultMessage": "Search and add members",
"id": "multiselect.placeholder",
}
}
saveButtonPosition="top" saveButtonPosition="top"
saving={false} saving={false}
savingEnabled={true} savingEnabled={true}

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

@@ -4,7 +4,7 @@
import React from 'react'; import React from 'react';
import {Modal} from 'react-bootstrap'; import {Modal} from 'react-bootstrap';
import type {IntlShape} from 'react-intl'; import type {IntlShape} from 'react-intl';
import {injectIntl, FormattedMessage} from 'react-intl'; import {injectIntl, FormattedMessage, defineMessage} from 'react-intl';
import type {Role} from '@mattermost/types/roles'; import type {Role} from '@mattermost/types/roles';
import type {UserProfile} from '@mattermost/types/users'; import type {UserProfile} from '@mattermost/types/users';
@@ -20,7 +20,7 @@ import ProfilePicture from 'components/profile_picture';
import BotTag from 'components/widgets/tag/bot_tag'; import BotTag from 'components/widgets/tag/bot_tag';
import GuestTag from 'components/widgets/tag/guest_tag'; import GuestTag from 'components/widgets/tag/guest_tag';
import {displayEntireNameForUser, localizeMessage} from 'utils/utils'; import {displayEntireNameForUser} from 'utils/utils';
import {rolesStrings} from '../../strings'; import {rolesStrings} from '../../strings';
@@ -194,8 +194,8 @@ export class AddUsersToRoleModal extends React.PureComponent<Props, State> {
</div> </div>
); );
const buttonSubmitText = localizeMessage({id: 'multiselect.add', defaultMessage: 'Add'}); const buttonSubmitText = defineMessage({id: 'multiselect.add', defaultMessage: 'Add'});
const buttonSubmitLoadingText = localizeMessage({id: 'multiselect.adding', defaultMessage: 'Adding...'}); const buttonSubmitLoadingText = defineMessage({id: 'multiselect.adding', defaultMessage: 'Adding...'});
let addError = null; let addError = null;
if (this.state.addError) { if (this.state.addError) {
@@ -268,7 +268,7 @@ export class AddUsersToRoleModal extends React.PureComponent<Props, State> {
buttonSubmitLoadingText={buttonSubmitLoadingText} buttonSubmitLoadingText={buttonSubmitLoadingText}
saving={this.state.saving} saving={this.state.saving}
loading={this.state.loading} loading={this.state.loading}
placeholderText={localizeMessage({id: 'multiselect.placeholder', defaultMessage: 'Search and add members'})} placeholderText={defineMessage({id: 'multiselect.placeholder', defaultMessage: 'Search and add members'})}
/> />
</Modal.Body> </Modal.Body>
</Modal> </Modal>

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

@@ -361,7 +361,6 @@ exports[`admin_console/system_role_users should match snapshot 1`] = `
}, },
] ]
} }
searchPlaceholder=""
startCount={1} startCount={1}
term="asdfasdf" term="asdfasdf"
total={2} total={2}
@@ -730,7 +729,6 @@ exports[`admin_console/system_role_users should match snapshot with readOnly tru
}, },
] ]
} }
searchPlaceholder=""
startCount={1} startCount={1}
term="asdfasdf" term="asdfasdf"
total={2} total={2}

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

@@ -194,7 +194,6 @@ exports[`admin_console/team_channel_settings/channel/ChannelList should match sn
"minHeight": "40px", "minHeight": "40px",
} }
} }
searchPlaceholder=""
startCount={1} startCount={1}
term="" term=""
total={1} total={1}
@@ -801,7 +800,6 @@ exports[`admin_console/team_channel_settings/channel/ChannelList should match sn
"minHeight": "400px", "minHeight": "400px",
} }
} }
searchPlaceholder=""
startCount={1} startCount={1}
term="" term=""
total={30} total={30}
@@ -1007,7 +1005,6 @@ exports[`admin_console/team_channel_settings/channel/ChannelList should match sn
"minHeight": "40px", "minHeight": "40px",
} }
} }
searchPlaceholder=""
startCount={1} startCount={1}
term="" term=""
total={1} total={1}

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

@@ -98,7 +98,6 @@ exports[`components/admin_console/team_channel_settings/group/UsersToRemove shou
} }
previousPage={[Function]} previousPage={[Function]}
rows={Array []} rows={Array []}
searchPlaceholder=""
startCount={1} startCount={1}
term="" term=""
total={2} total={2}
@@ -204,7 +203,6 @@ exports[`components/admin_console/team_channel_settings/group/UsersToRemove shou
} }
previousPage={[Function]} previousPage={[Function]}
rows={Array []} rows={Array []}
searchPlaceholder=""
startCount={1} startCount={1}
term="foo" term="foo"
total={2} total={2}
@@ -310,7 +308,6 @@ exports[`components/admin_console/team_channel_settings/group/UsersToRemove shou
} }
previousPage={[Function]} previousPage={[Function]}
rows={Array []} rows={Array []}
searchPlaceholder=""
startCount={1} startCount={1}
term="" term=""
total={2} total={2}
@@ -408,7 +405,6 @@ exports[`components/admin_console/team_channel_settings/group/UsersToRemove shou
} }
previousPage={[Function]} previousPage={[Function]}
rows={Array []} rows={Array []}
searchPlaceholder=""
startCount={1} startCount={1}
term="" term=""
total={2} total={2}

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

@@ -140,7 +140,6 @@ exports[`admin_console/team_channel_settings/team/TeamList should match snapshot
"minHeight": "80px", "minHeight": "80px",
} }
} }
searchPlaceholder=""
startCount={1} startCount={1}
term="" term=""
total={1} total={1}
@@ -747,7 +746,6 @@ exports[`admin_console/team_channel_settings/team/TeamList should match snapshot
"minHeight": "800px", "minHeight": "800px",
} }
} }
searchPlaceholder=""
startCount={1} startCount={1}
term="" term=""
total={30} total={30}

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

@@ -368,7 +368,6 @@ exports[`components/admin_console/user_grid/UserGrid should match snapshot with
"minHeight": "160px", "minHeight": "160px",
} }
} }
searchPlaceholder=""
startCount={1} startCount={1}
term="" term=""
total={2} total={2}
@@ -896,7 +895,6 @@ exports[`components/admin_console/user_grid/UserGrid should match snapshot with
"minHeight": "240px", "minHeight": "240px",
} }
} }
searchPlaceholder=""
startCount={1} startCount={1}
term="" term=""
total={3} total={3}
@@ -1118,7 +1116,6 @@ exports[`components/admin_console/user_grid/UserGrid should match snapshot with
"minHeight": "80px", "minHeight": "80px",
} }
} }
searchPlaceholder=""
startCount={1} startCount={1}
term="" term=""
total={1} total={1}

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

@@ -208,7 +208,12 @@ exports[`AppsFormComponent should set match snapshot 1`] = `
id="appsModalSubmit" id="appsModalSubmit"
key="submit" key="submit"
spinning={false} spinning={false}
spinningText="Submitting..." spinningText={
Object {
"defaultMessage": "Submitting...",
"id": "interactive_dialog.submitting",
}
}
type="submit" type="submit"
> >
<MemoizedFormattedMessage <MemoizedFormattedMessage

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

@@ -3,7 +3,7 @@
import React from 'react'; import React from 'react';
import {Modal, Fade} from 'react-bootstrap'; import {Modal, Fade} from 'react-bootstrap';
import {FormattedMessage, injectIntl} from 'react-intl'; import {defineMessage, FormattedMessage, injectIntl} from 'react-intl';
import type {WrappedComponentProps} from 'react-intl'; import type {WrappedComponentProps} from 'react-intl';
import type {AppCallResponse, AppField, AppForm, AppFormValues, AppSelectOption, FormResponseData, AppLookupResponse, AppFormValue} from '@mattermost/types/apps'; import type {AppCallResponse, AppField, AppForm, AppFormValues, AppSelectOption, FormResponseData, AppLookupResponse, AppFormValue} from '@mattermost/types/apps';
@@ -21,7 +21,6 @@ import SuggestionList from 'components/suggestion/suggestion_list';
import LoadingSpinner from 'components/widgets/loading/loading_spinner'; import LoadingSpinner from 'components/widgets/loading/loading_spinner';
import {filterEmptyOptions} from 'utils/apps'; import {filterEmptyOptions} from 'utils/apps';
import {localizeMessage} from 'utils/utils';
import type {DoAppCallResult} from 'types/apps'; import type {DoAppCallResult} from 'types/apps';
@@ -518,7 +517,7 @@ export class AppsForm extends React.PureComponent<Props, State> {
autoFocus={!fields || fields.length === 0} autoFocus={!fields || fields.length === 0}
className='btn btn-primary save-button' className='btn btn-primary save-button'
spinning={Boolean(this.state.submitting)} spinning={Boolean(this.state.submitting)}
spinningText={localizeMessage({ spinningText={defineMessage({
id: 'interactive_dialog.submitting', id: 'interactive_dialog.submitting',
defaultMessage: 'Submitting...', defaultMessage: 'Submitting...',
})} })}

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

@@ -11,8 +11,6 @@ import NextIcon from 'components/widgets/icons/fa_next_icon';
import PreviousIcon from 'components/widgets/icons/fa_previous_icon'; import PreviousIcon from 'components/widgets/icons/fa_previous_icon';
import SearchIcon from 'components/widgets/icons/fa_search_icon'; import SearchIcon from 'components/widgets/icons/fa_search_icon';
import {localizeMessage} from 'utils/utils';
import './backstage_list.scss'; import './backstage_list.scss';
type Props = { type Props = {
@@ -51,13 +49,20 @@ const getPaging = (remainingProps: Props, childCount: number, hasFilter: boolean
return {startCount, endCount, total, isFirstPage, isLastPage}; return {startCount, endCount, total, isFirstPage, isLastPage};
}; };
const BackstageList = ({searchPlaceholder = localizeMessage({id: 'backstage_list.search', defaultMessage: 'Search'}), ...remainingProps}: Props) => { const BackstageList = (remainingProps: Props) => {
const {formatMessage} = useIntl(); const {formatMessage} = useIntl();
const [filter, setFilter] = useState(''); const [filter, setFilter] = useState('');
const updateFilter = (e: ChangeEvent<HTMLInputElement>) => setFilter(e.target.value); const updateFilter = (e: ChangeEvent<HTMLInputElement>) => setFilter(e.target.value);
const filterLowered = filter.toLowerCase(); const filterLowered = filter.toLowerCase();
let searchPlaceholder;
if (remainingProps.searchPlaceholder) {
searchPlaceholder = remainingProps.searchPlaceholder;
} else {
searchPlaceholder = formatMessage({id: 'backstage_list.search', defaultMessage: 'Search'});
}
let children = []; let children = [];
let childCount = 0; let childCount = 0;
if (remainingProps.loading) { if (remainingProps.loading) {

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

@@ -73,9 +73,19 @@ class ChannelGroupsManageModal extends React.PureComponent<Props> {
public renderRow = (item: Group, listModal: any) => { public renderRow = (item: Group, listModal: any) => {
let title; let title;
if (item.scheme_admin) { if (item.scheme_admin) {
title = Utils.localizeMessage({id: 'channel_members_dropdown.channel_admins', defaultMessage: 'Channel Admins'}); title = (
<FormattedMessage
id='channel_members_dropdown.channel_admins'
defaultMessage='Channel Admins'
/>
);
} else { } else {
title = Utils.localizeMessage({id: 'channel_members_dropdown.channel_members', defaultMessage: 'Channel Members'}); title = (
<FormattedMessage
id='channel_members_dropdown.channel_members'
defaultMessage='Channel Members'
/>
);
} }
return ( return (

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

@@ -2,19 +2,22 @@
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import React, {memo} from 'react'; import React, {memo} from 'react';
import {useIntl} from 'react-intl';
import {ChannelHeaderDropdownItems} from 'components/channel_header_dropdown'; import {ChannelHeaderDropdownItems} from 'components/channel_header_dropdown';
import Menu from 'components/widgets/menu/menu'; import Menu from 'components/widgets/menu/menu';
import {localizeMessage} from 'utils/utils'; const ChannelHeaderDropdown = () => {
const intl = useIntl();
const ChannelHeaderDropdown = () => ( return (
<Menu <Menu
id='channelHeaderDropdownMenu' id='channelHeaderDropdownMenu'
ariaLabel={localizeMessage({id: 'channel_header.menuAriaLabel', defaultMessage: 'Channel Menu'}).toLowerCase()} ariaLabel={intl.formatMessage({id: 'channel_header.menuAriaLabel', defaultMessage: 'Channel Menu'}).toLowerCase()}
> >
<ChannelHeaderDropdownItems isMobile={false}/> <ChannelHeaderDropdownItems isMobile={false}/>
</Menu> </Menu>
); );
};
export default memo(ChannelHeaderDropdown); export default memo(ChannelHeaderDropdown);

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

@@ -2,13 +2,12 @@
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import React from 'react'; import React from 'react';
import {useIntl} from 'react-intl';
import type {Channel} from '@mattermost/types/channels'; import type {Channel} from '@mattermost/types/channels';
import Menu from 'components/widgets/menu/menu'; import Menu from 'components/widgets/menu/menu';
import {localizeMessage} from 'utils/utils';
type Action = { type Action = {
closeRightHandSide: () => void; closeRightHandSide: () => void;
showChannelInfo: (channelId: string) => void; showChannelInfo: (channelId: string) => void;
@@ -22,6 +21,8 @@ type Props = {
}; };
const ToggleInfo = ({show, channel, rhsOpen, actions}: Props) => { const ToggleInfo = ({show, channel, rhsOpen, actions}: Props) => {
const intl = useIntl();
const toggleRHS = () => { const toggleRHS = () => {
if (rhsOpen) { if (rhsOpen) {
actions.closeRightHandSide(); actions.closeRightHandSide();
@@ -30,7 +31,12 @@ const ToggleInfo = ({show, channel, rhsOpen, actions}: Props) => {
actions.showChannelInfo(channel.id); actions.showChannelInfo(channel.id);
}; };
const text = rhsOpen ? localizeMessage({id: 'channelHeader.hideInfo', defaultMessage: 'Close Info'}) : localizeMessage({id: 'channelHeader.viewInfo', defaultMessage: 'View Info'}); let text;
if (rhsOpen) {
text = intl.formatMessage({id: 'channelHeader.hideInfo', defaultMessage: 'Close Info'});
} else {
text = intl.formatMessage({id: 'channelHeader.viewInfo', defaultMessage: 'View Info'});
}
return ( return (
<Menu.ItemAction <Menu.ItemAction

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

@@ -2,13 +2,12 @@
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import React from 'react'; import React from 'react';
import {useIntl} from 'react-intl';
import type {Channel} from '@mattermost/types/channels'; import type {Channel} from '@mattermost/types/channels';
import InfoIcon from 'components/widgets/icons/info_icon'; import InfoIcon from 'components/widgets/icons/info_icon';
import {localizeMessage} from 'utils/utils';
type Props = { type Props = {
channel: Channel; channel: Channel;
actions: { actions: {
@@ -16,17 +15,21 @@ type Props = {
}; };
}; };
const NavbarInfoButton: React.FunctionComponent<Props> = ({channel, actions}: Props): JSX.Element => ( const NavbarInfoButton: React.FunctionComponent<Props> = ({channel, actions}: Props): JSX.Element => {
<button const intl = useIntl();
className='navbar-toggle navbar-right__icon navbar-info-button pull-right'
aria-label={localizeMessage({id: 'accessibility.button.Info', defaultMessage: 'Info'})} return (
onClick={() => actions.showChannelInfo(channel.id)} <button
> className='navbar-toggle navbar-right__icon navbar-info-button pull-right'
<InfoIcon aria-label={intl.formatMessage({id: 'accessibility.button.Info', defaultMessage: 'Info'})}
className='icon icon__info' onClick={() => actions.showChannelInfo(channel.id)}
aria-hidden='true' >
/> <InfoIcon
</button> className='icon icon__info'
); aria-hidden='true'
/>
</button>
);
};
export default NavbarInfoButton; export default NavbarInfoButton;

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

@@ -2,11 +2,10 @@
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import React from 'react'; import React from 'react';
import {useIntl} from 'react-intl';
import SearchIcon from 'components/widgets/icons/search_icon'; import SearchIcon from 'components/widgets/icons/search_icon';
import {localizeMessage} from 'utils/utils';
type Actions = { type Actions = {
openRHSSearch: () => void; openRHSSearch: () => void;
} }
@@ -16,6 +15,8 @@ type Props = {
} }
const ShowSearchButton = ({actions}: Props) => { const ShowSearchButton = ({actions}: Props) => {
const intl = useIntl();
const handleClick = () => { const handleClick = () => {
actions.openRHSSearch(); actions.openRHSSearch();
}; };
@@ -25,7 +26,7 @@ const ShowSearchButton = ({actions}: Props) => {
type='button' type='button'
className='navbar-toggle navbar-right__icon navbar-search pull-right' className='navbar-toggle navbar-right__icon navbar-search pull-right'
onClick={handleClick} onClick={handleClick}
aria-label={localizeMessage({id: 'accessibility.button.Search', defaultMessage: 'Search'})} aria-label={intl.formatMessage({id: 'accessibility.button.Search', defaultMessage: 'Search'})}
> >
<SearchIcon <SearchIcon
className='icon icon__search' className='icon icon__search'

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

@@ -66,6 +66,24 @@ exports[`components/channel_invite_modal should match snapshot for channel_invit
ariaLabelRenderer={[Function]} ariaLabelRenderer={[Function]}
backButtonClass="btn-tertiary tertiary-button" backButtonClass="btn-tertiary tertiary-button"
backButtonClick={[Function]} backButtonClick={[Function]}
backButtonText={
Object {
"defaultMessage": "Cancel",
"id": "multiselect.cancel",
}
}
buttonSubmitLoadingText={
Object {
"defaultMessage": "Adding...",
"id": "multiselect.adding",
}
}
buttonSubmitText={
Object {
"defaultMessage": "Add",
"id": "multiselect.add",
}
}
customNoOptionsMessage={null} customNoOptionsMessage={null}
focusOnLoad={true} focusOnLoad={true}
handleAdd={[Function]} handleAdd={[Function]}
@@ -117,6 +135,12 @@ exports[`components/channel_invite_modal should match snapshot for channel_invit
optionRenderer={[Function]} optionRenderer={[Function]}
options={Array []} options={Array []}
perPage={50} perPage={50}
placeholderText={
Object {
"defaultMessage": "Search for people or groups",
"id": "multiselect.placeholder.peopleOrGroups",
}
}
saveButtonPosition="bottom" saveButtonPosition="bottom"
saving={false} saving={false}
savingEnabled={true} savingEnabled={true}
@@ -204,6 +228,24 @@ exports[`components/channel_invite_modal should match snapshot for channel_invit
ariaLabelRenderer={[Function]} ariaLabelRenderer={[Function]}
backButtonClass="btn-tertiary tertiary-button" backButtonClass="btn-tertiary tertiary-button"
backButtonClick={[Function]} backButtonClick={[Function]}
backButtonText={
Object {
"defaultMessage": "Cancel",
"id": "multiselect.cancel",
}
}
buttonSubmitLoadingText={
Object {
"defaultMessage": "Adding...",
"id": "multiselect.adding",
}
}
buttonSubmitText={
Object {
"defaultMessage": "Add",
"id": "multiselect.add",
}
}
customNoOptionsMessage={null} customNoOptionsMessage={null}
focusOnLoad={true} focusOnLoad={true}
handleAdd={[Function]} handleAdd={[Function]}
@@ -255,6 +297,12 @@ exports[`components/channel_invite_modal should match snapshot for channel_invit
optionRenderer={[Function]} optionRenderer={[Function]}
options={Array []} options={Array []}
perPage={50} perPage={50}
placeholderText={
Object {
"defaultMessage": "Search for people or groups",
"id": "multiselect.placeholder.peopleOrGroups",
}
}
saveButtonPosition="bottom" saveButtonPosition="bottom"
saving={false} saving={false}
savingEnabled={true} savingEnabled={true}
@@ -364,6 +412,24 @@ exports[`components/channel_invite_modal should match snapshot with exclude and
ariaLabelRenderer={[Function]} ariaLabelRenderer={[Function]}
backButtonClass="btn-tertiary tertiary-button" backButtonClass="btn-tertiary tertiary-button"
backButtonClick={[Function]} backButtonClick={[Function]}
backButtonText={
Object {
"defaultMessage": "Cancel",
"id": "multiselect.cancel",
}
}
buttonSubmitLoadingText={
Object {
"defaultMessage": "Adding...",
"id": "multiselect.adding",
}
}
buttonSubmitText={
Object {
"defaultMessage": "Add",
"id": "multiselect.add",
}
}
customNoOptionsMessage={null} customNoOptionsMessage={null}
focusOnLoad={true} focusOnLoad={true}
handleAdd={[Function]} handleAdd={[Function]}
@@ -415,6 +481,12 @@ exports[`components/channel_invite_modal should match snapshot with exclude and
optionRenderer={[Function]} optionRenderer={[Function]}
options={Array []} options={Array []}
perPage={50} perPage={50}
placeholderText={
Object {
"defaultMessage": "Search for people or groups",
"id": "multiselect.placeholder.peopleOrGroups",
}
}
saveButtonPosition="bottom" saveButtonPosition="bottom"
saving={false} saving={false}
savingEnabled={true} savingEnabled={true}

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

@@ -22,7 +22,6 @@ jest.mock('utils/utils', () => {
const original = jest.requireActual('utils/utils'); const original = jest.requireActual('utils/utils');
return { return {
...original, ...original,
localizeMessage: jest.fn(),
sortUsersAndGroups: jest.fn(), sortUsersAndGroups: jest.fn(),
}; };
}); });

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

@@ -5,7 +5,7 @@ import isEqual from 'lodash/isEqual';
import React from 'react'; import React from 'react';
import {Modal} from 'react-bootstrap'; import {Modal} from 'react-bootstrap';
import type {IntlShape} from 'react-intl'; import type {IntlShape} from 'react-intl';
import {injectIntl, FormattedMessage} from 'react-intl'; import {injectIntl, FormattedMessage, defineMessage} from 'react-intl';
import styled from 'styled-components'; import styled from 'styled-components';
import type {Channel} from '@mattermost/types/channels'; import type {Channel} from '@mattermost/types/channels';
@@ -28,7 +28,7 @@ import BotTag from 'components/widgets/tag/bot_tag';
import GuestTag from 'components/widgets/tag/guest_tag'; import GuestTag from 'components/widgets/tag/guest_tag';
import Constants, {ModalIdentifiers} from 'utils/constants'; import Constants, {ModalIdentifiers} from 'utils/constants';
import {localizeMessage, sortUsersAndGroups} from 'utils/utils'; import {sortUsersAndGroups} from 'utils/utils';
import GroupOption from './group_option'; import GroupOption from './group_option';
import TeamWarningBanner from './team_warning_banner'; import TeamWarningBanner from './team_warning_banner';
@@ -454,8 +454,8 @@ export class ChannelInviteModal extends React.PureComponent<Props, State> {
inviteError = (<label className='has-error control-label'>{this.state.inviteError}</label>); inviteError = (<label className='has-error control-label'>{this.state.inviteError}</label>);
} }
const buttonSubmitText = localizeMessage({id: 'multiselect.add', defaultMessage: 'Add'}); const buttonSubmitText = defineMessage({id: 'multiselect.add', defaultMessage: 'Add'});
const buttonSubmitLoadingText = localizeMessage({id: 'multiselect.adding', defaultMessage: 'Adding...'}); const buttonSubmitLoadingText = defineMessage({id: 'multiselect.adding', defaultMessage: 'Adding...'});
const closeMembersInviteModal = () => { const closeMembersInviteModal = () => {
this.props.actions.closeModal(ModalIdentifiers.CHANNEL_INVITE); this.props.actions.closeModal(ModalIdentifiers.CHANNEL_INVITE);
@@ -517,9 +517,9 @@ export class ChannelInviteModal extends React.PureComponent<Props, State> {
buttonSubmitLoadingText={buttonSubmitLoadingText} buttonSubmitLoadingText={buttonSubmitLoadingText}
saving={this.state.saving} saving={this.state.saving}
loading={this.state.loadingUsers} loading={this.state.loadingUsers}
placeholderText={this.props.isGroupsEnabled ? localizeMessage({id: 'multiselect.placeholder.peopleOrGroups', defaultMessage: 'Search for people or groups'}) : localizeMessage({id: 'multiselect.placeholder', defaultMessage: 'Search for people'})} placeholderText={this.props.isGroupsEnabled ? defineMessage({id: 'multiselect.placeholder.peopleOrGroups', defaultMessage: 'Search for people or groups'}) : defineMessage({id: 'multiselect.placeholder', defaultMessage: 'Search for people'})}
valueWithImage={true} valueWithImage={true}
backButtonText={localizeMessage({id: 'multiselect.cancel', defaultMessage: 'Cancel'})} backButtonText={defineMessage({id: 'multiselect.cancel', defaultMessage: 'Cancel'})}
backButtonClick={closeMembersInviteModal} backButtonClick={closeMembersInviteModal}
backButtonClass={'btn-tertiary tertiary-button'} backButtonClass={'btn-tertiary tertiary-button'}
customNoOptionsMessage={this.props.emailInvitationsEnabled ? customNoOptionsMessage : null} customNoOptionsMessage={this.props.emailInvitationsEnabled ? customNoOptionsMessage : null}

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

@@ -2,7 +2,7 @@
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import React, {useState} from 'react'; import React, {useState} from 'react';
import {FormattedMessage} from 'react-intl'; import {FormattedMessage, useIntl} from 'react-intl';
import {useDispatch} from 'react-redux'; import {useDispatch} from 'react-redux';
import type {Channel, ChannelMembership} from '@mattermost/types/channels'; import type {Channel, ChannelMembership} from '@mattermost/types/channels';
@@ -17,7 +17,6 @@ import Menu from 'components/widgets/menu/menu';
import MenuWrapper from 'components/widgets/menu/menu_wrapper'; import MenuWrapper from 'components/widgets/menu/menu_wrapper';
import {Constants, ModalIdentifiers} from 'utils/constants'; import {Constants, ModalIdentifiers} from 'utils/constants';
import * as Utils from 'utils/utils';
import type {ModalData} from 'types/actions'; import type {ModalData} from 'types/actions';
@@ -58,6 +57,8 @@ export default function ChannelMembersDropdown({
guestLabel, guestLabel,
actions, actions,
}: Props) { }: Props) {
const intl = useIntl();
const [removing, setRemoving] = useState(false); const [removing, setRemoving] = useState(false);
const [serverError, setServerError] = useState<string | null>(null); const [serverError, setServerError] = useState<string | null>(null);
const dispatch = useDispatch(); const dispatch = useDispatch();
@@ -159,7 +160,7 @@ export default function ChannelMembersDropdown({
const canMakeUserChannelMember = canChangeMemberRoles && isChannelAdmin; const canMakeUserChannelMember = canChangeMemberRoles && isChannelAdmin;
const canMakeUserChannelAdmin = canChangeMemberRoles && isMember; const canMakeUserChannelAdmin = canChangeMemberRoles && isMember;
const canRemoveUserFromChannel = canRemoveMember && (!channel.group_constrained || user.is_bot) && (!isDefaultChannel || isGuest); const canRemoveUserFromChannel = canRemoveMember && (!channel.group_constrained || user.is_bot) && (!isDefaultChannel || isGuest);
const removeFromChannelText = user.id === currentUserId ? Utils.localizeMessage({id: 'channel_header.leave', defaultMessage: 'Leave Channel'}) : Utils.localizeMessage({id: 'channel_members_dropdown.remove_from_channel', defaultMessage: 'Remove from Channel'}); const removeFromChannelText = user.id === currentUserId ? intl.formatMessage({id: 'channel_header.leave', defaultMessage: 'Leave Channel'}) : intl.formatMessage({id: 'channel_members_dropdown.remove_from_channel', defaultMessage: 'Remove from Channel'});
const removeFromChannelTestId = user.id === currentUserId ? 'leaveChannel' : 'removeFromChannel'; const removeFromChannelTestId = user.id === currentUserId ? 'leaveChannel' : 'removeFromChannel';
if (canMakeUserChannelMember || canMakeUserChannelAdmin || canRemoveUserFromChannel) { if (canMakeUserChannelMember || canMakeUserChannelAdmin || canRemoveUserFromChannel) {
@@ -177,7 +178,7 @@ export default function ChannelMembersDropdown({
id={`${user.username}-make-channel-admin`} id={`${user.username}-make-channel-admin`}
show={canMakeUserChannelAdmin} show={canMakeUserChannelAdmin}
onClick={handleMakeChannelAdmin} onClick={handleMakeChannelAdmin}
text={Utils.localizeMessage({id: 'channel_members_dropdown.make_channel_admin', defaultMessage: 'Make Channel Admin'})} text={intl.formatMessage({id: 'channel_members_dropdown.make_channel_admin', defaultMessage: 'Make Channel Admin'})}
/> />
); );
const makeMemberMenu = ( const makeMemberMenu = (
@@ -185,7 +186,7 @@ export default function ChannelMembersDropdown({
id={`${user.username}-make-channel-member`} id={`${user.username}-make-channel-member`}
show={canMakeUserChannelMember} show={canMakeUserChannelMember}
onClick={handleMakeChannelMember} onClick={handleMakeChannelMember}
text={Utils.localizeMessage({id: 'channel_members_dropdown.make_channel_member', defaultMessage: 'Make Channel Member'})} text={intl.formatMessage({id: 'channel_members_dropdown.make_channel_member', defaultMessage: 'Make Channel Member'})}
/> />
); );
return ( return (
@@ -201,7 +202,7 @@ export default function ChannelMembersDropdown({
<Menu <Menu
openLeft={true} openLeft={true}
openUp={totalUsers > ROWS_FROM_BOTTOM_TO_OPEN_UP && totalUsers - index <= ROWS_FROM_BOTTOM_TO_OPEN_UP} openUp={totalUsers > ROWS_FROM_BOTTOM_TO_OPEN_UP && totalUsers - index <= ROWS_FROM_BOTTOM_TO_OPEN_UP}
ariaLabel={Utils.localizeMessage({id: 'channel_members_dropdown.menuAriaLabel', defaultMessage: 'Change the role of channel member'})} ariaLabel={intl.formatMessage({id: 'channel_members_dropdown.menuAriaLabel', defaultMessage: 'Change the role of channel member'})}
> >
{canMakeUserChannelMember ? makeMemberMenu : null} {canMakeUserChannelMember ? makeMemberMenu : null}
{canMakeUserChannelAdmin ? makeAdminMenu : null} {canMakeUserChannelAdmin ? makeAdminMenu : null}

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

@@ -2,6 +2,7 @@
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import React, {useCallback, useEffect, useRef, useState} from 'react'; import React, {useCallback, useEffect, useRef, useState} from 'react';
import type {IntlShape} from 'react-intl';
import {useIntl} from 'react-intl'; import {useIntl} from 'react-intl';
import {useSelector} from 'react-redux'; import {useSelector} from 'react-redux';
@@ -15,7 +16,7 @@ import URLInput from 'components/widgets/inputs/url_input/url_input';
import Constants from 'utils/constants'; import Constants from 'utils/constants';
import {cleanUpUrlable, getSiteURL, validateChannelUrl} from 'utils/url'; import {cleanUpUrlable, getSiteURL, validateChannelUrl} from 'utils/url';
import {generateSlug, localizeMessage} from 'utils/utils'; import {generateSlug} from 'utils/utils';
export type Props = { export type Props = {
value: string; value: string;
@@ -31,17 +32,17 @@ export type Props = {
import './channel_name_form_field.scss'; import './channel_name_form_field.scss';
function validateDisplayName(displayNameParam: string) { function validateDisplayName(intl: IntlShape, displayNameParam: string) {
const errors: string[] = []; const errors: string[] = [];
const displayName = displayNameParam.trim(); const displayName = displayNameParam.trim();
if (displayName.length < Constants.MIN_CHANNELNAME_LENGTH) { if (displayName.length < Constants.MIN_CHANNELNAME_LENGTH) {
errors.push(localizeMessage({id: 'channel_modal.name.longer', defaultMessage: 'Channel names must have at least 2 characters.'})); errors.push(intl.formatMessage({id: 'channel_modal.name.longer', defaultMessage: 'Channel names must have at least 2 characters.'}));
} }
if (displayName.length > Constants.MAX_CHANNELNAME_LENGTH) { if (displayName.length > Constants.MAX_CHANNELNAME_LENGTH) {
errors.push(localizeMessage({id: 'channel_modal.name.shorter', defaultMessage: 'Channel names must have maximum 64 characters.'})); errors.push(intl.formatMessage({id: 'channel_modal.name.shorter', defaultMessage: 'Channel names must have maximum 64 characters.'}));
} }
return errors; return errors;
@@ -68,7 +69,7 @@ const ChannelNameFormField = (props: Props): JSX.Element => {
e.preventDefault(); e.preventDefault();
const {target: {value: updatedDisplayName}} = e; const {target: {value: updatedDisplayName}} = e;
const displayNameErrors = validateDisplayName(updatedDisplayName); const displayNameErrors = validateDisplayName(intl, updatedDisplayName);
// set error if any, else clear it // set error if any, else clear it
setDisplayNameError(displayNameErrors.length ? displayNameErrors[displayNameErrors.length - 1] : ''); setDisplayNameError(displayNameErrors.length ? displayNameErrors[displayNameErrors.length - 1] : '');

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

@@ -57,7 +57,12 @@ exports[`components/ChannelSelectorModal exclude already selected 1`] = `
> >
<MultiSelect <MultiSelect
ariaLabelRenderer={[Function]} ariaLabelRenderer={[Function]}
buttonSubmitText="Add" buttonSubmitText={
Object {
"defaultMessage": "Add",
"id": "multiselect.add",
}
}
focusOnLoad={true} focusOnLoad={true}
handleAdd={[Function]} handleAdd={[Function]}
handleDelete={[Function]} handleDelete={[Function]}
@@ -138,7 +143,12 @@ exports[`components/ChannelSelectorModal exclude already selected 1`] = `
] ]
} }
perPage={50} perPage={50}
placeholderText="Search and add channels" placeholderText={
Object {
"defaultMessage": "Search and add channels",
"id": "multiselect.addChannelsPlaceholder",
}
}
saveButtonPosition="top" saveButtonPosition="top"
saving={false} saving={false}
savingEnabled={true} savingEnabled={true}
@@ -212,7 +222,12 @@ exports[`components/ChannelSelectorModal should match snapshot 1`] = `
> >
<MultiSelect <MultiSelect
ariaLabelRenderer={[Function]} ariaLabelRenderer={[Function]}
buttonSubmitText="Add" buttonSubmitText={
Object {
"defaultMessage": "Add",
"id": "multiselect.add",
}
}
focusOnLoad={true} focusOnLoad={true}
handleAdd={[Function]} handleAdd={[Function]}
handleDelete={[Function]} handleDelete={[Function]}
@@ -315,7 +330,12 @@ exports[`components/ChannelSelectorModal should match snapshot 1`] = `
] ]
} }
perPage={50} perPage={50}
placeholderText="Search and add channels" placeholderText={
Object {
"defaultMessage": "Search and add channels",
"id": "multiselect.addChannelsPlaceholder",
}
}
saveButtonPosition="top" saveButtonPosition="top"
saving={false} saving={false}
savingEnabled={true} savingEnabled={true}

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

@@ -4,7 +4,7 @@
import React from 'react'; import React from 'react';
import {Modal} from 'react-bootstrap'; import {Modal} from 'react-bootstrap';
import type {IntlShape} from 'react-intl'; import type {IntlShape} from 'react-intl';
import {injectIntl, FormattedMessage} from 'react-intl'; import {injectIntl, FormattedMessage, defineMessage} from 'react-intl';
import type {Channel, ChannelSearchOpts, ChannelWithTeamData} from '@mattermost/types/channels'; import type {Channel, ChannelSearchOpts, ChannelWithTeamData} from '@mattermost/types/channels';
@@ -14,7 +14,6 @@ import MultiSelect from 'components/multiselect/multiselect';
import type {Value} from 'components/multiselect/multiselect'; import type {Value} from 'components/multiselect/multiselect';
import Constants from 'utils/constants'; import Constants from 'utils/constants';
import {localizeMessage} from 'utils/utils';
type ChannelWithTeamDataValue = ChannelWithTeamData & Value; type ChannelWithTeamDataValue = ChannelWithTeamData & Value;
@@ -207,7 +206,7 @@ export class ChannelSelectorModal extends React.PureComponent<Props, State> {
/> />
); );
const buttonSubmitText = localizeMessage({id: 'multiselect.add', defaultMessage: 'Add'}); const buttonSubmitText = defineMessage({id: 'multiselect.add', defaultMessage: 'Add'});
let options = this.state.channels.map((i): ChannelWithTeamDataValue => ({...i, label: i.display_name, value: i.id})); let options = this.state.channels.map((i): ChannelWithTeamDataValue => ({...i, label: i.display_name, value: i.id}));
if (this.props.alreadySelected) { if (this.props.alreadySelected) {
@@ -263,7 +262,7 @@ export class ChannelSelectorModal extends React.PureComponent<Props, State> {
buttonSubmitText={buttonSubmitText} buttonSubmitText={buttonSubmitText}
saving={false} saving={false}
loading={this.state.loadingChannels} loading={this.state.loadingChannels}
placeholderText={localizeMessage({id: 'multiselect.addChannelsPlaceholder', defaultMessage: 'Search and add channels'})} placeholderText={defineMessage({id: 'multiselect.addChannelsPlaceholder', defaultMessage: 'Search and add channels'})}
/> />
</Modal.Body> </Modal.Body>
</Modal> </Modal>

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

@@ -13,7 +13,6 @@ import LoginMfa from 'components/login/login_mfa';
import {ClaimErrors} from 'utils/constants'; import {ClaimErrors} from 'utils/constants';
import {isValidPassword} from 'utils/password'; import {isValidPassword} from 'utils/password';
import {localizeMessage} from 'utils/utils';
import type {SubmitOptions} from './email_to_ldap'; import type {SubmitOptions} from './email_to_ldap';
import ErrorLabel from './error_label'; import ErrorLabel from './error_label';
@@ -46,7 +45,7 @@ const LDAPToEmail = (props: Props) => {
const ldapPassword = ldapPasswordInput.current?.value; const ldapPassword = ldapPasswordInput.current?.value;
if (!ldapPassword) { if (!ldapPassword) {
setLdapPasswordError(localizeMessage({id: 'claim.ldap_to_email.ldapPasswordError', defaultMessage: 'Please enter your AD/LDAP password.'})); setLdapPasswordError(formatMessage({id: 'claim.ldap_to_email.ldapPasswordError', defaultMessage: 'Please enter your AD/LDAP password.'}));
setPasswordError(''); setPasswordError('');
setConfirmError(''); setConfirmError('');
setServerError(''); setServerError('');
@@ -55,7 +54,7 @@ const LDAPToEmail = (props: Props) => {
const password = passwordInput.current?.value; const password = passwordInput.current?.value;
if (!password) { if (!password) {
setPasswordError(localizeMessage({id: 'claim.ldap_to_email.pwdError', defaultMessage: 'Please enter your password.'})); setPasswordError(formatMessage({id: 'claim.ldap_to_email.pwdError', defaultMessage: 'Please enter your password.'}));
setConfirmError(''); setConfirmError('');
setLdapPasswordError(''); setLdapPasswordError('');
setServerError(''); setServerError('');
@@ -75,7 +74,7 @@ const LDAPToEmail = (props: Props) => {
const confirmPassword = passwordConfirmInput.current?.value; const confirmPassword = passwordConfirmInput.current?.value;
if (!confirmPassword || password !== confirmPassword) { if (!confirmPassword || password !== confirmPassword) {
setConfirmError(localizeMessage({id: 'claim.ldap_to_email.pwdNotMatch', defaultMessage: 'Passwords do not match.'})); setConfirmError(formatMessage({id: 'claim.ldap_to_email.pwdNotMatch', defaultMessage: 'Passwords do not match.'}));
setPasswordError(''); setPasswordError('');
setLdapPasswordError(''); setLdapPasswordError('');
setServerError(''); setServerError('');

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

@@ -13,7 +13,7 @@ import {oauthToEmail} from 'actions/admin_actions.jsx';
import Constants from 'utils/constants'; import Constants from 'utils/constants';
import {isValidPassword} from 'utils/password'; import {isValidPassword} from 'utils/password';
import {localizeMessage, toTitleCase} from 'utils/utils'; import {toTitleCase} from 'utils/utils';
import ErrorLabel from './error_label'; import ErrorLabel from './error_label';
@@ -36,7 +36,7 @@ const OAuthToEmail = (props: Props) => {
const password = passwordInput.current?.value; const password = passwordInput.current?.value;
if (!password) { if (!password) {
setError(localizeMessage({id: 'claim.oauth_to_email.enterPwd', defaultMessage: 'Please enter a password.'})); setError(intl.formatMessage({id: 'claim.oauth_to_email.enterPwd', defaultMessage: 'Please enter a password.'}));
return; return;
} }
@@ -50,7 +50,7 @@ const OAuthToEmail = (props: Props) => {
const confirmPassword = passwordConfirmInput.current?.value; const confirmPassword = passwordConfirmInput.current?.value;
if (!confirmPassword || password !== confirmPassword) { if (!confirmPassword || password !== confirmPassword) {
setError(localizeMessage({id: 'claim.oauth_to_email.pwdNotMatch', defaultMessage: 'Passwords do not match.'})); setError(intl.formatMessage({id: 'claim.oauth_to_email.pwdNotMatch', defaultMessage: 'Passwords do not match.'}));
return; return;
} }

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

@@ -82,7 +82,12 @@ exports[`component/create_user_groups_modal should match snapshot with back butt
data-testid="nameInput" data-testid="nameInput"
maxLength={64} maxLength={64}
onChange={[Function]} onChange={[Function]}
placeholder="Name" placeholder={
Object {
"defaultMessage": "Name",
"id": "user_groups_modal.name",
}
}
type="text" type="text"
value="" value=""
/> />
@@ -100,7 +105,12 @@ exports[`component/create_user_groups_modal should match snapshot with back butt
data-testid="mentionInput" data-testid="mentionInput"
maxLength={64} maxLength={64}
onChange={[Function]} onChange={[Function]}
placeholder="Mention" placeholder={
Object {
"defaultMessage": "Mention",
"id": "user_groups_modal.mention",
}
}
type="text" type="text"
value="" value=""
/> />
@@ -118,7 +128,12 @@ exports[`component/create_user_groups_modal should match snapshot with back butt
addUserCallback={[Function]} addUserCallback={[Function]}
backButtonClass="multiselect-back" backButtonClass="multiselect-back"
backButtonClick={[Function]} backButtonClick={[Function]}
backButtonText="Cancel" backButtonText={
Object {
"defaultMessage": "Cancel",
"id": "multiselect.cancelButton",
}
}
deleteUserCallback={[Function]} deleteUserCallback={[Function]}
focusOnLoad={false} focusOnLoad={false}
multilSelectKey="addUsersToGroupKey" multilSelectKey="addUsersToGroupKey"
@@ -200,7 +215,12 @@ exports[`component/create_user_groups_modal should match snapshot without back b
data-testid="nameInput" data-testid="nameInput"
maxLength={64} maxLength={64}
onChange={[Function]} onChange={[Function]}
placeholder="Name" placeholder={
Object {
"defaultMessage": "Name",
"id": "user_groups_modal.name",
}
}
type="text" type="text"
value="" value=""
/> />
@@ -218,7 +238,12 @@ exports[`component/create_user_groups_modal should match snapshot without back b
data-testid="mentionInput" data-testid="mentionInput"
maxLength={64} maxLength={64}
onChange={[Function]} onChange={[Function]}
placeholder="Mention" placeholder={
Object {
"defaultMessage": "Mention",
"id": "user_groups_modal.mention",
}
}
type="text" type="text"
value="" value=""
/> />
@@ -236,7 +261,12 @@ exports[`component/create_user_groups_modal should match snapshot without back b
addUserCallback={[Function]} addUserCallback={[Function]}
backButtonClass="multiselect-back" backButtonClass="multiselect-back"
backButtonClick={[Function]} backButtonClick={[Function]}
backButtonText="Cancel" backButtonText={
Object {
"defaultMessage": "Cancel",
"id": "multiselect.cancelButton",
}
}
deleteUserCallback={[Function]} deleteUserCallback={[Function]}
focusOnLoad={false} focusOnLoad={false}
multilSelectKey="addUsersToGroupKey" multilSelectKey="addUsersToGroupKey"

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

@@ -83,7 +83,7 @@ describe('component/create_user_groups_modal', () => {
expect(baseProps.actions.createGroupWithUserIds).toHaveBeenCalledTimes(0); expect(baseProps.actions.createGroupWithUserIds).toHaveBeenCalledTimes(0);
process.nextTick(() => { process.nextTick(() => {
expect(wrapper.state('showUnknownError')).toEqual(false); expect(wrapper.state('showUnknownError')).toEqual(false);
expect(wrapper.state('mentionInputErrorText')).toEqual('Invalid character in mention.'); expect((wrapper.state('mentionInputErrorText') as React.JSX.Element).props.defaultMessage).toEqual('Invalid character in mention.');
}); });
}); });
@@ -115,7 +115,7 @@ describe('component/create_user_groups_modal', () => {
expect(baseProps.actions.createGroupWithUserIds).toHaveBeenCalledTimes(0); expect(baseProps.actions.createGroupWithUserIds).toHaveBeenCalledTimes(0);
process.nextTick(() => { process.nextTick(() => {
expect(wrapper.state('showUnknownError')).toEqual(false); expect(wrapper.state('showUnknownError')).toEqual(false);
expect(wrapper.state('nameInputErrorText')).toEqual('Name is a required field.'); expect((wrapper.state('nameInputErrorText') as React.JSX.Element).props.defaultMessage).toEqual('Name is a required field.');
}); });
}); });
@@ -131,7 +131,7 @@ describe('component/create_user_groups_modal', () => {
expect(baseProps.actions.createGroupWithUserIds).toHaveBeenCalledTimes(0); expect(baseProps.actions.createGroupWithUserIds).toHaveBeenCalledTimes(0);
process.nextTick(() => { process.nextTick(() => {
expect(wrapper.state('showUnknownError')).toEqual(false); expect(wrapper.state('showUnknownError')).toEqual(false);
expect(wrapper.state('mentionInputErrorText')).toEqual('Mention is a required field.'); expect((wrapper.state('mentionInputErrorText') as React.JSX.Element).props.defaultMessage).toEqual('Mention is a required field.');
}); });
}); });
@@ -193,7 +193,7 @@ describe('component/create_user_groups_modal', () => {
expect(instance.props.actions.createGroupWithUserIds).toHaveBeenCalledTimes(1); expect(instance.props.actions.createGroupWithUserIds).toHaveBeenCalledTimes(1);
process.nextTick(() => { process.nextTick(() => {
expect(wrapper.state('showUnknownError')).toEqual(false); expect(wrapper.state('showUnknownError')).toEqual(false);
expect(wrapper.state('mentionInputErrorText')).toEqual('Mention needs to be unique.'); expect((wrapper.state('mentionInputErrorText') as React.JSX.Element).props.defaultMessage).toEqual('Mention needs to be unique.');
expect(wrapper.state('nameInputErrorText')).toEqual(''); expect(wrapper.state('nameInputErrorText')).toEqual('');
}); });
}); });
@@ -210,7 +210,7 @@ describe('component/create_user_groups_modal', () => {
expect(baseProps.actions.createGroupWithUserIds).toHaveBeenCalledTimes(0); expect(baseProps.actions.createGroupWithUserIds).toHaveBeenCalledTimes(0);
process.nextTick(() => { process.nextTick(() => {
expect(wrapper.state('showUnknownError')).toEqual(false); expect(wrapper.state('showUnknownError')).toEqual(false);
expect(wrapper.state('mentionInputErrorText')).toEqual('Mention contains a reserved word.'); expect((wrapper.state('mentionInputErrorText') as React.JSX.Element).props.defaultMessage).toEqual('Mention contains a reserved word.');
}); });
wrapper.setState({name: 'Ursa', mention: 'here'}); wrapper.setState({name: 'Ursa', mention: 'here'});
@@ -219,7 +219,7 @@ describe('component/create_user_groups_modal', () => {
expect(baseProps.actions.createGroupWithUserIds).toHaveBeenCalledTimes(0); expect(baseProps.actions.createGroupWithUserIds).toHaveBeenCalledTimes(0);
process.nextTick(() => { process.nextTick(() => {
expect(wrapper.state('showUnknownError')).toEqual(false); expect(wrapper.state('showUnknownError')).toEqual(false);
expect(wrapper.state('mentionInputErrorText')).toEqual('Mention contains a reserved word.'); expect((wrapper.state('mentionInputErrorText') as React.JSX.Element).props.defaultMessage).toEqual('Mention contains a reserved word.');
}); });
wrapper.setState({name: 'Ursa', mention: 'channel'}); wrapper.setState({name: 'Ursa', mention: 'channel'});
@@ -228,7 +228,7 @@ describe('component/create_user_groups_modal', () => {
expect(baseProps.actions.createGroupWithUserIds).toHaveBeenCalledTimes(0); expect(baseProps.actions.createGroupWithUserIds).toHaveBeenCalledTimes(0);
process.nextTick(() => { process.nextTick(() => {
expect(wrapper.state('showUnknownError')).toEqual(false); expect(wrapper.state('showUnknownError')).toEqual(false);
expect(wrapper.state('mentionInputErrorText')).toEqual('Mention contains a reserved word.'); expect((wrapper.state('mentionInputErrorText') as React.JSX.Element).props.defaultMessage).toEqual('Mention contains a reserved word.');
}); });
}); });
test('should fail to create with duplicate mention error', () => { test('should fail to create with duplicate mention error', () => {
@@ -249,7 +249,7 @@ describe('component/create_user_groups_modal', () => {
expect(instance.props.actions.createGroupWithUserIds).toHaveBeenCalledTimes(1); expect(instance.props.actions.createGroupWithUserIds).toHaveBeenCalledTimes(1);
process.nextTick(() => { process.nextTick(() => {
expect(wrapper.state('showUnknownError')).toEqual(false); expect(wrapper.state('showUnknownError')).toEqual(false);
expect(wrapper.state('mentionInputErrorText')).toEqual('A username already exists with this name. Mention must be unique.'); expect((wrapper.state('mentionInputErrorText') as React.JSX.Element).props.defaultMessage).toEqual('A username already exists with this name. Mention must be unique.');
expect(wrapper.state('nameInputErrorText')).toEqual(''); expect(wrapper.state('nameInputErrorText')).toEqual('');
}); });
}); });

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

@@ -3,7 +3,7 @@
import React from 'react'; import React from 'react';
import {Modal} from 'react-bootstrap'; import {Modal} from 'react-bootstrap';
import {FormattedMessage, type IntlShape, injectIntl} from 'react-intl'; import {FormattedMessage, type IntlShape, defineMessage, injectIntl} from 'react-intl';
import type {GroupCreateWithUserIds} from '@mattermost/types/groups'; import type {GroupCreateWithUserIds} from '@mattermost/types/groups';
import type {UserProfile} from '@mattermost/types/users'; import type {UserProfile} from '@mattermost/types/users';
@@ -14,8 +14,6 @@ import AddUserToGroupMultiSelect from 'components/add_user_to_group_multiselect'
import Input from 'components/widgets/inputs/input/input'; import Input from 'components/widgets/inputs/input/input';
import Constants, {ItemStatus} from 'utils/constants'; import Constants, {ItemStatus} from 'utils/constants';
import * as Utils from 'utils/utils';
import {localizeMessage} from 'utils/utils';
import type {ModalData} from 'types/actions'; import type {ModalData} from 'types/actions';
@@ -39,8 +37,8 @@ type State = {
savingEnabled: boolean; savingEnabled: boolean;
usersToAdd: UserProfile[]; usersToAdd: UserProfile[];
mentionUpdatedManually: boolean; mentionUpdatedManually: boolean;
mentionInputErrorText: string; mentionInputErrorText: React.ReactNode;
nameInputErrorText: string; nameInputErrorText: React.ReactNode;
showUnknownError: boolean; showUnknownError: boolean;
saving: boolean; saving: boolean;
} }
@@ -107,7 +105,15 @@ export class CreateUserGroupsModal extends React.PureComponent<Props, State> {
const displayName = this.state.name; const displayName = this.state.name;
if (!displayName || !displayName.trim()) { if (!displayName || !displayName.trim()) {
this.setState({nameInputErrorText: Utils.localizeMessage({id: 'user_groups_modal.nameIsEmpty', defaultMessage: 'Name is a required field.'}), saving: false}); this.setState({
nameInputErrorText: (
<FormattedMessage
id='user_groups_modal.nameIsEmpty'
defaultMessage='Name is a required field.'
/>
),
saving: false,
});
return; return;
} }
@@ -120,18 +126,42 @@ export class CreateUserGroupsModal extends React.PureComponent<Props, State> {
} }
if (mention.length < 1) { if (mention.length < 1) {
this.setState({mentionInputErrorText: Utils.localizeMessage({id: 'user_groups_modal.mentionIsEmpty', defaultMessage: 'Mention is a required field.'}), saving: false}); this.setState({
mentionInputErrorText: (
<FormattedMessage
id='user_groups_modal.mentionIsEmpty'
defaultMessage='Mention is a required field.'
/>
),
saving: false,
});
return; return;
} }
if (Constants.SPECIAL_MENTIONS.includes(mention.toLowerCase())) { if (Constants.SPECIAL_MENTIONS.includes(mention.toLowerCase())) {
this.setState({mentionInputErrorText: Utils.localizeMessage({id: 'user_groups_modal.mentionReservedWord', defaultMessage: 'Mention contains a reserved word.'}), saving: false}); this.setState({
mentionInputErrorText: (
<FormattedMessage
id='user_groups_modal.mentionReservedWord'
defaultMessage='Mention contains a reserved word.'
/>
),
saving: false,
});
return; return;
} }
const mentionRegEx = new RegExp(/^[a-z0-9.\-_]+$/); const mentionRegEx = new RegExp(/^[a-z0-9.\-_]+$/);
if (!mentionRegEx.test(mention)) { if (!mentionRegEx.test(mention)) {
this.setState({mentionInputErrorText: Utils.localizeMessage({id: 'user_groups_modal.mentionInvalidError', defaultMessage: 'Invalid character in mention.'}), saving: false}); this.setState({
mentionInputErrorText: (
<FormattedMessage
id='user_groups_modal.mentionInvalidError'
defaultMessage='Invalid character in mention.'
/>
),
saving: false,
});
return; return;
} }
@@ -149,9 +179,23 @@ export class CreateUserGroupsModal extends React.PureComponent<Props, State> {
if (data?.error) { if (data?.error) {
if (data.error?.server_error_id === 'app.custom_group.unique_name') { if (data.error?.server_error_id === 'app.custom_group.unique_name') {
this.setState({mentionInputErrorText: Utils.localizeMessage({id: 'user_groups_modal.mentionNotUnique', defaultMessage: 'Mention needs to be unique.'})}); this.setState({
mentionInputErrorText: (
<FormattedMessage
id='user_groups_modal.mentionNotUnique'
defaultMessage='Mention needs to be unique.'
/>
),
});
} else if (data.error?.server_error_id === 'app.group.username_conflict') { } else if (data.error?.server_error_id === 'app.group.username_conflict') {
this.setState({mentionInputErrorText: Utils.localizeMessage({id: 'user_groups_modal.mentionUsernameConflict', defaultMessage: 'A username already exists with this name. Mention must be unique.'})}); this.setState({
mentionInputErrorText: (
<FormattedMessage
id='user_groups_modal.mentionUsernameConflict'
defaultMessage='A username already exists with this name. Mention must be unique.'
/>
),
});
} else { } else {
this.setState({showUnknownError: true}); this.setState({showUnknownError: true});
} }
@@ -217,7 +261,7 @@ export class CreateUserGroupsModal extends React.PureComponent<Props, State> {
<div className='group-name-input-wrapper'> <div className='group-name-input-wrapper'>
<Input <Input
type='text' type='text'
placeholder={Utils.localizeMessage({id: 'user_groups_modal.name', defaultMessage: 'Name'})} placeholder={defineMessage({id: 'user_groups_modal.name', defaultMessage: 'Name'})}
onChange={this.updateNameState} onChange={this.updateNameState}
value={this.state.name} value={this.state.name}
data-testid='nameInput' data-testid='nameInput'
@@ -229,7 +273,7 @@ export class CreateUserGroupsModal extends React.PureComponent<Props, State> {
<div className='group-mention-input-wrapper'> <div className='group-mention-input-wrapper'>
<Input <Input
type='text' type='text'
placeholder={Utils.localizeMessage({id: 'user_groups_modal.mention', defaultMessage: 'Mention'})} placeholder={defineMessage({id: 'user_groups_modal.mention', defaultMessage: 'Mention'})}
onChange={this.updateMentionState} onChange={this.updateMentionState}
value={this.state.mention} value={this.state.mention}
maxLength={64} maxLength={64}
@@ -251,7 +295,7 @@ export class CreateUserGroupsModal extends React.PureComponent<Props, State> {
savingEnabled={this.isSaveEnabled()} savingEnabled={this.isSaveEnabled()}
addUserCallback={this.addUserCallback} addUserCallback={this.addUserCallback}
deleteUserCallback={this.deleteUserCallback} deleteUserCallback={this.deleteUserCallback}
backButtonText={localizeMessage({id: 'multiselect.cancelButton', defaultMessage: 'Cancel'})} backButtonText={defineMessage({id: 'multiselect.cancelButton', defaultMessage: 'Cancel'})}
backButtonClick={ backButtonClick={
typeof this.props.backButtonCallback === 'function' ? this.goBack : this.doHide typeof this.props.backButtonCallback === 'function' ? this.goBack : this.doHide
} }

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

@@ -5,7 +5,7 @@ import classNames from 'classnames';
import {DateTime} from 'luxon'; import {DateTime} from 'luxon';
import React from 'react'; import React from 'react';
import type {DayPickerProps} from 'react-day-picker'; import type {DayPickerProps} from 'react-day-picker';
import {FormattedMessage} from 'react-intl'; import {defineMessage, FormattedMessage} from 'react-intl';
import IconButton from '@mattermost/compass-components/components/icon-button'; // eslint-disable-line no-restricted-imports import IconButton from '@mattermost/compass-components/components/icon-button'; // eslint-disable-line no-restricted-imports
import {GenericModal} from '@mattermost/components'; import {GenericModal} from '@mattermost/components';
@@ -260,7 +260,7 @@ export default class DndCustomTimePicker extends React.PureComponent<Props, Stat
readOnly={true} readOnly={true}
id='DndModal__calendar-input' id='DndModal__calendar-input'
className={classNames('DndModal__calendar-input', {'popper-open': isPopperOpen})} className={classNames('DndModal__calendar-input', {'popper-open': isPopperOpen})}
label={localizeMessage({id: 'dnd_custom_time_picker_modal.date', defaultMessage: 'Date'})} label={defineMessage({id: 'dnd_custom_time_picker_modal.date', defaultMessage: 'Date'})}
onClick={() => this.handlePopperOpenState(true)} onClick={() => this.handlePopperOpenState(true)}
tabIndex={-1} tabIndex={-1}
inputPrefix={inputIcon} inputPrefix={inputIcon}

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

@@ -95,7 +95,7 @@ type Props = {
/** /**
* Function to set the editing post * Function to set the editing post
*/ */
setEditingPost: (postId?: string, refocusId?: string, title?: string, isRHS?: boolean) => void; setEditingPost: (postId?: string, refocusId?: string, isRHS?: boolean) => void;
/** /**
* Function to pin the post * Function to pin the post
@@ -297,7 +297,6 @@ export class DotMenuClass extends React.PureComponent<Props, State> {
this.props.actions.setEditingPost( this.props.actions.setEditingPost(
this.props.post.id, this.props.post.id,
this.props.location === Locations.CENTER ? 'post_textbox' : 'reply_textbox', this.props.location === Locations.CENTER ? 'post_textbox' : 'reply_textbox',
this.props.post.root_id ? Utils.localizeMessage({id: 'rhs_comment.comment', defaultMessage: 'Comment'}) : Utils.localizeMessage({id: 'create_post.post', defaultMessage: 'Post'}),
this.props.location === Locations.RHS_ROOT || this.props.location === Locations.RHS_COMMENT || this.props.location === Locations.SEARCH, this.props.location === Locations.RHS_ROOT || this.props.location === Locations.RHS_COMMENT || this.props.location === Locations.SEARCH,
); );
trackDotMenuEvent(e, TELEMETRY_LABELS.EDIT); trackDotMenuEvent(e, TELEMETRY_LABELS.EDIT);

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

@@ -36,7 +36,7 @@ exports[`EmojiPage should render without crashing 1`] = `
</Link> </Link>
</Memo(AnyTeamPermissionGate)> </Memo(AnyTeamPermissionGate)>
</div> </div>
<Connect(injectIntl(EmojiList)) <Connect(EmojiList)
scrollToTop={[MockFunction]} scrollToTop={[MockFunction]}
/> />
</div> </div>

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

@@ -125,7 +125,12 @@ exports[`components/emoji/components/AddEmoji should match snapshot 1`] = `
data-testid="save-button" data-testid="save-button"
onClick={[Function]} onClick={[Function]}
spinning={false} spinning={false}
spinningText="Saving..." spinningText={
Object {
"defaultMessage": "Saving...",
"id": "add_emoji.saving",
}
}
type="submit" type="submit"
> >
<MemoizedFormattedMessage <MemoizedFormattedMessage
@@ -300,7 +305,12 @@ exports[`components/emoji/components/AddEmoji should select a file and match sna
data-testid="save-button" data-testid="save-button"
onClick={[Function]} onClick={[Function]}
spinning={false} spinning={false}
spinningText="Saving..." spinningText={
Object {
"defaultMessage": "Saving...",
"id": "add_emoji.saving",
}
}
type="submit" type="submit"
> >
<MemoizedFormattedMessage <MemoizedFormattedMessage
@@ -439,7 +449,12 @@ exports[`components/emoji/components/AddEmoji should update emoji name and match
data-testid="save-button" data-testid="save-button"
onClick={[Function]} onClick={[Function]}
spinning={false} spinning={false}
spinningText="Saving..." spinningText={
Object {
"defaultMessage": "Saving...",
"id": "add_emoji.saving",
}
}
type="submit" type="submit"
> >
<MemoizedFormattedMessage <MemoizedFormattedMessage

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

@@ -3,7 +3,7 @@
import React from 'react'; import React from 'react';
import type {ChangeEvent, FormEvent, SyntheticEvent} from 'react'; import type {ChangeEvent, FormEvent, SyntheticEvent} from 'react';
import {FormattedMessage} from 'react-intl'; import {defineMessage, FormattedMessage} from 'react-intl';
import {Link} from 'react-router-dom'; import {Link} from 'react-router-dom';
import type {CustomEmoji} from '@mattermost/types/emojis'; import type {CustomEmoji} from '@mattermost/types/emojis';
@@ -19,7 +19,6 @@ import SpinnerButton from 'components/spinner_button';
import {getHistory} from 'utils/browser_history'; import {getHistory} from 'utils/browser_history';
import {Constants} from 'utils/constants'; import {Constants} from 'utils/constants';
import type EmojiMap from 'utils/emoji_map'; import type EmojiMap from 'utils/emoji_map';
import {localizeMessage} from 'utils/utils';
export interface AddEmojiProps { export interface AddEmojiProps {
actions: { actions: {
@@ -389,7 +388,7 @@ export default class AddEmoji extends React.PureComponent<AddEmojiProps, AddEmoj
className='btn btn-primary' className='btn btn-primary'
type='submit' type='submit'
spinning={this.state.saving} spinning={this.state.saving}
spinningText={localizeMessage({id: 'add_emoji.saving', defaultMessage: 'Saving...'})} spinningText={defineMessage({id: 'add_emoji.saving', defaultMessage: 'Saving...'})}
onClick={this.handleSaveButtonClick} onClick={this.handleSaveButtonClick}
> >
<FormattedMessage <FormattedMessage

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

@@ -3,7 +3,7 @@
import React from 'react'; import React from 'react';
import type {ChangeEvent, ChangeEventHandler} from 'react'; import type {ChangeEvent, ChangeEventHandler} from 'react';
import {FormattedMessage, injectIntl, type IntlShape} from 'react-intl'; import {defineMessage, FormattedMessage} from 'react-intl';
import type {CustomEmoji} from '@mattermost/types/emojis'; import type {CustomEmoji} from '@mattermost/types/emojis';
@@ -13,6 +13,7 @@ import type {ActionResult} from 'mattermost-redux/types/actions';
import EmojiListItem from 'components/emoji/emoji_list_item'; import EmojiListItem from 'components/emoji/emoji_list_item';
import LoadingScreen from 'components/loading_screen'; import LoadingScreen from 'components/loading_screen';
import LocalizedPlaceholderInput from 'components/localized_placeholder_input';
import SaveButton from 'components/save_button'; import SaveButton from 'components/save_button';
import NextIcon from 'components/widgets/icons/fa_next_icon'; import NextIcon from 'components/widgets/icons/fa_next_icon';
import PreviousIcon from 'components/widgets/icons/fa_previous_icon'; import PreviousIcon from 'components/widgets/icons/fa_previous_icon';
@@ -32,7 +33,6 @@ export interface Props {
* Function to scroll list to top. * Function to scroll list to top.
*/ */
scrollToTop: () => void; scrollToTop: () => void;
intl: IntlShape;
actions: { actions: {
/** /**
@@ -56,7 +56,7 @@ interface State {
missingPages: boolean; missingPages: boolean;
} }
class EmojiList extends React.PureComponent<Props, State> { export default class EmojiList extends React.PureComponent<Props, State> {
private searchTimeout: NodeJS.Timeout | null; private searchTimeout: NodeJS.Timeout | null;
constructor(props: Props) { constructor(props: Props) {
@@ -267,10 +267,10 @@ class EmojiList extends React.PureComponent<Props, State> {
<div className='backstage-filters'> <div className='backstage-filters'>
<div className='backstage-filter__search'> <div className='backstage-filter__search'>
<SearchIcon/> <SearchIcon/>
<input <LocalizedPlaceholderInput
type='search' type='search'
className='form-control' className='form-control'
placeholder={this.props.intl.formatMessage({id: 'emoji_list.search', defaultMessage: 'Search Custom Emoji'})} placeholder={defineMessage({id: 'emoji_list.search', defaultMessage: 'Search Custom Emoji'})}
onChange={this.onSearchChange} onChange={this.onSearchChange}
style={style.search} style={style.search}
/> />
@@ -335,5 +335,3 @@ class EmojiList extends React.PureComponent<Props, State> {
const style = { const style = {
search: {flexGrow: 0, flexShrink: 0}, search: {flexGrow: 0, flexShrink: 0},
}; };
export default injectIntl(EmojiList);

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

@@ -21,9 +21,10 @@ exports[`components/error_page/ErrorTitle should match snapshot, no type but wit
`; `;
exports[`components/error_page/ErrorTitle should match snapshot, no type nor title 1`] = ` exports[`components/error_page/ErrorTitle should match snapshot, no type nor title 1`] = `
<Fragment> <MemoizedFormattedMessage
Error defaultMessage="Error"
</Fragment> id="error.generic.title"
/>
`; `;
exports[`components/error_page/ErrorTitle should match snapshot, oauth_access_denied type 1`] = ` exports[`components/error_page/ErrorTitle should match snapshot, oauth_access_denied type 1`] = `

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

@@ -5,7 +5,6 @@ import React from 'react';
import {FormattedMessage} from 'react-intl'; import {FormattedMessage} from 'react-intl';
import {ErrorPageTypes} from 'utils/constants'; import {ErrorPageTypes} from 'utils/constants';
import * as Utils from 'utils/utils';
type Props = { type Props = {
type?: string | null; type?: string | null;
@@ -93,7 +92,12 @@ const ErrorTitle: React.FC<Props> = ({type, title}: Props) => {
} else if (title) { } else if (title) {
errorTitle = <>{title}</>; errorTitle = <>{title}</>;
} else { } else {
errorTitle = <>{Utils.localizeMessage({id: 'error.generic.title', defaultMessage: 'Error'})}</>; errorTitle = (
<FormattedMessage
id='error.generic.title'
defaultMessage='Error'
/>
);
} }
return errorTitle; return errorTitle;

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

@@ -127,7 +127,6 @@ const FeatureRestrictedModal = ({
const trialBtn = ( const trialBtn = (
<StartTrialBtn <StartTrialBtn
message={formatMessage({id: 'trial_btn.free.tryFreeFor30Days', defaultMessage: 'Start trial'})}
onClick={dismissAction} onClick={dismissAction}
telemetryId='start_self_hosted_trial_after_team_creation_restricted' telemetryId='start_self_hosted_trial_after_team_creation_restricted'
btnClass='btn btn-primary' btnClass='btn btn-primary'

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

@@ -2,8 +2,7 @@
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import React, {useState} from 'react'; import React, {useState} from 'react';
import {injectIntl} from 'react-intl'; import {useIntl} from 'react-intl';
import type {WrappedComponentProps} from 'react-intl';
import {useDispatch} from 'react-redux'; import {useDispatch} from 'react-redux';
import {GenericModal} from '@mattermost/components'; import {GenericModal} from '@mattermost/components';
@@ -28,11 +27,13 @@ type Props = {
submitText: string; submitText: string;
feedbackOptions: FeedbackOption[]; feedbackOptions: FeedbackOption[];
freeformTextPlaceholder: string; freeformTextPlaceholder: string;
} & WrappedComponentProps }
export default function FeedbackModal(props: Props) {
const intl = useIntl();
function FeedbackModal(props: Props) {
const maxFreeFormTextLength = 500; const maxFreeFormTextLength = 500;
const optionOther = {translatedMessage: props.intl.formatMessage({id: 'feedback.other', defaultMessage: 'Other'}), submissionValue: 'Other'}; const optionOther = {translatedMessage: intl.formatMessage({id: 'feedback.other', defaultMessage: 'Other'}), submissionValue: 'Other'};
const feedbackModalOptions: FeedbackOption[] = [ const feedbackModalOptions: FeedbackOption[] = [
...props.feedbackOptions, ...props.feedbackOptions,
optionOther, optionOther,
@@ -69,7 +70,7 @@ function FeedbackModal(props: Props) {
handleCancel={handleCancel} handleCancel={handleCancel}
handleConfirm={handleSubmitFeedbackModal} handleConfirm={handleSubmitFeedbackModal}
confirmButtonText={props.submitText} confirmButtonText={props.submitText}
cancelButtonText={props.intl.formatMessage({id: 'feedback.cancelButton.text', defaultMessage: 'Cancel'})} cancelButtonText={intl.formatMessage({id: 'feedback.cancelButton.text', defaultMessage: 'Cancel'})}
modalHeaderText={props.title} modalHeaderText={props.title}
autoCloseOnConfirmButton={false} autoCloseOnConfirmButton={false}
> >
@@ -107,5 +108,3 @@ function FeedbackModal(props: Props) {
</GenericModal> </GenericModal>
); );
} }
export default injectIntl(FeedbackModal);

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

@@ -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 {useIntl} from 'react-intl';
import type {FileInfo} from '@mattermost/types/files'; import type {FileInfo} from '@mattermost/types/files';
@@ -18,19 +19,21 @@ const FileInfoPreview = ({
fileUrl, fileUrl,
canDownloadFiles, canDownloadFiles,
}: Props) => { }: Props) => {
const intl = useIntl();
// non-image files include a section providing details about the file // non-image files include a section providing details about the file
const infoParts = []; const infoParts = [];
if (fileInfo.extension !== '') { if (fileInfo.extension !== '') {
infoParts.push( infoParts.push(
Utils.localizeMessage({id: 'file_info_preview.type', defaultMessage: 'File type '}) + intl.formatMessage({id: 'file_info_preview.type', defaultMessage: 'File type '}) +
fileInfo.extension.toUpperCase(), fileInfo.extension.toUpperCase(),
); );
} }
if (fileInfo.size) { if (fileInfo.size) {
infoParts.push( infoParts.push(
Utils.localizeMessage({id: 'file_info_preview.size', defaultMessage: 'Size '}) + intl.formatMessage({id: 'file_info_preview.size', defaultMessage: 'Size '}) +
Utils.fileSizeToString(fileInfo.size), Utils.fileSizeToString(fileInfo.size),
); );
} }

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

@@ -125,7 +125,12 @@ exports[`components/FilePreviewModal should fall back to default preview if plug
> >
<LoadingImagePreview <LoadingImagePreview
containerClass="view-image__loading" containerClass="view-image__loading"
loading="Loading" loading={
<Memo(MemoizedFormattedMessage)
defaultMessage="Loading"
id="view_image.loading"
/>
}
progress={0} progress={0}
/> />
</div> </div>
@@ -260,7 +265,12 @@ exports[`components/FilePreviewModal should match snapshot 1`] = `
> >
<LoadingImagePreview <LoadingImagePreview
containerClass="view-image__loading" containerClass="view-image__loading"
loading="Loading" loading={
<Memo(MemoizedFormattedMessage)
defaultMessage="Loading"
id="view_image.loading"
/>
}
progress={0} progress={0}
/> />
</div> </div>
@@ -395,7 +405,12 @@ exports[`components/FilePreviewModal should match snapshot for external file 1`]
> >
<LoadingImagePreview <LoadingImagePreview
containerClass="view-image__loading" containerClass="view-image__loading"
loading="Loading" loading={
<Memo(MemoizedFormattedMessage)
defaultMessage="Loading"
id="view_image.loading"
/>
}
progress={0} progress={0}
/> />
</div> </div>

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

@@ -4,6 +4,7 @@
import classNames from 'classnames'; import classNames from 'classnames';
import React from 'react'; import React from 'react';
import {Modal} from 'react-bootstrap'; import {Modal} from 'react-bootstrap';
import {FormattedMessage} from 'react-intl';
import type {FileInfo} from '@mattermost/types/files'; import type {FileInfo} from '@mattermost/types/files';
import type {Post} from '@mattermost/types/posts'; import type {Post} from '@mattermost/types/posts';
@@ -365,12 +366,16 @@ export default class FilePreviewModal extends React.PureComponent<Props, State>
} }
} else { } else {
// display a progress indicator when the preview for an image is still loading // display a progress indicator when the preview for an image is still loading
const loading = Utils.localizeMessage({id: 'view_image.loading', defaultMessage: 'Loading'});
const progress = Math.floor(this.state.progress[this.state.imageIndex]); const progress = Math.floor(this.state.progress[this.state.imageIndex]);
content = ( content = (
<LoadingImagePreview <LoadingImagePreview
loading={loading} loading={
<FormattedMessage
id='view_image.loading'
defaultMessage='Loading'
/>
}
progress={progress} progress={progress}
/> />
); );

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

@@ -2,6 +2,7 @@
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import React, {useEffect, useState} from 'react'; import React, {useEffect, useState} from 'react';
import {useIntl} from 'react-intl';
import {useHistory} from 'react-router-dom'; import {useHistory} from 'react-router-dom';
import styled from 'styled-components'; import styled from 'styled-components';
@@ -17,7 +18,6 @@ import type {
import WithTooltip from 'components/with_tooltip'; import WithTooltip from 'components/with_tooltip';
import DesktopApp from 'utils/desktop_api'; import DesktopApp from 'utils/desktop_api';
import * as Utils from 'utils/utils';
const HistoryButtonsContainer = styled.nav` const HistoryButtonsContainer = styled.nav`
display: flex; display: flex;
@@ -30,6 +30,7 @@ const HistoryButtonsContainer = styled.nav`
const HistoryButtons = (): JSX.Element => { const HistoryButtons = (): JSX.Element => {
const history = useHistory(); const history = useHistory();
const intl = useIntl();
const [canGoBack, setCanGoBack] = useState(true); const [canGoBack, setCanGoBack] = useState(true);
const [canGoForward, setCanGoForward] = useState(true); const [canGoForward, setCanGoForward] = useState(true);
@@ -83,7 +84,7 @@ const HistoryButtons = (): JSX.Element => {
compact={true} compact={true}
inverted={true} inverted={true}
disabled={!canGoBack} disabled={!canGoBack}
aria-label={Utils.localizeMessage({id: 'sidebar_left.channel_navigator.goBackLabel', defaultMessage: 'Back'})} aria-label={intl.formatMessage({id: 'sidebar_left.channel_navigator.goBackLabel', defaultMessage: 'Back'})}
/> />
</WithTooltip> </WithTooltip>
<WithTooltip <WithTooltip
@@ -98,7 +99,7 @@ const HistoryButtons = (): JSX.Element => {
compact={true} compact={true}
inverted={true} inverted={true}
disabled={!canGoForward} disabled={!canGoForward}
aria-label={Utils.localizeMessage({id: 'sidebar_left.channel_navigator.goForwardLabel', defaultMessage: 'Forward'})} aria-label={intl.formatMessage({id: 'sidebar_left.channel_navigator.goForwardLabel', defaultMessage: 'Forward'})}
/> />
</WithTooltip> </WithTooltip>
</HistoryButtonsContainer> </HistoryButtonsContainer>

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

@@ -106,12 +106,17 @@ exports[`components/integrations/AbstractCommand should match snapshot 1`] = `
<div <div
className="col-md-5 col-sm-8" className="col-md-5 col-sm-8"
> >
<input <LocalizedPlaceholderInput
className="form-control" className="form-control"
id="trigger" id="trigger"
maxLength={128} maxLength={128}
onChange={[Function]} onChange={[Function]}
placeholder="Command trigger e.g. \\"hello\\" not including the slash" placeholder={
Object {
"defaultMessage": "Command trigger e.g. \\"hello\\" not including the slash",
"id": "add_command.trigger.placeholder",
}
}
type="text" type="text"
value="trigger" value="trigger"
/> />
@@ -171,7 +176,12 @@ exports[`components/integrations/AbstractCommand should match snapshot 1`] = `
> >
<OAuthConnectionAudienceInput <OAuthConnectionAudienceInput
onChange={[Function]} onChange={[Function]}
placeholder="Must start with http:// or https://" placeholder={
Object {
"defaultMessage": "Must start with http:// or https://",
"id": "add_command.url.placeholder",
}
}
value="https://google.com/command" value="https://google.com/command"
/> />
<div <div
@@ -254,12 +264,17 @@ exports[`components/integrations/AbstractCommand should match snapshot 1`] = `
<div <div
className="col-md-5 col-sm-8" className="col-md-5 col-sm-8"
> >
<input <LocalizedPlaceholderInput
className="form-control" className="form-control"
id="username" id="username"
maxLength={64} maxLength={64}
onChange={[Function]} onChange={[Function]}
placeholder="Username" placeholder={
Object {
"defaultMessage": "Username",
"id": "add_command.username.placeholder",
}
}
type="text" type="text"
value="username" value="username"
/> />
@@ -288,12 +303,17 @@ exports[`components/integrations/AbstractCommand should match snapshot 1`] = `
<div <div
className="col-md-5 col-sm-8" className="col-md-5 col-sm-8"
> >
<input <LocalizedPlaceholderInput
className="form-control" className="form-control"
id="iconUrl" id="iconUrl"
maxLength={1024} maxLength={1024}
onChange={[Function]} onChange={[Function]}
placeholder="https://www.example.com/myicon.png" placeholder={
Object {
"defaultMessage": "https://www.example.com/myicon.png",
"id": "add_command.iconUrl.placeholder",
}
}
type="text" type="text"
value="https://google.com/icon" value="https://google.com/icon"
/> />
@@ -353,12 +373,17 @@ exports[`components/integrations/AbstractCommand should match snapshot 1`] = `
<div <div
className="col-md-5 col-sm-8" className="col-md-5 col-sm-8"
> >
<input <LocalizedPlaceholderInput
className="form-control" className="form-control"
id="autocompleteHint" id="autocompleteHint"
maxLength={1024} maxLength={1024}
onChange={[Function]} onChange={[Function]}
placeholder="Example: [Patient Name]" placeholder={
Object {
"defaultMessage": "Example: [Patient Name]",
"id": "add_command.autocompleteHint.placeholder",
}
}
type="text" type="text"
value="auto_complete_hint" value="auto_complete_hint"
/> />
@@ -387,12 +412,17 @@ exports[`components/integrations/AbstractCommand should match snapshot 1`] = `
<div <div
className="col-md-5 col-sm-8" className="col-md-5 col-sm-8"
> >
<input <LocalizedPlaceholderInput
className="form-control" className="form-control"
id="description" id="description"
maxLength={128} maxLength={128}
onChange={[Function]} onChange={[Function]}
placeholder="Example: \\"Returns search results for patient records\\"" placeholder={
Object {
"defaultMessage": "Example: \\"Returns search results for patient records\\"",
"id": "add_command.autocompleteDescription.placeholder",
}
}
type="text" type="text"
value="auto_complete_desc" value="auto_complete_desc"
/> />
@@ -432,7 +462,12 @@ exports[`components/integrations/AbstractCommand should match snapshot 1`] = `
id="saveCommand" id="saveCommand"
onClick={[Function]} onClick={[Function]}
spinning={false} spinning={false}
spinningText="Loading" spinningText={
Object {
"defaultMessage": "Loading",
"id": "Loading",
}
}
type="submit" type="submit"
> >
<MemoizedFormattedMessage <MemoizedFormattedMessage
@@ -554,12 +589,17 @@ exports[`components/integrations/AbstractCommand should match snapshot when head
<div <div
className="col-md-5 col-sm-8" className="col-md-5 col-sm-8"
> >
<input <LocalizedPlaceholderInput
className="form-control" className="form-control"
id="trigger" id="trigger"
maxLength={128} maxLength={128}
onChange={[Function]} onChange={[Function]}
placeholder="Command trigger e.g. \\"hello\\" not including the slash" placeholder={
Object {
"defaultMessage": "Command trigger e.g. \\"hello\\" not including the slash",
"id": "add_command.trigger.placeholder",
}
}
type="text" type="text"
value="trigger" value="trigger"
/> />
@@ -619,7 +659,12 @@ exports[`components/integrations/AbstractCommand should match snapshot when head
> >
<OAuthConnectionAudienceInput <OAuthConnectionAudienceInput
onChange={[Function]} onChange={[Function]}
placeholder="Must start with http:// or https://" placeholder={
Object {
"defaultMessage": "Must start with http:// or https://",
"id": "add_command.url.placeholder",
}
}
value="https://google.com/command" value="https://google.com/command"
/> />
<div <div
@@ -702,12 +747,17 @@ exports[`components/integrations/AbstractCommand should match snapshot when head
<div <div
className="col-md-5 col-sm-8" className="col-md-5 col-sm-8"
> >
<input <LocalizedPlaceholderInput
className="form-control" className="form-control"
id="username" id="username"
maxLength={64} maxLength={64}
onChange={[Function]} onChange={[Function]}
placeholder="Username" placeholder={
Object {
"defaultMessage": "Username",
"id": "add_command.username.placeholder",
}
}
type="text" type="text"
value="username" value="username"
/> />
@@ -736,12 +786,17 @@ exports[`components/integrations/AbstractCommand should match snapshot when head
<div <div
className="col-md-5 col-sm-8" className="col-md-5 col-sm-8"
> >
<input <LocalizedPlaceholderInput
className="form-control" className="form-control"
id="iconUrl" id="iconUrl"
maxLength={1024} maxLength={1024}
onChange={[Function]} onChange={[Function]}
placeholder="https://www.example.com/myicon.png" placeholder={
Object {
"defaultMessage": "https://www.example.com/myicon.png",
"id": "add_command.iconUrl.placeholder",
}
}
type="text" type="text"
value="https://google.com/icon" value="https://google.com/icon"
/> />
@@ -801,12 +856,17 @@ exports[`components/integrations/AbstractCommand should match snapshot when head
<div <div
className="col-md-5 col-sm-8" className="col-md-5 col-sm-8"
> >
<input <LocalizedPlaceholderInput
className="form-control" className="form-control"
id="autocompleteHint" id="autocompleteHint"
maxLength={1024} maxLength={1024}
onChange={[Function]} onChange={[Function]}
placeholder="Example: [Patient Name]" placeholder={
Object {
"defaultMessage": "Example: [Patient Name]",
"id": "add_command.autocompleteHint.placeholder",
}
}
type="text" type="text"
value="auto_complete_hint" value="auto_complete_hint"
/> />
@@ -835,12 +895,17 @@ exports[`components/integrations/AbstractCommand should match snapshot when head
<div <div
className="col-md-5 col-sm-8" className="col-md-5 col-sm-8"
> >
<input <LocalizedPlaceholderInput
className="form-control" className="form-control"
id="description" id="description"
maxLength={128} maxLength={128}
onChange={[Function]} onChange={[Function]}
placeholder="Example: \\"Returns search results for patient records\\"" placeholder={
Object {
"defaultMessage": "Example: \\"Returns search results for patient records\\"",
"id": "add_command.autocompleteDescription.placeholder",
}
}
type="text" type="text"
value="auto_complete_desc" value="auto_complete_desc"
/> />
@@ -1002,12 +1067,17 @@ exports[`components/integrations/AbstractCommand should match snapshot, displays
<div <div
className="col-md-5 col-sm-8" className="col-md-5 col-sm-8"
> >
<input <LocalizedPlaceholderInput
className="form-control" className="form-control"
id="trigger" id="trigger"
maxLength={128} maxLength={128}
onChange={[Function]} onChange={[Function]}
placeholder="Command trigger e.g. \\"hello\\" not including the slash" placeholder={
Object {
"defaultMessage": "Command trigger e.g. \\"hello\\" not including the slash",
"id": "add_command.trigger.placeholder",
}
}
type="text" type="text"
value="" value=""
/> />
@@ -1067,7 +1137,12 @@ exports[`components/integrations/AbstractCommand should match snapshot, displays
> >
<OAuthConnectionAudienceInput <OAuthConnectionAudienceInput
onChange={[Function]} onChange={[Function]}
placeholder="Must start with http:// or https://" placeholder={
Object {
"defaultMessage": "Must start with http:// or https://",
"id": "add_command.url.placeholder",
}
}
value="https://google.com/command" value="https://google.com/command"
/> />
<div <div
@@ -1150,12 +1225,17 @@ exports[`components/integrations/AbstractCommand should match snapshot, displays
<div <div
className="col-md-5 col-sm-8" className="col-md-5 col-sm-8"
> >
<input <LocalizedPlaceholderInput
className="form-control" className="form-control"
id="username" id="username"
maxLength={64} maxLength={64}
onChange={[Function]} onChange={[Function]}
placeholder="Username" placeholder={
Object {
"defaultMessage": "Username",
"id": "add_command.username.placeholder",
}
}
type="text" type="text"
value="username" value="username"
/> />
@@ -1184,12 +1264,17 @@ exports[`components/integrations/AbstractCommand should match snapshot, displays
<div <div
className="col-md-5 col-sm-8" className="col-md-5 col-sm-8"
> >
<input <LocalizedPlaceholderInput
className="form-control" className="form-control"
id="iconUrl" id="iconUrl"
maxLength={1024} maxLength={1024}
onChange={[Function]} onChange={[Function]}
placeholder="https://www.example.com/myicon.png" placeholder={
Object {
"defaultMessage": "https://www.example.com/myicon.png",
"id": "add_command.iconUrl.placeholder",
}
}
type="text" type="text"
value="https://google.com/icon" value="https://google.com/icon"
/> />
@@ -1249,12 +1334,17 @@ exports[`components/integrations/AbstractCommand should match snapshot, displays
<div <div
className="col-md-5 col-sm-8" className="col-md-5 col-sm-8"
> >
<input <LocalizedPlaceholderInput
className="form-control" className="form-control"
id="autocompleteHint" id="autocompleteHint"
maxLength={1024} maxLength={1024}
onChange={[Function]} onChange={[Function]}
placeholder="Example: [Patient Name]" placeholder={
Object {
"defaultMessage": "Example: [Patient Name]",
"id": "add_command.autocompleteHint.placeholder",
}
}
type="text" type="text"
value="auto_complete_hint" value="auto_complete_hint"
/> />
@@ -1283,12 +1373,17 @@ exports[`components/integrations/AbstractCommand should match snapshot, displays
<div <div
className="col-md-5 col-sm-8" className="col-md-5 col-sm-8"
> >
<input <LocalizedPlaceholderInput
className="form-control" className="form-control"
id="description" id="description"
maxLength={128} maxLength={128}
onChange={[Function]} onChange={[Function]}
placeholder="Example: \\"Returns search results for patient records\\"" placeholder={
Object {
"defaultMessage": "Example: \\"Returns search results for patient records\\"",
"id": "add_command.autocompleteDescription.placeholder",
}
}
type="text" type="text"
value="auto_complete_desc" value="auto_complete_desc"
/> />
@@ -1331,7 +1426,12 @@ exports[`components/integrations/AbstractCommand should match snapshot, displays
id="saveCommand" id="saveCommand"
onClick={[Function]} onClick={[Function]}
spinning={false} spinning={false}
spinningText="Loading" spinningText={
Object {
"defaultMessage": "Loading",
"id": "Loading",
}
}
type="submit" type="submit"
> >
<MemoizedFormattedMessage <MemoizedFormattedMessage

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

@@ -246,7 +246,12 @@ exports[`components/integrations/AbstractIncomingWebhook should call action func
id="saveWebhook" id="saveWebhook"
onClick={[Function]} onClick={[Function]}
spinning={false} spinning={false}
spinningText="Loading" spinningText={
Object {
"defaultMessage": "Loading",
"id": "loading_id",
}
}
type="submit" type="submit"
> >
<MemoizedFormattedMessage <MemoizedFormattedMessage
@@ -506,7 +511,12 @@ exports[`components/integrations/AbstractIncomingWebhook should match snapshot 1
id="saveWebhook" id="saveWebhook"
onClick={[Function]} onClick={[Function]}
spinning={false} spinning={false}
spinningText="Loading" spinningText={
Object {
"defaultMessage": "Loading",
"id": "loading_id",
}
}
type="submit" type="submit"
> >
<MemoizedFormattedMessage <MemoizedFormattedMessage
@@ -769,7 +779,12 @@ exports[`components/integrations/AbstractIncomingWebhook should match snapshot,
id="saveWebhook" id="saveWebhook"
onClick={[Function]} onClick={[Function]}
spinning={false} spinning={false}
spinningText="Loading" spinningText={
Object {
"defaultMessage": "Loading",
"id": "loading_id",
}
}
type="submit" type="submit"
> >
<MemoizedFormattedMessage <MemoizedFormattedMessage
@@ -996,7 +1011,12 @@ exports[`components/integrations/AbstractIncomingWebhook should match snapshot,
id="saveWebhook" id="saveWebhook"
onClick={[Function]} onClick={[Function]}
spinning={false} spinning={false}
spinningText="Loading" spinningText={
Object {
"defaultMessage": "Loading",
"id": "loading_id",
}
}
type="submit" type="submit"
> >
<MemoizedFormattedMessage <MemoizedFormattedMessage
@@ -1223,7 +1243,12 @@ exports[`components/integrations/AbstractIncomingWebhook should match snapshot,
id="saveWebhook" id="saveWebhook"
onClick={[Function]} onClick={[Function]}
spinning={false} spinning={false}
spinningText="Loading" spinningText={
Object {
"defaultMessage": "Loading",
"id": "loading_id",
}
}
type="submit" type="submit"
> >
<MemoizedFormattedMessage <MemoizedFormattedMessage
@@ -1483,7 +1508,12 @@ exports[`components/integrations/AbstractIncomingWebhook should match snapshot,
id="saveWebhook" id="saveWebhook"
onClick={[Function]} onClick={[Function]}
spinning={false} spinning={false}
spinningText="Loading" spinningText={
Object {
"defaultMessage": "Loading",
"id": "loading_id",
}
}
type="submit" type="submit"
> >
<MemoizedFormattedMessage <MemoizedFormattedMessage

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

@@ -287,7 +287,12 @@ https://test.com/callback2"
id="saveOauthApp" id="saveOauthApp"
onClick={[Function]} onClick={[Function]}
spinning={false} spinning={false}
spinningText="Loading" spinningText={
Object {
"defaultMessage": "Loading",
"id": "Loading",
}
}
type="submit" type="submit"
> >
<MemoizedFormattedMessage <MemoizedFormattedMessage
@@ -593,7 +598,12 @@ exports[`components/integrations/AbstractOAuthApp should match snapshot, display
id="saveOauthApp" id="saveOauthApp"
onClick={[Function]} onClick={[Function]}
spinning={false} spinning={false}
spinningText="Loading" spinningText={
Object {
"defaultMessage": "Loading",
"id": "Loading",
}
}
type="submit" type="submit"
> >
<MemoizedFormattedMessage <MemoizedFormattedMessage

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

@@ -332,7 +332,12 @@ callbackUrl2.com
id="saveWebhook" id="saveWebhook"
onClick={[Function]} onClick={[Function]}
spinning={false} spinning={false}
spinningText="Loading" spinningText={
Object {
"defaultMessage": "Loading",
"id": "loading_id",
}
}
type="submit" type="submit"
> >
<MemoizedFormattedMessage <MemoizedFormattedMessage

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

@@ -1,14 +1,13 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import {shallow} from 'enzyme';
import React from 'react'; import React from 'react';
import type {FormEvent} from 'react'; import type {FormEvent} from 'react';
import {FormattedMessage} from 'react-intl'; import {FormattedMessage} from 'react-intl';
import AbstractCommand from 'components/integrations/abstract_command'; import AbstractCommand from 'components/integrations/abstract_command';
import type {AbstractCommand as AbstractCommandClass} from 'components/integrations/abstract_command';
import {shallowWithIntl} from 'tests/helpers/intl-test-helper';
import {TestHelper} from 'utils/test_helper'; import {TestHelper} from 'utils/test_helper';
describe('components/integrations/AbstractCommand', () => { describe('components/integrations/AbstractCommand', () => {
@@ -57,14 +56,14 @@ describe('components/integrations/AbstractCommand', () => {
}; };
test('should match snapshot', () => { test('should match snapshot', () => {
const wrapper = shallowWithIntl( const wrapper = shallow(
<AbstractCommand {...baseProps}/>, <AbstractCommand {...baseProps}/>,
); );
expect(wrapper).toMatchSnapshot(); expect(wrapper).toMatchSnapshot();
}); });
test('should match snapshot when header/footer/loading is a string', () => { test('should match snapshot when header/footer/loading is a string', () => {
const wrapper = shallowWithIntl( const wrapper = shallow(
<AbstractCommand <AbstractCommand
{...baseProps} {...baseProps}
header='Header as string' header='Header as string'
@@ -78,7 +77,7 @@ describe('components/integrations/AbstractCommand', () => {
test('should match snapshot, displays client error', () => { test('should match snapshot, displays client error', () => {
const newSeverError = 'server error'; const newSeverError = 'server error';
const props = {...baseProps, serverError: newSeverError}; const props = {...baseProps, serverError: newSeverError};
const wrapper = shallowWithIntl( const wrapper = shallow(
<AbstractCommand {...props}/>, <AbstractCommand {...props}/>,
); );
@@ -90,7 +89,7 @@ describe('components/integrations/AbstractCommand', () => {
}); });
test('should call action function', () => { test('should call action function', () => {
const wrapper = shallowWithIntl( const wrapper = shallow(
<AbstractCommand {...baseProps}/>, <AbstractCommand {...baseProps}/>,
); );
@@ -101,10 +100,10 @@ describe('components/integrations/AbstractCommand', () => {
}); });
test('should match object returned by getStateFromCommand', () => { test('should match object returned by getStateFromCommand', () => {
const wrapper = shallowWithIntl( const wrapper = shallow<AbstractCommand>(
<AbstractCommand {...baseProps}/>, <AbstractCommand {...baseProps}/>,
); );
const instance = wrapper.instance() as AbstractCommandClass; const instance = wrapper.instance();
const expectedOutput = { const expectedOutput = {
autocomplete: true, autocomplete: true,
@@ -125,10 +124,10 @@ describe('components/integrations/AbstractCommand', () => {
}); });
test('should match state when method is called', () => { test('should match state when method is called', () => {
const wrapper = shallowWithIntl( const wrapper = shallow<AbstractCommand>(
<AbstractCommand {...baseProps}/>, <AbstractCommand {...baseProps}/>,
); );
const instance = wrapper.instance() as AbstractCommandClass; const instance = wrapper.instance();
const displayName = 'new display_name'; const displayName = 'new display_name';
const displayNameEvent = {preventDefault: jest.fn(), target: {value: displayName}} as any; const displayNameEvent = {preventDefault: jest.fn(), target: {value: displayName}} as any;
@@ -192,10 +191,10 @@ describe('components/integrations/AbstractCommand', () => {
}, },
); );
const props = {...baseProps, action: newAction}; const props = {...baseProps, action: newAction};
const wrapper = shallowWithIntl( const wrapper = shallow<AbstractCommand>(
<AbstractCommand {...props}/>, <AbstractCommand {...props}/>,
); );
const instance = wrapper.instance() as AbstractCommandClass; const instance = wrapper.instance();
expect(newAction).toHaveBeenCalledTimes(0); expect(newAction).toHaveBeenCalledTimes(0);
const evt = {preventDefault: jest.fn()} as unknown as FormEvent<Element>; const evt = {preventDefault: jest.fn()} as unknown as FormEvent<Element>;

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

@@ -3,7 +3,7 @@
import React from 'react'; import React from 'react';
import type {ChangeEvent} from 'react'; import type {ChangeEvent} from 'react';
import {FormattedMessage, type MessageDescriptor, injectIntl, type IntlShape} from 'react-intl'; import {defineMessage, FormattedMessage, type MessageDescriptor} from 'react-intl';
import {Link} from 'react-router-dom'; import {Link} from 'react-router-dom';
import type {Command} from '@mattermost/types/integrations'; import type {Command} from '@mattermost/types/integrations';
@@ -12,6 +12,7 @@ import type {Team} from '@mattermost/types/teams';
import BackstageHeader from 'components/backstage/components/backstage_header'; import BackstageHeader from 'components/backstage/components/backstage_header';
import ExternalLink from 'components/external_link'; import ExternalLink from 'components/external_link';
import FormError from 'components/form_error'; import FormError from 'components/form_error';
import LocalizedPlaceholderInput from 'components/localized_placeholder_input';
import SpinnerButton from 'components/spinner_button'; import SpinnerButton from 'components/spinner_button';
import {Constants, DeveloperLinks} from 'utils/constants'; import {Constants, DeveloperLinks} from 'utils/constants';
@@ -63,8 +64,6 @@ type Props = {
* The async function to run when the action button is pressed * The async function to run when the action button is pressed
*/ */
action: (command: Command) => Promise<void>; action: (command: Command) => Promise<void>;
intl: IntlShape;
} }
type State = { type State = {
@@ -82,7 +81,7 @@ type State = {
autocompleteDescription: string; autocompleteDescription: string;
} }
export class AbstractCommand extends React.PureComponent<Props, State> { export default class AbstractCommand extends React.PureComponent<Props, State> {
constructor(props: Props) { constructor(props: Props) {
super(props); super(props);
@@ -331,14 +330,14 @@ export class AbstractCommand extends React.PureComponent<Props, State> {
/> />
</label> </label>
<div className='col-md-5 col-sm-8'> <div className='col-md-5 col-sm-8'>
<input <LocalizedPlaceholderInput
id='autocompleteHint' id='autocompleteHint'
type='text' type='text'
maxLength={1024} maxLength={1024}
className='form-control' className='form-control'
value={this.state.autocompleteHint} value={this.state.autocompleteHint}
onChange={this.updateAutocompleteHint} onChange={this.updateAutocompleteHint}
placeholder={this.props.intl.formatMessage({ placeholder={defineMessage({
id: 'add_command.autocompleteHint.placeholder', id: 'add_command.autocompleteHint.placeholder',
defaultMessage: 'Example: [Patient Name]', defaultMessage: 'Example: [Patient Name]',
})} })}
@@ -365,14 +364,14 @@ export class AbstractCommand extends React.PureComponent<Props, State> {
/> />
</label> </label>
<div className='col-md-5 col-sm-8'> <div className='col-md-5 col-sm-8'>
<input <LocalizedPlaceholderInput
id='description' id='description'
type='text' type='text'
maxLength={128} maxLength={128}
className='form-control' className='form-control'
value={this.state.autocompleteDescription} value={this.state.autocompleteDescription}
onChange={this.updateAutocompleteDescription} onChange={this.updateAutocompleteDescription}
placeholder={this.props.intl.formatMessage({ placeholder={defineMessage({
id: 'add_command.autocompleteDescription.placeholder', id: 'add_command.autocompleteDescription.placeholder',
defaultMessage: 'Example: "Returns search results for patient records"', defaultMessage: 'Example: "Returns search results for patient records"',
})} })}
@@ -469,14 +468,14 @@ export class AbstractCommand extends React.PureComponent<Props, State> {
/> />
</label> </label>
<div className='col-md-5 col-sm-8'> <div className='col-md-5 col-sm-8'>
<input <LocalizedPlaceholderInput
id='trigger' id='trigger'
type='text' type='text'
maxLength={Constants.MAX_TRIGGER_LENGTH} maxLength={Constants.MAX_TRIGGER_LENGTH}
className='form-control' className='form-control'
value={this.state.trigger} value={this.state.trigger}
onChange={this.updateTrigger} onChange={this.updateTrigger}
placeholder={this.props.intl.formatMessage({ placeholder={defineMessage({
id: 'add_command.trigger.placeholder', id: 'add_command.trigger.placeholder',
defaultMessage: 'Command trigger e.g. "hello" not including the slash', defaultMessage: 'Command trigger e.g. "hello" not including the slash',
})} })}
@@ -528,7 +527,7 @@ export class AbstractCommand extends React.PureComponent<Props, State> {
<OAuthConnectionAudienceInput <OAuthConnectionAudienceInput
value={this.state.url} value={this.state.url}
onChange={this.updateUrl} onChange={this.updateUrl}
placeholder={this.props.intl.formatMessage({ placeholder={defineMessage({
id: 'add_command.url.placeholder', id: 'add_command.url.placeholder',
defaultMessage: 'Must start with http:// or https://', defaultMessage: 'Must start with http:// or https://',
})} })}
@@ -595,14 +594,14 @@ export class AbstractCommand extends React.PureComponent<Props, State> {
/> />
</label> </label>
<div className='col-md-5 col-sm-8'> <div className='col-md-5 col-sm-8'>
<input <LocalizedPlaceholderInput
id='username' id='username'
type='text' type='text'
maxLength={64} maxLength={64}
className='form-control' className='form-control'
value={this.state.username} value={this.state.username}
onChange={this.updateUsername} onChange={this.updateUsername}
placeholder={this.props.intl.formatMessage({ placeholder={defineMessage({
id: 'add_command.username.placeholder', id: 'add_command.username.placeholder',
defaultMessage: 'Username', defaultMessage: 'Username',
})} })}
@@ -626,14 +625,14 @@ export class AbstractCommand extends React.PureComponent<Props, State> {
/> />
</label> </label>
<div className='col-md-5 col-sm-8'> <div className='col-md-5 col-sm-8'>
<input <LocalizedPlaceholderInput
id='iconUrl' id='iconUrl'
type='text' type='text'
maxLength={1024} maxLength={1024}
className='form-control' className='form-control'
value={this.state.iconUrl} value={this.state.iconUrl}
onChange={this.updateIconUrl} onChange={this.updateIconUrl}
placeholder={this.props.intl.formatMessage({ placeholder={defineMessage({
id: 'add_command.iconUrl.placeholder', id: 'add_command.iconUrl.placeholder',
defaultMessage: 'https://www.example.com/myicon.png', defaultMessage: 'https://www.example.com/myicon.png',
})} })}
@@ -691,7 +690,7 @@ export class AbstractCommand extends React.PureComponent<Props, State> {
className='btn btn-primary' className='btn btn-primary'
type='submit' type='submit'
spinning={this.state.saving} spinning={this.state.saving}
spinningText={typeof this.props.loading === 'string' ? this.props.loading : Utils.localizeMessage({id: this.props.loading?.id ?? '', defaultMessage: this.props.loading?.defaultMessage as string})} spinningText={this.props.loading}
onClick={this.handleSubmit} onClick={this.handleSubmit}
id='saveCommand' id='saveCommand'
> >
@@ -705,5 +704,3 @@ export class AbstractCommand extends React.PureComponent<Props, State> {
); );
} }
} }
export default injectIntl(AbstractCommand);

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

@@ -15,8 +15,6 @@ import ChannelSelect from 'components/channel_select';
import FormError from 'components/form_error'; import FormError from 'components/form_error';
import SpinnerButton from 'components/spinner_button'; import SpinnerButton from 'components/spinner_button';
import {localizeMessage} from 'utils/utils';
interface State { interface State {
displayName: string; displayName: string;
description: string; description: string;
@@ -383,7 +381,7 @@ export default class AbstractIncomingWebhook extends PureComponent<Props, State>
className='btn btn-primary' className='btn btn-primary'
type='submit' type='submit'
spinning={this.state.saving} spinning={this.state.saving}
spinningText={localizeMessage({id: this.props.loading.id as string, defaultMessage: this.props.loading.defaultMessage as string})} spinningText={this.props.loading}
onClick={(e) => this.handleSubmit(e)} onClick={(e) => this.handleSubmit(e)}
id='saveWebhook' id='saveWebhook'
> >

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

@@ -17,8 +17,6 @@ import FormError from 'components/form_error';
import SystemPermissionGate from 'components/permissions_gates/system_permission_gate'; import SystemPermissionGate from 'components/permissions_gates/system_permission_gate';
import SpinnerButton from 'components/spinner_button'; import SpinnerButton from 'components/spinner_button';
import {localizeMessage} from 'utils/utils';
type Props = { type Props = {
/** /**
@@ -477,7 +475,7 @@ export default class AbstractOAuthApp extends React.PureComponent<Props, State>
className='btn btn-primary' className='btn btn-primary'
type='submit' type='submit'
spinning={this.state.saving} spinning={this.state.saving}
spinningText={localizeMessage({id: this.props.loading?.id || '', defaultMessage: (this.props.loading?.defaultMessage || '') as string})} spinningText={this.props.loading}
onClick={this.handleSubmit} onClick={this.handleSubmit}
id='saveOauthApp' id='saveOauthApp'
> >

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

@@ -594,7 +594,7 @@ export default class AbstractOutgoingWebhook extends React.PureComponent<Props,
className='btn btn-primary' className='btn btn-primary'
type='submit' type='submit'
spinning={this.state.saving} spinning={this.state.saving}
spinningText={localizeMessage({id: this.props.loading.id as string, defaultMessage: this.props.loading.defaultMessage as string})} spinningText={this.props.loading}
onClick={this.handleSubmit} onClick={this.handleSubmit}
id='saveWebhook' id='saveWebhook'
> >

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

@@ -1,7 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`components/integrations/AddCommand should match snapshot 1`] = ` exports[`components/integrations/AddCommand should match snapshot 1`] = `
<injectIntl(AbstractCommand) <AbstractCommand
action={[Function]} action={[Function]}
footer="Save" footer="Save"
header="Add" header="Add"

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

@@ -29,7 +29,7 @@ exports[`components/integrations/EditCommand should have match renderExtra 1`] =
`; `;
exports[`components/integrations/EditCommand should match snapshot 1`] = ` exports[`components/integrations/EditCommand should match snapshot 1`] = `
<injectIntl(AbstractCommand) <AbstractCommand
action={[Function]} action={[Function]}
footer={ footer={
Object { Object {

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше