PLT-7: Refactoring frontend (chunk 9)
- sidebar right & rhs
Этот коммит содержится в:
@@ -16,10 +16,32 @@ import FilePreview from './file_preview.jsx';
|
||||
import * as Utils from '../utils/utils.jsx';
|
||||
|
||||
import Constants from '../utils/constants.jsx';
|
||||
|
||||
import {intlShape, injectIntl, defineMessages, FormattedMessage} from 'mm-intl';
|
||||
|
||||
const ActionTypes = Constants.ActionTypes;
|
||||
const KeyCodes = Constants.KeyCodes;
|
||||
|
||||
export default class CreateComment extends React.Component {
|
||||
const holders = defineMessages({
|
||||
commentLength: {
|
||||
id: 'create_comment.commentLength',
|
||||
defaultMessage: 'Comment length must be less than {max} characters.'
|
||||
},
|
||||
comment: {
|
||||
id: 'create_comment.comment',
|
||||
defaultMessage: 'Add Comment'
|
||||
},
|
||||
addComment: {
|
||||
id: 'create_comment.addComment',
|
||||
defaultMessage: 'Add a comment...'
|
||||
},
|
||||
commentTitle: {
|
||||
id: 'create_comment.commentTitle',
|
||||
defaultMessage: 'Comment'
|
||||
}
|
||||
});
|
||||
|
||||
class CreateComment extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
@@ -93,7 +115,7 @@ export default class CreateComment extends React.Component {
|
||||
}
|
||||
|
||||
if (post.message.length > Constants.CHARACTER_LIMIT) {
|
||||
this.setState({postError: `Comment length must be less than ${Constants.CHARACTER_LIMIT} characters.`});
|
||||
this.setState({postError: this.props.intl.formatMessage(holders.commentLength, {max: Constants.CHARACTER_LIMIT})});
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -189,7 +211,7 @@ export default class CreateComment extends React.Component {
|
||||
AppDispatcher.handleViewAction({
|
||||
type: ActionTypes.RECIEVED_EDIT_POST,
|
||||
refocusId: '#reply_textbox',
|
||||
title: 'Comment',
|
||||
title: this.props.intl.formatMessage(holders.commentTitle),
|
||||
message: lastPost.message,
|
||||
postId: lastPost.id,
|
||||
channelId: lastPost.channel_id,
|
||||
@@ -305,14 +327,23 @@ export default class CreateComment extends React.Component {
|
||||
let uploadsInProgressText = null;
|
||||
if (this.state.uploadsInProgress.length > 0) {
|
||||
uploadsInProgressText = (
|
||||
<span
|
||||
className='pull-right post-right-comments-upload-in-progress'
|
||||
>
|
||||
{this.state.uploadsInProgress.length === 1 ? 'File uploading' : 'Files uploading'}
|
||||
<span className='pull-right post-right-comments-upload-in-progress'>
|
||||
{this.state.uploadsInProgress.length === 1 ? (
|
||||
<FormattedMessage
|
||||
id='create_comment.file'
|
||||
defaultMessage='File uploading'
|
||||
/>
|
||||
) : (
|
||||
<FormattedMessage
|
||||
id='create_comment.files'
|
||||
defaultMessage='Files uploading'
|
||||
/>
|
||||
)}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
const {formatMessage} = this.props.intl;
|
||||
return (
|
||||
<form onSubmit={this.handleSubmit}>
|
||||
<div className='post-create'>
|
||||
@@ -326,7 +357,7 @@ export default class CreateComment extends React.Component {
|
||||
onKeyPress={this.commentMsgKeyPress}
|
||||
onKeyDown={this.handleKeyDown}
|
||||
messageText={this.state.messageText}
|
||||
createMessage='Add a comment...'
|
||||
createMessage={formatMessage(holders.addComment)}
|
||||
initialText=''
|
||||
supportsCommands={false}
|
||||
id='reply_textbox'
|
||||
@@ -351,7 +382,7 @@ export default class CreateComment extends React.Component {
|
||||
<input
|
||||
type='button'
|
||||
className='btn btn-primary comment-btn pull-right'
|
||||
value='Add Comment'
|
||||
value={formatMessage(holders.comment)}
|
||||
onClick={this.handleSubmit}
|
||||
/>
|
||||
{uploadsInProgressText}
|
||||
@@ -366,6 +397,9 @@ export default class CreateComment extends React.Component {
|
||||
}
|
||||
|
||||
CreateComment.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
channelId: React.PropTypes.string.isRequired,
|
||||
rootId: React.PropTypes.string.isRequired
|
||||
};
|
||||
|
||||
export default injectIntl(CreateComment);
|
||||
@@ -6,7 +6,24 @@ import Constants from '../utils/constants.jsx';
|
||||
import ChannelStore from '../stores/channel_store.jsx';
|
||||
import * as Utils from '../utils/utils.jsx';
|
||||
|
||||
export default class FileUpload extends React.Component {
|
||||
import {intlShape, injectIntl, defineMessages} from 'mm-intl';
|
||||
|
||||
const holders = defineMessages({
|
||||
limited: {
|
||||
id: 'file_upload.limited',
|
||||
defaultMessage: 'Uploads limited to {count} files maximum. Please use additional posts for more files.'
|
||||
},
|
||||
filesAbove: {
|
||||
id: 'file_upload.filesAbove',
|
||||
defaultMessage: 'Files above {max}MB could not be uploaded: {filenames}'
|
||||
},
|
||||
fileAbove: {
|
||||
id: 'file_upload.fileAbove',
|
||||
defaultMessage: 'File above {max}MB could not be uploaded: {filename}'
|
||||
}
|
||||
});
|
||||
|
||||
class FileUpload extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
@@ -74,14 +91,15 @@ export default class FileUpload extends React.Component {
|
||||
numUploads += 1;
|
||||
}
|
||||
|
||||
const {formatMessage} = this.props.intl;
|
||||
if (files.length > uploadsRemaining) {
|
||||
this.props.onUploadError(`Uploads limited to ${Constants.MAX_UPLOAD_FILES} files maximum. Please use additional posts for more files.`);
|
||||
this.props.onUploadError(formatMessage(holders.limited, {count: Constants.MAX_UPLOAD_FILES}));
|
||||
} else if (tooLargeFiles.length > 1) {
|
||||
var tooLargeFilenames = tooLargeFiles.map((file) => file.name).join(', ');
|
||||
|
||||
this.props.onUploadError(`Files above ${Constants.MAX_FILE_SIZE / 1000000}MB could not be uploaded: ${tooLargeFilenames}`);
|
||||
this.props.onUploadError(formatMessage(holders.filesAbove, {max: (Constants.MAX_FILE_SIZE / 1000000), files: tooLargeFilenames}));
|
||||
} else if (tooLargeFiles.length > 0) {
|
||||
this.props.onUploadError(`File above ${Constants.MAX_FILE_SIZE / 1000000}MB could not be uploaded: ${tooLargeFiles[0].name}`);
|
||||
this.props.onUploadError(formatMessage(holders.fileAbove, {max: (Constants.MAX_FILE_SIZE / 1000000), file: tooLargeFiles[0].name}));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,6 +124,7 @@ export default class FileUpload extends React.Component {
|
||||
componentDidMount() {
|
||||
var inputDiv = ReactDOM.findDOMNode(this.refs.input);
|
||||
var self = this;
|
||||
const {formatMessage} = this.props.intl;
|
||||
|
||||
if (this.props.postType === 'post') {
|
||||
$('.row.main').dragster({
|
||||
@@ -184,7 +203,7 @@ export default class FileUpload extends React.Component {
|
||||
var numToUpload = Math.min(Constants.MAX_UPLOAD_FILES - self.props.getFileCount(ChannelStore.getCurrentId()), numItems);
|
||||
|
||||
if (numItems > numToUpload) {
|
||||
self.props.onUploadError('Uploads limited to ' + Constants.MAX_UPLOAD_FILES + ' files maximum. Please use additional posts for more files.');
|
||||
self.props.onUploadError(formatMessage(holders.limited, {count: Constants.MAX_UPLOAD_FILES}));
|
||||
}
|
||||
|
||||
for (var i = 0; i < items.length && i < numToUpload; i++) {
|
||||
@@ -296,6 +315,7 @@ export default class FileUpload extends React.Component {
|
||||
}
|
||||
|
||||
FileUpload.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
onUploadError: React.PropTypes.func,
|
||||
getFileCount: React.PropTypes.func,
|
||||
onFileUpload: React.PropTypes.func,
|
||||
@@ -304,3 +324,5 @@ FileUpload.propTypes = {
|
||||
channelId: React.PropTypes.string,
|
||||
postType: React.PropTypes.string
|
||||
};
|
||||
|
||||
export default injectIntl(FileUpload);
|
||||
@@ -1,6 +1,8 @@
|
||||
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import {FormattedMessage} from 'mm-intl';
|
||||
|
||||
export default class FileUploadOverlay extends React.Component {
|
||||
render() {
|
||||
var overlayClass = 'file-overlay hidden';
|
||||
@@ -19,7 +21,12 @@ export default class FileUploadOverlay extends React.Component {
|
||||
src='/static/images/filesOverlay.png'
|
||||
alt='Files'
|
||||
/>
|
||||
<span><i className='fa fa-upload'></i>{'Drop a file to upload it.'}</span>
|
||||
<span><i className='fa fa-upload'></i>
|
||||
<FormattedMessage
|
||||
id='upload_overlay.info'
|
||||
defaultMessage='Drop a file to upload it.'
|
||||
/>
|
||||
</span>
|
||||
<img
|
||||
className='overlay__logo'
|
||||
src='/static/images/logoWhite.png'
|
||||
|
||||
@@ -5,9 +5,19 @@ import SocketStore from '../stores/socket_store.jsx';
|
||||
import UserStore from '../stores/user_store.jsx';
|
||||
|
||||
import Constants from '../utils/constants.jsx';
|
||||
|
||||
import {intlShape, injectIntl, defineMessages, FormattedMessage} from 'mm-intl';
|
||||
|
||||
const SocketEvents = Constants.SocketEvents;
|
||||
|
||||
export default class MsgTyping extends React.Component {
|
||||
const holders = defineMessages({
|
||||
someone: {
|
||||
id: 'msg_typing.someone',
|
||||
defaultMessage: 'Someone'
|
||||
}
|
||||
});
|
||||
|
||||
class MsgTyping extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
@@ -44,10 +54,10 @@ export default class MsgTyping extends React.Component {
|
||||
}
|
||||
|
||||
onChange(msg) {
|
||||
let username = 'Someone';
|
||||
let username = this.props.intl.formatMessage(holders.someone);
|
||||
if (msg.action === SocketEvents.TYPING &&
|
||||
this.props.channelId === msg.channel_id &&
|
||||
this.props.parentId === msg.props.parent_id) {
|
||||
this.props.channelId === msg.channel_id &&
|
||||
this.props.parentId === msg.props.parent_id) {
|
||||
if (UserStore.hasProfile(msg.user_id)) {
|
||||
username = UserStore.getProfile(msg.user_id).username;
|
||||
}
|
||||
@@ -80,11 +90,28 @@ export default class MsgTyping extends React.Component {
|
||||
text = '';
|
||||
break;
|
||||
case 1:
|
||||
text = users[0] + ' is typing...';
|
||||
text = (
|
||||
<FormattedMessage
|
||||
id='msg_typing.isTyping'
|
||||
defaultMessage='{user} is typing...'
|
||||
values={{
|
||||
user: users[0]
|
||||
}}
|
||||
/>
|
||||
);
|
||||
break;
|
||||
default: {
|
||||
const last = users.pop();
|
||||
text = users.join(', ') + ' and ' + last + ' are typing...';
|
||||
text = (
|
||||
<FormattedMessage
|
||||
id='msg_typing.areTyping'
|
||||
defaultMessage='{users} and {last} are typing...'
|
||||
vaues={{
|
||||
users: users.join(', '),
|
||||
last: last
|
||||
}}
|
||||
/>
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -100,6 +127,9 @@ export default class MsgTyping extends React.Component {
|
||||
}
|
||||
|
||||
MsgTyping.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
channelId: React.PropTypes.string,
|
||||
parentId: React.PropTypes.string
|
||||
};
|
||||
|
||||
export default injectIntl(MsgTyping);
|
||||
@@ -16,7 +16,16 @@ import * as TextFormatting from '../utils/text_formatting.jsx';
|
||||
import twemoji from 'twemoji';
|
||||
import * as EventHelpers from '../dispatcher/event_helpers.jsx';
|
||||
|
||||
export default class RhsComment extends React.Component {
|
||||
import {intlShape, injectIntl, defineMessages, FormattedMessage, FormattedDate} from 'mm-intl';
|
||||
|
||||
const holders = defineMessages({
|
||||
comment: {
|
||||
id: 'rhs_comment.comment',
|
||||
defaultMessage: 'Comment'
|
||||
}
|
||||
});
|
||||
|
||||
class RhsComment extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
@@ -95,12 +104,15 @@ export default class RhsComment extends React.Component {
|
||||
data-toggle='modal'
|
||||
data-target='#edit_post'
|
||||
data-refocusid='#reply_textbox'
|
||||
data-title='Comment'
|
||||
data-title={this.props.intl.formatMessage(holders.comment)}
|
||||
data-message={post.message}
|
||||
data-postid={post.id}
|
||||
data-channelid={post.channel_id}
|
||||
>
|
||||
{'Edit'}
|
||||
<FormattedMessage
|
||||
id='rhs_comment.edit'
|
||||
defaultMessage='Edit'
|
||||
/>
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
@@ -117,7 +129,10 @@ export default class RhsComment extends React.Component {
|
||||
role='menuitem'
|
||||
onClick={() => EventHelpers.showDeletePostModal(post, 0)}
|
||||
>
|
||||
{'Delete'}
|
||||
<FormattedMessage
|
||||
id='rhs_comment.del'
|
||||
defaultMessage='Delete'
|
||||
/>
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
@@ -165,7 +180,10 @@ export default class RhsComment extends React.Component {
|
||||
href='#'
|
||||
onClick={this.retryComment}
|
||||
>
|
||||
{'Retry'}
|
||||
<FormattedMessage
|
||||
id='rhs_comment.retry'
|
||||
defaultMessage='Retry'
|
||||
/>
|
||||
</a>
|
||||
);
|
||||
} else if (post.state === Constants.POST_LOADING) {
|
||||
@@ -208,7 +226,15 @@ export default class RhsComment extends React.Component {
|
||||
</li>
|
||||
<li className='col'>
|
||||
<time className='post__time'>
|
||||
{Utils.displayCommentDateTime(post.create_at)}
|
||||
<FormattedDate
|
||||
value={post.create_at}
|
||||
day='numeric'
|
||||
month='long'
|
||||
year='numeric'
|
||||
hour12='true'
|
||||
hour='2-digit'
|
||||
minute='2-digit'
|
||||
/>
|
||||
</time>
|
||||
</li>
|
||||
<li className='col col__reply'>
|
||||
@@ -237,5 +263,8 @@ RhsComment.defaultProps = {
|
||||
post: null
|
||||
};
|
||||
RhsComment.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
post: React.PropTypes.object
|
||||
};
|
||||
|
||||
export default injectIntl(RhsComment);
|
||||
@@ -3,6 +3,9 @@
|
||||
|
||||
import AppDispatcher from '../dispatcher/app_dispatcher.jsx';
|
||||
import Constants from '../utils/constants.jsx';
|
||||
|
||||
import {FormattedMessage} from 'mm-intl';
|
||||
|
||||
const ActionTypes = Constants.ActionTypes;
|
||||
|
||||
export default class RhsHeaderPost extends React.Component {
|
||||
@@ -58,7 +61,13 @@ export default class RhsHeaderPost extends React.Component {
|
||||
|
||||
return (
|
||||
<div className='sidebar--right__header'>
|
||||
<span className='sidebar--right__title'>{back}Message Details</span>
|
||||
<span className='sidebar--right__title'>
|
||||
{back}
|
||||
<FormattedMessage
|
||||
id='rhs_header.details'
|
||||
defaultMessage='Message Details'
|
||||
/>
|
||||
</span>
|
||||
<button
|
||||
type='button'
|
||||
className='sidebar--right__close'
|
||||
|
||||
@@ -14,6 +14,8 @@ import * as EventHelpers from '../dispatcher/event_helpers.jsx';
|
||||
|
||||
import Constants from '../utils/constants.jsx';
|
||||
|
||||
import {FormattedMessage, FormattedDate} from 'mm-intl';
|
||||
|
||||
export default class RhsRootPost extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
@@ -68,7 +70,12 @@ export default class RhsRootPost extends React.Component {
|
||||
var channelName;
|
||||
if (channel) {
|
||||
if (channel.type === 'D') {
|
||||
channelName = 'Direct Message';
|
||||
channelName = (
|
||||
<FormattedMessage
|
||||
id='rhs_root.direct'
|
||||
defaultMessage='Direct Message'
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
channelName = channel.display_name;
|
||||
}
|
||||
@@ -93,7 +100,10 @@ export default class RhsRootPost extends React.Component {
|
||||
data-postid={post.id}
|
||||
data-channelid={post.channel_id}
|
||||
>
|
||||
{'Edit'}
|
||||
<FormattedMessage
|
||||
id='rhs_root.edit'
|
||||
defaultMessage='Edit'
|
||||
/>
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
@@ -110,7 +120,10 @@ export default class RhsRootPost extends React.Component {
|
||||
role='menuitem'
|
||||
onClick={() => EventHelpers.showDeletePostModal(post, this.props.commentCount)}
|
||||
>
|
||||
{'Delete'}
|
||||
<FormattedMessage
|
||||
id='rhs_root.del'
|
||||
defaultMessage='Delete'
|
||||
/>
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
@@ -205,7 +218,15 @@ export default class RhsRootPost extends React.Component {
|
||||
{botIndicator}
|
||||
<li className='col'>
|
||||
<time className='post__time'>
|
||||
{utils.displayCommentDateTime(post.create_at)}
|
||||
<FormattedDate
|
||||
value={post.create_at}
|
||||
day='numeric'
|
||||
month='long'
|
||||
year='numeric'
|
||||
hour12='true'
|
||||
hour='2-digit'
|
||||
minute='2-digit'
|
||||
/>
|
||||
</time>
|
||||
</li>
|
||||
<li className='col col__reply'>
|
||||
|
||||
@@ -11,10 +11,20 @@ import SearchSuggestionList from './suggestion/search_suggestion_list.jsx';
|
||||
import SearchUserProvider from './suggestion/search_user_provider.jsx';
|
||||
import * as utils from '../utils/utils.jsx';
|
||||
import Constants from '../utils/constants.jsx';
|
||||
|
||||
import {intlShape, injectIntl, defineMessages, FormattedMessage, FormattedHTMLMessage} from 'mm-intl';
|
||||
|
||||
var ActionTypes = Constants.ActionTypes;
|
||||
var Popover = ReactBootstrap.Popover;
|
||||
|
||||
export default class SearchBar extends React.Component {
|
||||
const holders = defineMessages({
|
||||
search: {
|
||||
id: 'search_bar.search',
|
||||
defaultMessage: 'Search'
|
||||
}
|
||||
});
|
||||
|
||||
class SearchBar extends React.Component {
|
||||
constructor() {
|
||||
super();
|
||||
this.mounted = false;
|
||||
@@ -147,7 +157,10 @@ export default class SearchBar extends React.Component {
|
||||
className='search__clear'
|
||||
onClick={this.clearFocus}
|
||||
>
|
||||
{'Cancel'}
|
||||
<FormattedMessage
|
||||
id='search_bar.cancel'
|
||||
defaultMessage='Cancel'
|
||||
/>
|
||||
</span>
|
||||
<form
|
||||
role='form'
|
||||
@@ -160,7 +173,7 @@ export default class SearchBar extends React.Component {
|
||||
<SuggestionBox
|
||||
ref='search'
|
||||
className='form-control search-bar'
|
||||
placeholder='Search'
|
||||
placeholder={this.props.intl.formatMessage(holders.search)}
|
||||
value={this.state.searchTerm}
|
||||
onFocus={this.handleUserFocus}
|
||||
onBlur={this.handleUserBlur}
|
||||
@@ -174,18 +187,20 @@ export default class SearchBar extends React.Component {
|
||||
placement='bottom'
|
||||
className={helpClass}
|
||||
>
|
||||
<h4>{'Search Options'}</h4>
|
||||
<ul>
|
||||
<li>
|
||||
<span>{'Use '}</span><b>{'"quotation marks"'}</b><span>{' to search for phrases'}</span>
|
||||
</li>
|
||||
<li>
|
||||
<span>{'Use '}</span><b>{'from:'}</b><span>{' to find posts from specific users and '}</span><b>{'in:'}</b><span>{' to find posts in specific channels'}</span>
|
||||
</li>
|
||||
</ul>
|
||||
<FormattedHTMLMessage
|
||||
id='search_bar.usage'
|
||||
defaultMessage='<h4>Search Options</h4><ul><li><span>Use </span><b>"quotation marks"</b><span> to search for phrases</span></li><li><span>Use </span><b>from:</b><span> to find posts from specific users and </span><b>in:</b><span> to find posts in specific channels</span></li></ul>'
|
||||
/>
|
||||
</Popover>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
SearchBar.propTypes = {
|
||||
intl: intlShape.isRequired
|
||||
};
|
||||
|
||||
export default injectIntl(SearchBar);
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@ import * as Utils from '../utils/utils.jsx';
|
||||
import SearchResultsHeader from './search_results_header.jsx';
|
||||
import SearchResultsItem from './search_results_item.jsx';
|
||||
|
||||
import {FormattedMessage, FormattedHTMLMessage} from 'mm-intl';
|
||||
|
||||
function getStateFromStores() {
|
||||
return {results: SearchStore.getSearchResults()};
|
||||
}
|
||||
@@ -83,25 +85,29 @@ export default class SearchResults extends React.Component {
|
||||
if (!searchTerm && noResults) {
|
||||
ctls = (
|
||||
<div className='sidebar--right__subheader'>
|
||||
<ul>
|
||||
<li>
|
||||
{'Use '}<b>{'"quotation marks"'}</b>{' to search for phrases'}
|
||||
</li>
|
||||
<li>
|
||||
{'Use '}<b>{'from:'}</b>{' to find posts from specific users and '}<b>{'in:'}</b>{' to find posts in specific channels'}
|
||||
</li>
|
||||
</ul>
|
||||
<FormattedHTMLMessage
|
||||
id='search_results.usage'
|
||||
defaultMessage='<ul><li>Use <b>"quotation marks"</b> to search for phrases</li><li>Use <b>from:</b> to find posts from specific users and <b>in:</b> to find posts in specific channels</li></ul>'
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
} else if (noResults) {
|
||||
ctls =
|
||||
(
|
||||
<div className='sidebar--right__subheader'>
|
||||
<h4>{'NO RESULTS'}</h4>
|
||||
<ul>
|
||||
<li>{'If you\'re searching a partial phrase (ex. searching "rea", looking for "reach" or "reaction"), append a * to your search term'}</li>
|
||||
<li>{'Due to the volume of results, two letter searches and common words like "this", "a" and "is" won\'t appear in search results'}</li>
|
||||
</ul>
|
||||
<h4>
|
||||
<FormattedMessage
|
||||
id='search_results.noResults'
|
||||
defaultMessage='NO RESULTS'
|
||||
/>
|
||||
</h4>
|
||||
<FormattedHTMLMessage
|
||||
id='search_results.because'
|
||||
defaultMessage='<ul>
|
||||
<li>If you're searching a partial phrase (ex. searching "rea", looking for "reach" or "reaction"), append a * to your search term</li>
|
||||
<li>Due to the volume of results, two letter searches and common words like "this", "a" and "is" won't appear in search results</li>
|
||||
</ul>'
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
|
||||
import AppDispatcher from '../dispatcher/app_dispatcher.jsx';
|
||||
import Constants from '../utils/constants.jsx';
|
||||
|
||||
import {FormattedMessage} from 'mm-intl';
|
||||
|
||||
var ActionTypes = Constants.ActionTypes;
|
||||
|
||||
export default class SearchResultsHeader extends React.Component {
|
||||
@@ -34,10 +37,20 @@ export default class SearchResultsHeader extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
var title = 'Search Results';
|
||||
var title = (
|
||||
<FormattedMessage
|
||||
id='search_header.results'
|
||||
defaultMessage='Search Results'
|
||||
/>
|
||||
);
|
||||
|
||||
if (this.props.isMentionSearch) {
|
||||
title = 'Recent Mentions';
|
||||
title = (
|
||||
<FormattedMessage
|
||||
id='search_header.title2'
|
||||
defaultMessage='Recent Mentions'
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -10,6 +10,8 @@ import * as TextFormatting from '../utils/text_formatting.jsx';
|
||||
|
||||
import Constants from '../utils/constants.jsx';
|
||||
|
||||
import {FormattedMessage, FormattedDate} from 'mm-intl';
|
||||
|
||||
export default class SearchResultsItem extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
@@ -42,7 +44,12 @@ export default class SearchResultsItem extends React.Component {
|
||||
if (channel) {
|
||||
channelName = channel.display_name;
|
||||
if (channel.type === 'D') {
|
||||
channelName = 'Direct Message';
|
||||
channelName = (
|
||||
<FormattedMessage
|
||||
id='search_item.direct'
|
||||
defaultMessage='Direct Message'
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,7 +76,15 @@ export default class SearchResultsItem extends React.Component {
|
||||
<li className='col__name'><strong><UserProfile userId={this.props.post.user_id} /></strong></li>
|
||||
<li className='col'>
|
||||
<time className='search-item-time'>
|
||||
{utils.displayDate(this.props.post.create_at) + ' ' + utils.displayTime(this.props.post.create_at)}
|
||||
<FormattedDate
|
||||
value={this.props.post.create_at}
|
||||
day='numeric'
|
||||
month='long'
|
||||
year='numeric'
|
||||
hour12='true'
|
||||
hour='2-digit'
|
||||
minute='2-digit'
|
||||
/>
|
||||
</time>
|
||||
</li>
|
||||
<li>
|
||||
@@ -78,7 +93,10 @@ export default class SearchResultsItem extends React.Component {
|
||||
className='search-item__jump'
|
||||
onClick={this.handleClick}
|
||||
>
|
||||
{'Jump'}
|
||||
<FormattedMessage
|
||||
id='search_item.jump'
|
||||
defaultMessage='Jump'
|
||||
/>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
|
||||
@@ -9,6 +9,8 @@ import * as client from '../utils/client.jsx';
|
||||
import * as EventHelpers from '../dispatcher/event_helpers.jsx';
|
||||
import * as utils from '../utils/utils.jsx';
|
||||
|
||||
import {FormattedMessage} from 'mm-intl';
|
||||
|
||||
export default class SidebarRightMenu extends React.Component {
|
||||
componentDidMount() {
|
||||
$('.sidebar--left .dropdown-menu').perfectScrollbar();
|
||||
@@ -49,7 +51,11 @@ export default class SidebarRightMenu extends React.Component {
|
||||
href='#'
|
||||
onClick={EventHelpers.showInviteMemberModal}
|
||||
>
|
||||
<i className='fa fa-user'></i>{'Invite New Member'}
|
||||
<i className='fa fa-user'></i>
|
||||
<FormattedMessage
|
||||
id='sidebar_right_menu.inviteNew'
|
||||
defaultMessage='Invite New Member'
|
||||
/>
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
@@ -61,7 +67,11 @@ export default class SidebarRightMenu extends React.Component {
|
||||
href='#'
|
||||
onClick={EventHelpers.showGetTeamInviteLinkModal}
|
||||
>
|
||||
<i className='glyphicon glyphicon-link'></i>{'Get Team Invite Link'}
|
||||
<i className='glyphicon glyphicon-link'></i>
|
||||
<FormattedMessage
|
||||
id='sidebar_right_menu.teamLink'
|
||||
defaultMessage='Get Team Invite Link'
|
||||
/>
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
@@ -75,13 +85,23 @@ export default class SidebarRightMenu extends React.Component {
|
||||
href='#'
|
||||
data-toggle='modal'
|
||||
data-target='#team_settings'
|
||||
><i className='fa fa-globe'></i>{'Team Settings'}</a>
|
||||
>
|
||||
<i className='fa fa-globe'></i>
|
||||
<FormattedMessage
|
||||
id='sidebar_right_menu.teamSettings'
|
||||
defaultMessage='Team Settings'
|
||||
/>
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
manageLink = (
|
||||
<li>
|
||||
<ToggleModalButton dialogType={TeamMembersModal}>
|
||||
<i className='fa fa-users'></i>{'Manage Members'}
|
||||
<i className='fa fa-users'></i>
|
||||
<FormattedMessage
|
||||
id='sidebar_right_menu.manageMembers'
|
||||
defaultMessage='Manage Members'
|
||||
/>
|
||||
</ToggleModalButton>
|
||||
</li>
|
||||
);
|
||||
@@ -93,7 +113,12 @@ export default class SidebarRightMenu extends React.Component {
|
||||
<a
|
||||
href={'/admin_console?' + utils.getSessionIndex()}
|
||||
>
|
||||
<i className='fa fa-wrench'></i>{'System Console'}</a>
|
||||
<i className='fa fa-wrench'></i>
|
||||
<FormattedMessage
|
||||
id='sidebar_right_menu.console'
|
||||
defaultMessage='System Console'
|
||||
/>
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
@@ -114,7 +139,14 @@ export default class SidebarRightMenu extends React.Component {
|
||||
<a
|
||||
target='_blank'
|
||||
href={global.window.mm_config.HelpLink}
|
||||
><i className='fa fa-question'></i>{'Help'}</a></li>
|
||||
>
|
||||
<i className='fa fa-question'></i>
|
||||
<FormattedMessage
|
||||
id='sidebar_right_menu.help'
|
||||
defaultMessage='Help'
|
||||
/>
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -125,7 +157,14 @@ export default class SidebarRightMenu extends React.Component {
|
||||
<a
|
||||
target='_blank'
|
||||
href={global.window.mm_config.ReportAProblemLink}
|
||||
><i className='fa fa-phone'></i>{'Report a Problem'}</a></li>
|
||||
>
|
||||
<i className='fa fa-phone'></i>
|
||||
<FormattedMessage
|
||||
id='sidebar_right_menu.report'
|
||||
defaultMessage='Report a Problem'
|
||||
/>
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
return (
|
||||
@@ -144,7 +183,11 @@ export default class SidebarRightMenu extends React.Component {
|
||||
href='#'
|
||||
onClick={() => this.setState({showUserSettingsModal: true})}
|
||||
>
|
||||
<i className='fa fa-cog'></i>{'Account Settings'}
|
||||
<i className='fa fa-cog'></i>
|
||||
<FormattedMessage
|
||||
id='sidebar_right_menu.accountSettings'
|
||||
defaultMessage='Account Settings'
|
||||
/>
|
||||
</a>
|
||||
</li>
|
||||
{teamSettingsLink}
|
||||
@@ -156,7 +199,14 @@ export default class SidebarRightMenu extends React.Component {
|
||||
<a
|
||||
href='#'
|
||||
onClick={this.handleLogoutClick}
|
||||
><i className='fa fa-sign-out'></i>{'Logout'}</a></li>
|
||||
>
|
||||
<i className='fa fa-sign-out'></i>
|
||||
<FormattedMessage
|
||||
id='sidebar_right_menu.logout'
|
||||
defaultMessage='Logout'
|
||||
/>
|
||||
</a>
|
||||
</li>
|
||||
<li className='divider'></li>
|
||||
{helpLink}
|
||||
{reportLink}
|
||||
|
||||
@@ -11,6 +11,9 @@ import ErrorStore from '../stores/error_store.jsx';
|
||||
import * as TextFormatting from '../utils/text_formatting.jsx';
|
||||
import * as Utils from '../utils/utils.jsx';
|
||||
import Constants from '../utils/constants.jsx';
|
||||
|
||||
import {FormattedMessage} from 'mm-intl';
|
||||
|
||||
const PreReleaseFeatures = Constants.PRE_RELEASE_FEATURES;
|
||||
|
||||
export default class Textbox extends React.Component {
|
||||
@@ -143,7 +146,17 @@ export default class Textbox extends React.Component {
|
||||
onClick={this.showPreview}
|
||||
className='textbox-preview-link'
|
||||
>
|
||||
{this.state.preview ? 'Edit message' : 'Preview'}
|
||||
{this.state.preview ? (
|
||||
<FormattedMessage
|
||||
id='textbox.edit'
|
||||
defaultMessage='Edit message'
|
||||
/>
|
||||
) : (
|
||||
<FormattedMessage
|
||||
id='textbox.preview'
|
||||
defaultMessage='Preview'
|
||||
/>
|
||||
)}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
@@ -184,7 +197,10 @@ export default class Textbox extends React.Component {
|
||||
onClick={this.showHelp}
|
||||
className='textbox-help-link'
|
||||
>
|
||||
{'Help'}
|
||||
<FormattedMessage
|
||||
id='textbox.help'
|
||||
defaultMessage='Help'
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
|
||||
import * as Utils from '../utils/utils.jsx';
|
||||
import UserStore from '../stores/user_store.jsx';
|
||||
|
||||
import {FormattedMessage} from 'mm-intl';
|
||||
|
||||
var Popover = ReactBootstrap.Popover;
|
||||
var OverlayTrigger = ReactBootstrap.OverlayTrigger;
|
||||
|
||||
@@ -87,7 +90,10 @@ export default class UserProfile extends React.Component {
|
||||
className='text-nowrap'
|
||||
key='user-popover-no-email'
|
||||
>
|
||||
{'Email not shared'}
|
||||
<FormattedMessage
|
||||
id='user_profile.notShared'
|
||||
defaultMessage='Email not shared'
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
|
||||
Ссылка в новой задаче
Block a user