From 768911a6f94307b56fb8a1d50eb11eccc8f888da Mon Sep 17 00:00:00 2001 From: Tobias Skarhed <1438972+tskarhed@users.noreply.github.com> Date: Fri, 28 Feb 2020 15:45:00 +0100 Subject: [PATCH] Migration: Invite Signup (#22437) * Inital commit with new page * Make routing work * Correct field * Move submit button and fix routing after signup * Remove comments * Fix feedback * Undo mistake --- public/app/features/users/SignupInvited.tsx | 135 ++++++++++++++++++++ public/app/routes/routes.ts | 7 +- 2 files changed, 140 insertions(+), 2 deletions(-) create mode 100644 public/app/features/users/SignupInvited.tsx diff --git a/public/app/features/users/SignupInvited.tsx b/public/app/features/users/SignupInvited.tsx new file mode 100644 index 00000000000..2eeb88e45c8 --- /dev/null +++ b/public/app/features/users/SignupInvited.tsx @@ -0,0 +1,135 @@ +import React, { FC, useState } from 'react'; +import { hot } from 'react-hot-loader'; +import { connect, MapStateToProps, MapDispatchToProps } from 'react-redux'; +import { StoreState } from 'app/types'; +import { updateLocation } from 'app/core/actions'; +import { UrlQueryValue, getBackendSrv } from '@grafana/runtime'; +import { Forms } from '@grafana/ui'; +import { useAsync } from 'react-use'; +import Page from 'app/core/components/Page/Page'; +import { contextSrv } from 'app/core/core'; +import { getConfig } from 'app/core/config'; + +interface ConnectedProps { + code?: UrlQueryValue; +} + +interface DispatchProps { + updateLocation: typeof updateLocation; +} + +interface FormModel { + email: string; + name?: string; + username: string; + password?: string; +} + +const navModel = { + main: { + icon: 'gicon gicon-branding', + text: 'Invite', + subTitle: 'Register your Grafana account', + breadcrumbs: [{ title: 'Login', url: 'login' }], + }, + node: { + text: '', + }, +}; + +const SingupInvitedPageUnconnected: FC = ({ code }) => { + const [initFormModel, setInitFormModel] = useState(); + const [greeting, setGreeting] = useState(); + const [invitedBy, setInvitedBy] = useState(); + useAsync(async () => { + const invite = await getBackendSrv().get('/api/user/invite/' + code); + setInitFormModel({ + email: invite.email, + name: invite.name, + username: invite.email, + }); + + setGreeting(invite.name || invite.email || invite.username); + setInvitedBy(invite.invitedBy); + }, []); + + const onSubmit = async (formData: FormModel) => { + await getBackendSrv().post('/api/user/invite/complete', { ...formData, inviteCode: code }); + window.location.href = getConfig().appSubUrl + '/'; + }; + + return ( + + +

Hello {greeting || 'there'}.

+ +
+ {invitedBy || 'Someone'} has invited you to join Grafana and the organization{' '} + {contextSrv.user.orgName} +
+ Please complete the following and choose a password to accept your invitation and continue: +
+ + {({ register, errors }) => ( + <> + + + + + + + + + + + + + + Sign Up + + )} + +
+
+ ); +}; + +const mapStateToProps: MapStateToProps = (state: StoreState) => ({ + code: state.location.routeParams.code, +}); + +const mapDispatchToProps: MapDispatchToProps = { + updateLocation, +}; + +export default hot(module)(connect(mapStateToProps, mapDispatchToProps)(SingupInvitedPageUnconnected)); diff --git a/public/app/routes/routes.ts b/public/app/routes/routes.ts index 6e6b7727b72..79fed580568 100644 --- a/public/app/routes/routes.ts +++ b/public/app/routes/routes.ts @@ -350,9 +350,12 @@ export function setupAngularRoutes($routeProvider: route.IRouteProvider, $locati pageClass: 'login-page sidemenu-hidden', }) .when('/invite/:code', { - templateUrl: 'public/app/partials/signup_invited.html', - controller: 'InvitedCtrl', + template: '', pageClass: 'sidemenu-hidden', + resolve: { + component: () => + SafeDynamicImport(import(/* webpackChunkName: "SignupInvited" */ 'app/features/users/SignupInvited')), + }, }) .when('/signup', { template: '',