From a72ba140240266b03558dba716e6f4815392d491 Mon Sep 17 00:00:00 2001 From: Elias Nahum Date: Thu, 28 Jan 2016 11:21:12 -0300 Subject: PLT-7: Refactoring frontend (chunk 3) - Tutorial components - Claim components - Suggestion components --- web/react/components/claim/claim_account.jsx | 11 +++- web/react/components/claim/email_to_sso.jsx | 61 +++++++++++++++--- web/react/components/claim/sso_to_email.jsx | 72 +++++++++++++++++++--- .../components/suggestion/at_mention_provider.jsx | 16 ++++- .../suggestion/search_suggestion_list.jsx | 17 ++++- .../components/tutorial/tutorial_intro_screens.jsx | 65 ++++++++++++++----- web/react/components/tutorial/tutorial_tip.jsx | 25 +++++++- web/static/i18n/en.json | 35 ++++++++++- web/static/i18n/es.json | 39 +++++++++++- 9 files changed, 297 insertions(+), 44 deletions(-) (limited to 'web') diff --git a/web/react/components/claim/claim_account.jsx b/web/react/components/claim/claim_account.jsx index f38f558db..87026b762 100644 --- a/web/react/components/claim/claim_account.jsx +++ b/web/react/components/claim/claim_account.jsx @@ -4,6 +4,8 @@ import EmailToSSO from './email_to_sso.jsx'; import SSOToEmail from './sso_to_email.jsx'; +import {FormattedMessage} from 'mm-intl'; + export default class ClaimAccount extends React.Component { constructor(props) { super(props); @@ -13,7 +15,14 @@ export default class ClaimAccount extends React.Component { render() { let content; if (this.props.email === '') { - content =

{'No email specified.'}

; + content = ( +

+ +

+ ); } else if (this.props.currentType === '' && this.props.newType !== '') { content = (
-

{'Switch Email/Password Account to ' + uiType}

+

+ +

-

{'Upon claiming your account, you will only be able to login with ' + Utils.toTitleCase(this.props.type) + ' SSO.'}

-

{'Enter the password for your ' + this.props.teamDisplayName + ' ' + global.window.mm_config.SiteName + ' account.'}

+

+ +

+

+ +

@@ -78,7 +116,13 @@ export default class EmailToSSO extends React.Component { type='submit' className='btn btn-primary' > - {'Switch account to ' + uiType} +
@@ -90,8 +134,11 @@ export default class EmailToSSO extends React.Component { EmailToSSO.defaultProps = { }; EmailToSSO.propTypes = { + intl: intlShape.isRequired, type: React.PropTypes.string.isRequired, email: React.PropTypes.string.isRequired, teamName: React.PropTypes.string.isRequired, teamDisplayName: React.PropTypes.string.isRequired }; + +export default injectIntl(EmailToSSO); \ No newline at end of file diff --git a/web/react/components/claim/sso_to_email.jsx b/web/react/components/claim/sso_to_email.jsx index 0868b7f2f..73ff13cc9 100644 --- a/web/react/components/claim/sso_to_email.jsx +++ b/web/react/components/claim/sso_to_email.jsx @@ -4,7 +4,28 @@ import * as Utils from '../../utils/utils.jsx'; import * as Client from '../../utils/client.jsx'; -export default class SSOToEmail extends React.Component { +import {intlShape, injectIntl, defineMessages, FormattedMessage} from 'mm-intl'; + +const holders = defineMessages({ + enterPwd: { + id: 'claim.sso_to_email.enterPwd', + defaultMessage: 'Please enter a password.' + }, + pwdNotMatch: { + id: 'claim.sso_to_email.pwdNotMatch', + defaultMessage: 'Password do not match.' + }, + newPwd: { + id: 'claim.sso_to_email.newPwd', + defaultMessage: 'New Password' + }, + confirm: { + id: 'claim.sso_to_email.confirm', + defaultMessage: 'Confirm Password' + } +}); + +class SSOToEmail extends React.Component { constructor(props) { super(props); @@ -13,19 +34,20 @@ export default class SSOToEmail extends React.Component { this.state = {}; } submit(e) { + const {formatMessage} = this.props.intl; e.preventDefault(); const state = {}; const password = ReactDOM.findDOMNode(this.refs.password).value.trim(); if (!password) { - state.error = 'Please enter a password.'; + state.error = formatMessage(holders.enterPwd); this.setState(state); return; } const confirmPassword = ReactDOM.findDOMNode(this.refs.passwordconfirm).value.trim(); if (!confirmPassword || password !== confirmPassword) { - state.error = 'Passwords do not match.'; + state.error = formatMessage(holders.pwdNotMatch); this.setState(state); return; } @@ -50,6 +72,7 @@ export default class SSOToEmail extends React.Component { ); } render() { + const {formatMessage} = this.props.intl; var error = null; if (this.state.error) { error =
; @@ -65,17 +88,39 @@ export default class SSOToEmail extends React.Component { return (
-

{'Switch ' + uiType + ' Account to Email'}

+

+ +

-

{'Upon changing your account type, you will only be able to login with your email and password.'}

-

{'Enter a new password for your ' + this.props.teamDisplayName + ' ' + global.window.mm_config.SiteName + ' account.'}

+

+ +

+

+ +

@@ -85,7 +130,7 @@ export default class SSOToEmail extends React.Component { className='form-control' name='passwordconfirm' ref='passwordconfirm' - placeholder='Confirm Password' + placeholder={formatMessage(holders.confirm)} spellCheck='false' />
@@ -94,7 +139,13 @@ export default class SSOToEmail extends React.Component { type='submit' className='btn btn-primary' > - {'Switch ' + uiType + ' account to email and password'} +
@@ -106,8 +157,11 @@ export default class SSOToEmail extends React.Component { SSOToEmail.defaultProps = { }; SSOToEmail.propTypes = { + intl: intlShape.isRequired, currentType: React.PropTypes.string.isRequired, email: React.PropTypes.string.isRequired, teamName: React.PropTypes.string.isRequired, teamDisplayName: React.PropTypes.string.isRequired }; + +export default injectIntl(SSOToEmail); \ No newline at end of file diff --git a/web/react/components/suggestion/at_mention_provider.jsx b/web/react/components/suggestion/at_mention_provider.jsx index e502c981d..50231ad15 100644 --- a/web/react/components/suggestion/at_mention_provider.jsx +++ b/web/react/components/suggestion/at_mention_provider.jsx @@ -5,6 +5,8 @@ import SuggestionStore from '../../stores/suggestion_store.jsx'; import UserStore from '../../stores/user_store.jsx'; import * as Utils from '../../utils/utils.jsx'; +import {FormattedMessage} from 'mm-intl'; + const MaxUserSuggestions = 40; class AtMentionSuggestion extends React.Component { @@ -16,11 +18,21 @@ class AtMentionSuggestion extends React.Component { let icon; if (item.username === 'all') { username = 'all'; - description = 'Notifies everyone in the team'; + description = ( + + ); icon = ; } else if (item.username === 'channel') { username = 'channel'; - description = 'Notifies everyone in the channel'; + description = ( + + ); icon = ; } else { username = item.username; diff --git a/web/react/components/suggestion/search_suggestion_list.jsx b/web/react/components/suggestion/search_suggestion_list.jsx index 3378a33a0..40f5d8777 100644 --- a/web/react/components/suggestion/search_suggestion_list.jsx +++ b/web/react/components/suggestion/search_suggestion_list.jsx @@ -3,7 +3,8 @@ import Constants from '../../utils/constants.jsx'; import SuggestionList from './suggestion_list.jsx'; -import * as Utils from '../../utils/utils.jsx'; + +import {FormattedMessage} from 'mm-intl'; export default class SearchSuggestionList extends SuggestionList { componentDidUpdate(prevProps, prevState) { @@ -19,9 +20,19 @@ export default class SearchSuggestionList extends SuggestionList { renderChannelDivider(type) { let text; if (type === Constants.OPEN_CHANNEL) { - text = 'Public ' + Utils.getChannelTerm(type) + 's'; + text = ( + + ); } else { - text = 'Private ' + Utils.getChannelTerm(type) + 's'; + text = ( + + ); } return ( diff --git a/web/react/components/tutorial/tutorial_intro_screens.jsx b/web/react/components/tutorial/tutorial_intro_screens.jsx index 7ab1e5512..78cfb7b60 100644 --- a/web/react/components/tutorial/tutorial_intro_screens.jsx +++ b/web/react/components/tutorial/tutorial_intro_screens.jsx @@ -9,6 +9,9 @@ import * as Utils from '../../utils/utils.jsx'; import * as AsyncClient from '../../utils/async_client.jsx'; import Constants from '../../utils/constants.jsx'; + +import {FormattedMessage, FormattedHTMLMessage} from 'mm-intl'; + const Preferences = Constants.Preferences; const NUM_SCREENS = 3; @@ -61,10 +64,13 @@ export default class TutorialIntroScreens extends React.Component { return (
-

{'Welcome to:'}

-

{'Mattermost'}

-

{'Your team communication all in one place, instantly searchable and available anywhere.'}

-

{'Keep your team connected to help them achieve what matters most.'}

+ {circles}
); @@ -74,9 +80,12 @@ export default class TutorialIntroScreens extends React.Component { return (
-

{'How Mattermost works:'}

-

{'Communication happens in public discussion channels, private groups and direct messages.'}

-

{'Everything is archived and searchable from any web-enabled desktop, laptop or phone.'}

+ {circles}
); @@ -92,7 +101,10 @@ export default class TutorialIntroScreens extends React.Component { data-toggle='modal' data-target='#invite_member' > - {'Invite teammates'} + ); } else { @@ -105,7 +117,10 @@ export default class TutorialIntroScreens extends React.Component { data-title='Team Invite' data-value={Utils.getWindowLocationOrigin() + '/signup_user_complete/?id=' + team.id} > - {'Invite teammates'} + ); } @@ -116,7 +131,10 @@ export default class TutorialIntroScreens extends React.Component { if (global.window.mm_config.SupportEmail) { supportInfo = (

- {'Need anything, just email us at '} + -

{'You’re all set'}

+

+ +

{inviteModalLink} - {' when you’re ready.'} +

{supportInfo} - {'Click “Next” to enter Town Square. This is the first channel teammates see when they sign up. Use it for posting updates everyone needs to know.'} + {circles} ); @@ -186,14 +215,20 @@ export default class TutorialIntroScreens extends React.Component { tabIndex='1' onClick={this.handleNext} > - {'Next'} +
- {'Skip tutorial'} + diff --git a/web/react/components/tutorial/tutorial_tip.jsx b/web/react/components/tutorial/tutorial_tip.jsx index 03ecdabab..3bab7570a 100644 --- a/web/react/components/tutorial/tutorial_tip.jsx +++ b/web/react/components/tutorial/tutorial_tip.jsx @@ -6,6 +6,9 @@ import PreferenceStore from '../../stores/preference_store.jsx'; import * as AsyncClient from '../../utils/async_client.jsx'; import Constants from '../../utils/constants.jsx'; + +import {FormattedMessage} from 'mm-intl'; + const Preferences = Constants.Preferences; const Overlay = ReactBootstrap.Overlay; @@ -46,7 +49,17 @@ export default class TutorialTip extends React.Component { AsyncClient.savePreferences([preference]); } render() { - const buttonText = this.state.currentScreen === this.props.screens.length - 1 ? 'Okay' : 'Next'; + const buttonText = this.state.currentScreen === this.props.screens.length - 1 ? ( + + ) : ( + + ); const dots = []; if (this.props.screens.length > 1) { @@ -111,12 +124,18 @@ export default class TutorialTip extends React.Component { {buttonText}
- {'Seen this before? '} + - {'Opt out of these tips.'} +
diff --git a/web/static/i18n/en.json b/web/static/i18n/en.json index a713be74c..ae302b86e 100644 --- a/web/static/i18n/en.json +++ b/web/static/i18n/en.json @@ -396,6 +396,39 @@ "admin.user_item.makeActive": "Make Active", "admin.user_item.makeInactive": "Make Inactive", "admin.user_item.resetPwd": "Reset Password", + "claim.account.noEmail": "No email specified", + "claim.email_to_sso.pwdError": "Please enter your password.", + "claim.email_to_sso.pwd": "Password", + "claim.email_to_sso.title": "Switch Email/Password Account to {uiType}", + "claim.email_to_sso.ssoType": "Upon claiming your account, you will only be able to login with {type} SSO", + "claim.email_to_sso.enterPwd": "Enter the password for your {team} {site} account", + "claim.email_to_sso.switchTo": "Switch account to {uiType}", + "claim.sso_to_email.enterPwd": "Please enter a password.", + "claim.sso_to_email.pwdNotMatch": "Password do not match.", + "claim.sso_to_email.newPwd": "New Password", + "claim.sso_to_email.confirm": "Confirm Password", + "claim.sso_to_email.title": "Switch {type} Account to Email", + "claim.sso_to_email.description": "Upon changing your account type, you will only be able to login with your email and password.", + "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", "error_bar.preview_mode": "Preview Mode: Email notifications have not been configured", - "loading_screen.loading": "Loading" + "loading_screen.loading": "Loading", + "suggestion.mention.all": "Notifies everyone in the team", + "suggestion.mention.channel": "Notifies everyone in the channel", + "suggestion.search.public": "Public Channels", + "suggestion.search.private": "Private Groups", + "tutorial_intro.screenOne": "

Welcome to:

\n

Mattermost

\n

Your team communication all in one place, instantly searchable and available anywhere

\n

Keep your team connected to help them achieve what matters most.

", + "tutorial_intro.screenTwo": "

How Mattermost works:

\n

Communication happens in public discussion channels, private groups and direct messages.

\n

Everything is archived and searchable from any web-enabled desktop, laptop or phone.

", + "tutorial_intro.invite": "Invite teammates", + "tutorial_intro.teamInvite": "Team Invite", + "tutorial_intro.support": "Need anything, just email us at ", + "tutorial_intro.allSet": "You’re all set", + "tutorial_intro.whenReady": " when you’re ready.", + "tutorial_intro.end": "Click “Next” to enter Town Square. This is the first channel teammates see when they sign up. Use it for posting updates everyone needs to know.", + "tutorial_intro.next": "Next", + "tutorial_intro.skip": "Skip tutorial", + "tutorial_tip.ok": "Okay", + "tutorial_tip.next": "Next", + "tutorial_tip.seen": "Seen this before? ", + "tutorial_tip.out": "Opt out of these tips." } \ No newline at end of file diff --git a/web/static/i18n/es.json b/web/static/i18n/es.json index 45f8754bd..12f9b5fc5 100644 --- a/web/static/i18n/es.json +++ b/web/static/i18n/es.json @@ -250,7 +250,7 @@ "admin.reset_password.close": "Cerrar", "admin.reset_password.newPassword": "Nueva contraseña", "admin.reset_password.select": "Seleccionar", - "admin.reset_password.submit": "Por favor, introducir como mínimo {chars} caracteres.", + "admin.reset_password.submit": "Por favor, introducir como mínimo 5 caracteres.", "admin.reset_password.title": "Reiniciar Contraseña", "admin.select_team.close": "Cerrar", "admin.select_team.select": "Seleccionar", @@ -384,7 +384,7 @@ "admin.team.userCreationTitle": "Habilitar Creación de Usuarios: ", "admin.team_analytics.activeUsers": "Active Users With Posts", "admin.team_analytics.totalPosts": "Total de Mensajes", - "admin.userList.title": "Usuarios para {team}", + "admin.userList.title": "Usuarios para ", "admin.userList.title2": "Usuarios para {team} ({count})", "admin.user_item.inactive": "Inactivo", "admin.user_item.makeActive": "Activar", @@ -396,6 +396,39 @@ "admin.user_item.resetPwd": "Reiniciar Contraseña", "admin.user_item.sysAdmin": "Admin de Sistema", "admin.user_item.teamAdmin": "Admin de Equipo", + "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.pwd": "Contraseña", + "claim.email_to_sso.pwdError": "Por favor introduce tu contraseña.", + "claim.email_to_sso.ssoType": "Al reclamar tu cuenta, sólo podrás iniciar sesión con {type} SSO", + "claim.email_to_sso.switchTo": "Cambiar cuenta a ", + "claim.email_to_sso.title": "Cambiar Cuenta de Correo/Contraseña a ", + "claim.sso_to_email.confirm": "Confirmar Contraseña", + "claim.sso_to_email.description": "Al cambiar el tipo de cuenta, sólo podrás iniciar sesión con tu correo electrónico y contraseña.", + "claim.sso_to_email.enterPwd": "Por favor ingresa una contraseña.", + "claim.sso_to_email.newPwd": "Nueva Contraseña", + "claim.sso_to_email.pwdNotMatch": "Las contraseñas no coinciden.", + "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_newPwd": "Ingresa una nueva contraseña para tu cuenta de {team} {site}", "error_bar.preview_mode": "Modo de prueba: Las notificaciones por correo electrónico no han sido configuradas", - "loading_screen.loading": "Cargando" + "loading_screen.loading": "Cargando", + "suggestion.mention.all": "Notifica a todas las personas en el equipo", + "suggestion.mention.channel": "Notifica a todas las personas en el canal", + "suggestion.search.private": "Grupos Privados", + "suggestion.search.public": "Canales Públicos", + "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.invite": "Invitar compañeros", + "tutorial_intro.next": "Seguir", + "tutorial_intro.screenOne": "

Bienvenido a:

Mattermost

Las comunicaciones de tu equipo en un solo lugar, con búsquedas instantáneas y disponible desde donde sea.

Mantén a tu equipo conectado para ayudarlos a conseguir lo que realmente importa.

", + "tutorial_intro.screenTwo": "

Cómo funciona Mattermost:

Las comunicaciones ocurren en los canales de discusión los cuales son públicos, o en grupos privados e incluso con mensajes privados.

Todo lo que ocurre es archivado y se puede buscar en cualquier momento desde cualquier dispositivo con acceso a Mattermost.

", + "tutorial_intro.skip": "Saltar el tutorial", + "tutorial_intro.support": "Necesitas algo, escribemos a ", + "tutorial_intro.teamInvite": "Invitar a tu Equipo", + "tutorial_intro.whenReady": " cuando estés listo(a).", + "tutorial_tip.next": "Siguiente", + "tutorial_tip.ok": "Aceptar", + "tutorial_tip.out": "No optar por estos consejos.", + "tutorial_tip.seen": "¿Haz visto esto antes? " } \ No newline at end of file -- cgit v1.2.3-1-g7c22