Merge pull request #2015 from ZBoxApp/PLT-7-pages

PLT-7: Refactoring frontend (chunk 4)
Этот коммит содержится в:
Joram Wilander
2016-01-29 08:24:35 -05:00
родитель 761488b745 baa499d97b
Коммит 1009e9f745
24 изменённых файлов: 767 добавлений и 108 удалений

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

@@ -579,6 +579,10 @@
"id": "api.license.add_license.invalid.app_error", "id": "api.license.add_license.invalid.app_error",
"translation": "Invalid license file." "translation": "Invalid license file."
}, },
{
"id": "api.license.add_license.invalid_count.app_error",
"translation": "Unable to count total unique users."
},
{ {
"id": "api.license.add_license.no_file.app_error", "id": "api.license.add_license.no_file.app_error",
"translation": "No file under 'license' in request" "translation": "No file under 'license' in request"
@@ -588,17 +592,13 @@
"translation": "Could not open license file" "translation": "Could not open license file"
}, },
{ {
"id": "api.license.add_license.invalid_count.app_error", "id": "api.license.add_license.save.app_error",
"translation": "Unable to count total unique users." "translation": "License did not save properly."
}, },
{ {
"id": "api.license.add_license.unique_users.app_error", "id": "api.license.add_license.unique_users.app_error",
"translation": "This license only supports {{.Users}} users, when your system has {{.Count}} unique users. Unique users are counted distinctly by email address. You can see total user count under Site Reports -> View Statistics." "translation": "This license only supports {{.Users}} users, when your system has {{.Count}} unique users. Unique users are counted distinctly by email address. You can see total user count under Site Reports -> View Statistics."
}, },
{
"id": "api.license.add_license.save.app_error",
"translation": "License did not save properly."
},
{ {
"id": "api.license.init.debug", "id": "api.license.init.debug",
"translation": "Initializing license api routes" "translation": "Initializing license api routes"
@@ -1551,10 +1551,6 @@
"id": "api.user.upload_profile_user.encode.app_error", "id": "api.user.upload_profile_user.encode.app_error",
"translation": "Could not encode profile image" "translation": "Could not encode profile image"
}, },
{
"id": "api.user.upload_profile_user.upload_profile.app_error",
"translation": "Couldn't upload profile image"
},
{ {
"id": "api.user.upload_profile_user.no_file.app_error", "id": "api.user.upload_profile_user.no_file.app_error",
"translation": "No file under 'image' in request" "translation": "No file under 'image' in request"
@@ -1575,6 +1571,10 @@
"id": "api.user.upload_profile_user.too_large.app_error", "id": "api.user.upload_profile_user.too_large.app_error",
"translation": "Unable to upload profile image. File is too large." "translation": "Unable to upload profile image. File is too large."
}, },
{
"id": "api.user.upload_profile_user.upload_profile.app_error",
"translation": "Couldn't upload profile image"
},
{ {
"id": "api.web_conn.new_web_conn.last_activity.error", "id": "api.web_conn.new_web_conn.last_activity.error",
"translation": "Failed to update LastActivityAt for user_id=%v and session_id=%v, err=%v" "translation": "Failed to update LastActivityAt for user_id=%v and session_id=%v, err=%v"
@@ -2775,6 +2775,10 @@
"id": "store.sql_session.save.existing.app_error", "id": "store.sql_session.save.existing.app_error",
"translation": "Cannot update existing session" "translation": "Cannot update existing session"
}, },
{
"id": "store.sql_session.update_device_id.app_error",
"translation": "We couldn't update the device id"
},
{ {
"id": "store.sql_session.update_last_activity.app_error", "id": "store.sql_session.update_last_activity.app_error",
"translation": "We couldn't update the last_activity_at" "translation": "We couldn't update the last_activity_at"
@@ -2783,10 +2787,6 @@
"id": "store.sql_session.update_roles.app_error", "id": "store.sql_session.update_roles.app_error",
"translation": "We couldn't update the roles" "translation": "We couldn't update the roles"
}, },
{
"id": "store.sql_session.update_device_id.app_error",
"translation": "We couldn't update the device id"
},
{ {
"id": "store.sql_system.get.app_error", "id": "store.sql_system.get.app_error",
"translation": "We encountered an error finding the system properties" "translation": "We encountered an error finding the system properties"
@@ -3335,6 +3335,10 @@
"id": "web.root.home_title", "id": "web.root.home_title",
"translation": "Home" "translation": "Home"
}, },
{
"id": "web.root.singup_info",
"translation": "All team communication in one place, searchable and accessible anywhere"
},
{ {
"id": "web.root.singup_title", "id": "web.root.singup_title",
"translation": "Signup" "translation": "Signup"

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

@@ -3335,6 +3335,10 @@
"id": "web.root.home_title", "id": "web.root.home_title",
"translation": "Inicio" "translation": "Inicio"
}, },
{
"id": "web.root.singup_info",
"translation": "Todas las comunicaciones del equipo en un sólo lugar, con búsquedas y accesible desde cualquier parte"
},
{ {
"id": "web.root.singup_title", "id": "web.root.singup_title",
"translation": "Registrar" "translation": "Registrar"

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

@@ -3,6 +3,8 @@
import * as Client from '../utils/client.jsx'; import * as Client from '../utils/client.jsx';
import {FormattedMessage} from 'mm-intl';
export default class Authorize extends React.Component { export default class Authorize extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
@@ -35,25 +37,55 @@ export default class Authorize extends React.Component {
return ( return (
<div className='authorize-box'> <div className='authorize-box'>
<div className='authorize-inner'> <div className='authorize-inner'>
<h3>{'An application would like to connect to your '}{this.props.teamName}{' account'}</h3> <h3>
<label>{'The app '}{this.props.appName}{' would like the ability to access and modify your basic information.'}</label> <FormattedMessage
id='authorize.title'
defaultMessage='An application would like to connect to your {teamName} account'
values={{
teamName: this.props.teamName
}}
/>
</h3>
<label>
<FormattedMessage
id='authorize.app'
defaultMessage='The app {appName} would like the ability to access and modify your basic information.'
values={{
appName: this.props.appName
}}
/>
</label>
<br/> <br/>
<br/> <br/>
<label>{'Allow '}{this.props.appName}{' access?'}</label> <label>
<FormattedMessage
id='authorize.access'
defaultMessage='Allow {appName} access?'
values={{
appName: this.props.appName
}}
/>
</label>
<br/> <br/>
<button <button
type='submit' type='submit'
className='btn authorize-btn' className='btn authorize-btn'
onClick={this.handleDeny} onClick={this.handleDeny}
> >
{'Deny'} <FormattedMessage
id='authorize.deny'
defaultMessage='Deny'
/>
</button> </button>
<button <button
type='submit' type='submit'
className='btn btn-primary authorize-btn' className='btn btn-primary authorize-btn'
onClick={this.handleAllow} onClick={this.handleAllow}
> >
{'Allow'} <FormattedMessage
id='authorize.allow'
defaultMessage='Allow'
/>
</button> </button>
</div> </div>
</div> </div>

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

@@ -13,7 +13,7 @@ export default class Docs extends React.Component {
const errorState = {text: '## 404'}; const errorState = {text: '## 404'};
if (props.site) { if (props.site) {
$.get('/static/help/' + props.site + '.md').then((response) => { $.get(`/static/help/${props.site}_${global.window.mm_locale}.md`).then((response) => {
this.setState({text: response}); this.setState({text: response});
}, () => { }, () => {
this.setState(errorState); this.setState(errorState);

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

@@ -4,7 +4,20 @@
import * as utils from '../utils/utils.jsx'; import * as utils from '../utils/utils.jsx';
import * as client from '../utils/client.jsx'; import * as client from '../utils/client.jsx';
export default class FindTeam extends React.Component { import {injectIntl, intlShape, defineMessages, FormattedMessage} from 'mm-intl';
var holders = defineMessages({
submitError: {
id: 'find_team.submitError',
defaultMessage: 'Please enter a valid email address'
},
placeholder: {
id: 'find_team.placeholder',
defaultMessage: 'you@domain.com'
}
});
class FindTeam extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = {}; this.state = {};
@@ -19,7 +32,7 @@ export default class FindTeam extends React.Component {
var email = ReactDOM.findDOMNode(this.refs.email).value.trim().toLowerCase(); var email = ReactDOM.findDOMNode(this.refs.email).value.trim().toLowerCase();
if (!email || !utils.isEmail(email)) { if (!email || !utils.isEmail(email)) {
state.email_error = 'Please enter a valid email address'; state.email_error = this.props.intl.formatMessage(holders.submitError);
this.setState(state); this.setState(state);
return; return;
} }
@@ -50,25 +63,50 @@ export default class FindTeam extends React.Component {
if (this.state.sent) { if (this.state.sent) {
return ( return (
<div> <div>
<h4>{'Find Your teams'}</h4> <h4>
<p>{'An email was sent with links to any teams to which you are a member.'}</p> <FormattedMessage
id='find_team.findTitle'
defaultMessage='Find Your Team'
/>
</h4>
<p>
<FormattedMessage
id='find_team.findDescription'
defaultMessage='An email was sent with links to any teams to which you are a member.'
/>
</p>
</div> </div>
); );
} }
return ( return (
<div> <div>
<h4>Find Your Team</h4> <h4>
<FormattedMessage
id='find_team.findTitle'
defaultMessage='Find Your Team'
/>
</h4>
<form onSubmit={this.handleSubmit}> <form onSubmit={this.handleSubmit}>
<p>{'Get an email with links to any teams to which you are a member.'}</p> <p>
<FormattedMessage
id='find_team.getLinks'
defaultMessage='Get an email with links to any teams to which you are a member.'
/>
</p>
<div className='form-group'> <div className='form-group'>
<label className='control-label'>Email</label> <label className='control-label'>
<FormattedMessage
id='find_team.email'
defaultMessage='Email'
/>
</label>
<div className={emailErrorClass}> <div className={emailErrorClass}>
<input <input
type='text' type='text'
ref='email' ref='email'
className='form-control' className='form-control'
placeholder='you@domain.com' placeholder={this.props.intl.formatMessage(holders.placeholder)}
maxLength='128' maxLength='128'
spellCheck='false' spellCheck='false'
/> />
@@ -79,10 +117,19 @@ export default class FindTeam extends React.Component {
className='btn btn-md btn-primary' className='btn btn-md btn-primary'
type='submit' type='submit'
> >
Send <FormattedMessage
id='find_team.send'
defaultMessage='Send'
/>
</button> </button>
</form> </form>
</div> </div>
); );
} }
} }
FindTeam.propTypes = {
intl: intlShape.isRequired
};
export default injectIntl(FindTeam);

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

@@ -7,7 +7,7 @@ import LoginLdap from './login_ldap.jsx';
import * as Utils from '../utils/utils.jsx'; import * as Utils from '../utils/utils.jsx';
import Constants from '../utils/constants.jsx'; import Constants from '../utils/constants.jsx';
var FormattedMessage = ReactIntl.FormattedMessage; import {FormattedMessage} from 'mm-intl';
export default class Login extends React.Component { export default class Login extends React.Component {
constructor(props) { constructor(props) {
@@ -24,10 +24,16 @@ export default class Login extends React.Component {
loginMessage.push( loginMessage.push(
<a <a
className='btn btn-custom-login gitlab' className='btn btn-custom-login gitlab'
key='gitlab'
href={'/' + teamName + '/login/gitlab'} href={'/' + teamName + '/login/gitlab'}
> >
<span className='icon' /> <span className='icon' />
<span>{'with GitLab'}</span> <span>
<FormattedMessage
id='login.gitlab'
defaultMessage='with GitLab'
/>
</span>
</a> </a>
); );
} }
@@ -36,10 +42,16 @@ export default class Login extends React.Component {
loginMessage.push( loginMessage.push(
<a <a
className='btn btn-custom-login google' className='btn btn-custom-login google'
key='google'
href={'/' + teamName + '/login/google'} href={'/' + teamName + '/login/google'}
> >
<span className='icon' /> <span className='icon' />
<span>{'with Google Apps'}</span> <span>
<FormattedMessage
id='login.google'
defaultMessage='with Google Apps'
/>
</span>
</a> </a>
); );
} }
@@ -49,9 +61,19 @@ export default class Login extends React.Component {
if (extraParam) { if (extraParam) {
let msg; let msg;
if (extraParam === Constants.SIGNIN_CHANGE) { if (extraParam === Constants.SIGNIN_CHANGE) {
msg = ' Sign-in method changed successfully'; msg = (
<FormattedMessage
id='login.changed'
defaultMessage=' Sign-in method changed successfully'
/>
);
} else if (extraParam === Constants.SIGNIN_VERIFIED) { } else if (extraParam === Constants.SIGNIN_VERIFIED) {
msg = ' Email Verified'; msg = (
<FormattedMessage
id='login.verified'
defaultMessage=' Email Verified'
/>
);
} }
if (msg != null) { if (msg != null) {
@@ -78,7 +100,12 @@ export default class Login extends React.Component {
<div> <div>
{loginMessage} {loginMessage}
<div className='or__container'> <div className='or__container'>
<span>{'or'}</span> <span>
<FormattedMessage
id='login.or'
defaultMessage='or'
/>
</span>
</div> </div>
</div> </div>
); );
@@ -90,7 +117,7 @@ export default class Login extends React.Component {
<div className='form-group'> <div className='form-group'>
<a href={'/' + teamName + '/reset_password'}> <a href={'/' + teamName + '/reset_password'}>
<FormattedMessage <FormattedMessage
id='login.forgot_password' id='login.forgot'
defaultMessage='I forgot my password' defaultMessage='I forgot my password'
/> />
</a> </a>
@@ -102,12 +129,19 @@ export default class Login extends React.Component {
if (this.props.inviteId) { if (this.props.inviteId) {
userSignUp = ( userSignUp = (
<div> <div>
<span>{`Don't have an account? `} <span>
<FormattedMessage
id='login.noAccount'
defaultMessage="Don't have an account? "
/>
<a <a
href={'/signup_user_complete/?id=' + this.props.inviteId} href={'/signup_user_complete/?id=' + this.props.inviteId}
className='signup-team-login' className='signup-team-login'
> >
{'Create one now'} <FormattedMessage
id='login.create'
defaultMessage='Create one now'
/>
</a> </a>
</span> </span>
</div> </div>
@@ -122,7 +156,10 @@ export default class Login extends React.Component {
href='/' href='/'
className='signup-team-login' className='signup-team-login'
> >
{'Create a new team'} <FormattedMessage
id='login.createTeam'
defaultMessage='Create a new team'
/>
</a> </a>
</div> </div>
); );
@@ -144,7 +181,7 @@ export default class Login extends React.Component {
<span> <span>
<a href='/find_team'> <a href='/find_team'>
<FormattedMessage <FormattedMessage
id='login.find_teams' id='login.find'
defaultMessage='Find your other teams' defaultMessage='Find your other teams'
/> />
</a></span> </a></span>
@@ -154,9 +191,22 @@ export default class Login extends React.Component {
return ( return (
<div className='signup-team__container'> <div className='signup-team__container'>
<h5 className='margin--less'>{'Sign in to:'}</h5> <h5 className='margin--less'>
<FormattedMessage
id='login.signTo'
defaultMessage='Sign in to:'
/>
</h5>
<h2 className='signup-team__name'>{teamDisplayName}</h2> <h2 className='signup-team__name'>{teamDisplayName}</h2>
<h2 className='signup-team__subdomain'>{'on '}{global.window.mm_config.SiteName}</h2> <h2 className='signup-team__subdomain'>
<FormattedMessage
id='login.on'
defaultMessage='on {siteName}'
values={{
siteName: global.window.mm_config.SiteName
}}
/>
</h2>
{extraBox} {extraBox}
{loginMessage} {loginMessage}
{emailSignup} {emailSignup}

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

@@ -5,7 +5,32 @@ import * as Utils from '../utils/utils.jsx';
import * as Client from '../utils/client.jsx'; import * as Client from '../utils/client.jsx';
import UserStore from '../stores/user_store.jsx'; import UserStore from '../stores/user_store.jsx';
export default class LoginEmail extends React.Component { import {injectIntl, intlShape, defineMessages, FormattedMessage} from 'mm-intl';
var holders = defineMessages({
badTeam: {
id: 'login_email.badTeam',
defaultMessage: 'Bad team name'
},
emailReq: {
id: 'login_email.emailReq',
defaultMessage: 'An email is required'
},
pwdReq: {
id: 'login_email.pwdReq',
defaultMessage: 'A password is required'
},
email: {
id: 'login_email.email',
defaultMessage: 'Email'
},
pwd: {
id: 'login_email.pwd',
defaultMessage: 'Password'
}
});
class LoginEmail extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
@@ -17,25 +42,26 @@ export default class LoginEmail extends React.Component {
} }
handleSubmit(e) { handleSubmit(e) {
e.preventDefault(); e.preventDefault();
const {formatMessage} = this.props.intl;
var state = {}; var state = {};
const name = this.props.teamName; const name = this.props.teamName;
if (!name) { if (!name) {
state.serverError = 'Bad team name'; state.serverError = formatMessage(holders.badTeam);
this.setState(state); this.setState(state);
return; return;
} }
const email = this.refs.email.value.trim(); const email = this.refs.email.value.trim();
if (!email) { if (!email) {
state.serverError = 'An email is required'; state.serverError = formatMessage(holders.emailReq);
this.setState(state); this.setState(state);
return; return;
} }
const password = this.refs.password.value.trim(); const password = this.refs.password.value.trim();
if (!password) { if (!password) {
state.serverError = 'A password is required'; state.serverError = formatMessage(holders.pwdReq);
this.setState(state); this.setState(state);
return; return;
} }
@@ -55,7 +81,7 @@ export default class LoginEmail extends React.Component {
} }
}, },
(err) => { (err) => {
if (err.message === 'Login failed because email address has not been verified') { if (err.id === 'api.user.login.not_verified.app_error') {
window.location.href = '/verify_email?teamname=' + encodeURIComponent(name) + '&email=' + encodeURIComponent(email); window.location.href = '/verify_email?teamname=' + encodeURIComponent(name) + '&email=' + encodeURIComponent(email);
return; return;
} }
@@ -87,6 +113,7 @@ export default class LoginEmail extends React.Component {
priorEmail = decodeURIComponent(emailParam); priorEmail = decodeURIComponent(emailParam);
} }
const {formatMessage} = this.props.intl;
return ( return (
<form onSubmit={this.handleSubmit}> <form onSubmit={this.handleSubmit}>
<div className='signup__email-container'> <div className='signup__email-container'>
@@ -101,7 +128,7 @@ export default class LoginEmail extends React.Component {
name='email' name='email'
defaultValue={priorEmail} defaultValue={priorEmail}
ref='email' ref='email'
placeholder='Email' placeholder={formatMessage(holders.email)}
spellCheck='false' spellCheck='false'
/> />
</div> </div>
@@ -112,7 +139,7 @@ export default class LoginEmail extends React.Component {
className='form-control' className='form-control'
name='password' name='password'
ref='password' ref='password'
placeholder='Password' placeholder={formatMessage(holders.pwd)}
spellCheck='false' spellCheck='false'
/> />
</div> </div>
@@ -121,7 +148,10 @@ export default class LoginEmail extends React.Component {
type='submit' type='submit'
className='btn btn-primary' className='btn btn-primary'
> >
{'Sign in'} <FormattedMessage
id='login_email.signin'
defaultMessage='Sign in'
/>
</button> </button>
</div> </div>
</div> </div>
@@ -133,5 +163,8 @@ LoginEmail.defaultProps = {
}; };
LoginEmail.propTypes = { LoginEmail.propTypes = {
intl: intlShape.isRequired,
teamName: React.PropTypes.string.isRequired teamName: React.PropTypes.string.isRequired
}; };
export default injectIntl(LoginEmail);

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

@@ -4,7 +4,32 @@
import * as Utils from '../utils/utils.jsx'; import * as Utils from '../utils/utils.jsx';
import * as Client from '../utils/client.jsx'; import * as Client from '../utils/client.jsx';
export default class LoginLdap extends React.Component { import {injectIntl, intlShape, defineMessages, FormattedMessage} from 'mm-intl';
const holders = defineMessages({
badTeam: {
id: 'login_ldap.badTeam',
defaultMessage: 'Bad team name'
},
idReq: {
id: 'login_ldap.idlReq',
defaultMessage: 'An LDAP ID is required'
},
pwdReq: {
id: 'login_ldap.pwdReq',
defaultMessage: 'An LDAP password is required'
},
username: {
id: 'login_ldap.username',
defaultMessage: 'LDAP Username'
},
pwd: {
id: 'login_ldap.pwd',
defaultMessage: 'LDAP Password'
}
});
class LoginLdap extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
@@ -16,25 +41,26 @@ export default class LoginLdap extends React.Component {
} }
handleSubmit(e) { handleSubmit(e) {
e.preventDefault(); e.preventDefault();
const {formatMessage} = this.props.intl;
var state = {}; var state = {};
const teamName = this.props.teamName; const teamName = this.props.teamName;
if (!teamName) { if (!teamName) {
state.serverError = 'Bad team name'; state.serverError = formatMessage(holders.badTeam);
this.setState(state); this.setState(state);
return; return;
} }
const id = this.refs.id.value.trim(); const id = this.refs.id.value.trim();
if (!id) { if (!id) {
state.serverError = 'An LDAP ID is required'; state.serverError = formatMessage(holders.idReq);
this.setState(state); this.setState(state);
return; return;
} }
const password = this.refs.password.value.trim(); const password = this.refs.password.value.trim();
if (!password) { if (!password) {
state.serverError = 'An LDAP password is required'; state.serverError = formatMessage(holders.pwdReq);
this.setState(state); this.setState(state);
return; return;
} }
@@ -64,7 +90,7 @@ export default class LoginLdap extends React.Component {
serverError = <label className='control-label'>{this.state.serverError}</label>; serverError = <label className='control-label'>{this.state.serverError}</label>;
errorClass = ' has-error'; errorClass = ' has-error';
} }
const {formatMessage} = this.props.intl;
return ( return (
<form onSubmit={this.handleSubmit}> <form onSubmit={this.handleSubmit}>
<div className='signup__email-container'> <div className='signup__email-container'>
@@ -76,7 +102,7 @@ export default class LoginLdap extends React.Component {
autoFocus={true} autoFocus={true}
className='form-control' className='form-control'
ref='id' ref='id'
placeholder='LDAP Username' placeholder={formatMessage(holders.username)}
spellCheck='false' spellCheck='false'
/> />
</div> </div>
@@ -85,7 +111,7 @@ export default class LoginLdap extends React.Component {
type='password' type='password'
className='form-control' className='form-control'
ref='password' ref='password'
placeholder='LDAP Password' placeholder={formatMessage(holders.pwd)}
spellCheck='false' spellCheck='false'
/> />
</div> </div>
@@ -94,7 +120,10 @@ export default class LoginLdap extends React.Component {
type='submit' type='submit'
className='btn btn-primary' className='btn btn-primary'
> >
{'Sign in'} <FormattedMessage
id='login_ldap.signin'
defaultMessage='Sign in'
/>
</button> </button>
</div> </div>
</div> </div>
@@ -106,5 +135,8 @@ LoginLdap.defaultProps = {
}; };
LoginLdap.propTypes = { LoginLdap.propTypes = {
intl: intlShape.isRequired,
teamName: React.PropTypes.string.isRequired teamName: React.PropTypes.string.isRequired
}; };
export default injectIntl(LoginLdap);

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

@@ -4,7 +4,24 @@
import * as Client from '../utils/client.jsx'; import * as Client from '../utils/client.jsx';
import Constants from '../utils/constants.jsx'; import Constants from '../utils/constants.jsx';
export default class PasswordResetForm extends React.Component { import {injectIntl, intlShape, defineMessages, FormattedMessage, FormattedHTMLMessage} from 'mm-intl';
const holders = defineMessages({
error: {
id: 'password_form.error',
defaultMessage: 'Please enter at least {chars} characters.'
},
update: {
id: 'password_form.update',
defaultMessage: 'Your password has been updated successfully.'
},
pwd: {
id: 'password_form.pwd',
defaultMessage: 'Password'
}
});
class PasswordResetForm extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
@@ -14,11 +31,13 @@ export default class PasswordResetForm extends React.Component {
} }
handlePasswordReset(e) { handlePasswordReset(e) {
e.preventDefault(); e.preventDefault();
const {formatMessage} = this.props.intl;
var state = {}; var state = {};
var password = ReactDOM.findDOMNode(this.refs.password).value.trim(); var password = ReactDOM.findDOMNode(this.refs.password).value.trim();
if (!password || password.length < Constants.MIN_PASSWORD_LENGTH) { if (!password || password.length < Constants.MIN_PASSWORD_LENGTH) {
state.error = 'Please enter at least ' + Constants.MIN_PASSWORD_LENGTH + ' characters.'; state.error = formatMessage(holders.error, {chars: Constants.MIN_PASSWORD_LENGTH});
this.setState(state); this.setState(state);
return; return;
} }
@@ -34,7 +53,7 @@ export default class PasswordResetForm extends React.Component {
Client.resetPassword(data, Client.resetPassword(data,
function resetSuccess() { function resetSuccess() {
this.setState({error: null, updateText: 'Your password has been updated successfully.'}); this.setState({error: null, updateText: formatMessage(holders.update)});
}.bind(this), }.bind(this),
function resetFailure(err) { function resetFailure(err) {
this.setState({error: err.message, updateText: null}); this.setState({error: err.message, updateText: null});
@@ -44,7 +63,15 @@ export default class PasswordResetForm extends React.Component {
render() { render() {
var updateText = null; var updateText = null;
if (this.state.updateText) { if (this.state.updateText) {
updateText = <div className='form-group'><br/><label className='control-label reset-form'>{this.state.updateText} Click <a href={'/' + this.props.teamName + '/login'}>here</a> to log in.</label></div>; updateText = (<div className='form-group'><br/><label className='control-label reset-form'>{this.state.updateText}
<FormattedHTMLMessage
id='password_form.click'
defaultMessage='Click <a href={url}>here</a> to log in.'
values={{
url: '/' + this.props.teamName + '/login'
}}
/>
</label></div>);
} }
var error = null; var error = null;
@@ -57,19 +84,34 @@ export default class PasswordResetForm extends React.Component {
formClass += ' has-error'; formClass += ' has-error';
} }
const {formatMessage} = this.props.intl;
return ( return (
<div className='col-sm-12'> <div className='col-sm-12'>
<div className='signup-team__container'> <div className='signup-team__container'>
<h3>{'Password Reset'}</h3> <h3>
<FormattedMessage
id='password_form.title'
defaultMessage='Password Reset'
/>
</h3>
<form onSubmit={this.handlePasswordReset}> <form onSubmit={this.handlePasswordReset}>
<p>{'Enter a new password for your ' + this.props.teamDisplayName + ' ' + global.window.mm_config.SiteName + ' account.'}</p> <p>
<FormattedMessage
id='password_form.enter'
defaultMessage='Enter a new password for your {teamDisplayName} {siteName} account.'
values={{
teamDisplayName: this.props.teamDisplayName,
siteName: global.window.mm_config.SiteName
}}
/>
</p>
<div className={formClass}> <div className={formClass}>
<input <input
type='password' type='password'
className='form-control' className='form-control'
name='password' name='password'
ref='password' ref='password'
placeholder='Password' placeholder={formatMessage(holders.pwd)}
spellCheck='false' spellCheck='false'
/> />
</div> </div>
@@ -78,7 +120,10 @@ export default class PasswordResetForm extends React.Component {
type='submit' type='submit'
className='btn btn-primary' className='btn btn-primary'
> >
{'Change my password'} <FormattedMessage
id='password_form.change'
defaultMessage='Change my password'
/>
</button> </button>
{updateText} {updateText}
</form> </form>
@@ -95,8 +140,11 @@ PasswordResetForm.defaultProps = {
data: '' data: ''
}; };
PasswordResetForm.propTypes = { PasswordResetForm.propTypes = {
intl: intlShape.isRequired,
teamName: React.PropTypes.string, teamName: React.PropTypes.string,
teamDisplayName: React.PropTypes.string, teamDisplayName: React.PropTypes.string,
hash: React.PropTypes.string, hash: React.PropTypes.string,
data: React.PropTypes.string data: React.PropTypes.string
}; };
export default injectIntl(PasswordResetForm);

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

@@ -4,7 +4,28 @@
import * as Utils from '../utils/utils.jsx'; import * as Utils from '../utils/utils.jsx';
import * as client from '../utils/client.jsx'; import * as client from '../utils/client.jsx';
export default class PasswordResetSendLink extends React.Component { import {injectIntl, intlShape, defineMessages, FormattedMessage} from 'mm-intl';
const holders = defineMessages({
error: {
id: 'password_send.error',
defaultMessage: 'Please enter a valid email address.'
},
link: {
id: 'password_send.link',
defaultMessage: '<p>A password reset link has been sent to <b>{email}</b> for your <b>{teamDisplayName}</b> team on {hostname}.</p>'
},
checkInbox: {
id: 'password_send.checkInbox',
defaultMessage: 'Please check your inbox.'
},
email: {
id: 'password_send.email',
defaultMessage: 'Email'
}
});
class PasswordResetSendLink extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
@@ -15,10 +36,11 @@ export default class PasswordResetSendLink extends React.Component {
handleSendLink(e) { handleSendLink(e) {
e.preventDefault(); e.preventDefault();
var state = {}; var state = {};
const {formatMessage} = this.props.intl;
var email = ReactDOM.findDOMNode(this.refs.email).value.trim().toLowerCase(); var email = ReactDOM.findDOMNode(this.refs.email).value.trim().toLowerCase();
if (!email || !Utils.isEmail(email)) { if (!email || !Utils.isEmail(email)) {
state.error = 'Please enter a valid email address.'; state.error = formatMessage(holders.error);
this.setState(state); this.setState(state);
return; return;
} }
@@ -32,7 +54,7 @@ export default class PasswordResetSendLink extends React.Component {
client.sendPasswordReset(data, client.sendPasswordReset(data,
function passwordResetSent() { function passwordResetSent() {
this.setState({error: null, updateText: <p>A password reset link has been sent to <b>{email}</b> for your <b>{this.props.teamDisplayName}</b> team on {window.location.hostname}.</p>, moreUpdateText: 'Please check your inbox.'}); this.setState({error: null, updateText: formatMessage(holders.link, {email: email, teamDisplayName: this.props.teamDisplayName, hostname: window.location.hostname}), moreUpdateText: formatMessage(holders.checkInbox)});
$(ReactDOM.findDOMNode(this.refs.reset_form)).hide(); $(ReactDOM.findDOMNode(this.refs.reset_form)).hide();
}.bind(this), }.bind(this),
function passwordResetFailedToSend(err) { function passwordResetFailedToSend(err) {
@@ -43,7 +65,12 @@ export default class PasswordResetSendLink extends React.Component {
render() { render() {
var updateText = null; var updateText = null;
if (this.state.updateText) { if (this.state.updateText) {
updateText = <div className='reset-form alert alert-success'>{this.state.updateText}{this.state.moreUpdateText}</div>; updateText = (
<div className='reset-form alert alert-success'
dangerouslySetInnerHTML={{__html: this.state.updateText + this.state.moreUpdateText}}
>
</div>
);
} }
var error = null; var error = null;
@@ -56,23 +83,37 @@ export default class PasswordResetSendLink extends React.Component {
formClass += ' has-error'; formClass += ' has-error';
} }
const {formatMessage} = this.props.intl;
return ( return (
<div className='col-sm-12'> <div className='col-sm-12'>
<div className='signup-team__container'> <div className='signup-team__container'>
<h3>Password Reset</h3> <h3>
<FormattedMessage
id='password_send.title'
defaultMessage='Password Reset'
/>
</h3>
{updateText} {updateText}
<form <form
onSubmit={this.handleSendLink} onSubmit={this.handleSendLink}
ref='reset_form' ref='reset_form'
> >
<p>{'To reset your password, enter the email address you used to sign up for ' + this.props.teamDisplayName + '.'}</p> <p>
<FormattedMessage
id='password_send.description'
defaultMessage='To reset your password, enter the email address you used to sign up for {teamName}.'
values={{
teamName: this.props.teamDisplayName
}}
/>
</p>
<div className={formClass}> <div className={formClass}>
<input <input
type='email' type='email'
className='form-control' className='form-control'
name='email' name='email'
ref='email' ref='email'
placeholder='Email' placeholder={formatMessage(holders.email)}
spellCheck='false' spellCheck='false'
/> />
</div> </div>
@@ -81,7 +122,10 @@ export default class PasswordResetSendLink extends React.Component {
type='submit' type='submit'
className='btn btn-primary' className='btn btn-primary'
> >
Reset my password <FormattedMessage
id='password_send.reset'
defaultMessage='Reset my password'
/>
</button> </button>
</form> </form>
</div> </div>
@@ -95,6 +139,9 @@ PasswordResetSendLink.defaultProps = {
teamDisplayName: '' teamDisplayName: ''
}; };
PasswordResetSendLink.propTypes = { PasswordResetSendLink.propTypes = {
intl: intlShape.isRequired,
teamName: React.PropTypes.string, teamName: React.PropTypes.string,
teamDisplayName: React.PropTypes.string teamDisplayName: React.PropTypes.string
}; };
export default injectIntl(PasswordResetSendLink);

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

@@ -6,6 +6,8 @@ import EmailSignUpPage from './team_signup_with_email.jsx';
import SSOSignupPage from './team_signup_with_sso.jsx'; import SSOSignupPage from './team_signup_with_sso.jsx';
import Constants from '../utils/constants.jsx'; import Constants from '../utils/constants.jsx';
import {FormattedMessage} from 'mm-intl';
export default class TeamSignUp extends React.Component { export default class TeamSignUp extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
@@ -43,12 +45,24 @@ export default class TeamSignUp extends React.Component {
if (global.window.mm_config.EnableTeamListing === 'true') { if (global.window.mm_config.EnableTeamListing === 'true') {
if (this.props.teams.length === 0) { if (this.props.teams.length === 0) {
if (global.window.mm_config.EnableTeamCreation !== 'true') { if (global.window.mm_config.EnableTeamCreation !== 'true') {
teamListing = (<div>{'There are no teams include in the Team Directory and team creation has been disabled.'}</div>); teamListing = (
<div>
<FormattedMessage
id='signup_team.noTeams'
defaultMessage='There are no teams include in the Team Directory and team creation has been disabled.'
/>
</div>
);
} }
} else { } else {
teamListing = ( teamListing = (
<div> <div>
<h4>{'Choose a Team'}</h4> <h4>
<FormattedMessage
id='signup_team.choose'
defaultMessage='Choose a Team'
/>
</h4>
<div className='signup-team-all'> <div className='signup-team-all'>
{ {
this.props.teams.map((team) => { this.props.teams.map((team) => {
@@ -71,7 +85,12 @@ export default class TeamSignUp extends React.Component {
}) })
} }
</div> </div>
<h4>{'Or Create a Team'}</h4> <h4>
<FormattedMessage
id='signup_team.createTeam'
defaultMessage='Or Create a Team'
/>
</h4>
</div> </div>
); );
} }
@@ -79,7 +98,14 @@ export default class TeamSignUp extends React.Component {
if (global.window.mm_config.EnableTeamCreation !== 'true') { if (global.window.mm_config.EnableTeamCreation !== 'true') {
if (teamListing == null) { if (teamListing == null) {
return (<div>{'Team creation has been disabled. Please contact an administrator for access.'}</div>); return (
<div>
<FormattedMessage
id='signup_team.disabled'
defaultMessage='Team creation has been disabled. Please contact an administrator for access.'
/>
</div>
);
} }
return ( return (
@@ -122,7 +148,14 @@ export default class TeamSignUp extends React.Component {
</div> </div>
); );
} else if (this.state.page === 'none') { } else if (this.state.page === 'none') {
return (<div>{'No team creation method has been enabled. Please contact an administrator for access.'}</div>); return (
<div>
<FormattedMessage
id='signup_team.none'
defaultMessage='No team creation method has been enabled. Please contact an administrator for access.'
/>
</div>
);
} }
} }
} }

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

@@ -1,6 +1,8 @@
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information. // See License.txt for license information.
import {FormattedMessage} from 'mm-intl';
export default class ChooseAuthPage extends React.Component { export default class ChooseAuthPage extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
@@ -12,6 +14,7 @@ export default class ChooseAuthPage extends React.Component {
buttons.push( buttons.push(
<a <a
className='btn btn-custom-login gitlab btn-full' className='btn btn-custom-login gitlab btn-full'
key='gitlab'
href='#' href='#'
onClick={ onClick={
function clickGit(e) { function clickGit(e) {
@@ -21,7 +24,12 @@ export default class ChooseAuthPage extends React.Component {
} }
> >
<span className='icon' /> <span className='icon' />
<span>{'Create new team with GitLab Account'}</span> <span>
<FormattedMessage
id='choose_auth_page.gitlabCreate'
defaultMessage='Create new team with GitLab Account'
/>
</span>
</a> </a>
); );
} }
@@ -30,6 +38,7 @@ export default class ChooseAuthPage extends React.Component {
buttons.push( buttons.push(
<a <a
className='btn btn-custom-login google btn-full' className='btn btn-custom-login google btn-full'
key='google'
href='#' href='#'
onClick={ onClick={
(e) => { (e) => {
@@ -39,7 +48,12 @@ export default class ChooseAuthPage extends React.Component {
} }
> >
<span className='icon' /> <span className='icon' />
<span>{'Create new team with Google Apps Account'}</span> <span>
<FormattedMessage
id='choose_auth_page.googleCreate'
defaultMessage='Create new team with Google Apps Account'
/>
</span>
</a> </a>
); );
} }
@@ -48,6 +62,7 @@ export default class ChooseAuthPage extends React.Component {
buttons.push( buttons.push(
<a <a
className='btn btn-custom-login email btn-full' className='btn btn-custom-login email btn-full'
key='email'
href='#' href='#'
onClick={ onClick={
function clickEmail(e) { function clickEmail(e) {
@@ -57,20 +72,37 @@ export default class ChooseAuthPage extends React.Component {
} }
> >
<span className='fa fa-envelope' /> <span className='fa fa-envelope' />
<span>{'Create new team with email address'}</span> <span>
<FormattedMessage
id='choose_auth_page.emailCreate'
defaultMessage='Create new team with email address'
/>
</span>
</a> </a>
); );
} }
if (buttons.length === 0) { if (buttons.length === 0) {
buttons = <span>{'No sign-up methods configured, please contact your system administrator.'}</span>; buttons = (
<span>
<FormattedMessage
id='choose_auth_page.noSignup'
defaultMessage='No sign-up methods configured, please contact your system administrator.'
/>
</span>
);
} }
return ( return (
<div> <div>
{buttons} {buttons}
<div className='form-group margin--extra-2x'> <div className='form-group margin--extra-2x'>
<span><a href='/find_team'>{'Find my teams'}</a></span> <span><a href='/find_team'>
<FormattedMessage
id='choose_auth_page.find'
defaultMessage='Find my teams'
/>
</a></span>
</div> </div>
</div> </div>
); );

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

@@ -4,7 +4,20 @@
import * as Utils from '../utils/utils.jsx'; import * as Utils from '../utils/utils.jsx';
import * as Client from '../utils/client.jsx'; import * as Client from '../utils/client.jsx';
export default class EmailSignUpPage extends React.Component { import {injectIntl, intlShape, defineMessages, FormattedMessage} from 'mm-intl';
const holders = defineMessages({
emailError: {
id: 'email_signup.emailError',
defaultMessage: 'Please enter a valid email address'
},
address: {
id: 'email_signup.address',
defaultMessage: 'Email Address'
}
});
class EmailSignUpPage extends React.Component {
constructor() { constructor() {
super(); super();
@@ -20,7 +33,7 @@ export default class EmailSignUpPage extends React.Component {
team.email = ReactDOM.findDOMNode(this.refs.email).value.trim().toLowerCase(); team.email = ReactDOM.findDOMNode(this.refs.email).value.trim().toLowerCase();
if (!team.email || !Utils.isEmail(team.email)) { if (!team.email || !Utils.isEmail(team.email)) {
state.emailError = 'Please enter a valid email address'; state.emailError = this.props.intl.formatMessage(holders.emailError);
isValid = false; isValid = false;
} else { } else {
state.emailError = null; state.emailError = null;
@@ -67,7 +80,7 @@ export default class EmailSignUpPage extends React.Component {
type='email' type='email'
ref='email' ref='email'
className='form-control' className='form-control'
placeholder='Email Address' placeholder={this.props.intl.formatMessage(holders.address)}
maxLength='128' maxLength='128'
spellCheck='false' spellCheck='false'
/> />
@@ -78,12 +91,20 @@ export default class EmailSignUpPage extends React.Component {
className='btn btn-md btn-primary' className='btn btn-md btn-primary'
type='submit' type='submit'
> >
{'Create Team'} <FormattedMessage
id='email_signup.createTeam'
defaultMessage='Create Team'
/>
</button> </button>
{serverError} {serverError}
</div> </div>
<div className='form-group margin--extra-2x'> <div className='form-group margin--extra-2x'>
<span><a href='/find_team'>{`Find my teams`}</a></span> <span><a href='/find_team'>
<FormattedMessage
id='email_signup.find'
defaultMessage='Find my teams'
/>
</a></span>
</div> </div>
</form> </form>
); );
@@ -93,4 +114,7 @@ export default class EmailSignUpPage extends React.Component {
EmailSignUpPage.defaultProps = { EmailSignUpPage.defaultProps = {
}; };
EmailSignUpPage.propTypes = { EmailSignUpPage.propTypes = {
intl: intlShape.isRequired
}; };
export default injectIntl(EmailSignUpPage);

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

@@ -5,7 +5,24 @@ import * as utils from '../utils/utils.jsx';
import * as client from '../utils/client.jsx'; import * as client from '../utils/client.jsx';
import Constants from '../utils/constants.jsx'; import Constants from '../utils/constants.jsx';
export default class SSOSignUpPage extends React.Component { import {injectIntl, intlShape, defineMessages, FormattedMessage} from 'mm-intl';
const holders = defineMessages({
team_error: {
id: 'sso_signup.team_error',
defaultMessage: 'Please enter a team name'
},
length_error: {
id: 'sso_signup.length_error',
defaultMessage: 'Name must be 3 or more characters up to a maximum of 15'
},
teamName: {
id: 'sso_signup.teamName',
defaultMessage: 'Enter name of new team'
}
});
class SSOSignUpPage extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
@@ -16,6 +33,7 @@ export default class SSOSignUpPage extends React.Component {
} }
handleSubmit(e) { handleSubmit(e) {
e.preventDefault(); e.preventDefault();
const {formatMessage} = this.props.intl;
var team = {}; var team = {};
var state = this.state; var state = this.state;
state.nameError = null; state.nameError = null;
@@ -24,13 +42,13 @@ export default class SSOSignUpPage extends React.Component {
team.display_name = this.state.name; team.display_name = this.state.name;
if (!team.display_name) { if (!team.display_name) {
state.nameError = 'Please enter a team name'; state.nameError = formatMessage(holders.team_error);
this.setState(state); this.setState(state);
return; return;
} }
if (team.display_name.length <= 2) { if (team.display_name.length <= 2) {
state.nameError = 'Name must be 3 or more characters up to a maximum of 15'; state.nameError = formatMessage(holders.length_error);
this.setState(state); this.setState(state);
return; return;
} }
@@ -80,24 +98,36 @@ export default class SSOSignUpPage extends React.Component {
button = ( button = (
<a <a
className='btn btn-custom-login gitlab btn-full' className='btn btn-custom-login gitlab btn-full'
key='gitlab'
href='#' href='#'
onClick={this.handleSubmit} onClick={this.handleSubmit}
disabled={disabled} disabled={disabled}
> >
<span className='icon'/> <span className='icon'/>
<span>{'Create team with GitLab Account'}</span> <span>
<FormattedMessage
id='sso_signup.gitlab'
defaultMessage='Create team with GitLab Account'
/>
</span>
</a> </a>
); );
} else if (this.props.service === Constants.GOOGLE_SERVICE) { } else if (this.props.service === Constants.GOOGLE_SERVICE) {
button = ( button = (
<a <a
className='btn btn-custom-login google btn-full' className='btn btn-custom-login google btn-full'
key='google'
href='#' href='#'
onClick={this.handleSubmit} onClick={this.handleSubmit}
disabled={disabled} disabled={disabled}
> >
<span className='icon'/> <span className='icon'/>
<span>{'Create team with Google Apps Account'}</span> <span>
<FormattedMessage
id='sso_signup.google'
defaultMessage='Create team with Google Apps Account'
/>
</span>
</a> </a>
); );
} }
@@ -113,7 +143,7 @@ export default class SSOSignUpPage extends React.Component {
type='text' type='text'
ref='teamname' ref='teamname'
className='form-control' className='form-control'
placeholder='Enter name of new team' placeholder={this.props.intl.formatMessage(holders.teamName)}
maxLength='128' maxLength='128'
onChange={this.nameChange} onChange={this.nameChange}
spellCheck='false' spellCheck='false'
@@ -125,7 +155,12 @@ export default class SSOSignUpPage extends React.Component {
{serverError} {serverError}
</div> </div>
<div className='form-group margin--extra-2x'> <div className='form-group margin--extra-2x'>
<span><a href='/find_team'>{'Find my teams'}</a></span> <span><a href='/find_team'>
<FormattedMessage
id='sso_signup.find'
defaultMessage='Find my teams'
/>
</a></span>
</div> </div>
</form> </form>
); );
@@ -136,5 +171,8 @@ SSOSignUpPage.defaultProps = {
service: '' service: ''
}; };
SSOSignUpPage.propTypes = { SSOSignUpPage.propTypes = {
intl: intlShape.isRequired,
service: React.PropTypes.string service: React.PropTypes.string
}; };
export default injectIntl(SSOSignUpPage);

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

@@ -2,12 +2,61 @@
// See License.txt for license information. // See License.txt for license information.
import FindTeam from '../components/find_team.jsx'; import FindTeam from '../components/find_team.jsx';
import * as Client from '../utils/client.jsx';
function setupFindTeamPage() { var IntlProvider = ReactIntl.IntlProvider;
ReactDOM.render(
<FindTeam />, class Root extends React.Component {
document.getElementById('find-team') constructor() {
); super();
this.state = {
translations: null,
loaded: false
};
}
static propTypes() {
return {
map: React.PropTypes.object.isRequired
};
}
componentWillMount() {
Client.getTranslations(
this.props.map.Locale,
(data) => {
this.setState({
translations: data,
loaded: true
});
},
() => {
this.setState({
loaded: true
});
}
);
}
render() {
if (!this.state.loaded) {
return <div></div>;
}
return (
<IntlProvider
locale={this.props.map.Locale}
messages={this.state.translations}
>
<FindTeam />
</IntlProvider>
);
}
} }
global.window.setup_find_team_page = setupFindTeamPage; global.window.setup_find_team_page = function setup(props) {
ReactDOM.render(
<Root map={props} />,
document.getElementById('find-team')
);
};

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

@@ -60,7 +60,7 @@ global.window.setup_signup_team_page = function setup(props) {
for (var prop in props) { for (var prop in props) {
if (props.hasOwnProperty(prop)) { if (props.hasOwnProperty(prop)) {
if (prop !== 'Title') { if (prop !== 'Title' && prop !== 'Locale' && prop !== 'Info') {
teams.push({name: prop, display_name: props[prop]}); teams.push({name: prop, display_name: props[prop]});
} }
} }

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

@@ -1 +0,0 @@
../../../doc/help/Messaging.md

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

37
web/static/help/Messaging_es.md Обычный файл
Просмотреть файл

@@ -0,0 +1,37 @@
# Mensajes
## Escribiendo Mensajes
Puedes escribir mensajes utilizando el cuadro de texto que dice "Escribe un mensaje..." al final de Mattermost.
Presiona **RETORNO** para enviar un mensaje. Utiliza **Shift+RETORNO** para crear una nueva linea sin enviar el mensaje.
## Darle formato a los Mensajes
Los mensajes de Mattermost se les asigna formato utilizando un estándard que se llama "markdown". Aquí algunos ejemplos:
| Texto escrito | Como aparece |
|:--------------|:-------------|
|`**negrita**`| **negrita** |
| `_italica_`|_italica_|
|`[hipervinculo](http://mattermost.org)`|[hipervinculo](http://mattermost.org)|
|`![imagen embebida](https://travis-ci.org/mattermost/platform.svg)`|![imagen embebida](https://travis-ci.org/mattermost/platform.svg)|
|`:smile:` `:sheep:` `:alien:`|:smile: :sheep: :alien:|
Revisa la lista completa de Emojis [aquí](http://www.emoji-cheat-sheet.com/).
## Mencionando a compañeros
Puedes mencionar a un compañero al utilizar el simbolo `@` más el nombre de usuario para enviarles una notificación especial que llame su atención.
Por ejemplo, podrías escribir:
```
@alicia como te fue con la entrevista del nuevo candidato?
```
Lo cual enviará una notificación especial de mención a **alicia** para que lea tu mensaje.
Para mencionar un compañero, presiona `@` y podrás ver una lista de los miembros de equipo a quienes puedes mandarles un mensaje. Puedes escribir su nombre de usuario o utilizar las flechas de **Arriba** y **Abajo** y presionar **RETORNO** para seleccionarlos.
Puedes configurar como te gustaría ser notificado cuando alguien te menciona por nombre de usuario, tu primer nombre, sobrenombre o cualquier otra palabra clave en **Configurar Cuenta** > **Notificaciones** y puedes asignar preferencias especificas para un canal en **[Nombre del Canal]** > **Preferencias de Notificación**

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

@@ -396,6 +396,11 @@
"admin.user_item.makeActive": "Make Active", "admin.user_item.makeActive": "Make Active",
"admin.user_item.makeInactive": "Make Inactive", "admin.user_item.makeInactive": "Make Inactive",
"admin.user_item.resetPwd": "Reset Password", "admin.user_item.resetPwd": "Reset Password",
"authorize.title": "An application would like to connect to your {teamName} account",
"authorize.app": "The app {appName} would like the ability to access and modify your basic information.",
"authorize.access": "Allow {appName} access?",
"authorize.deny": "Deny",
"authorize.allow": "Allow",
"claim.account.noEmail": "No email specified", "claim.account.noEmail": "No email specified",
"claim.email_to_sso.pwdError": "Please enter your password.", "claim.email_to_sso.pwdError": "Please enter your password.",
"claim.email_to_sso.pwd": "Password", "claim.email_to_sso.pwd": "Password",
@@ -412,11 +417,76 @@
"claim.sso_to_email_newPwd": "Enter a new password for your {team} {site} account", "claim.sso_to_email_newPwd": "Enter a new password for your {team} {site} account",
"claim.sso_to_email.switchTo": "Switch {type} to email and password", "claim.sso_to_email.switchTo": "Switch {type} to email and password",
"error_bar.preview_mode": "Preview Mode: Email notifications have not been configured", "error_bar.preview_mode": "Preview Mode: Email notifications have not been configured",
"find_team.submitError": "Please enter a valid email address",
"find_team.placeholder": "you@domain.com",
"find_team.findTitle": "Find Your Team",
"find_team.findDescription": "An email was sent with links to any teams to which you are a member.",
"find_team.getLinks": "Get an email with links to any teams to which you are a member.",
"find_team.email": "Email",
"find_team.send": "Send",
"loading_screen.loading": "Loading", "loading_screen.loading": "Loading",
"login_email.badTeam": "Bad team name",
"login_email.emailReq": "An email is required",
"login_email.pwdReq": "A password is required",
"login_email.email": "Email",
"login_email.pwd": "Password",
"login_email.signin": "Sign in",
"login_ldap.badTeam": "Bad team name",
"login_ldap.idlReq": "An LDAP ID is required",
"login_ldap.pwdReq": "An LDAP password is required",
"login_ldap.username": "LDAP Username",
"login_ldap.pwd": "LDAP Password",
"login_ldap.signin": "Sign in",
"login.gitlab": "with GitLab",
"login.google": "with Google Apps",
"login.changed": " Sign-in method changed successfully",
"login.verified": " Email Verified",
"login.or": "or",
"login.forgot": "I forgot my password",
"login.noAccount": "Don't have an account? ",
"login.create": "Create one now",
"login.createTeam": "Create a new team",
"login.find": "Find your other teams",
"login.signTo": "Sign in to:",
"login.on": "on {siteName}",
"password_form.error": "Please enter at least {chars} characters.",
"password_form.update": "Your password has been updated successfully.",
"password_form.pwd": "Password",
"password_form.click": "Click <a href={url}>here</a> to log in.",
"password_form.title": "Password Reset",
"password_form.enter": "Enter a new password for your {teamDisplayName} {siteName} account.",
"password_form.change": "Change my password",
"password_send.error": "Please enter a valid email address.",
"password_send.link": "<p>A password reset link has been sent to <b>{email}</b> for your <b>{teamDisplayName}</b> team on {hostname}.</p>",
"password_send.checkInbox": "Please check your inbox.",
"password_send.email": "Email",
"password_send.title": "Password Reset",
"password_send.description": "To reset your password, enter the email address you used to sign up for {teamName}.",
"password_send.reset": "Reset my password",
"signup_team.noTeams": "There are no teams include in the Team Directory and team creation has been disabled.",
"signup_team.choose": "Choose a Team",
"signup_team.createTeam": "Or Create a Team",
"signup_team.disabled": "Team creation has been disabled. Please contact an administrator for access.",
"signup_team.none": "No team creation method has been enabled. Please contact an administrator for access.",
"suggestion.mention.all": "Notifies everyone in the team", "suggestion.mention.all": "Notifies everyone in the team",
"suggestion.mention.channel": "Notifies everyone in the channel", "suggestion.mention.channel": "Notifies everyone in the channel",
"suggestion.search.public": "Public Channels", "suggestion.search.public": "Public Channels",
"suggestion.search.private": "Private Groups", "suggestion.search.private": "Public Groups",
"choose_auth_page.gitlabCreate": "Create new team with GitLab Account",
"choose_auth_page.googleCreate": "Create new team with Google Apps Account",
"choose_auth_page.emailCreate": "Create new team with email address",
"choose_auth_page.noSignup": "No sign-up methods configured, please contact your system administrator.",
"choose_auth_page.find": "Find my teams",
"email_signup.emailError": "Please enter a valid email address",
"email_signup.address": "Email Address",
"email_signup.createTeam": "Create Team",
"email_signup.find": "Find my teams",
"sso_signup.team_error": "Please enter a team name",
"sso_signup.length_error": "Name must be 3 or more characters up to a maximum of 15",
"sso_signup.teamName": "Enter name of new team",
"sso_signup.gitlab": "Create team with GitLab Account",
"sso_signup.google": "Create team with Google Apps Account",
"sso_signup.find": "Find my teams",
"tutorial_intro.screenOne": "<h3>Welcome to:</h3>\n <h1>Mattermost</h1>\n <p>Your team communication all in one place, instantly searchable and available anywhere</p>\n <p>Keep your team connected to help them achieve what matters most.</p>", "tutorial_intro.screenOne": "<h3>Welcome to:</h3>\n <h1>Mattermost</h1>\n <p>Your team communication all in one place, instantly searchable and available anywhere</p>\n <p>Keep your team connected to help them achieve what matters most.</p>",
"tutorial_intro.screenTwo": "<h3>How Mattermost works:</h3>\n <p>Communication happens in public discussion channels, private groups and direct messages.</p>\n <p>Everything is archived and searchable from any web-enabled desktop, laptop or phone.</p>", "tutorial_intro.screenTwo": "<h3>How Mattermost works:</h3>\n <p>Communication happens in public discussion channels, private groups and direct messages.</p>\n <p>Everything is archived and searchable from any web-enabled desktop, laptop or phone.</p>",
"tutorial_intro.invite": "Invite teammates", "tutorial_intro.invite": "Invite teammates",

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

@@ -396,6 +396,16 @@
"admin.user_item.resetPwd": "Reiniciar Contraseña", "admin.user_item.resetPwd": "Reiniciar Contraseña",
"admin.user_item.sysAdmin": "Admin de Sistema", "admin.user_item.sysAdmin": "Admin de Sistema",
"admin.user_item.teamAdmin": "Admin de Equipo", "admin.user_item.teamAdmin": "Admin de Equipo",
"authorize.access": "¿Permitir acceso a {appName}?",
"authorize.allow": "Permitir",
"authorize.app": "La app {appName} quiere tener la abilidad de accesar y modificar tu información básica.",
"authorize.deny": "Denegar",
"authorize.title": "Una aplicación quiere conectarse con tu cuenta de {teamName}",
"choose_auth_page.emailCreate": "Crea un nuevo equipo con tu cuenta de correo",
"choose_auth_page.find": "Encontrar mi equipo",
"choose_auth_page.gitlabCreate": "Crear un nuevo equipo con una cuenta de GitLab",
"choose_auth_page.googleCreate": "Crear un nuevo equipo con una cuenta de Google Apps",
"choose_auth_page.noSignup": "No hay métodos de inicio de sesión configurad, por favor contacte al administrador de sistemasos",
"claim.account.noEmail": "No se especifico un correo electrónico.", "claim.account.noEmail": "No se especifico un correo electrónico.",
"claim.email_to_sso.enterPwd": "Ingresa la contraseña para tu cuenta para {team} {site}", "claim.email_to_sso.enterPwd": "Ingresa la contraseña para tu cuenta para {team} {site}",
"claim.email_to_sso.pwd": "Contraseña", "claim.email_to_sso.pwd": "Contraseña",
@@ -411,8 +421,68 @@
"claim.sso_to_email.switchTo": "Cambiar {type} a correo electrónico y contraseña", "claim.sso_to_email.switchTo": "Cambiar {type} a correo electrónico y contraseña",
"claim.sso_to_email.title": "Cambiar la cuenta de {type} a Correo Electrónico", "claim.sso_to_email.title": "Cambiar la cuenta de {type} a Correo Electrónico",
"claim.sso_to_email_newPwd": "Ingresa una nueva contraseña para tu cuenta de {team} {site}", "claim.sso_to_email_newPwd": "Ingresa una nueva contraseña para tu cuenta de {team} {site}",
"email_signup.address": "Correo electrónico",
"email_signup.createTeam": "Crear Equipo",
"email_signup.emailError": "Por favor ingresa una dirección de correos válida",
"email_signup.find": "Encontrar mi equipo",
"error_bar.preview_mode": "Modo de prueba: Las notificaciones por correo electrónico no han sido configuradas", "error_bar.preview_mode": "Modo de prueba: Las notificaciones por correo electrónico no han sido configuradas",
"find_team.email": "Correo electrónico",
"find_team.findDescription": "Enviamos un correo electrónico con los equipos a los que perteneces.",
"find_team.findTitle": "Encuentra tu equipo",
"find_team.getLinks": "Obtén un correo electrónico con los equipos a los que perteneces.",
"find_team.placeholder": "tu@ejemplo.com",
"find_team.send": "Enviar",
"find_team.submitError": "Por favor ingresa una dirección válida",
"loading_screen.loading": "Cargando", "loading_screen.loading": "Cargando",
"login.changed": " Cambiado el método de inicio de sesión satisfactoriamente",
"login.create": "Crea uno ahora",
"login.createTeam": "Crear un nuevo equipo",
"login.find": "Encuentra tus otros equipos",
"login.forgot": "Olvide mi contraseña",
"login.gitlab": "con GitLab",
"login.google": "con Google Apps",
"login.noAccount": "¿No tienes una cuenta? ",
"login.on": "en {siteName}",
"login.or": "o",
"login.signTo": "Ingresar a:",
"login.verified": " Correo electrónico Verificado",
"login_email.badTeam": "Nombre de Equipo inválido",
"login_email.email": "Correo electrónico",
"login_email.emailReq": "El correo electrónico es obligatorio",
"login_email.pwd": "Contraseña",
"login_email.pwdReq": "La contraseña es obligatoria",
"login_email.signin": "Entrar",
"login_ldap.badTeam": "Nombre de Equipo inválido",
"login_ldap.idlReq": "El ID de LDAP es obligatorio",
"login_ldap.pwd": "Contraseña LDAP",
"login_ldap.pwdReq": "La contraseña LDAP es obligatoria",
"login_ldap.signin": "Entrar",
"login_ldap.username": "Usuario LDAP",
"password_form.change": "Cambiar mi contraseña",
"password_form.click": " Pincha <a href={url}>aquí</a> para iniciar sesión.",
"password_form.enter": "Ingresa una nueva contraseña para tu cuenta en {teamDisplayName} {SiteName}.",
"password_form.error": "Por favor ingresa al menos {chars} caracteres.",
"password_form.pwd": "Contraseña",
"password_form.title": "Restablecer Contraseña",
"password_form.update": "Tu contraseña ha sido actualizada satisfactoriamente.",
"password_send.checkInbox": "Por favor revisa tu bandeja de entrada.",
"password_send.description": "Para restablecer tu contraseña, ingresa la dirección de correo electrónico que utilizaste para registrarte en {teamName}.",
"password_send.email": "Correo electrónico",
"password_send.error": "Por favor ingresa una dirección correo electrónico válida.",
"password_send.link": "<p>Se ha enviado un enlace para restablecer la contraseña a <b>{email}</b> para tu equipo <b>{teamDisplayName}</b> en {hostname}.</p>",
"password_send.reset": "Restablecer mi contraseña",
"password_send.title": "Restablecer Contraseña",
"signup_team.choose": "Selecciona un Equipo",
"signup_team.createTeam": "O Crea un Equipo",
"signup_team.disabled": "La creación de Equipos ha sido deshabilitada.",
"signup_team.noTeams": "No hay equipos en el Directorio de Equipos y la creación de equipos ha sido deshabilitada.",
"signup_team.none": "No se ha habilitado ningún método para creación de equipos. Por favor contacta a un administrador de sistema para solicitar acceso.",
"sso_signup.find": "Encontrar mi equipo",
"sso_signup.gitlab": "Crea un equipo con una cuenta de GitLab",
"sso_signup.google": "Crea un equipo con una cuenta de Google Apps",
"sso_signup.length_error": "Name must be 3 or more characters up to a maximum of 15",
"sso_signup.teamName": "Ingresa el nombre del nuevo equipo",
"sso_signup.team_error": "Please enter a team name",
"suggestion.mention.all": "Notifica a todas las personas en el equipo", "suggestion.mention.all": "Notifica a todas las personas en el equipo",
"suggestion.mention.channel": "Notifica a todas las personas en el canal", "suggestion.mention.channel": "Notifica a todas las personas en el canal",
"suggestion.search.private": "Grupos Privados", "suggestion.search.private": "Grupos Privados",
@@ -420,7 +490,7 @@
"tutorial_intro.allSet": "Ya estás listo para comenzar", "tutorial_intro.allSet": "Ya estás listo para comenzar",
"tutorial_intro.end": "Pincha “Siguiente” para entrar al Canal General. Este es el primer canal que ven tus compañeros cuando ingresan. Utilizalo para mandar mensajes que todos deben leer.", "tutorial_intro.end": "Pincha “Siguiente” para entrar al Canal General. Este es el primer canal que ven tus compañeros cuando ingresan. Utilizalo para mandar mensajes que todos deben leer.",
"tutorial_intro.invite": "Invitar compañeros", "tutorial_intro.invite": "Invitar compañeros",
"tutorial_intro.next": "Seguir", "tutorial_intro.next": "Siguiente",
"tutorial_intro.screenOne": "<h3>Bienvenido a:</h3> <h1>Mattermost</h1> <p>Las comunicaciones de tu equipo en un solo lugar, con búsquedas instantáneas y disponible desde donde sea.</p> <p>Mantén a tu equipo conectado para ayudarlos a conseguir lo que realmente importa.</p>", "tutorial_intro.screenOne": "<h3>Bienvenido a:</h3> <h1>Mattermost</h1> <p>Las comunicaciones de tu equipo en un solo lugar, con búsquedas instantáneas y disponible desde donde sea.</p> <p>Mantén a tu equipo conectado para ayudarlos a conseguir lo que realmente importa.</p>",
"tutorial_intro.screenTwo": "<h3>Cómo funciona Mattermost:</h3> <p>Las comunicaciones ocurren en los canales de discusión los cuales son públicos, o en grupos privados e incluso con mensajes privados.</p> <p>Todo lo que ocurre es archivado y se puede buscar en cualquier momento desde cualquier dispositivo con acceso a Mattermost.</p>", "tutorial_intro.screenTwo": "<h3>Cómo funciona Mattermost:</h3> <p>Las comunicaciones ocurren en los canales de discusión los cuales son públicos, o en grupos privados e incluso con mensajes privados.</p> <p>Todo lo que ocurre es archivado y se puede buscar en cualquier momento desde cualquier dispositivo con acceso a Mattermost.</p>",
"tutorial_intro.skip": "Saltar el tutorial", "tutorial_intro.skip": "Saltar el tutorial",

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

@@ -23,7 +23,7 @@
</div> </div>
</div> </div>
<script> <script>
window.setup_find_team_page(); window.setup_find_team_page({{ .Props }});
</script> </script>
</body> </body>
</html> </html>

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

@@ -10,7 +10,7 @@
<div class="signup-team__container"> <div class="signup-team__container">
<img class="signup-team-logo" src="/static/images/logo.png" /> <img class="signup-team-logo" src="/static/images/logo.png" />
<h1>{{ .ClientCfg.SiteName }}</h1> <h1>{{ .ClientCfg.SiteName }}</h1>
<h4 class="color--light">All team communication in one place, searchable and accessible anywhere</h4> <h4 class="color--light">{{.Props.Info}}</h4>
<div id="signup-team"></div> <div id="signup-team"></div>
</div> </div>
</div> </div>

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

@@ -173,6 +173,7 @@ func root(c *api.Context, w http.ResponseWriter, r *http.Request) {
if len(c.Session.UserId) == 0 { if len(c.Session.UserId) == 0 {
page := NewHtmlTemplatePage("signup_team", c.T("web.root.singup_title"), c.Locale) page := NewHtmlTemplatePage("signup_team", c.T("web.root.singup_title"), c.Locale)
page.Props["Info"] = c.T("web.root.singup_info")
if result := <-api.Srv.Store.Team().GetAllTeamListing(); result.Err != nil { if result := <-api.Srv.Store.Team().GetAllTeamListing(); result.Err != nil {
c.Err = result.Err c.Err = result.Err
@@ -611,8 +612,17 @@ func docs(c *api.Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r) params := mux.Vars(r)
doc := params["doc"] doc := params["doc"]
var user *model.User
if len(c.Session.UserId) != 0 {
userChan := api.Srv.Store.User().Get(c.Session.UserId)
if userChan := <-userChan; userChan.Err == nil {
user = userChan.Data.(*model.User)
}
}
page := NewHtmlTemplatePage("docs", c.T("web.doc.title"), c.Locale) page := NewHtmlTemplatePage("docs", c.T("web.doc.title"), c.Locale)
page.Props["Site"] = doc page.Props["Site"] = doc
page.User = user
page.Render(c, w) page.Render(c, w)
} }