mirror of
https://github.com/grafana/grafana.git
synced 2025-07-30 23:32:11 +08:00
Fixes signup workflow and UI (#26263)
* fixes signup flow * Apply suggestions from code review Co-authored-by: Hugo Häggmark <hugo.haggmark@gmail.com> * Update ForgottenPassword.tsx * fixes build failure * fixes build failure Co-authored-by: Hugo Häggmark <hugo.haggmark@gmail.com>
This commit is contained in:
@ -88,6 +88,7 @@ func (hs *HTTPServer) registerRoutes() {
|
|||||||
r.Get("/alerting/*", reqEditorRole, hs.Index)
|
r.Get("/alerting/*", reqEditorRole, hs.Index)
|
||||||
|
|
||||||
// sign up
|
// sign up
|
||||||
|
r.Get("/verify", hs.Index)
|
||||||
r.Get("/signup", hs.Index)
|
r.Get("/signup", hs.Index)
|
||||||
r.Get("/api/user/signup/options", Wrap(GetSignUpOptions))
|
r.Get("/api/user/signup/options", Wrap(GetSignUpOptions))
|
||||||
r.Post("/api/user/signup", quota("user"), bind(dtos.SignUpForm{}), Wrap(SignUp))
|
r.Post("/api/user/signup", quota("user"), bind(dtos.SignUpForm{}), Wrap(SignUp))
|
||||||
|
@ -3,7 +3,6 @@ import { Form, Field, Input, Button, Legend, Container, useStyles, HorizontalGro
|
|||||||
import { getBackendSrv } from '@grafana/runtime';
|
import { getBackendSrv } from '@grafana/runtime';
|
||||||
import { css } from 'emotion';
|
import { css } from 'emotion';
|
||||||
import { GrafanaTheme } from '@grafana/data';
|
import { GrafanaTheme } from '@grafana/data';
|
||||||
|
|
||||||
import config from 'app/core/config';
|
import config from 'app/core/config';
|
||||||
|
|
||||||
interface EmailDTO {
|
interface EmailDTO {
|
||||||
@ -21,6 +20,7 @@ const paragraphStyles = (theme: GrafanaTheme) => css`
|
|||||||
export const ForgottenPassword: FC = () => {
|
export const ForgottenPassword: FC = () => {
|
||||||
const [emailSent, setEmailSent] = useState(false);
|
const [emailSent, setEmailSent] = useState(false);
|
||||||
const styles = useStyles(paragraphStyles);
|
const styles = useStyles(paragraphStyles);
|
||||||
|
const loginHref = `${config.appSubUrl}/login`;
|
||||||
|
|
||||||
const sendEmail = async (formModel: EmailDTO) => {
|
const sendEmail = async (formModel: EmailDTO) => {
|
||||||
const res = await getBackendSrv().post('/api/user/password/send-reset-email', formModel);
|
const res = await getBackendSrv().post('/api/user/password/send-reset-email', formModel);
|
||||||
@ -34,7 +34,7 @@ export const ForgottenPassword: FC = () => {
|
|||||||
<div>
|
<div>
|
||||||
<p>An email with a reset link has been sent to the email address. You should receive it shortly.</p>
|
<p>An email with a reset link has been sent to the email address. You should receive it shortly.</p>
|
||||||
<Container margin="md" />
|
<Container margin="md" />
|
||||||
<LinkButton variant="primary" href="/login">
|
<LinkButton variant="primary" href={loginHref}>
|
||||||
Back to login
|
Back to login
|
||||||
</LinkButton>
|
</LinkButton>
|
||||||
</div>
|
</div>
|
||||||
@ -55,7 +55,7 @@ export const ForgottenPassword: FC = () => {
|
|||||||
</Field>
|
</Field>
|
||||||
<HorizontalGroup>
|
<HorizontalGroup>
|
||||||
<Button>Send reset email</Button>
|
<Button>Send reset email</Button>
|
||||||
<LinkButton variant="link" href={`${config.appSubUrl}/login`}>
|
<LinkButton variant="link" href={loginHref}>
|
||||||
Back to login
|
Back to login
|
||||||
</LinkButton>
|
</LinkButton>
|
||||||
</HorizontalGroup>
|
</HorizontalGroup>
|
||||||
|
@ -11,7 +11,6 @@ import { ChangePassword } from '../ForgottenPassword/ChangePassword';
|
|||||||
import { Branding } from 'app/core/components/Branding/Branding';
|
import { Branding } from 'app/core/components/Branding/Branding';
|
||||||
import { HorizontalGroup, LinkButton } from '@grafana/ui';
|
import { HorizontalGroup, LinkButton } from '@grafana/ui';
|
||||||
import { LoginLayout, InnerBox } from './LoginLayout';
|
import { LoginLayout, InnerBox } from './LoginLayout';
|
||||||
|
|
||||||
import config from 'app/core/config';
|
import config from 'app/core/config';
|
||||||
|
|
||||||
const forgottenPasswordStyles = css`
|
const forgottenPasswordStyles = css`
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
import React, { FC } from 'react';
|
import React, { FC } from 'react';
|
||||||
import { LinkButton, VerticalGroup } from '@grafana/ui';
|
import { LinkButton, VerticalGroup } from '@grafana/ui';
|
||||||
import { css } from 'emotion';
|
import { css } from 'emotion';
|
||||||
|
import { getConfig } from 'app/core/config';
|
||||||
|
|
||||||
export const UserSignup: FC<{}> = () => {
|
export const UserSignup: FC<{}> = () => {
|
||||||
|
const href = getConfig().verifyEmailEnabled ? `${getConfig().appSubUrl}/verify` : `${getConfig().appSubUrl}/signup`;
|
||||||
return (
|
return (
|
||||||
<VerticalGroup
|
<VerticalGroup
|
||||||
className={css`
|
className={css`
|
||||||
@ -15,7 +17,7 @@ export const UserSignup: FC<{}> = () => {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
`}
|
`}
|
||||||
href="signup"
|
href={href}
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
>
|
>
|
||||||
Sign Up
|
Sign Up
|
||||||
|
126
public/app/core/components/Signup/Signup.tsx
Normal file
126
public/app/core/components/Signup/Signup.tsx
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
import React, { FC } from 'react';
|
||||||
|
import { connect, MapStateToProps } from 'react-redux';
|
||||||
|
import { StoreState } from 'app/types';
|
||||||
|
import { Form, Field, Input, Button, HorizontalGroup, LinkButton } from '@grafana/ui';
|
||||||
|
import { getConfig } from 'app/core/config';
|
||||||
|
import { getBackendSrv } from '@grafana/runtime';
|
||||||
|
import appEvents from 'app/core/app_events';
|
||||||
|
import { AppEvents } from '@grafana/data';
|
||||||
|
|
||||||
|
interface SignupDTO {
|
||||||
|
name: string;
|
||||||
|
email: string;
|
||||||
|
username: string;
|
||||||
|
orgName?: string;
|
||||||
|
password: string;
|
||||||
|
code: string;
|
||||||
|
confirm: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ConnectedProps {
|
||||||
|
email?: string;
|
||||||
|
code?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SignupUnconnected: FC<ConnectedProps> = props => {
|
||||||
|
const onSubmit = async (formData: SignupDTO) => {
|
||||||
|
if (formData.name === '') {
|
||||||
|
delete formData.name;
|
||||||
|
}
|
||||||
|
delete formData.confirm;
|
||||||
|
|
||||||
|
const response = await getBackendSrv()
|
||||||
|
.post('/api/user/signup/step2', {
|
||||||
|
email: formData.email,
|
||||||
|
code: formData.code,
|
||||||
|
username: formData.email,
|
||||||
|
orgName: formData.orgName,
|
||||||
|
password: formData.password,
|
||||||
|
name: formData.name,
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
const msg = err.data?.message || err;
|
||||||
|
appEvents.emit(AppEvents.alertWarning, [msg]);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.code === 'redirect-to-select-org') {
|
||||||
|
window.location.href = getConfig().appSubUrl + '/profile/select-org?signup=1';
|
||||||
|
}
|
||||||
|
window.location.href = getConfig().appSubUrl + '/';
|
||||||
|
};
|
||||||
|
|
||||||
|
const defaultValues = {
|
||||||
|
email: props.email,
|
||||||
|
code: props.code,
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Form defaultValues={defaultValues} onSubmit={onSubmit}>
|
||||||
|
{({ errors, register, getValues }) => (
|
||||||
|
<>
|
||||||
|
<Field label="Your name">
|
||||||
|
<Input name="name" placeholder="(optional)" ref={register} />
|
||||||
|
</Field>
|
||||||
|
<Field label="Email" invalid={!!errors.email} error={errors.email?.message}>
|
||||||
|
<Input
|
||||||
|
name="email"
|
||||||
|
type="email"
|
||||||
|
placeholder="Email"
|
||||||
|
ref={register({
|
||||||
|
required: 'Email is required',
|
||||||
|
pattern: {
|
||||||
|
value: /^\S+@\S+$/,
|
||||||
|
message: 'Email is invalid',
|
||||||
|
},
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
</Field>
|
||||||
|
{!getConfig().autoAssignOrg && (
|
||||||
|
<Field label="Org. name">
|
||||||
|
<Input name="orgName" placeholder="Org. name" ref={register} />
|
||||||
|
</Field>
|
||||||
|
)}
|
||||||
|
{getConfig().verifyEmailEnabled && (
|
||||||
|
<Field label="Email verification code (sent to your email)">
|
||||||
|
<Input name="code" ref={register} placeholder="Code" />
|
||||||
|
</Field>
|
||||||
|
)}
|
||||||
|
<Field label="Password" invalid={!!errors.password} error={errors?.password?.message}>
|
||||||
|
<Input
|
||||||
|
autoFocus
|
||||||
|
type="password"
|
||||||
|
name="password"
|
||||||
|
ref={register({
|
||||||
|
required: 'Password is required',
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
</Field>
|
||||||
|
<Field label="Confirm password" invalid={!!errors.confirm} error={errors?.confirm?.message}>
|
||||||
|
<Input
|
||||||
|
type="password"
|
||||||
|
name="confirm"
|
||||||
|
ref={register({
|
||||||
|
required: 'Confirmed password is required',
|
||||||
|
validate: v => v === getValues().password || 'Passwords must match!',
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
</Field>
|
||||||
|
|
||||||
|
<HorizontalGroup>
|
||||||
|
<Button type="submit">Submit</Button>
|
||||||
|
<LinkButton variant="link" href={getConfig().appSubUrl + '/login'}>
|
||||||
|
Back to login
|
||||||
|
</LinkButton>
|
||||||
|
</HorizontalGroup>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Form>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const mapStateToProps: MapStateToProps<ConnectedProps, {}, StoreState> = (state: StoreState) => ({
|
||||||
|
email: state.location.routeParams.email?.toString(),
|
||||||
|
code: state.location.routeParams.code?.toString(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const Signup = connect(mapStateToProps)(SignupUnconnected);
|
15
public/app/core/components/Signup/SignupPage.tsx
Normal file
15
public/app/core/components/Signup/SignupPage.tsx
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import React, { FC } from 'react';
|
||||||
|
import { LoginLayout, InnerBox } from '../Login/LoginLayout';
|
||||||
|
import { Signup } from './Signup';
|
||||||
|
|
||||||
|
export const SignupPage: FC = () => {
|
||||||
|
return (
|
||||||
|
<LoginLayout>
|
||||||
|
<InnerBox>
|
||||||
|
<Signup />
|
||||||
|
</InnerBox>
|
||||||
|
</LoginLayout>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SignupPage;
|
62
public/app/core/components/Signup/VerifyEmail.tsx
Normal file
62
public/app/core/components/Signup/VerifyEmail.tsx
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
import React, { FC, useState } from 'react';
|
||||||
|
import { Form, Field, Input, Button, Legend, Container, HorizontalGroup, LinkButton } from '@grafana/ui';
|
||||||
|
import { getConfig } from 'app/core/config';
|
||||||
|
import { getBackendSrv } from '@grafana/runtime';
|
||||||
|
import appEvents from 'app/core/app_events';
|
||||||
|
import { AppEvents } from '@grafana/data';
|
||||||
|
|
||||||
|
interface EmailDTO {
|
||||||
|
email: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const VerifyEmail: FC = () => {
|
||||||
|
const [emailSent, setEmailSent] = useState(false);
|
||||||
|
|
||||||
|
const onSubmit = (formModel: EmailDTO) => {
|
||||||
|
getBackendSrv()
|
||||||
|
.post('/api/user/signup', formModel)
|
||||||
|
.then(() => {
|
||||||
|
setEmailSent(true);
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
const msg = err.data?.message || err;
|
||||||
|
appEvents.emit(AppEvents.alertWarning, [msg]);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
if (emailSent) {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<p>An email with a verification link has been sent to the email address. You should receive it shortly.</p>
|
||||||
|
<Container margin="md" />
|
||||||
|
<LinkButton variant="primary" href={getConfig().appSubUrl + '/signup'}>
|
||||||
|
Complete Signup
|
||||||
|
</LinkButton>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Form onSubmit={onSubmit}>
|
||||||
|
{({ register, errors }) => (
|
||||||
|
<>
|
||||||
|
<Legend>Verify Email</Legend>
|
||||||
|
<Field
|
||||||
|
label="Email"
|
||||||
|
description="Enter your email address to get a verification link sent to you"
|
||||||
|
invalid={!!(errors as any).email}
|
||||||
|
error={(errors as any).email?.message}
|
||||||
|
>
|
||||||
|
<Input placeholder="Email" name="email" ref={register({ required: true })} />
|
||||||
|
</Field>
|
||||||
|
<HorizontalGroup>
|
||||||
|
<Button>Send verification email</Button>
|
||||||
|
<LinkButton variant="link" href={getConfig().appSubUrl + '/login'}>
|
||||||
|
Back to login
|
||||||
|
</LinkButton>
|
||||||
|
</HorizontalGroup>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Form>
|
||||||
|
);
|
||||||
|
};
|
22
public/app/core/components/Signup/VerifyEmailPage.tsx
Normal file
22
public/app/core/components/Signup/VerifyEmailPage.tsx
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import React, { FC } from 'react';
|
||||||
|
|
||||||
|
import { LoginLayout, InnerBox } from '../Login/LoginLayout';
|
||||||
|
import { VerifyEmail } from './VerifyEmail';
|
||||||
|
import { getConfig } from 'app/core/config';
|
||||||
|
|
||||||
|
export const VerifyEmailPage: FC = () => {
|
||||||
|
if (!getConfig().verifyEmailEnabled) {
|
||||||
|
window.location.href = getConfig().appSubUrl + '/signup';
|
||||||
|
return <></>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<LoginLayout>
|
||||||
|
<InnerBox>
|
||||||
|
<VerifyEmail />
|
||||||
|
</InnerBox>
|
||||||
|
</LoginLayout>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default VerifyEmailPage;
|
@ -1,18 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { shallow } from 'enzyme';
|
|
||||||
import { SignupForm } from './SignupForm';
|
|
||||||
|
|
||||||
describe('SignupForm', () => {
|
|
||||||
describe('With different values for verifyEmail and autoAssignOrg', () => {
|
|
||||||
it('should render input fields', () => {
|
|
||||||
const wrapper = shallow(<SignupForm verifyEmailEnabled={true} autoAssignOrg={false} />);
|
|
||||||
expect(wrapper.exists('Forms.Input[name="orgName"]'));
|
|
||||||
expect(wrapper.exists('Forms.Input[name="code"]'));
|
|
||||||
});
|
|
||||||
it('should not render input fields', () => {
|
|
||||||
const wrapper = shallow(<SignupForm verifyEmailEnabled={false} autoAssignOrg={true} />);
|
|
||||||
expect(wrapper.exists('Forms.Input[name="orgName"]')).toBeFalsy();
|
|
||||||
expect(wrapper.exists('Forms.Input[name="code"]')).toBeFalsy();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,114 +0,0 @@
|
|||||||
import React, { FC } from 'react';
|
|
||||||
import { Button, LinkButton, Input, Form, Field } from '@grafana/ui';
|
|
||||||
import { css } from 'emotion';
|
|
||||||
|
|
||||||
import { getConfig } from 'app/core/config';
|
|
||||||
import { getBackendSrv } from '@grafana/runtime';
|
|
||||||
|
|
||||||
interface SignupFormModel {
|
|
||||||
email: string;
|
|
||||||
username?: string;
|
|
||||||
password: string;
|
|
||||||
orgName: string;
|
|
||||||
code?: string;
|
|
||||||
name?: string;
|
|
||||||
}
|
|
||||||
interface Props {
|
|
||||||
email?: string;
|
|
||||||
orgName?: string;
|
|
||||||
username?: string;
|
|
||||||
code?: string;
|
|
||||||
name?: string;
|
|
||||||
verifyEmailEnabled?: boolean;
|
|
||||||
autoAssignOrg?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
const buttonSpacing = css`
|
|
||||||
margin-left: 15px;
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const SignupForm: FC<Props> = props => {
|
|
||||||
const verifyEmailEnabled = props.verifyEmailEnabled;
|
|
||||||
const autoAssignOrg = props.autoAssignOrg;
|
|
||||||
|
|
||||||
const onSubmit = async (formData: SignupFormModel) => {
|
|
||||||
if (formData.name === '') {
|
|
||||||
delete formData.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
const response = await getBackendSrv().post('/api/user/signup/step2', {
|
|
||||||
email: formData.email,
|
|
||||||
code: formData.code,
|
|
||||||
username: formData.email,
|
|
||||||
orgName: formData.orgName,
|
|
||||||
password: formData.password,
|
|
||||||
name: formData.name,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (response.code === 'redirect-to-select-org') {
|
|
||||||
window.location.href = getConfig().appSubUrl + '/profile/select-org?signup=1';
|
|
||||||
}
|
|
||||||
window.location.href = getConfig().appSubUrl + '/';
|
|
||||||
};
|
|
||||||
|
|
||||||
const defaultValues = {
|
|
||||||
orgName: props.orgName,
|
|
||||||
email: props.email,
|
|
||||||
username: props.email,
|
|
||||||
code: props.code,
|
|
||||||
name: props.name,
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Form defaultValues={defaultValues} onSubmit={onSubmit}>
|
|
||||||
{({ register, errors }) => {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{verifyEmailEnabled && (
|
|
||||||
<Field label="Email verification code (sent to your email)">
|
|
||||||
<Input name="code" ref={register} placeholder="Code" />
|
|
||||||
</Field>
|
|
||||||
)}
|
|
||||||
{!autoAssignOrg && (
|
|
||||||
<Field label="Org. name">
|
|
||||||
<Input name="orgName" placeholder="Org. name" ref={register} />
|
|
||||||
</Field>
|
|
||||||
)}
|
|
||||||
<Field label="Your name">
|
|
||||||
<Input name="name" placeholder="(optional)" ref={register} />
|
|
||||||
</Field>
|
|
||||||
<Field label="Email" invalid={!!errors.email} error={errors.email?.message}>
|
|
||||||
<Input
|
|
||||||
name="email"
|
|
||||||
type="email"
|
|
||||||
placeholder="Email"
|
|
||||||
ref={register({
|
|
||||||
required: 'Email is required',
|
|
||||||
pattern: {
|
|
||||||
value: /^\S+@\S+$/,
|
|
||||||
message: 'Email is invalid',
|
|
||||||
},
|
|
||||||
})}
|
|
||||||
/>
|
|
||||||
</Field>
|
|
||||||
<Field label="Password" invalid={!!errors.password} error={errors.password?.message}>
|
|
||||||
<Input
|
|
||||||
name="password"
|
|
||||||
type="password"
|
|
||||||
placeholder="Password"
|
|
||||||
ref={register({ required: 'Password is required' })}
|
|
||||||
/>
|
|
||||||
</Field>
|
|
||||||
|
|
||||||
<Button type="submit">Submit</Button>
|
|
||||||
<span className={buttonSpacing}>
|
|
||||||
<LinkButton href={getConfig().appSubUrl + '/login'} variant="secondary">
|
|
||||||
Back
|
|
||||||
</LinkButton>
|
|
||||||
</span>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
</Form>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,51 +0,0 @@
|
|||||||
import React, { FC } from 'react';
|
|
||||||
import { SignupForm } from './SignupForm';
|
|
||||||
import Page from 'app/core/components/Page/Page';
|
|
||||||
import { getConfig } from 'app/core/config';
|
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import { hot } from 'react-hot-loader';
|
|
||||||
import { StoreState } from 'app/types';
|
|
||||||
|
|
||||||
const navModel = {
|
|
||||||
main: {
|
|
||||||
icon: 'grafana',
|
|
||||||
text: 'Sign Up',
|
|
||||||
subTitle: 'Register your Grafana account',
|
|
||||||
breadcrumbs: [{ title: 'Login', url: 'login' }],
|
|
||||||
},
|
|
||||||
node: {
|
|
||||||
text: '',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
interface Props {
|
|
||||||
email?: string;
|
|
||||||
orgName?: string;
|
|
||||||
username?: string;
|
|
||||||
code?: string;
|
|
||||||
name?: string;
|
|
||||||
}
|
|
||||||
export const SignupPage: FC<Props> = props => {
|
|
||||||
return (
|
|
||||||
<Page navModel={navModel}>
|
|
||||||
<Page.Contents>
|
|
||||||
<h3 className="p-b-1">You're almost there.</h3>
|
|
||||||
<div className="p-b-1">
|
|
||||||
We just need a couple of more bits of
|
|
||||||
<br /> information to finish creating your account.
|
|
||||||
</div>
|
|
||||||
<SignupForm
|
|
||||||
{...props}
|
|
||||||
verifyEmailEnabled={getConfig().verifyEmailEnabled}
|
|
||||||
autoAssignOrg={getConfig().autoAssignOrg}
|
|
||||||
/>
|
|
||||||
</Page.Contents>
|
|
||||||
</Page>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const mapStateToProps = (state: StoreState) => ({
|
|
||||||
...state.location.routeParams,
|
|
||||||
});
|
|
||||||
|
|
||||||
export default hot(module)(connect(mapStateToProps)(SignupPage));
|
|
@ -4,7 +4,6 @@ import { applyRouteRegistrationHandlers } from './registry';
|
|||||||
// Pages
|
// Pages
|
||||||
import LdapPage from 'app/features/admin/ldap/LdapPage';
|
import LdapPage from 'app/features/admin/ldap/LdapPage';
|
||||||
import UserAdminPage from 'app/features/admin/UserAdminPage';
|
import UserAdminPage from 'app/features/admin/UserAdminPage';
|
||||||
import SignupPage from 'app/features/profile/SignupPage';
|
|
||||||
import { LoginPage } from 'app/core/components/Login/LoginPage';
|
import { LoginPage } from 'app/core/components/Login/LoginPage';
|
||||||
|
|
||||||
import config from 'app/core/config';
|
import config from 'app/core/config';
|
||||||
@ -436,13 +435,25 @@ export function setupAngularRoutes($routeProvider: route.IRouteProvider, $locati
|
|||||||
SafeDynamicImport(import(/* webpackChunkName: "SignupInvited" */ 'app/features/users/SignupInvited')),
|
SafeDynamicImport(import(/* webpackChunkName: "SignupInvited" */ 'app/features/users/SignupInvited')),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.when('/signup', {
|
.when('/verify', {
|
||||||
template: '<react-container/>',
|
template: '<react-container />',
|
||||||
//@ts-ignore
|
|
||||||
pageClass: 'sidemenu-hidden',
|
|
||||||
resolve: {
|
resolve: {
|
||||||
component: () => SignupPage,
|
component: () =>
|
||||||
|
SafeDynamicImport(
|
||||||
|
import(/* webpackChunkName: "VerifyEmailPage" */ 'app/core/components/Signup/VerifyEmailPage')
|
||||||
|
),
|
||||||
},
|
},
|
||||||
|
// @ts-ignore
|
||||||
|
pageClass: 'login-page sidemenu-hidden',
|
||||||
|
})
|
||||||
|
.when('/signup', {
|
||||||
|
template: '<react-container />',
|
||||||
|
resolve: {
|
||||||
|
component: () =>
|
||||||
|
SafeDynamicImport(import(/* webpackChunkName: "SignupPage" */ 'app/core/components/Signup/SignupPage')),
|
||||||
|
},
|
||||||
|
// @ts-ignore
|
||||||
|
pageClass: 'login-page sidemenu-hidden',
|
||||||
})
|
})
|
||||||
.when('/user/password/send-reset-email', {
|
.when('/user/password/send-reset-email', {
|
||||||
template: '<react-container />',
|
template: '<react-container />',
|
||||||
|
Reference in New Issue
Block a user