diff --git a/client/coral-admin/src/actions/install.js b/client/coral-admin/src/actions/install.js
index 9fc308d2f..ceecf16c9 100644
--- a/client/coral-admin/src/actions/install.js
+++ b/client/coral-admin/src/actions/install.js
@@ -20,13 +20,17 @@ const validation = (formData, dispatch, next) => {
return dispatch(hasError());
}
+ const validKeys = Object.keys(formData)
+ .filter(name => name !== 'domains');
+
// Required Validation
- const empty = Object.keys(formData).filter(name => {
+ const empty = validKeys
+ .filter(name => {
const cond = !formData[name].length;
if (cond) {
- // Adding Error
+ // Adding Error
dispatch(addError(name, 'This field is required.'));
} else {
dispatch(addError(name, ''));
@@ -40,18 +44,19 @@ const validation = (formData, dispatch, next) => {
}
// RegExp Validation
- const validation = Object.keys(formData).filter(name => {
- const cond = !validate[name](formData[name]);
- if (cond) {
+ const validation = validKeys
+ .filter(name => {
+ const cond = !validate[name](formData[name]);
+ if (cond) {
// Adding Error
- dispatch(addError(name, errorMsj[name]));
- } else {
- dispatch(addError(name, ''));
- }
+ dispatch(addError(name, errorMsj[name]));
+ } else {
+ dispatch(addError(name, ''));
+ }
- return cond;
- });
+ return cond;
+ });
if (validation.length) {
return dispatch(hasError());
@@ -71,22 +76,27 @@ export const submitSettings = () => (dispatch, getState) => {
export const submitUser = () => (dispatch, getState) => {
const userFormData = getState().install.toJS().data.user;
validation(userFormData, dispatch, function() {
- const data = getState().install.toJS().data;
- dispatch(installRequest());
- coralApi('/setup', {method: 'POST', body: data})
- .then(result => {
- dispatch(installSuccess(result));
- dispatch(nextStep());
- })
- .catch(error => {
- console.error(error);
- dispatch(installFailure(`${error.translation_key}`));
- });
+ dispatch(nextStep());
});
};
+export const finishInstall = () => (dispatch, getState) => {
+ const data = getState().install.toJS().data;
+ dispatch(installRequest());
+ return coralApi('/setup', {method: 'POST', body: data})
+ .then(() => {
+ dispatch(installSuccess());
+ dispatch(nextStep());
+ })
+ .catch(error => {
+ console.error(error);
+ dispatch(installFailure(`${error.translation_key}`));
+ });
+};
+
export const updateSettingsFormData = (name, value) => ({type: actions.UPDATE_FORMDATA_SETTINGS, name, value});
export const updateUserFormData = (name, value) => ({type: actions.UPDATE_FORMDATA_USER, name, value});
+export const updatePermittedDomains = (value) => ({type: actions.UPDATE_PERMITTED_DOMAINS_SETTINGS, value});
const checkInstallRequest = () => ({type: actions.CHECK_INSTALL_REQUEST});
const checkInstallSuccess = installed => ({type: actions.CHECK_INSTALL_SUCCESS, installed});
diff --git a/client/coral-admin/src/constants/install.js b/client/coral-admin/src/constants/install.js
index b3fd7e0d0..743d68593 100644
--- a/client/coral-admin/src/constants/install.js
+++ b/client/coral-admin/src/constants/install.js
@@ -10,6 +10,7 @@ export const INSTALL_SUCCESS = 'INSTALL_SUCCESS';
export const INSTALL_FAILURE = 'INSTALL_FAILURE';
export const UPDATE_FORMDATA_USER = 'UPDATE_FORMDATA_USER';
export const UPDATE_FORMDATA_SETTINGS = 'UPDATE_FORMDATA_SETTINGS';
+export const UPDATE_PERMITTED_DOMAINS_SETTINGS = 'UPDATE_PERMITTED_DOMAINS_SETTINGS';
export const CHECK_INSTALL_REQUEST = 'CHECK_INSTALL_REQUEST';
export const CHECK_INSTALL_SUCCESS = 'CHECK_INSTALL_SUCCESS';
diff --git a/client/coral-admin/src/containers/Configure/Domainlist.js b/client/coral-admin/src/containers/Configure/Domainlist.js
index f845dfeaa..6918c0471 100644
--- a/client/coral-admin/src/containers/Configure/Domainlist.js
+++ b/client/coral-admin/src/containers/Configure/Domainlist.js
@@ -1,26 +1,28 @@
import React from 'react';
+import {Card} from 'coral-ui';
+import styles from './Configure.css';
+import TagsInput from 'react-tagsinput';
+
import I18n from 'coral-framework/modules/i18n/i18n';
import translations from '../../translations.json';
-import TagsInput from 'react-tagsinput';
-import styles from './Configure.css';
-import {Card} from 'coral-ui';
+const lang = new I18n(translations);
-const Domainlist = ({domains, onChangeDomainlist}) => (
-
-
{lang.t('configure.domain-list-title')}
-
- {lang.t('configure.domain-list-text')}
- data.split(',').map(d => d.trim())}
- onChange={tags => onChangeDomainlist('whitelist', tags)}
- />
-
-
-);
+const Domainlist = ({domains, onChangeDomainlist}) => {
+ return (
+
+
{lang.t('configure.domain-list-title')}
+
+ {lang.t('configure.domain-list-text')}
+ data.split(',').map(d => d.trim())}
+ onChange={tags => onChangeDomainlist('whitelist', tags)}
+ />
+
+
+ );
+};
export default Domainlist;
-
-const lang = new I18n(translations);
diff --git a/client/coral-admin/src/containers/Install/InstallContainer.js b/client/coral-admin/src/containers/Install/InstallContainer.js
index 7a8634180..b70d3b8c9 100644
--- a/client/coral-admin/src/containers/Install/InstallContainer.js
+++ b/client/coral-admin/src/containers/Install/InstallContainer.js
@@ -5,19 +5,22 @@ import {Wizard, WizardNav} from 'coral-ui';
import {Layout} from '../../components/ui/Layout';
import {
- nextStep,
- previousStep,
goToStep,
+ nextStep,
+ submitUser,
+ checkInstall,
+ previousStep,
+ finishInstall,
+ submitSettings,
updateUserFormData,
updateSettingsFormData,
- submitSettings,
- submitUser,
- checkInstall
+ updatePermittedDomains
} from '../../actions/install';
import InitialStep from './components/Steps/InitialStep';
import AddOrganizationName from './components/Steps/AddOrganizationName';
import CreateYourAccount from './components/Steps/CreateYourAccount';
+import PermittedDomainsStep from './components/Steps/PermittedDomainsStep';
import FinalStep from './components/Steps/FinalStep';
class InstallContainer extends Component {
@@ -43,6 +46,7 @@ class InstallContainer extends Component {
+
@@ -65,10 +69,14 @@ const mapStateToProps = state => ({
});
const mapDispatchToProps = dispatch => ({
- checkInstall: next => dispatch(checkInstall(next)),
nextStep: () => dispatch(nextStep()),
- previousStep: () => dispatch(previousStep()),
goToStep: step => dispatch(goToStep(step)),
+ previousStep: () => dispatch(previousStep()),
+ finishInstall: () => dispatch(finishInstall()),
+ checkInstall: next => dispatch(checkInstall(next)),
+ handleDomainsChange: value => {
+ dispatch(updatePermittedDomains(value));
+ },
handleSettingsChange: e => {
const {name, value} = e.currentTarget;
dispatch(updateSettingsFormData(name, value));
diff --git a/client/coral-admin/src/containers/Install/components/Steps/AddOrganizationName.js b/client/coral-admin/src/containers/Install/components/Steps/AddOrganizationName.js
index ae23d0048..bcac6ef29 100644
--- a/client/coral-admin/src/containers/Install/components/Steps/AddOrganizationName.js
+++ b/client/coral-admin/src/containers/Install/components/Steps/AddOrganizationName.js
@@ -2,25 +2,26 @@ import React from 'react';
import styles from './style.css';
import {TextField, Button} from 'coral-ui';
+const lang = new I18n(translations);
+import translations from '../../translations.json';
+import I18n from 'coral-framework/modules/i18n/i18n';
+
const AddOrganizationName = props => {
const {handleSettingsChange, handleSettingsSubmit, install} = props;
return (
-
- Please tell us the name of your organization. This will appear in emails when
- inviting new team members
-
+
{lang.t('ADD_ORGANIZATION.DESCRIPTION')}
diff --git a/client/coral-admin/src/containers/Install/components/Steps/CreateYourAccount.js b/client/coral-admin/src/containers/Install/components/Steps/CreateYourAccount.js
index cb0f4635f..416fac195 100644
--- a/client/coral-admin/src/containers/Install/components/Steps/CreateYourAccount.js
+++ b/client/coral-admin/src/containers/Install/components/Steps/CreateYourAccount.js
@@ -2,6 +2,10 @@ import React from 'react';
import styles from './style.css';
import {TextField, Button, Spinner} from 'coral-ui';
+const lang = new I18n(translations);
+import translations from '../../translations.json';
+import I18n from 'coral-framework/modules/i18n/i18n';
+
const InitialStep = props => {
const {handleUserChange, handleUserSubmit, install} = props;
return (
@@ -12,7 +16,7 @@ const InitialStep = props => {
className={styles.textField}
id="email"
type="email"
- label='Email address'
+ label={lang.t('CREATE.EMAIL')}
onChange={handleUserChange}
showErrors={install.showErrors}
errorMsg={install.errors.email}
@@ -23,7 +27,7 @@ const InitialStep = props => {
className={styles.textField}
id="username"
type="text"
- label='Username'
+ label={lang.t('CREATE.USERNAME')}
onChange={handleUserChange}
showErrors={install.showErrors}
errorMsg={install.errors.username}
@@ -33,7 +37,7 @@ const InitialStep = props => {
className={styles.textField}
id="password"
type="password"
- label='Password'
+ label={lang.t('CREATE.PASSWORD')}
onChange={handleUserChange}
showErrors={install.showErrors}
errorMsg={install.errors.password}
@@ -43,7 +47,7 @@ const InitialStep = props => {
className={styles.textField}
id="confirmPassword"
type="password"
- label='Confirm Password'
+ label={lang.t('CREATE.CONFIRM_PASSWORD')}
onChange={handleUserChange}
showErrors={install.showErrors}
errorMsg={install.errors.confirmPassword}
@@ -51,7 +55,7 @@ const InitialStep = props => {
{
!props.install.isLoading ?
- Save
+ {lang.t('CREATE.SAVE')}
:
}
diff --git a/client/coral-admin/src/containers/Install/components/Steps/FinalStep.js b/client/coral-admin/src/containers/Install/components/Steps/FinalStep.js
index e549ebe63..0ad918487 100644
--- a/client/coral-admin/src/containers/Install/components/Steps/FinalStep.js
+++ b/client/coral-admin/src/containers/Install/components/Steps/FinalStep.js
@@ -3,16 +3,16 @@ import styles from './style.css';
import {Button} from 'coral-ui';
import {Link} from 'react-router';
+const lang = new I18n(translations);
+import translations from '../../translations.json';
+import I18n from 'coral-framework/modules/i18n/i18n';
+
const InitialStep = () => {
return (
-
- Thanks for installing Talk! We sent an email to verify your email
- address. While you finish setting the account, you can start engaging
- with your readers now.
-
-
Launch Talk
-
Close this Installer
+
{lang.t('FINAL.DESCRIPTION')}
+
{lang.t('FINAL.LAUNCH')}
+
{lang.t('FINAL.CLOSE')}
);
};
diff --git a/client/coral-admin/src/containers/Install/components/Steps/InitialStep.js b/client/coral-admin/src/containers/Install/components/Steps/InitialStep.js
index 9f9770fe9..1838e3178 100644
--- a/client/coral-admin/src/containers/Install/components/Steps/InitialStep.js
+++ b/client/coral-admin/src/containers/Install/components/Steps/InitialStep.js
@@ -2,16 +2,16 @@ import React from 'react';
import styles from './style.css';
import {Button} from 'coral-ui';
+const lang = new I18n(translations);
+import translations from '../../translations.json';
+import I18n from 'coral-framework/modules/i18n/i18n';
+
const InitialStep = props => {
const {nextStep} = props;
return (
-
- The remainder of the Talk installation will take about ten minutes.
- Once you complete the following two steps, you will have a free
- installation and provision of Mongo and Redis.
-
-
Get Started
+
{lang.t('INITIAL.DESCRIPTION')}
+
{lang.t('INITIAL.SUBMIT')}
);
};
diff --git a/client/coral-admin/src/containers/Install/components/Steps/PermittedDomainsStep.js b/client/coral-admin/src/containers/Install/components/Steps/PermittedDomainsStep.js
new file mode 100644
index 000000000..f2c1546f6
--- /dev/null
+++ b/client/coral-admin/src/containers/Install/components/Steps/PermittedDomainsStep.js
@@ -0,0 +1,31 @@
+import React from 'react';
+import styles from './style.css';
+import {Button, Card} from 'coral-ui';
+import TagsInput from 'react-tagsinput';
+
+const lang = new I18n(translations);
+import translations from '../../translations.json';
+import I18n from 'coral-framework/modules/i18n/i18n';
+
+const PermittedDomainsStep = props => {
+ const {finishInstall, install, handleDomainsChange} = props;
+ const domains = install.data.settings.domains.whitelist;
+ return (
+
+
{lang.t('PERMITTED_DOMAINS.TITLE')}
+
+ {lang.t('PERMITTED_DOMAINS.DESCRIPTION')}
+ data.split(',').map(d => d.trim())}
+ onChange={tags => handleDomainsChange(tags)}
+ />
+
+
{lang.t('PERMITTED_DOMAINS.SUBMIT')}
+
+ );
+};
+
+export default PermittedDomainsStep;
diff --git a/client/coral-admin/src/containers/Install/components/Steps/style.css b/client/coral-admin/src/containers/Install/components/Steps/style.css
index a5867e960..dea752298 100644
--- a/client/coral-admin/src/containers/Install/components/Steps/style.css
+++ b/client/coral-admin/src/containers/Install/components/Steps/style.css
@@ -59,6 +59,12 @@
}
}
}
+
+ .card {
+ max-width: 500px;
+ margin: 20px auto;
+ text-align: left;
+ }
}
.finalStep {
diff --git a/client/coral-admin/src/containers/Install/translations.json b/client/coral-admin/src/containers/Install/translations.json
new file mode 100644
index 000000000..e5b9f1542
--- /dev/null
+++ b/client/coral-admin/src/containers/Install/translations.json
@@ -0,0 +1,58 @@
+{
+ "en": {
+ "INITIAL" : {
+ "DESCRIPTION": "Let's set up your Talk community in just a few short steps.",
+ "SUBMIT": "Get Started"
+ },
+ "ADD_ORGANIZATION": {
+ "DESCRIPTION": "Please tell us the name of your organization. This will appear in emails when inviting new team members.",
+ "LABEL": "Organization Name",
+ "SAVE": "Save"
+ },
+ "CREATE": {
+ "EMAIL": "Email address",
+ "USERNAME": "Username",
+ "PASSWORD": "Password",
+ "CONFIRM_PASSWORD": "Confirm Password",
+ "SAVE": "Save"
+ },
+ "PERMITTED_DOMAINS": {
+ "TITLE": "Permitted domains",
+ "DESCRIPTION": "Enter the domains you would like to permit for Talk, e.g. your local, staging and production environments (ex. localhost:3000, staging.domain.com, domain.com).",
+ "SUBMIT": "Finish install"
+ },
+ "FINAL": {
+ "DESCRIPTION": "Thanks for installing Talk! We sent an email to verify your email address. While you finish setting up the account, you can start engaging with your readers now.",
+ "LAUNCH": "Launch Talk",
+ "CLOSE": "Close this Installer"
+ }
+ },
+ "es": {
+ "INITIAL" : {
+ "DESCRIPTION": "Configuremos tu comunidad de Talk en sólo algunos pasos.",
+ "SUBMIT": "Empezá!"
+ },
+ "ADD_ORGANIZATION": {
+ "DESCRIPTION": "Por favor, dinos el nombre de tu organización. Este aparecerá en los emails cuando invites nuevos miembros.",
+ "LABEL": "Nombre de la Organización",
+ "SAVE": "Guardar"
+ },
+ "CREATE": {
+ "EMAIL": "Dirección de E-Mail",
+ "USERNAME": "Usuario",
+ "PASSWORD": "Contraseña",
+ "CONFIRM_PASSWORD": "Confirmar contraseña",
+ "SAVE": "Guardar"
+ },
+ "PERMITTED_DOMAINS": {
+ "TITLE": "Dominios Permitidos",
+ "DESCRIPTION": "Agrega dominios permitidos a Talk, e.g. tu localhost, staging y ambientes de production (ex. localhost:3000, staging.domain.com, domain.com).",
+ "SUBMIT": "Finalizar instalación"
+ },
+ "FINAL": {
+ "DESCRIPTION": "Gracias por instalar Talk! Te enviamos un email para verificar tu identidad. Mientras se termina de configurar la cuenta, ya puedes empezar a interactuar con tus lectores",
+ "LAUNCH": "Lanzar Talk",
+ "CLOSE": "Cerrar este instalador"
+ }
+ }
+}
diff --git a/client/coral-admin/src/reducers/install.js b/client/coral-admin/src/reducers/install.js
index 596fd16cd..1f0f079ff 100644
--- a/client/coral-admin/src/reducers/install.js
+++ b/client/coral-admin/src/reducers/install.js
@@ -1,4 +1,4 @@
-import {Map} from 'immutable';
+import {Map, List} from 'immutable';
import * as actions from '../constants/install';
@@ -6,7 +6,10 @@ const initialState = Map({
isLoading: false,
data: Map({
settings: Map({
- organizationName: ''
+ organizationName: '',
+ domains: Map({
+ whitelist: List()
+ })
}),
user: Map({
username: '',
@@ -33,6 +36,10 @@ const initialState = Map({
{
text: '2. Create your account',
step: 2
+ },
+ {
+ text: '3. Domain Whitelist',
+ step: 3
}],
installRequest: null,
installRequestError: null,
@@ -50,6 +57,9 @@ export default function install (state = initialState, action) {
case actions.GO_TO_STEP:
return state
.set('step', action.step);
+ case actions.UPDATE_PERMITTED_DOMAINS_SETTINGS:
+ return state
+ .setIn(['data', 'settings', 'domains', 'whitelist'], action.value);
case actions.UPDATE_FORMDATA_SETTINGS:
return state
.setIn(['data', 'settings', action.name], action.value);
diff --git a/client/coral-admin/src/translations.json b/client/coral-admin/src/translations.json
index 92e5d098a..dbb3e650e 100644
--- a/client/coral-admin/src/translations.json
+++ b/client/coral-admin/src/translations.json
@@ -86,7 +86,7 @@
"comment-count-text-post": " characters.",
"comment-count-error": "Please enter a valid number.",
"domain-list-title": "Domain Whitelist",
- "domain-list-text": "Some instructions on how to type the urls."
+ "domain-list-text": "Enter the domains you would like to permit for Talk, e.g. your local, staging and production environments (ex. localhost:3000, staging.domain.com, domain.com)."
},
"bandialog": {
"ban_user": "Ban User?",
@@ -207,7 +207,7 @@
"comment-count-text-post": " caracteres",
"comment-count-error": "Por favor escribe un número válido.",
"domain-list-title": "Lista de Dominios Permitidos",
- "domain-list-text": "Instrucciones de como ingresar las URLs."
+ "domain-list-text": "Agrega dominios permitidos a Talk, e.g. tu localhost, staging y ambientes de production (ex. localhost:3000, staging.domain.com, domain.com)."
},
"embedlink": {
"copy": "Copiar"
diff --git a/client/coral-ui/components/WizardNav.css b/client/coral-ui/components/WizardNav.css
index 001ee8603..1f0b78d86 100644
--- a/client/coral-ui/components/WizardNav.css
+++ b/client/coral-ui/components/WizardNav.css
@@ -13,6 +13,7 @@
position: relative;
padding-left: 40px;
border-radius: 1px;
+ min-height: 24px;
&:hover {
cursor: pointer;