mirror of
https://github.com/astuto/astuto.git
synced 2025-12-16 03:37:56 +01:00
Add Site settings > General (#133)
This commit is contained in:
committed by
GitHub
parent
bdc4004e4a
commit
35831b9801
59
app/javascript/actions/Tenant/requestTenant.ts
Normal file
59
app/javascript/actions/Tenant/requestTenant.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
import { Action } from 'redux';
|
||||
import { ThunkAction } from 'redux-thunk';
|
||||
|
||||
import ITenantJSON from '../../interfaces/json/ITenant';
|
||||
import { State } from '../../reducers/rootReducer';
|
||||
|
||||
export const TENANT_REQUEST_START = 'TENANT_REQUEST_START';
|
||||
interface TenantRequestStartAction {
|
||||
type: typeof TENANT_REQUEST_START;
|
||||
}
|
||||
|
||||
export const TENANT_REQUEST_SUCCESS = 'TENANT_REQUEST_SUCCESS';
|
||||
interface TenantRequestSuccessAction {
|
||||
type: typeof TENANT_REQUEST_SUCCESS;
|
||||
tenant: ITenantJSON;
|
||||
}
|
||||
|
||||
export const TENANT_REQUEST_FAILURE = 'TENANT_REQUEST_FAILURE';
|
||||
interface TenantRequestFailureAction {
|
||||
type: typeof TENANT_REQUEST_FAILURE;
|
||||
error: string;
|
||||
}
|
||||
|
||||
export type TenantRequestActionTypes =
|
||||
TenantRequestStartAction |
|
||||
TenantRequestSuccessAction |
|
||||
TenantRequestFailureAction;
|
||||
|
||||
|
||||
const tenantRequestStart = (): TenantRequestActionTypes => ({
|
||||
type: TENANT_REQUEST_START,
|
||||
});
|
||||
|
||||
const tenantRequestSuccess = (
|
||||
tenant: ITenantJSON
|
||||
): TenantRequestActionTypes => ({
|
||||
type: TENANT_REQUEST_SUCCESS,
|
||||
tenant,
|
||||
});
|
||||
|
||||
const tenantRequestFailure = (error: string): TenantRequestActionTypes => ({
|
||||
type: TENANT_REQUEST_FAILURE,
|
||||
error,
|
||||
});
|
||||
|
||||
export const requestTenant = (): ThunkAction<void, State, null, Action<string>> => (
|
||||
async (dispatch) => {
|
||||
dispatch(tenantRequestStart());
|
||||
|
||||
try {
|
||||
const response = await fetch('/tenants/0');
|
||||
const json = await response.json();
|
||||
|
||||
dispatch(tenantRequestSuccess(json));
|
||||
} catch (e) {
|
||||
dispatch(tenantRequestFailure(e));
|
||||
}
|
||||
}
|
||||
);
|
||||
82
app/javascript/actions/Tenant/submitTenant.ts
Normal file
82
app/javascript/actions/Tenant/submitTenant.ts
Normal file
@@ -0,0 +1,82 @@
|
||||
import { Action } from "redux";
|
||||
import { ThunkAction } from "redux-thunk";
|
||||
import HttpStatus from "../../constants/http_status";
|
||||
import buildRequestHeaders from "../../helpers/buildRequestHeaders";
|
||||
import ITenantJSON from "../../interfaces/json/ITenant";
|
||||
import { State } from "../../reducers/rootReducer";
|
||||
|
||||
export const TENANT_SUBMIT_START = 'TENANT_SUBMIT_START';
|
||||
interface TenantSubmitStartAction {
|
||||
type: typeof TENANT_SUBMIT_START;
|
||||
}
|
||||
|
||||
export const TENANT_SUBMIT_SUCCESS = 'TENANT_SUBMIT_SUCCESS';
|
||||
interface TenantSubmitSuccessAction {
|
||||
type: typeof TENANT_SUBMIT_SUCCESS;
|
||||
tenant: ITenantJSON;
|
||||
}
|
||||
|
||||
export const TENANT_SUBMIT_FAILURE = 'TENANT_SUBMIT_FAILURE';
|
||||
interface TenantSubmitFailureAction {
|
||||
type: typeof TENANT_SUBMIT_FAILURE;
|
||||
error: string;
|
||||
}
|
||||
|
||||
export type TenantSubmitActionTypes =
|
||||
TenantSubmitStartAction |
|
||||
TenantSubmitSuccessAction |
|
||||
TenantSubmitFailureAction;
|
||||
|
||||
const tenantSubmitStart = (): TenantSubmitStartAction => ({
|
||||
type: TENANT_SUBMIT_START,
|
||||
});
|
||||
|
||||
const tenantSubmitSuccess = (
|
||||
tenantJSON: ITenantJSON,
|
||||
): TenantSubmitSuccessAction => ({
|
||||
type: TENANT_SUBMIT_SUCCESS,
|
||||
tenant: tenantJSON,
|
||||
});
|
||||
|
||||
const tenantSubmitFailure = (error: string): TenantSubmitFailureAction => ({
|
||||
type: TENANT_SUBMIT_FAILURE,
|
||||
error,
|
||||
});
|
||||
|
||||
export const submitTenant = (
|
||||
userFullName: string,
|
||||
userEmail: string,
|
||||
userPassword: string,
|
||||
siteName: string,
|
||||
subdomain: string,
|
||||
authenticityToken: string,
|
||||
): ThunkAction<void, State, null, Action<string>> => async (dispatch) => {
|
||||
dispatch(tenantSubmitStart());
|
||||
|
||||
try {
|
||||
const res = await fetch(`/tenants`, {
|
||||
method: 'POST',
|
||||
headers: buildRequestHeaders(authenticityToken),
|
||||
body: JSON.stringify({
|
||||
user: {
|
||||
full_name: userFullName,
|
||||
email: userEmail,
|
||||
password: userPassword,
|
||||
},
|
||||
tenant: {
|
||||
site_name: siteName,
|
||||
subdomain: subdomain,
|
||||
},
|
||||
}),
|
||||
});
|
||||
const json = await res.json();
|
||||
|
||||
if (res.status === HttpStatus.Created) {
|
||||
dispatch(tenantSubmitSuccess(json));
|
||||
} else {
|
||||
dispatch(tenantSubmitFailure(json.error));
|
||||
}
|
||||
} catch (e) {
|
||||
dispatch(tenantSubmitFailure(e));
|
||||
}
|
||||
};
|
||||
124
app/javascript/actions/Tenant/tenantSignUpFormActions.ts
Normal file
124
app/javascript/actions/Tenant/tenantSignUpFormActions.ts
Normal file
@@ -0,0 +1,124 @@
|
||||
export const TENANT_SIGN_UP_TOGGLE_EMAIL_AUTH = 'TENANT_SIGN_UP_TOGGLE_EMAIL_AUTH';
|
||||
|
||||
interface TenantSignUpToggleEmailAuth {
|
||||
type: typeof TENANT_SIGN_UP_TOGGLE_EMAIL_AUTH,
|
||||
}
|
||||
|
||||
export const toggleEmailAuthTenantSignUp = (
|
||||
|
||||
): TenantSignUpToggleEmailAuth => ({
|
||||
type: TENANT_SIGN_UP_TOGGLE_EMAIL_AUTH,
|
||||
});
|
||||
|
||||
|
||||
// User full name
|
||||
export const TENANT_SIGN_UP_CHANGE_USER_FULL_NAME = 'TENANT_SIGN_UP_CHANGE_USER_FULL_NAME';
|
||||
|
||||
interface TenantSignUpChangeUserFullName {
|
||||
type: typeof TENANT_SIGN_UP_CHANGE_USER_FULL_NAME,
|
||||
fullName: string,
|
||||
}
|
||||
|
||||
export const changeUserFullNameTenantSignUp = (
|
||||
fullName: string
|
||||
): TenantSignUpChangeUserFullName => ({
|
||||
type: TENANT_SIGN_UP_CHANGE_USER_FULL_NAME,
|
||||
fullName,
|
||||
});
|
||||
|
||||
// User email
|
||||
export const TENANT_SIGN_UP_CHANGE_USER_EMAIL = 'TENANT_SIGN_UP_CHANGE_USER_EMAIL';
|
||||
|
||||
interface TenantSignUpChangeUserEmail {
|
||||
type: typeof TENANT_SIGN_UP_CHANGE_USER_EMAIL,
|
||||
email: string,
|
||||
}
|
||||
|
||||
export const changeUserEmailTenantSignUp = (
|
||||
email: string
|
||||
): TenantSignUpChangeUserEmail => ({
|
||||
type: TENANT_SIGN_UP_CHANGE_USER_EMAIL,
|
||||
email,
|
||||
});
|
||||
|
||||
// User password
|
||||
export const TENANT_SIGN_UP_CHANGE_USER_PASSWORD = 'TENANT_SIGN_UP_CHANGE_USER_PASSWORD';
|
||||
|
||||
interface TenantSignUpChangeUserPassword {
|
||||
type: typeof TENANT_SIGN_UP_CHANGE_USER_PASSWORD,
|
||||
password: string,
|
||||
}
|
||||
|
||||
export const changeUserPasswordTenantSignUp = (
|
||||
password: string
|
||||
): TenantSignUpChangeUserPassword => ({
|
||||
type: TENANT_SIGN_UP_CHANGE_USER_PASSWORD,
|
||||
password,
|
||||
});
|
||||
|
||||
// User password confirmation
|
||||
export const TENANT_SIGN_UP_CHANGE_USER_PASSWORD_CONFIRMATION = 'TENANT_SIGN_UP_CHANGE_USER_PASSWORD_CONFIRMATION';
|
||||
|
||||
interface TenantSignUpChangeUserPasswordConfirmation {
|
||||
type: typeof TENANT_SIGN_UP_CHANGE_USER_PASSWORD_CONFIRMATION,
|
||||
passwordConfirmation: string,
|
||||
}
|
||||
|
||||
export const changeUserPasswordConfirmationTenantSignUp = (
|
||||
passwordConfirmation: string
|
||||
): TenantSignUpChangeUserPasswordConfirmation => ({
|
||||
type: TENANT_SIGN_UP_CHANGE_USER_PASSWORD_CONFIRMATION,
|
||||
passwordConfirmation,
|
||||
});
|
||||
|
||||
// Confirm user data, proceed to step 2
|
||||
export const TENANT_SIGN_UP_CONFIRM_USER_FORM = 'TENANT_SIGN_UP_CONFIRM_USER_FORM';
|
||||
|
||||
interface TenantSignUpConfirmUserForm {
|
||||
type: typeof TENANT_SIGN_UP_CONFIRM_USER_FORM;
|
||||
}
|
||||
|
||||
export const confirmUserFormTenantSignUp = (): TenantSignUpConfirmUserForm => ({
|
||||
type: TENANT_SIGN_UP_CONFIRM_USER_FORM,
|
||||
});
|
||||
|
||||
// Tenant site name
|
||||
export const TENANT_SIGN_UP_CHANGE_TENANT_SITE_NAME = 'TENANT_SIGN_UP_CHANGE_TENANT_SITE_NAME';
|
||||
|
||||
interface TenantSignUpChangeTenantSiteName {
|
||||
type: typeof TENANT_SIGN_UP_CHANGE_TENANT_SITE_NAME,
|
||||
siteName: string,
|
||||
}
|
||||
|
||||
export const changeTenantSiteNameTenantSignUp = (
|
||||
siteName: string
|
||||
): TenantSignUpChangeTenantSiteName => ({
|
||||
type: TENANT_SIGN_UP_CHANGE_TENANT_SITE_NAME,
|
||||
siteName,
|
||||
});
|
||||
|
||||
// Tenant site name
|
||||
export const TENANT_SIGN_UP_CHANGE_TENANT_SUBDOMAIN = 'TENANT_SIGN_UP_CHANGE_TENANT_SUBDOMAIN';
|
||||
|
||||
interface TenantSignUpChangeTenantSubdomain {
|
||||
type: typeof TENANT_SIGN_UP_CHANGE_TENANT_SUBDOMAIN,
|
||||
subdomain: string,
|
||||
}
|
||||
|
||||
export const changeTenantSubdomainTenantSignUp = (
|
||||
subdomain: string
|
||||
): TenantSignUpChangeTenantSubdomain => ({
|
||||
type: TENANT_SIGN_UP_CHANGE_TENANT_SUBDOMAIN,
|
||||
subdomain,
|
||||
});
|
||||
|
||||
|
||||
export type TenantSignUpFormActions =
|
||||
TenantSignUpToggleEmailAuth |
|
||||
TenantSignUpChangeUserFullName |
|
||||
TenantSignUpChangeUserEmail |
|
||||
TenantSignUpChangeUserPassword |
|
||||
TenantSignUpChangeUserPasswordConfirmation |
|
||||
TenantSignUpConfirmUserForm |
|
||||
TenantSignUpChangeTenantSiteName |
|
||||
TenantSignUpChangeTenantSubdomain;
|
||||
91
app/javascript/actions/Tenant/updateTenant.ts
Normal file
91
app/javascript/actions/Tenant/updateTenant.ts
Normal file
@@ -0,0 +1,91 @@
|
||||
import { Action } from "redux";
|
||||
import { ThunkAction } from "redux-thunk";
|
||||
|
||||
import HttpStatus from "../../constants/http_status";
|
||||
import buildRequestHeaders from "../../helpers/buildRequestHeaders";
|
||||
import ITenantJSON from "../../interfaces/json/ITenant";
|
||||
import { State } from "../../reducers/rootReducer";
|
||||
|
||||
export const TENANT_UPDATE_START = 'TENANT_UPDATE_START';
|
||||
interface TenantUpdateStartAction {
|
||||
type: typeof TENANT_UPDATE_START;
|
||||
}
|
||||
|
||||
export const TENANT_UPDATE_SUCCESS = 'TENANT_UPDATE_SUCCESS';
|
||||
interface TenantUpdateSuccessAction {
|
||||
type: typeof TENANT_UPDATE_SUCCESS;
|
||||
tenant: ITenantJSON;
|
||||
}
|
||||
|
||||
export const TENANT_UPDATE_FAILURE = 'TENANT_UPDATE_FAILURE';
|
||||
interface TenantUpdateFailureAction {
|
||||
type: typeof TENANT_UPDATE_FAILURE;
|
||||
error: string;
|
||||
}
|
||||
|
||||
export type TenantUpdateActionTypes =
|
||||
TenantUpdateStartAction |
|
||||
TenantUpdateSuccessAction |
|
||||
TenantUpdateFailureAction;
|
||||
|
||||
const tenantUpdateStart = (): TenantUpdateStartAction => ({
|
||||
type: TENANT_UPDATE_START,
|
||||
});
|
||||
|
||||
const tenantUpdateSuccess = (
|
||||
tenantJSON: ITenantJSON,
|
||||
): TenantUpdateSuccessAction => ({
|
||||
type: TENANT_UPDATE_SUCCESS,
|
||||
tenant: tenantJSON,
|
||||
});
|
||||
|
||||
const tenantUpdateFailure = (error: string): TenantUpdateFailureAction => ({
|
||||
type: TENANT_UPDATE_FAILURE,
|
||||
error,
|
||||
});
|
||||
|
||||
interface UpdateTenantParams {
|
||||
siteName?: string;
|
||||
siteLogo?: string;
|
||||
brandDisplaySetting?: string;
|
||||
locale?: string;
|
||||
authenticityToken: string;
|
||||
}
|
||||
|
||||
export const updateTenant = ({
|
||||
siteName = null,
|
||||
siteLogo = null,
|
||||
brandDisplaySetting = null,
|
||||
locale = null,
|
||||
authenticityToken,
|
||||
}: UpdateTenantParams): ThunkAction<void, State, null, Action<string>> => async (dispatch) => {
|
||||
dispatch(tenantUpdateStart());
|
||||
|
||||
const tenant = Object.assign({},
|
||||
siteName !== null ? { site_name: siteName } : null,
|
||||
siteLogo !== null ? { site_logo: siteLogo } : null,
|
||||
brandDisplaySetting !== null ? { brand_display_setting: brandDisplaySetting } : null,
|
||||
locale !== null ? { locale } : null
|
||||
);
|
||||
|
||||
try {
|
||||
const res = await fetch(`/tenants/0`, {
|
||||
method: 'PATCH',
|
||||
headers: buildRequestHeaders(authenticityToken),
|
||||
body: JSON.stringify({ tenant }),
|
||||
});
|
||||
const json = await res.json();
|
||||
|
||||
if (res.status === HttpStatus.OK) {
|
||||
dispatch(tenantUpdateSuccess(json));
|
||||
} else {
|
||||
dispatch(tenantUpdateFailure(json.error));
|
||||
}
|
||||
|
||||
return Promise.resolve(res);
|
||||
} catch (e) {
|
||||
dispatch(tenantUpdateFailure(e));
|
||||
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
};
|
||||
65
app/javascript/actions/changeSiteSettingsGeneralForm.ts
Normal file
65
app/javascript/actions/changeSiteSettingsGeneralForm.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
// siteName
|
||||
export const SITE_SETTINGS_CHANGE_GENERAL_FORM_SITE_NAME = 'SITE_SETTINGS_CHANGE_GENERAL_FORM_SITE_NAME';
|
||||
|
||||
interface SiteSettingsChangeGeneralFormSiteName {
|
||||
type: typeof SITE_SETTINGS_CHANGE_GENERAL_FORM_SITE_NAME,
|
||||
siteName: string,
|
||||
}
|
||||
|
||||
export const changeSiteSettingsGeneralFormSiteName = (
|
||||
siteName: string
|
||||
): SiteSettingsChangeGeneralFormSiteName => ({
|
||||
type: SITE_SETTINGS_CHANGE_GENERAL_FORM_SITE_NAME,
|
||||
siteName,
|
||||
});
|
||||
|
||||
// siteLogo
|
||||
export const SITE_SETTINGS_CHANGE_GENERAL_FORM_SITE_LOGO = 'SITE_SETTINGS_CHANGE_GENERAL_FORM_SITE_LOGO';
|
||||
|
||||
interface SiteSettingsChangeGeneralFormSiteLogo {
|
||||
type: typeof SITE_SETTINGS_CHANGE_GENERAL_FORM_SITE_LOGO,
|
||||
siteLogo: string,
|
||||
}
|
||||
|
||||
export const changeSiteSettingsGeneralFormSiteLogo = (
|
||||
siteLogo: string
|
||||
): SiteSettingsChangeGeneralFormSiteLogo => ({
|
||||
type: SITE_SETTINGS_CHANGE_GENERAL_FORM_SITE_LOGO,
|
||||
siteLogo,
|
||||
});
|
||||
|
||||
// brandDisplaySetting
|
||||
export const SITE_SETTINGS_CHANGE_GENERAL_FORM_BRAND_SETTING = 'SITE_SETTINGS_CHANGE_GENERAL_FORM_BRAND_SETTING';
|
||||
|
||||
interface SiteSettingsChangeGeneralFormBrandSetting {
|
||||
type: typeof SITE_SETTINGS_CHANGE_GENERAL_FORM_BRAND_SETTING,
|
||||
brandDisplaySetting: string,
|
||||
}
|
||||
|
||||
export const changeSiteSettingsGeneralFormBrandSetting = (
|
||||
brandDisplaySetting: string
|
||||
): SiteSettingsChangeGeneralFormBrandSetting => ({
|
||||
type: SITE_SETTINGS_CHANGE_GENERAL_FORM_BRAND_SETTING,
|
||||
brandDisplaySetting,
|
||||
});
|
||||
|
||||
// locale
|
||||
export const SITE_SETTINGS_CHANGE_GENERAL_FORM_LOCALE = 'SITE_SETTINGS_CHANGE_GENERAL_FORM_LOCALE';
|
||||
|
||||
interface SiteSettingsChangeGeneralFormLocale {
|
||||
type: typeof SITE_SETTINGS_CHANGE_GENERAL_FORM_LOCALE,
|
||||
locale: string,
|
||||
}
|
||||
|
||||
export const changeSiteSettingsGeneralFormLocale = (
|
||||
locale: string
|
||||
): SiteSettingsChangeGeneralFormLocale => ({
|
||||
type: SITE_SETTINGS_CHANGE_GENERAL_FORM_LOCALE,
|
||||
locale,
|
||||
});
|
||||
|
||||
export type ChangeSiteSettingsGeneralFormActionTypes =
|
||||
SiteSettingsChangeGeneralFormSiteName |
|
||||
SiteSettingsChangeGeneralFormSiteLogo |
|
||||
SiteSettingsChangeGeneralFormBrandSetting |
|
||||
SiteSettingsChangeGeneralFormLocale;
|
||||
@@ -80,18 +80,22 @@ class BoardForm extends React.Component<Props, State> {
|
||||
const {name, description} = this.state;
|
||||
|
||||
return (
|
||||
<div className="boardForm">
|
||||
<form className="boardForm">
|
||||
<div className="boardMandatoryForm">
|
||||
<input
|
||||
type="text"
|
||||
placeholder={I18n.t('site_settings.boards.form.name')}
|
||||
value={name}
|
||||
onChange={e => this.onNameChange(e.target.value)}
|
||||
autoFocus
|
||||
className="form-control"
|
||||
/>
|
||||
|
||||
<Button
|
||||
onClick={this.onSubmit}
|
||||
onClick={e => {
|
||||
e.preventDefault();
|
||||
this.onSubmit();
|
||||
}}
|
||||
className="newBoardButton"
|
||||
disabled={!this.isFormValid()}
|
||||
>
|
||||
@@ -110,7 +114,7 @@ class BoardForm extends React.Component<Props, State> {
|
||||
onChange={e => this.onDescriptionChange(e.target.value)}
|
||||
className="form-control"
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,166 @@
|
||||
import * as React from 'react';
|
||||
import I18n from 'i18n-js';
|
||||
|
||||
import Box from '../../common/Box';
|
||||
import SiteSettingsInfoBox from '../../common/SiteSettingsInfoBox';
|
||||
import { ISiteSettingsGeneralForm } from '../../../reducers/SiteSettings/generalReducer';
|
||||
import Button from '../../common/Button';
|
||||
import HttpStatus from '../../../constants/http_status';
|
||||
import {
|
||||
TENANT_BRAND_NAME_AND_LOGO,
|
||||
TENANT_BRAND_NAME_ONLY,
|
||||
TENANT_BRAND_LOGO_ONLY,
|
||||
TENANT_BRAND_NONE,
|
||||
} from '../../../interfaces/ITenant';
|
||||
|
||||
interface Props {
|
||||
originForm: ISiteSettingsGeneralForm;
|
||||
authenticityToken: string;
|
||||
|
||||
form: ISiteSettingsGeneralForm;
|
||||
areDirty: boolean;
|
||||
areLoading: boolean;
|
||||
areUpdating: boolean;
|
||||
error: string;
|
||||
|
||||
requestTenant(): void;
|
||||
updateTenant(
|
||||
siteName: string,
|
||||
siteLogo: string,
|
||||
brandDisplaySetting: string,
|
||||
locale: string,
|
||||
authenticityToken: string
|
||||
): Promise<any>;
|
||||
|
||||
handleChangeSiteName(siteName: string): void;
|
||||
handleChangeSiteLogo(siteLogo: string): void;
|
||||
handleChangeBrandDisplaySetting(brandDisplaySetting: string)
|
||||
handleChangeLocale(locale: string): void;
|
||||
}
|
||||
|
||||
class GeneralSiteSettingsP extends React.Component<Props> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
this._handleUpdateTenant = this._handleUpdateTenant.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.props.requestTenant();
|
||||
}
|
||||
|
||||
_handleUpdateTenant() {
|
||||
const { siteName, siteLogo, brandDisplaySetting, locale } = this.props.form;
|
||||
|
||||
this.props.updateTenant(
|
||||
siteName,
|
||||
siteLogo,
|
||||
brandDisplaySetting,
|
||||
locale,
|
||||
this.props.authenticityToken,
|
||||
).then(res => {
|
||||
if (res?.status !== HttpStatus.OK) return;
|
||||
|
||||
window.location.reload();
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
originForm,
|
||||
form,
|
||||
areDirty,
|
||||
areLoading,
|
||||
areUpdating,
|
||||
error,
|
||||
|
||||
handleChangeSiteName,
|
||||
handleChangeSiteLogo,
|
||||
handleChangeBrandDisplaySetting,
|
||||
handleChangeLocale,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<>
|
||||
<Box>
|
||||
<h2>{ I18n.t('site_settings.general.title') }</h2>
|
||||
|
||||
<form>
|
||||
<div className="formRow">
|
||||
<div className="formGroup col-4">
|
||||
<label htmlFor="siteName">{ I18n.t('site_settings.general.site_name') }</label>
|
||||
<input
|
||||
type="text"
|
||||
value={areLoading ? originForm.siteName : form.siteName}
|
||||
onChange={e => handleChangeSiteName(e.target.value)}
|
||||
id="siteName"
|
||||
className="formControl"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="formGroup col-4">
|
||||
<label htmlFor="siteLogo">{ I18n.t('site_settings.general.site_logo') }</label>
|
||||
<input
|
||||
type="text"
|
||||
value={areLoading ? originForm.siteLogo : form.siteLogo}
|
||||
onChange={e => handleChangeSiteLogo(e.target.value)}
|
||||
id="siteLogo"
|
||||
className="formControl"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="formGroup col-4">
|
||||
<label htmlFor="brandSetting">{ I18n.t('site_settings.general.brand_setting') }</label>
|
||||
<select
|
||||
value={form.brandDisplaySetting || originForm.brandDisplaySetting}
|
||||
onChange={e => handleChangeBrandDisplaySetting(e.target.value)}
|
||||
id="brandSetting"
|
||||
className="selectPicker"
|
||||
>
|
||||
<option value={TENANT_BRAND_NAME_AND_LOGO}>
|
||||
{ I18n.t('site_settings.general.brand_setting_both') }
|
||||
</option>
|
||||
<option value={TENANT_BRAND_NAME_ONLY}>
|
||||
{ I18n.t('site_settings.general.brand_setting_name') }
|
||||
</option>
|
||||
<option value={TENANT_BRAND_LOGO_ONLY}>
|
||||
{ I18n.t('site_settings.general.brand_setting_logo') }
|
||||
</option>
|
||||
<option value={TENANT_BRAND_NONE}>
|
||||
{ I18n.t('site_settings.general.brand_setting_none') }
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="formGroup">
|
||||
<label htmlFor="locale">{ I18n.t('site_settings.general.locale') }</label>
|
||||
<select
|
||||
value={form.locale || originForm.locale}
|
||||
onChange={e => handleChangeLocale(e.target.value)}
|
||||
id="locale"
|
||||
className="selectPicker"
|
||||
>
|
||||
<option value="en">🇬🇧 English</option>
|
||||
<option value="it">🇮🇹 Italiano</option>
|
||||
</select>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<br />
|
||||
|
||||
<Button
|
||||
onClick={this._handleUpdateTenant}
|
||||
disabled={!areDirty}
|
||||
>
|
||||
{ I18n.t('common.buttons.update') }
|
||||
</Button>
|
||||
</Box>
|
||||
|
||||
<SiteSettingsInfoBox areUpdating={areLoading || areUpdating} error={error} areDirty={areDirty} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default GeneralSiteSettingsP;
|
||||
36
app/javascript/components/SiteSettings/General/index.tsx
Normal file
36
app/javascript/components/SiteSettings/General/index.tsx
Normal file
@@ -0,0 +1,36 @@
|
||||
import * as React from 'react';
|
||||
import { Provider } from 'react-redux';
|
||||
import { Store } from 'redux';
|
||||
|
||||
import GeneralSiteSettings from '../../../containers/GeneralSiteSettings';
|
||||
import createStoreHelper from '../../../helpers/createStore';
|
||||
import { State } from '../../../reducers/rootReducer';
|
||||
import { ISiteSettingsGeneralForm } from '../../../reducers/SiteSettings/generalReducer';
|
||||
|
||||
interface Props {
|
||||
originForm: ISiteSettingsGeneralForm;
|
||||
authenticityToken: string;
|
||||
}
|
||||
|
||||
class GeneralSiteSettingsRoot extends React.Component<Props> {
|
||||
store: Store<State, any>;
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
this.store = createStoreHelper();
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Provider store={this.store}>
|
||||
<GeneralSiteSettings
|
||||
originForm={this.props.originForm}
|
||||
authenticityToken={this.props.authenticityToken}
|
||||
/>
|
||||
</Provider>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default GeneralSiteSettingsRoot;
|
||||
@@ -87,12 +87,13 @@ class PostStatusForm extends React.Component<Props, State> {
|
||||
const {name, color} = this.state;
|
||||
|
||||
return (
|
||||
<div className="postStatusForm">
|
||||
<form className="postStatusForm">
|
||||
<input
|
||||
type="text"
|
||||
placeholder={I18n.t('site_settings.post_statuses.form.name')}
|
||||
value={name}
|
||||
onChange={e => this.onNameChange(e.target.value)}
|
||||
autoFocus
|
||||
className="form-control"
|
||||
/>
|
||||
|
||||
@@ -104,7 +105,10 @@ class PostStatusForm extends React.Component<Props, State> {
|
||||
/>
|
||||
|
||||
<Button
|
||||
onClick={this.onSubmit}
|
||||
onClick={e => {
|
||||
e.preventDefault();
|
||||
this.onSubmit();
|
||||
}}
|
||||
className="newPostStatusButton"
|
||||
disabled={!this.isFormValid()}
|
||||
>
|
||||
@@ -115,7 +119,7 @@ class PostStatusForm extends React.Component<Props, State> {
|
||||
I18n.t('common.buttons.update')
|
||||
}
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
21
app/javascript/components/TenantSignUp/ConfirmSignUpPage.tsx
Normal file
21
app/javascript/components/TenantSignUp/ConfirmSignUpPage.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import * as React from 'react';
|
||||
import I18n from 'i18n-js';
|
||||
import Box from '../common/Box';
|
||||
|
||||
interface Props {
|
||||
subdomain: string;
|
||||
userEmail: string;
|
||||
}
|
||||
|
||||
const ConfirmSignUpPage = ({
|
||||
subdomain,
|
||||
userEmail,
|
||||
}: Props) => (
|
||||
<Box>
|
||||
<h3>{ I18n.t('signup.step3.title') }</h3>
|
||||
|
||||
<p>{ I18n.t('signup.step3.message', { email: userEmail, subdomain: `${subdomain}.astuto.io` }) }</p>
|
||||
</Box>
|
||||
);
|
||||
|
||||
export default ConfirmSignUpPage;
|
||||
92
app/javascript/components/TenantSignUp/TenantSignUpForm.tsx
Normal file
92
app/javascript/components/TenantSignUp/TenantSignUpForm.tsx
Normal file
@@ -0,0 +1,92 @@
|
||||
import * as React from 'react';
|
||||
import I18n from 'i18n-js';
|
||||
|
||||
import Box from '../common/Box';
|
||||
import { TenantSignUpTenantFormState } from '../../reducers/tenantSignUpReducer';
|
||||
import Button from '../common/Button';
|
||||
import Spinner from '../common/Spinner';
|
||||
import { DangerText } from '../common/CustomTexts';
|
||||
|
||||
interface Props {
|
||||
tenantForm: TenantSignUpTenantFormState;
|
||||
handleChangeTenantSiteName(siteName: string): void;
|
||||
handleChangeTenantSubdomain(subdomain: string): void;
|
||||
|
||||
isSubmitting: boolean;
|
||||
error: string;
|
||||
handleSubmit(): void;
|
||||
}
|
||||
|
||||
class TenantSignUpForm extends React.Component<Props> {
|
||||
form: any;
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
this.form = React.createRef();
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
tenantForm,
|
||||
handleChangeTenantSiteName,
|
||||
handleChangeTenantSubdomain,
|
||||
|
||||
isSubmitting,
|
||||
error,
|
||||
handleSubmit,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<Box customClass="tenantSignUpStep2">
|
||||
<h3>{ I18n.t('signup.step2.title') }</h3>
|
||||
|
||||
<form ref={this.form}>
|
||||
<div className="formRow">
|
||||
<input
|
||||
type="text"
|
||||
autoFocus
|
||||
value={tenantForm.siteName}
|
||||
onChange={e => handleChangeTenantSiteName(e.target.value)}
|
||||
placeholder={I18n.t('signup.step2.site_name')}
|
||||
required
|
||||
id="tenantSiteName"
|
||||
className="formControl"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="formRow">
|
||||
<div className="input-group">
|
||||
<input
|
||||
type="text"
|
||||
value={tenantForm.subdomain}
|
||||
onChange={e => handleChangeTenantSubdomain(e.target.value)}
|
||||
placeholder={I18n.t('signup.step2.subdomain')}
|
||||
required
|
||||
id="tenantSubdomain"
|
||||
className="formControl"
|
||||
/>
|
||||
<div className="input-group-append">
|
||||
<div className="input-group-text">.astuto.io</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
onClick={e => {
|
||||
e.preventDefault();
|
||||
handleSubmit();
|
||||
}}
|
||||
className="tenantConfirm"
|
||||
>
|
||||
{ isSubmitting ? <Spinner /> : I18n.t('signup.step2.create_button') }
|
||||
</Button>
|
||||
|
||||
{ error !== '' && <DangerText>{ error }</DangerText> }
|
||||
</form>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default TenantSignUpForm;
|
||||
124
app/javascript/components/TenantSignUp/TenantSignUpP.tsx
Normal file
124
app/javascript/components/TenantSignUp/TenantSignUpP.tsx
Normal file
@@ -0,0 +1,124 @@
|
||||
import * as React from 'react';
|
||||
import { TenantSignUpTenantFormState, TenantSignUpUserFormState } from '../../reducers/tenantSignUpReducer';
|
||||
import ConfirmSignUpPage from './ConfirmSignUpPage';
|
||||
|
||||
import TenantSignUpForm from './TenantSignUpForm';
|
||||
import UserSignUpForm from './UserSignUpForm';
|
||||
|
||||
interface Props {
|
||||
authenticityToken: string;
|
||||
|
||||
currentStep: number;
|
||||
emailAuth: boolean;
|
||||
isSubmitting: boolean;
|
||||
error: string;
|
||||
|
||||
toggleEmailAuth(): void;
|
||||
|
||||
userForm: TenantSignUpUserFormState;
|
||||
handleChangeUserFullName(fullName: string): void;
|
||||
handleChangeUserEmail(email: string): void;
|
||||
handleChangeUserPassword(password: string): void;
|
||||
handleChangeUserPasswordConfirmation(passwordConfirmation: string): void;
|
||||
handleUserFormConfirm(): void;
|
||||
|
||||
tenantForm: TenantSignUpTenantFormState;
|
||||
handleChangeTenantSiteName(siteName: string): void;
|
||||
handleChangeTenantSubdomain(subdomain: string): void;
|
||||
|
||||
handleSubmit(
|
||||
userFullName: string,
|
||||
userEmail: string,
|
||||
userPassword: string,
|
||||
siteName: string,
|
||||
subdomain: string,
|
||||
authenticityToken: string,
|
||||
): void;
|
||||
}
|
||||
|
||||
class TenantSignUpP extends React.Component<Props> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
this._handleSubmit = this._handleSubmit.bind(this);
|
||||
}
|
||||
|
||||
_handleSubmit() {
|
||||
const { userForm, tenantForm, handleSubmit } = this.props;
|
||||
|
||||
handleSubmit(
|
||||
userForm.fullName,
|
||||
userForm.email,
|
||||
userForm.password,
|
||||
tenantForm.siteName,
|
||||
tenantForm.subdomain,
|
||||
this.props.authenticityToken,
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
currentStep,
|
||||
emailAuth,
|
||||
toggleEmailAuth,
|
||||
|
||||
userForm,
|
||||
handleChangeUserFullName,
|
||||
handleChangeUserEmail,
|
||||
handleChangeUserPassword,
|
||||
handleChangeUserPasswordConfirmation,
|
||||
handleUserFormConfirm,
|
||||
|
||||
tenantForm,
|
||||
handleChangeTenantSiteName,
|
||||
handleChangeTenantSubdomain,
|
||||
|
||||
isSubmitting,
|
||||
error,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<div className="tenantSignUpContainer">
|
||||
{
|
||||
(currentStep === 1 || currentStep === 2) &&
|
||||
<UserSignUpForm
|
||||
currentStep={currentStep}
|
||||
|
||||
emailAuth={emailAuth}
|
||||
toggleEmailAuth={toggleEmailAuth}
|
||||
userForm={userForm}
|
||||
|
||||
handleChangeUserFullName={handleChangeUserFullName}
|
||||
handleChangeUserEmail={handleChangeUserEmail}
|
||||
handleChangeUserPassword={handleChangeUserPassword}
|
||||
handleChangeUserPasswordConfirmation={handleChangeUserPasswordConfirmation}
|
||||
handleUserFormConfirm={handleUserFormConfirm}
|
||||
/>
|
||||
}
|
||||
|
||||
{
|
||||
currentStep === 2 &&
|
||||
<TenantSignUpForm
|
||||
tenantForm={tenantForm}
|
||||
handleChangeTenantSiteName={handleChangeTenantSiteName}
|
||||
handleChangeTenantSubdomain={handleChangeTenantSubdomain}
|
||||
|
||||
isSubmitting={isSubmitting}
|
||||
error={error}
|
||||
handleSubmit={this._handleSubmit}
|
||||
/>
|
||||
}
|
||||
|
||||
{
|
||||
currentStep === 3 &&
|
||||
<ConfirmSignUpPage
|
||||
subdomain={tenantForm.subdomain}
|
||||
userEmail={userForm.email}
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default TenantSignUpP;
|
||||
147
app/javascript/components/TenantSignUp/UserSignUpForm.tsx
Normal file
147
app/javascript/components/TenantSignUp/UserSignUpForm.tsx
Normal file
@@ -0,0 +1,147 @@
|
||||
import * as React from 'react';
|
||||
import I18n from 'i18n-js';
|
||||
|
||||
import Box from '../common/Box';
|
||||
import Button from '../common/Button';
|
||||
import { TenantSignUpUserFormState } from '../../reducers/tenantSignUpReducer';
|
||||
|
||||
interface Props {
|
||||
currentStep: number;
|
||||
emailAuth: boolean;
|
||||
toggleEmailAuth(): void;
|
||||
userForm: TenantSignUpUserFormState;
|
||||
|
||||
handleChangeUserFullName(fullName: string): void;
|
||||
handleChangeUserEmail(email: string): void;
|
||||
handleChangeUserPassword(password: string): void;
|
||||
handleChangeUserPasswordConfirmation(passwordConfirmation: string): void;
|
||||
handleUserFormConfirm(): void;
|
||||
}
|
||||
|
||||
class UserSignUpForm extends React.Component<Props> {
|
||||
form: any;
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
this.form = React.createRef();
|
||||
}
|
||||
|
||||
validateUserForm(): boolean {
|
||||
let isValid: boolean = this.form.current.reportValidity();
|
||||
if (this.validateUserPasswordConfirmation() === false)
|
||||
isValid = false;
|
||||
|
||||
return isValid;
|
||||
}
|
||||
|
||||
validateUserPasswordConfirmation(): boolean {
|
||||
const isValid = this.props.userForm.password === this.props.userForm.passwordConfirmation;
|
||||
return isValid;
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
currentStep,
|
||||
emailAuth,
|
||||
toggleEmailAuth,
|
||||
userForm,
|
||||
|
||||
handleChangeUserFullName,
|
||||
handleChangeUserEmail,
|
||||
handleChangeUserPassword,
|
||||
handleChangeUserPasswordConfirmation,
|
||||
handleUserFormConfirm,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<Box customClass="tenantSignUpStep1">
|
||||
<h3>{ I18n.t('signup.step1.title') }</h3>
|
||||
|
||||
{
|
||||
currentStep === 1 && !emailAuth &&
|
||||
<Button className="emailAuth" onClick={toggleEmailAuth}>
|
||||
{ I18n.t('signup.step1.email_auth') }
|
||||
</Button>
|
||||
}
|
||||
|
||||
{
|
||||
currentStep === 1 && emailAuth &&
|
||||
<form ref={this.form}>
|
||||
<div className="formRow">
|
||||
<input
|
||||
type="text"
|
||||
autoFocus
|
||||
value={userForm.fullName}
|
||||
onChange={e => handleChangeUserFullName(e.target.value)}
|
||||
placeholder={I18n.t('common.forms.auth.full_name')}
|
||||
required
|
||||
id="userFullName"
|
||||
className="formControl"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="formRow">
|
||||
<input
|
||||
type="email"
|
||||
value={userForm.email}
|
||||
onChange={e => handleChangeUserEmail(e.target.value)}
|
||||
placeholder={I18n.t('common.forms.auth.email')}
|
||||
required
|
||||
id="userEmail"
|
||||
className="formControl"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="formRow">
|
||||
<div className="formGroup col-6">
|
||||
<input
|
||||
type="password"
|
||||
value={userForm.password}
|
||||
onChange={e => handleChangeUserPassword(e.target.value)}
|
||||
placeholder={I18n.t('common.forms.auth.password')}
|
||||
required
|
||||
minLength={6}
|
||||
maxLength={128}
|
||||
id="userPassword"
|
||||
className="formControl"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="formGroup col-6">
|
||||
<input
|
||||
type="password"
|
||||
value={userForm.passwordConfirmation}
|
||||
onChange={e => handleChangeUserPasswordConfirmation(e.target.value)}
|
||||
placeholder={I18n.t('common.forms.auth.password_confirmation')}
|
||||
required
|
||||
minLength={6}
|
||||
maxLength={128}
|
||||
id="userPasswordConfirmation"
|
||||
className={`formControl${userForm.passwordConfirmationError ? ' invalid' : ''}`}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
onClick={e => {
|
||||
e.preventDefault();
|
||||
this.validateUserForm() && handleUserFormConfirm();
|
||||
}}
|
||||
className="userConfirm"
|
||||
>
|
||||
{ I18n.t('common.buttons.confirm') }
|
||||
</Button>
|
||||
</form>
|
||||
}
|
||||
|
||||
{
|
||||
currentStep === 2 &&
|
||||
<p><b>{userForm.fullName}</b> ({userForm.email})</p>
|
||||
}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default UserSignUpForm;
|
||||
37
app/javascript/components/TenantSignUp/index.tsx
Normal file
37
app/javascript/components/TenantSignUp/index.tsx
Normal file
@@ -0,0 +1,37 @@
|
||||
import * as React from 'react';
|
||||
import { Provider } from 'react-redux';
|
||||
|
||||
import createStoreHelper from '../../helpers/createStore';
|
||||
|
||||
import TenantSignUp from '../../containers/TenantSignUp';
|
||||
|
||||
import { Store } from 'redux';
|
||||
import { State } from '../../reducers/rootReducer';
|
||||
|
||||
interface Props {
|
||||
authenticityToken: string;
|
||||
}
|
||||
|
||||
class TenantSignUpRoot extends React.Component<Props> {
|
||||
store: Store<State, any>;
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
this.store = createStoreHelper();
|
||||
}
|
||||
|
||||
render() {
|
||||
const { authenticityToken } = this.props;
|
||||
|
||||
return (
|
||||
<Provider store={this.store}>
|
||||
<TenantSignUp
|
||||
authenticityToken={authenticityToken}
|
||||
/>
|
||||
</Provider>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default TenantSignUpRoot;
|
||||
@@ -7,9 +7,10 @@ import Box from './Box';
|
||||
interface Props {
|
||||
areUpdating: boolean;
|
||||
error: string;
|
||||
areDirty?: boolean;
|
||||
}
|
||||
|
||||
const SiteSettingsInfoBox = ({ areUpdating, error }: Props) => (
|
||||
const SiteSettingsInfoBox = ({ areUpdating, error, areDirty = false }: Props) => (
|
||||
<Box customClass="siteSettingsInfo">
|
||||
{
|
||||
areUpdating ?
|
||||
@@ -17,10 +18,13 @@ const SiteSettingsInfoBox = ({ areUpdating, error }: Props) => (
|
||||
:
|
||||
error ?
|
||||
<span className="error">
|
||||
{I18n.t('site_settings.info_box.error', { message: JSON.stringify(error) })}
|
||||
{ I18n.t('site_settings.info_box.error', { message: JSON.stringify(error) }) }
|
||||
</span>
|
||||
:
|
||||
<span>{I18n.t('site_settings.info_box.up_to_date')}</span>
|
||||
areDirty ?
|
||||
<span className="warning">{ I18n.t('site_settings.info_box.dirty') }</span>
|
||||
:
|
||||
<span>{ I18n.t('site_settings.info_box.up_to_date') }</span>
|
||||
}
|
||||
</Box>
|
||||
);
|
||||
|
||||
@@ -1 +1 @@
|
||||
export const POSTS_PER_PAGE = parseInt(process.env.POSTS_PER_PAGE);
|
||||
export const POSTS_PER_PAGE = 15;
|
||||
63
app/javascript/containers/GeneralSiteSettings.tsx
Normal file
63
app/javascript/containers/GeneralSiteSettings.tsx
Normal file
@@ -0,0 +1,63 @@
|
||||
import { connect } from "react-redux";
|
||||
|
||||
import { requestTenant } from "../actions/Tenant/requestTenant";
|
||||
import {
|
||||
changeSiteSettingsGeneralFormBrandSetting,
|
||||
changeSiteSettingsGeneralFormLocale,
|
||||
changeSiteSettingsGeneralFormSiteLogo,
|
||||
changeSiteSettingsGeneralFormSiteName
|
||||
} from "../actions/changeSiteSettingsGeneralForm";
|
||||
import GeneralSiteSettingsP from "../components/SiteSettings/General/GeneralSiteSettingsP";
|
||||
import { State } from "../reducers/rootReducer";
|
||||
import { updateTenant } from "../actions/Tenant/updateTenant";
|
||||
|
||||
const mapStateToProps = (state: State) => ({
|
||||
form: state.siteSettings.general.form,
|
||||
areDirty: state.siteSettings.general.areDirty,
|
||||
areLoading: state.siteSettings.general.areLoading,
|
||||
areUpdating: state.siteSettings.general.areUpdating,
|
||||
error: state.siteSettings.general.error,
|
||||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch: any) => ({
|
||||
requestTenant() {
|
||||
dispatch(requestTenant());
|
||||
},
|
||||
|
||||
updateTenant(
|
||||
siteName: string,
|
||||
siteLogo: string,
|
||||
brandDisplaySetting: string,
|
||||
locale: string,
|
||||
authenticityToken: string
|
||||
): Promise<any> {
|
||||
return dispatch(updateTenant({
|
||||
siteName,
|
||||
siteLogo,
|
||||
brandDisplaySetting,
|
||||
locale,
|
||||
authenticityToken,
|
||||
}));
|
||||
},
|
||||
|
||||
handleChangeSiteName(siteName: string) {
|
||||
dispatch(changeSiteSettingsGeneralFormSiteName(siteName));
|
||||
},
|
||||
|
||||
handleChangeSiteLogo(siteLogo: string) {
|
||||
dispatch(changeSiteSettingsGeneralFormSiteLogo(siteLogo));
|
||||
},
|
||||
|
||||
handleChangeBrandDisplaySetting(brandDisplaySetting: string) {
|
||||
dispatch(changeSiteSettingsGeneralFormBrandSetting(brandDisplaySetting));
|
||||
},
|
||||
|
||||
handleChangeLocale(locale: string) {
|
||||
dispatch(changeSiteSettingsGeneralFormLocale(locale));
|
||||
},
|
||||
});
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(GeneralSiteSettingsP);
|
||||
82
app/javascript/containers/TenantSignUp.tsx
Normal file
82
app/javascript/containers/TenantSignUp.tsx
Normal file
@@ -0,0 +1,82 @@
|
||||
import { connect } from "react-redux";
|
||||
|
||||
import TenantSignUpP from "../components/TenantSignUp/TenantSignUpP";
|
||||
|
||||
import { State } from "../reducers/rootReducer";
|
||||
import {
|
||||
changeTenantSiteNameTenantSignUp,
|
||||
changeTenantSubdomainTenantSignUp,
|
||||
changeUserEmailTenantSignUp,
|
||||
changeUserFullNameTenantSignUp,
|
||||
changeUserPasswordConfirmationTenantSignUp,
|
||||
changeUserPasswordTenantSignUp,
|
||||
confirmUserFormTenantSignUp,
|
||||
toggleEmailAuthTenantSignUp
|
||||
} from "../actions/Tenant/tenantSignUpFormActions";
|
||||
import { submitTenant } from "../actions/Tenant/submitTenant";
|
||||
|
||||
const mapStateToProps = (state: State) => ({
|
||||
currentStep: state.tenantSignUp.currentStep,
|
||||
emailAuth: state.tenantSignUp.emailAuth,
|
||||
isSubmitting: state.tenantSignUp.isSubmitting,
|
||||
error: state.tenantSignUp.error,
|
||||
userForm: state.tenantSignUp.userForm,
|
||||
tenantForm: state.tenantSignUp.tenantForm,
|
||||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch: any) => ({
|
||||
toggleEmailAuth() {
|
||||
dispatch(toggleEmailAuthTenantSignUp());
|
||||
},
|
||||
|
||||
handleChangeUserFullName(fullName: string) {
|
||||
dispatch(changeUserFullNameTenantSignUp(fullName));
|
||||
},
|
||||
|
||||
handleChangeUserEmail(email: string) {
|
||||
dispatch(changeUserEmailTenantSignUp(email));
|
||||
},
|
||||
|
||||
handleChangeUserPassword(password: string) {
|
||||
dispatch(changeUserPasswordTenantSignUp(password));
|
||||
},
|
||||
|
||||
handleChangeUserPasswordConfirmation(passwordConfirmation: string) {
|
||||
dispatch(changeUserPasswordConfirmationTenantSignUp(passwordConfirmation));
|
||||
},
|
||||
|
||||
handleUserFormConfirm() {
|
||||
dispatch(confirmUserFormTenantSignUp());
|
||||
},
|
||||
|
||||
handleChangeTenantSiteName(siteName: string) {
|
||||
dispatch(changeTenantSiteNameTenantSignUp(siteName));
|
||||
},
|
||||
|
||||
handleChangeTenantSubdomain(subdomain: string) {
|
||||
dispatch(changeTenantSubdomainTenantSignUp(subdomain));
|
||||
},
|
||||
|
||||
handleSubmit(
|
||||
userFullName: string,
|
||||
userEmail: string,
|
||||
userPassword: string,
|
||||
siteName: string,
|
||||
subdomain: string,
|
||||
authenticityToken: string,
|
||||
) {
|
||||
dispatch(submitTenant(
|
||||
userFullName,
|
||||
userEmail,
|
||||
userPassword,
|
||||
siteName,
|
||||
subdomain,
|
||||
authenticityToken,
|
||||
));
|
||||
}
|
||||
});
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(TenantSignUpP);
|
||||
21
app/javascript/interfaces/ITenant.ts
Normal file
21
app/javascript/interfaces/ITenant.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
// Brand display setting
|
||||
export const TENANT_BRAND_NAME_AND_LOGO = 'name_and_logo';
|
||||
export const TENANT_BRAND_NAME_ONLY = 'name_only';
|
||||
export const TENANT_BRAND_LOGO_ONLY = 'logo_only';
|
||||
export const TENANT_BRAND_NONE = 'no_name_no_logo';
|
||||
|
||||
export type TenantBrandDisplaySetting =
|
||||
typeof TENANT_BRAND_NAME_AND_LOGO |
|
||||
typeof TENANT_BRAND_NAME_ONLY |
|
||||
typeof TENANT_BRAND_LOGO_ONLY |
|
||||
typeof TENANT_BRAND_NONE;
|
||||
|
||||
interface ITenant {
|
||||
id: number;
|
||||
siteName: string;
|
||||
siteLogo: string;
|
||||
brandDisplaySetting: TenantBrandDisplaySetting;
|
||||
locale: string;
|
||||
}
|
||||
|
||||
export default ITenant;
|
||||
9
app/javascript/interfaces/json/ITenant.ts
Normal file
9
app/javascript/interfaces/json/ITenant.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
interface ITenantJSON {
|
||||
id: number;
|
||||
site_name: string;
|
||||
site_logo: string;
|
||||
brand_display_setting: string;
|
||||
locale: string;
|
||||
}
|
||||
|
||||
export default ITenantJSON;
|
||||
140
app/javascript/reducers/SiteSettings/generalReducer.ts
Normal file
140
app/javascript/reducers/SiteSettings/generalReducer.ts
Normal file
@@ -0,0 +1,140 @@
|
||||
import {
|
||||
TenantRequestActionTypes,
|
||||
TENANT_REQUEST_START,
|
||||
TENANT_REQUEST_SUCCESS,
|
||||
TENANT_REQUEST_FAILURE,
|
||||
} from "../../actions/Tenant/requestTenant";
|
||||
|
||||
import {
|
||||
TenantUpdateActionTypes,
|
||||
TENANT_UPDATE_START,
|
||||
TENANT_UPDATE_SUCCESS,
|
||||
TENANT_UPDATE_FAILURE,
|
||||
} from '../../actions/Tenant/updateTenant';
|
||||
|
||||
import {
|
||||
ChangeSiteSettingsGeneralFormActionTypes,
|
||||
SITE_SETTINGS_CHANGE_GENERAL_FORM_SITE_NAME,
|
||||
SITE_SETTINGS_CHANGE_GENERAL_FORM_SITE_LOGO,
|
||||
SITE_SETTINGS_CHANGE_GENERAL_FORM_BRAND_SETTING,
|
||||
SITE_SETTINGS_CHANGE_GENERAL_FORM_LOCALE,
|
||||
} from '../../actions/changeSiteSettingsGeneralForm';
|
||||
|
||||
export interface ISiteSettingsGeneralForm {
|
||||
siteName: string;
|
||||
siteLogo: string;
|
||||
brandDisplaySetting: string;
|
||||
locale: string;
|
||||
}
|
||||
|
||||
export interface SiteSettingsGeneralState {
|
||||
form: ISiteSettingsGeneralForm,
|
||||
areDirty: boolean;
|
||||
areLoading: boolean;
|
||||
areUpdating: boolean;
|
||||
error: string;
|
||||
}
|
||||
|
||||
const initialState: SiteSettingsGeneralState = {
|
||||
form: {
|
||||
siteName: '',
|
||||
siteLogo: '',
|
||||
brandDisplaySetting: '',
|
||||
locale: '',
|
||||
},
|
||||
areDirty: false,
|
||||
areLoading: false,
|
||||
areUpdating: false,
|
||||
error: '',
|
||||
};
|
||||
|
||||
const siteSettingsGeneralReducer = (
|
||||
state = initialState,
|
||||
action:
|
||||
TenantRequestActionTypes |
|
||||
TenantUpdateActionTypes |
|
||||
ChangeSiteSettingsGeneralFormActionTypes
|
||||
) => {
|
||||
switch (action.type) {
|
||||
case TENANT_REQUEST_START:
|
||||
return {
|
||||
...state,
|
||||
areLoading: true,
|
||||
};
|
||||
|
||||
case TENANT_UPDATE_START:
|
||||
return {
|
||||
...state,
|
||||
areUpdating: true,
|
||||
};
|
||||
|
||||
case TENANT_REQUEST_SUCCESS:
|
||||
return {
|
||||
...state,
|
||||
form: {
|
||||
siteName: action.tenant.site_name,
|
||||
siteLogo: action.tenant.site_logo,
|
||||
brandDisplaySetting: action.tenant.brand_display_setting,
|
||||
locale: action.tenant.locale,
|
||||
},
|
||||
areDirty: false,
|
||||
areLoading: false,
|
||||
error: '',
|
||||
};
|
||||
|
||||
case TENANT_UPDATE_SUCCESS:
|
||||
return {
|
||||
...state,
|
||||
areDirty: false,
|
||||
areUpdating: false,
|
||||
error: '',
|
||||
};
|
||||
|
||||
case TENANT_REQUEST_FAILURE:
|
||||
return {
|
||||
...state,
|
||||
areLoading: false,
|
||||
error: action.error,
|
||||
};
|
||||
|
||||
case TENANT_UPDATE_FAILURE:
|
||||
return {
|
||||
...state,
|
||||
areUpdating: false,
|
||||
error: action.error,
|
||||
};
|
||||
|
||||
case SITE_SETTINGS_CHANGE_GENERAL_FORM_SITE_NAME:
|
||||
return {
|
||||
...state,
|
||||
form: { ...state.form, siteName: action.siteName },
|
||||
areDirty: true,
|
||||
};
|
||||
|
||||
case SITE_SETTINGS_CHANGE_GENERAL_FORM_SITE_LOGO:
|
||||
return {
|
||||
...state,
|
||||
form: { ...state.form, siteLogo: action.siteLogo },
|
||||
areDirty: true,
|
||||
};
|
||||
|
||||
case SITE_SETTINGS_CHANGE_GENERAL_FORM_BRAND_SETTING:
|
||||
return {
|
||||
...state,
|
||||
form: { ...state.form, brandDisplaySetting: action.brandDisplaySetting },
|
||||
areDirty: true,
|
||||
};
|
||||
|
||||
case SITE_SETTINGS_CHANGE_GENERAL_FORM_LOCALE:
|
||||
return {
|
||||
...state,
|
||||
form: { ...state.form, locale: action.locale },
|
||||
areDirty: true,
|
||||
};
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
export default siteSettingsGeneralReducer;
|
||||
@@ -1,3 +1,10 @@
|
||||
import {
|
||||
PostStatusesRequestActionTypes,
|
||||
POST_STATUSES_REQUEST_START,
|
||||
POST_STATUSES_REQUEST_SUCCESS,
|
||||
POST_STATUSES_REQUEST_FAILURE,
|
||||
} from '../../actions/PostStatus/requestPostStatuses';
|
||||
|
||||
import {
|
||||
PostStatusOrderUpdateActionTypes,
|
||||
POSTSTATUS_ORDER_UPDATE_START,
|
||||
@@ -38,12 +45,15 @@ const initialState: SiteSettingsPostStatusesState = {
|
||||
|
||||
const siteSettingsPostStatusesReducer = (
|
||||
state = initialState,
|
||||
action: PostStatusOrderUpdateActionTypes |
|
||||
action:
|
||||
PostStatusesRequestActionTypes |
|
||||
PostStatusOrderUpdateActionTypes |
|
||||
PostStatusDeleteActionTypes |
|
||||
PostStatusSubmitActionTypes |
|
||||
PostStatusUpdateActionTypes
|
||||
): SiteSettingsPostStatusesState => {
|
||||
switch (action.type) {
|
||||
case POST_STATUSES_REQUEST_START:
|
||||
case POSTSTATUS_SUBMIT_START:
|
||||
case POSTSTATUS_UPDATE_START:
|
||||
case POSTSTATUS_ORDER_UPDATE_START:
|
||||
@@ -53,6 +63,7 @@ const siteSettingsPostStatusesReducer = (
|
||||
areUpdating: true,
|
||||
};
|
||||
|
||||
case POST_STATUSES_REQUEST_SUCCESS:
|
||||
case POSTSTATUS_SUBMIT_SUCCESS:
|
||||
case POSTSTATUS_UPDATE_SUCCESS:
|
||||
case POSTSTATUS_ORDER_UPDATE_SUCCESS:
|
||||
@@ -63,6 +74,7 @@ const siteSettingsPostStatusesReducer = (
|
||||
error: '',
|
||||
};
|
||||
|
||||
case POST_STATUSES_REQUEST_FAILURE:
|
||||
case POSTSTATUS_SUBMIT_FAILURE:
|
||||
case POSTSTATUS_UPDATE_FAILURE:
|
||||
case POSTSTATUS_ORDER_UPDATE_FAILURE:
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { combineReducers } from 'redux';
|
||||
|
||||
import tenantSignUpReducer from './tenantSignUpReducer';
|
||||
|
||||
import postsReducer from './postsReducer';
|
||||
import boardsReducer from './boardsReducer';
|
||||
import postStatusesReducer from './postStatusesReducer';
|
||||
@@ -8,6 +10,8 @@ import currentPostReducer from './currentPostReducer';
|
||||
import siteSettingsReducer from './siteSettingsReducer';
|
||||
|
||||
const rootReducer = combineReducers({
|
||||
tenantSignUp: tenantSignUpReducer,
|
||||
|
||||
posts: postsReducer,
|
||||
boards: boardsReducer,
|
||||
postStatuses: postStatusesReducer,
|
||||
|
||||
@@ -1,3 +1,25 @@
|
||||
import {
|
||||
TenantRequestActionTypes,
|
||||
TENANT_REQUEST_START,
|
||||
TENANT_REQUEST_SUCCESS,
|
||||
TENANT_REQUEST_FAILURE,
|
||||
} from '../actions/Tenant/requestTenant';
|
||||
|
||||
import {
|
||||
TenantUpdateActionTypes,
|
||||
TENANT_UPDATE_START,
|
||||
TENANT_UPDATE_SUCCESS,
|
||||
TENANT_UPDATE_FAILURE,
|
||||
} from '../actions/Tenant/updateTenant';
|
||||
|
||||
import {
|
||||
ChangeSiteSettingsGeneralFormActionTypes,
|
||||
SITE_SETTINGS_CHANGE_GENERAL_FORM_SITE_NAME,
|
||||
SITE_SETTINGS_CHANGE_GENERAL_FORM_SITE_LOGO,
|
||||
SITE_SETTINGS_CHANGE_GENERAL_FORM_BRAND_SETTING,
|
||||
SITE_SETTINGS_CHANGE_GENERAL_FORM_LOCALE,
|
||||
} from '../actions/changeSiteSettingsGeneralForm';
|
||||
|
||||
import {
|
||||
BoardsRequestActionTypes,
|
||||
BOARDS_REQUEST_START,
|
||||
@@ -33,6 +55,13 @@ import {
|
||||
BOARD_DELETE_FAILURE,
|
||||
} from '../actions/Board/deleteBoard';
|
||||
|
||||
import {
|
||||
PostStatusesRequestActionTypes,
|
||||
POST_STATUSES_REQUEST_START,
|
||||
POST_STATUSES_REQUEST_SUCCESS,
|
||||
POST_STATUSES_REQUEST_FAILURE,
|
||||
} from '../actions/PostStatus/requestPostStatuses';
|
||||
|
||||
import {
|
||||
PostStatusOrderUpdateActionTypes,
|
||||
POSTSTATUS_ORDER_UPDATE_START,
|
||||
@@ -75,12 +104,14 @@ import {
|
||||
USER_UPDATE_FAILURE,
|
||||
} from '../actions/User/updateUser';
|
||||
|
||||
import siteSettingsGeneralReducer, { SiteSettingsGeneralState } from './SiteSettings/generalReducer';
|
||||
import siteSettingsBoardsReducer, { SiteSettingsBoardsState } from './SiteSettings/boardsReducer';
|
||||
import siteSettingsPostStatusesReducer, { SiteSettingsPostStatusesState } from './SiteSettings/postStatusesReducer';
|
||||
import siteSettingsRoadmapReducer, { SiteSettingsRoadmapState } from './SiteSettings/roadmapReducer';
|
||||
import siteSettingsUsersReducer, { SiteSettingsUsersState } from './SiteSettings/usersReducer';
|
||||
|
||||
interface SiteSettingsState {
|
||||
general: SiteSettingsGeneralState;
|
||||
boards: SiteSettingsBoardsState;
|
||||
postStatuses: SiteSettingsPostStatusesState;
|
||||
roadmap: SiteSettingsRoadmapState;
|
||||
@@ -88,6 +119,7 @@ interface SiteSettingsState {
|
||||
}
|
||||
|
||||
const initialState: SiteSettingsState = {
|
||||
general: siteSettingsGeneralReducer(undefined, {} as any),
|
||||
boards: siteSettingsBoardsReducer(undefined, {} as any),
|
||||
postStatuses: siteSettingsPostStatusesReducer(undefined, {} as any),
|
||||
roadmap: siteSettingsRoadmapReducer(undefined, {} as any),
|
||||
@@ -97,11 +129,15 @@ const initialState: SiteSettingsState = {
|
||||
const siteSettingsReducer = (
|
||||
state = initialState,
|
||||
action:
|
||||
TenantRequestActionTypes |
|
||||
TenantUpdateActionTypes |
|
||||
ChangeSiteSettingsGeneralFormActionTypes |
|
||||
BoardsRequestActionTypes |
|
||||
BoardSubmitActionTypes |
|
||||
BoardUpdateActionTypes |
|
||||
BoardOrderUpdateActionTypes |
|
||||
BoardDeleteActionTypes |
|
||||
PostStatusesRequestActionTypes |
|
||||
PostStatusOrderUpdateActionTypes |
|
||||
PostStatusDeleteActionTypes |
|
||||
PostStatusSubmitActionTypes |
|
||||
@@ -110,6 +146,21 @@ const siteSettingsReducer = (
|
||||
UserUpdateActionTypes
|
||||
): SiteSettingsState => {
|
||||
switch (action.type) {
|
||||
case TENANT_REQUEST_START:
|
||||
case TENANT_REQUEST_SUCCESS:
|
||||
case TENANT_REQUEST_FAILURE:
|
||||
case TENANT_UPDATE_START:
|
||||
case TENANT_UPDATE_SUCCESS:
|
||||
case TENANT_UPDATE_FAILURE:
|
||||
case SITE_SETTINGS_CHANGE_GENERAL_FORM_SITE_NAME:
|
||||
case SITE_SETTINGS_CHANGE_GENERAL_FORM_SITE_LOGO:
|
||||
case SITE_SETTINGS_CHANGE_GENERAL_FORM_BRAND_SETTING:
|
||||
case SITE_SETTINGS_CHANGE_GENERAL_FORM_LOCALE:
|
||||
return {
|
||||
...state,
|
||||
general: siteSettingsGeneralReducer(state.general, action),
|
||||
};
|
||||
|
||||
case BOARDS_REQUEST_START:
|
||||
case BOARDS_REQUEST_SUCCESS:
|
||||
case BOARDS_REQUEST_FAILURE:
|
||||
@@ -130,6 +181,9 @@ const siteSettingsReducer = (
|
||||
boards: siteSettingsBoardsReducer(state.boards, action),
|
||||
};
|
||||
|
||||
case POST_STATUSES_REQUEST_START:
|
||||
case POST_STATUSES_REQUEST_SUCCESS:
|
||||
case POST_STATUSES_REQUEST_FAILURE:
|
||||
case POSTSTATUS_SUBMIT_START:
|
||||
case POSTSTATUS_SUBMIT_SUCCESS:
|
||||
case POSTSTATUS_SUBMIT_FAILURE:
|
||||
|
||||
145
app/javascript/reducers/tenantSignUpReducer.ts
Normal file
145
app/javascript/reducers/tenantSignUpReducer.ts
Normal file
@@ -0,0 +1,145 @@
|
||||
import {
|
||||
TenantSignUpFormActions,
|
||||
TENANT_SIGN_UP_TOGGLE_EMAIL_AUTH,
|
||||
TENANT_SIGN_UP_CHANGE_USER_FULL_NAME,
|
||||
TENANT_SIGN_UP_CHANGE_USER_EMAIL,
|
||||
TENANT_SIGN_UP_CHANGE_USER_PASSWORD,
|
||||
TENANT_SIGN_UP_CHANGE_USER_PASSWORD_CONFIRMATION,
|
||||
TENANT_SIGN_UP_CONFIRM_USER_FORM,
|
||||
TENANT_SIGN_UP_CHANGE_TENANT_SITE_NAME,
|
||||
TENANT_SIGN_UP_CHANGE_TENANT_SUBDOMAIN,
|
||||
} from '../actions/Tenant/tenantSignUpFormActions';
|
||||
|
||||
import {
|
||||
TenantSubmitActionTypes,
|
||||
TENANT_SUBMIT_START,
|
||||
TENANT_SUBMIT_SUCCESS,
|
||||
TENANT_SUBMIT_FAILURE,
|
||||
} from '../actions/Tenant/submitTenant';
|
||||
|
||||
export interface TenantSignUpUserFormState {
|
||||
fullName: string;
|
||||
email: string;
|
||||
password: string;
|
||||
passwordConfirmation: string;
|
||||
passwordConfirmationError: boolean;
|
||||
}
|
||||
|
||||
export interface TenantSignUpTenantFormState {
|
||||
siteName: string;
|
||||
subdomain: string;
|
||||
}
|
||||
|
||||
export interface TenantSignUpState {
|
||||
currentStep: number;
|
||||
emailAuth: boolean;
|
||||
isSubmitting: boolean;
|
||||
error: string;
|
||||
|
||||
userForm: TenantSignUpUserFormState;
|
||||
tenantForm: TenantSignUpTenantFormState;
|
||||
}
|
||||
|
||||
const initialState: TenantSignUpState = {
|
||||
currentStep: 1,
|
||||
emailAuth: false,
|
||||
isSubmitting: false,
|
||||
error: '',
|
||||
|
||||
userForm: {
|
||||
fullName: '',
|
||||
email: '',
|
||||
password: '',
|
||||
passwordConfirmation: '',
|
||||
passwordConfirmationError: false,
|
||||
},
|
||||
tenantForm: {
|
||||
siteName: '',
|
||||
subdomain: '',
|
||||
},
|
||||
};
|
||||
|
||||
const tenantSignUpReducer = (
|
||||
state = initialState,
|
||||
action: TenantSignUpFormActions | TenantSubmitActionTypes,
|
||||
) => {
|
||||
switch (action.type) {
|
||||
case TENANT_SIGN_UP_TOGGLE_EMAIL_AUTH:
|
||||
return {
|
||||
...state,
|
||||
emailAuth: !state.emailAuth,
|
||||
};
|
||||
|
||||
case TENANT_SIGN_UP_CHANGE_USER_FULL_NAME:
|
||||
return {
|
||||
...state,
|
||||
userForm: { ...state.userForm, fullName: action.fullName },
|
||||
};
|
||||
|
||||
case TENANT_SIGN_UP_CHANGE_USER_EMAIL:
|
||||
return {
|
||||
...state,
|
||||
userForm: { ...state.userForm, email: action.email },
|
||||
};
|
||||
|
||||
case TENANT_SIGN_UP_CHANGE_USER_PASSWORD:
|
||||
return {
|
||||
...state,
|
||||
userForm: { ...state.userForm, password: action.password },
|
||||
};
|
||||
|
||||
case TENANT_SIGN_UP_CHANGE_USER_PASSWORD_CONFIRMATION:
|
||||
return {
|
||||
...state,
|
||||
userForm: {
|
||||
...state.userForm,
|
||||
passwordConfirmation: action.passwordConfirmation,
|
||||
passwordConfirmationError: state.userForm.password !== action.passwordConfirmation,
|
||||
},
|
||||
};
|
||||
|
||||
case TENANT_SIGN_UP_CONFIRM_USER_FORM:
|
||||
return {
|
||||
...state,
|
||||
currentStep: 2,
|
||||
};
|
||||
|
||||
case TENANT_SIGN_UP_CHANGE_TENANT_SITE_NAME:
|
||||
return {
|
||||
...state,
|
||||
tenantForm: { ...state.tenantForm, siteName: action.siteName },
|
||||
};
|
||||
|
||||
case TENANT_SIGN_UP_CHANGE_TENANT_SUBDOMAIN:
|
||||
return {
|
||||
...state,
|
||||
tenantForm: { ...state.tenantForm, subdomain: action.subdomain },
|
||||
};
|
||||
|
||||
case TENANT_SUBMIT_START:
|
||||
return {
|
||||
...state,
|
||||
isSubmitting: true,
|
||||
};
|
||||
|
||||
case TENANT_SUBMIT_SUCCESS:
|
||||
return {
|
||||
...state,
|
||||
currentStep: 3,
|
||||
isSubmitting: false,
|
||||
error: '',
|
||||
};
|
||||
|
||||
case TENANT_SUBMIT_FAILURE:
|
||||
return {
|
||||
...state,
|
||||
isSubmitting: false,
|
||||
error: action.error,
|
||||
};
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
export default tenantSignUpReducer;
|
||||
@@ -36,6 +36,25 @@
|
||||
a { color: $primary-color; }
|
||||
}
|
||||
|
||||
.formRow {
|
||||
@extend .form-row;
|
||||
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.formGroup {
|
||||
@extend .form-group;
|
||||
}
|
||||
|
||||
.formControl {
|
||||
@extend .form-control;
|
||||
|
||||
&.invalid {
|
||||
border-color: red;
|
||||
}
|
||||
}
|
||||
|
||||
.switch {
|
||||
@extend
|
||||
.custom-control-input;
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
.align-top,
|
||||
.mr-2;
|
||||
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -142,6 +142,11 @@
|
||||
max-width: 960px;
|
||||
}
|
||||
|
||||
.smallContainer {
|
||||
max-width: 540px;
|
||||
margin: 16px auto;
|
||||
}
|
||||
|
||||
.turbolinks-progress-bar {
|
||||
background-color: $primary-color;
|
||||
height: 2px;
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
.postStatusForm {
|
||||
@extend
|
||||
.d-flex,
|
||||
.flex-grow-1,
|
||||
.m-2;
|
||||
|
||||
column-gap: 8px;
|
||||
|
||||
@@ -4,4 +4,8 @@
|
||||
.error {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.warning {
|
||||
color: #fd7e14;
|
||||
}
|
||||
}
|
||||
3
app/javascript/stylesheets/components/TenantSignUp.scss
Normal file
3
app/javascript/stylesheets/components/TenantSignUp.scss
Normal file
@@ -0,0 +1,3 @@
|
||||
.tenantSignUpContainer {
|
||||
@extend .smallContainer;
|
||||
}
|
||||
@@ -9,6 +9,7 @@
|
||||
@import 'common/scroll_shadows';
|
||||
|
||||
/* Components */
|
||||
@import 'components/TenantSignUp';
|
||||
@import 'components/Board';
|
||||
@import 'components/Comments';
|
||||
@import 'components/LikeButton';
|
||||
|
||||
Reference in New Issue
Block a user