From 0c4dae321c7029d42e186badb4cd51278a2666f0 Mon Sep 17 00:00:00 2001 From: Tobias Skarhed <1438972+tskarhed@users.noreply.github.com> Date: Mon, 17 Feb 2020 11:13:13 +0100 Subject: [PATCH] Migrations: Signup page (#21514) * Start Angular migration * Add SignupCtrl * Change name signup * Add backend call * Put form in separate file * Add form model * Start using react-hook-forms * Add FormModel to state * Reduxify * Connect nav with Redux * Fix routing and navModel * Fetch state options on mount * Add default values and add button margin * Add errror messages * Fix title * Remove files and cleanup * Add Signup tests * Add boot config assingnAutoOrg and verifyEmailEnabled * Remove onmount call * Remove ctrl and move everything to SignupForm * Make routeParams optional for testing * Remove name if it is empty * Set username * Make function component * Fix subpath issues and add link button * Move redux to SignupPage --- package.json | 1 + packages/grafana-runtime/src/config.ts | 2 + pkg/api/frontendsettings.go | 2 + .../app/features/profile/SignupForm.test.tsx | 18 +++ public/app/features/profile/SignupForm.tsx | 120 ++++++++++++++++++ public/app/features/profile/SignupPage.tsx | 51 ++++++++ public/app/partials/signup_step2.html | 47 ------- public/app/routes/routes.ts | 8 +- public/test/jest-setup.ts | 1 + yarn.lock | 5 + 10 files changed, 206 insertions(+), 49 deletions(-) create mode 100644 public/app/features/profile/SignupForm.test.tsx create mode 100644 public/app/features/profile/SignupForm.tsx create mode 100644 public/app/features/profile/SignupPage.tsx delete mode 100644 public/app/partials/signup_step2.html diff --git a/package.json b/package.json index bc0216b1bc6..ea1eaa2bbd6 100644 --- a/package.json +++ b/package.json @@ -115,6 +115,7 @@ "mocha": "7.0.1", "module-alias": "2.2.0", "monaco-editor": "0.15.6", + "mutationobserver-shim": "0.3.3", "ngtemplate-loader": "2.0.1", "node-sass": "4.13.1", "npm": "6.13.4", diff --git a/packages/grafana-runtime/src/config.ts b/packages/grafana-runtime/src/config.ts index 9d273ad8e0f..f5b95c43a96 100644 --- a/packages/grafana-runtime/src/config.ts +++ b/packages/grafana-runtime/src/config.ts @@ -49,6 +49,8 @@ export class GrafanaBootConfig { exploreEnabled = false; ldapEnabled = false; samlEnabled = false; + autoAssignOrg = true; + verifyEmailEnabled = false; oauth: any; disableUserSignUp = false; loginHint: any; diff --git a/pkg/api/frontendsettings.go b/pkg/api/frontendsettings.go index e515abb1a60..f75c4790439 100644 --- a/pkg/api/frontendsettings.go +++ b/pkg/api/frontendsettings.go @@ -179,6 +179,8 @@ func (hs *HTTPServer) getFrontendSettingsMap(c *m.ReqContext) (map[string]interf "alertingErrorOrTimeout": setting.AlertingErrorOrTimeout, "alertingNoDataOrNullValues": setting.AlertingNoDataOrNullValues, "alertingMinInterval": setting.AlertingMinInterval, + "autoAssignOrg": setting.AutoAssignOrg, + "verfiyEmailEnabled": setting.VerifyEmailEnabled, "exploreEnabled": setting.ExploreEnabled, "googleAnalyticsId": setting.GoogleAnalyticsId, "disableLoginForm": setting.DisableLoginForm, diff --git a/public/app/features/profile/SignupForm.test.tsx b/public/app/features/profile/SignupForm.test.tsx new file mode 100644 index 00000000000..4c3822b7147 --- /dev/null +++ b/public/app/features/profile/SignupForm.test.tsx @@ -0,0 +1,18 @@ +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(); + expect(wrapper.exists('Forms.Input[name="orgName"]')); + expect(wrapper.exists('Forms.Input[name="code"]')); + }); + it('should not render input fields', () => { + const wrapper = shallow(); + expect(wrapper.exists('Forms.Input[name="orgName"]')).toBeFalsy(); + expect(wrapper.exists('Forms.Input[name="code"]')).toBeFalsy(); + }); + }); +}); diff --git a/public/app/features/profile/SignupForm.tsx b/public/app/features/profile/SignupForm.tsx new file mode 100644 index 00000000000..94a73836c32 --- /dev/null +++ b/public/app/features/profile/SignupForm.tsx @@ -0,0 +1,120 @@ +import React, { FC } from 'react'; +import { Forms } 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 => { + 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 ( + + {({ register, errors }) => { + return ( + <> + {verifyEmailEnabled && ( + + + + )} + {!autoAssignOrg && ( + + + + )} + + + + + + + + + + + Submit + + + Back + + + + ); + }} + + ); +}; diff --git a/public/app/features/profile/SignupPage.tsx b/public/app/features/profile/SignupPage.tsx new file mode 100644 index 00000000000..a5dad9c29a9 --- /dev/null +++ b/public/app/features/profile/SignupPage.tsx @@ -0,0 +1,51 @@ +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: 'gicon gicon-branding', + 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 => { + return ( + + +

You're almost there.

+
+ We just need a couple of more bits of +
information to finish creating your account. +
+ +
+
+ ); +}; + +const mapStateToProps = (state: StoreState) => ({ + ...state.location.routeParams, +}); + +export default hot(module)(connect(mapStateToProps)(SignupPage)); diff --git a/public/app/partials/signup_step2.html b/public/app/partials/signup_step2.html deleted file mode 100644 index e63f882fdde..00000000000 --- a/public/app/partials/signup_step2.html +++ /dev/null @@ -1,47 +0,0 @@ - - -
- -
- -