diff --git a/CHANGELOG.md b/CHANGELOG.md index 412cdfa8ef..459347f953 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ 1. [17095](https://github.com/influxdata/influxdb/pull/17095): Extend pkger dashboards with table view support 1. [17114](https://github.com/influxdata/influxdb/pull/17114): Allow for retention to be provided to influx setup command as a duration 1. [17138](https://github.com/influxdata/influxdb/pull/17138): Extend pkger export all capabilities to support filtering by lable name and resource type +1. [17049](https://github.com/influxdata/influxdb/pull/17049): Added new login and sign-up screen that for cloud users that allows direct login from their region ### Bug Fixes @@ -19,6 +20,7 @@ 1. [17113](https://github.com/influxdata/influxdb/pull/17113): Disabled group functionality for check query builder 1. [17120](https://github.com/influxdata/influxdb/pull/17120): Fixed cell configuration error that was popping up when users create a dashboard and accessed the disk usage cell for the first time 1. [17097](https://github.com/influxdata/influxdb/pull/17097): Listing all the default variables in the VariableTab of the script editor +1. [17049](https://github.com/influxdata/influxdb/pull/17049): Fixed bug that was preventing the interval status on the dashboard header from refreshing on selections ## v2.0.0-beta.5 [2020-02-27] diff --git a/ui/package.json b/ui/package.json index ab69b90e12..661e3de733 100644 --- a/ui/package.json +++ b/ui/package.json @@ -137,6 +137,7 @@ "@influxdata/influxdb-templates": "0.9.0", "@influxdata/react-custom-scrollbars": "4.3.8", "abortcontroller-polyfill": "^1.3.0", + "auth0-js": "^9.12.2", "axios": "^0.19.0", "babel-polyfill": "^6.26.0", "bignumber.js": "^4.0.2", @@ -157,8 +158,8 @@ "moment": "^2.13.0", "monaco-editor": "^0.19.2", "monaco-editor-textmate": "^2.2.1", - "monaco-languageclient": "^0.11.0", "monaco-editor-webpack-plugin": "^1.8.2", + "monaco-languageclient": "^0.11.0", "monaco-textmate": "^3.0.1", "normalizr": "^3.4.1", "onigasm": "^2.2.4", @@ -181,6 +182,7 @@ "react-router": "^3.0.2", "react-router-redux": "^4.0.8", "react-scrollbars-custom": "^4.0.0-alpha.8", + "react-spring": "^8.0.27", "react-virtualized": "^9.18.5", "redux": "^4.0.0", "redux-auth-wrapper": "^1.0.0", diff --git a/ui/src/Logout.tsx b/ui/src/Logout.tsx index 0c0bb5fe59..1605b10cac 100644 --- a/ui/src/Logout.tsx +++ b/ui/src/Logout.tsx @@ -1,9 +1,11 @@ // Libraries -import {PureComponent} from 'react' +import {FC, useEffect} from 'react' import {withRouter, WithRouterProps} from 'react-router' +import auth0js from 'auth0-js' // APIs import {postSignout} from 'src/client' +import {getAuth0Config} from 'src/authorizations/apis' // Constants import {CLOUD, CLOUD_URL, CLOUD_LOGOUT_PATH} from 'src/shared/constants' @@ -11,19 +13,20 @@ import {CLOUD, CLOUD_URL, CLOUD_LOGOUT_PATH} from 'src/shared/constants' // Components import {ErrorHandling} from 'src/shared/decorators/errors' -type Props = WithRouterProps +// Utils +import {isFlagEnabled} from 'src/shared/utils/featureFlag' -@ErrorHandling -export class Logout extends PureComponent { - public componentDidMount() { - this.handleSignOut() - } - - public render() { - return null - } - - private handleSignOut = async () => { +const Logout: FC = ({router}) => { + const handleSignOut = async () => { + if (CLOUD && isFlagEnabled('regionBasedLoginPage')) { + const config = await getAuth0Config() + const auth0 = new auth0js.WebAuth({ + domain: config.domain, + clientID: config.clientID, + }) + auth0.logout({}) + return + } if (CLOUD) { window.location.href = `${CLOUD_URL}${CLOUD_LOGOUT_PATH}` return @@ -34,9 +37,14 @@ export class Logout extends PureComponent { throw new Error(resp.data.message) } - this.props.router.push(`/signin`) + router.push(`/signin`) } } + + useEffect(() => { + handleSignOut() + }, []) + return null } -export default withRouter(Logout) +export default ErrorHandling(withRouter(Logout)) diff --git a/ui/src/Signin.tsx b/ui/src/Signin.tsx index c5e54f582c..e8c71b6af3 100644 --- a/ui/src/Signin.tsx +++ b/ui/src/Signin.tsx @@ -19,6 +19,9 @@ import {CLOUD, CLOUD_SIGNIN_PATHNAME} from 'src/shared/constants' // Types import {RemoteDataState} from 'src/types' +// Utils +import {isFlagEnabled} from 'src/shared/utils/featureFlag' + interface State { loading: RemoteDataState } @@ -81,6 +84,11 @@ export class Signin extends PureComponent { clearInterval(this.intervalID) + if (CLOUD && isFlagEnabled('regionBasedLoginPage')) { + this.props.router.replace('/login') + return + } + // TODO: add returnTo to CLOUD signin if (CLOUD) { window.location.pathname = CLOUD_SIGNIN_PATHNAME diff --git a/ui/src/authorizations/apis/index.ts b/ui/src/authorizations/apis/index.ts index fff18cf9fd..3154f43bf6 100644 --- a/ui/src/authorizations/apis/index.ts +++ b/ui/src/authorizations/apis/index.ts @@ -1,5 +1,5 @@ import AJAX from 'src/utils/ajax' -import {Authorization} from 'src/types' +import {Authorization, Auth0Config} from 'src/types' export const createAuthorization = async ( authorization @@ -17,3 +17,14 @@ export const createAuthorization = async ( throw error } } + +export const getAuth0Config = async (): Promise => { + try { + const response = await fetch('/api/v2private/oauth/clientConfig') + const data = await response.json() + return data + } catch (error) { + console.error(error) + throw error + } +} diff --git a/ui/src/clientLibraries/graphics/GithubLogo.tsx b/ui/src/clientLibraries/graphics/GithubLogo.tsx new file mode 100644 index 0000000000..09d7850df3 --- /dev/null +++ b/ui/src/clientLibraries/graphics/GithubLogo.tsx @@ -0,0 +1,18 @@ +// Libraries +import React, {FC} from 'react' +import classnames from 'classnames' + +interface Props { + className?: string +} + +export const GithubLogo: FC = ({className}) => ( + + GitHub icon + + +) diff --git a/ui/src/clientLibraries/graphics/GoogleLogo.tsx b/ui/src/clientLibraries/graphics/GoogleLogo.tsx new file mode 100644 index 0000000000..a142917baa --- /dev/null +++ b/ui/src/clientLibraries/graphics/GoogleLogo.tsx @@ -0,0 +1,33 @@ +// Libraries +import React, {FC} from 'react' +import classnames from 'classnames' + +interface Props { + className?: string +} + +export const GoogleLogo: FC = ({className}) => ( + + + + + + +) diff --git a/ui/src/clientLibraries/graphics/index.ts b/ui/src/clientLibraries/graphics/index.ts new file mode 100644 index 0000000000..4573b909dc --- /dev/null +++ b/ui/src/clientLibraries/graphics/index.ts @@ -0,0 +1,19 @@ +import CSharpLogo from 'src/clientLibraries/graphics/CSharpLogo' +import {GithubLogo} from 'src/clientLibraries/graphics/GithubLogo' +import GoLogo from 'src/clientLibraries/graphics/GoLogo' +import {GoogleLogo} from 'src/clientLibraries/graphics/GoogleLogo' +import JavaLogo from 'src/clientLibraries/graphics/JavaLogo' +import JSLogo from 'src/clientLibraries/graphics/JSLogo' +import PythonLogo from 'src/clientLibraries/graphics/PythonLogo' +import RubyLogo from 'src/clientLibraries/graphics/RubyLogo' + +export { + CSharpLogo, + GithubLogo, + GoLogo, + GoogleLogo, + JavaLogo, + JSLogo, + PythonLogo, + RubyLogo, +} diff --git a/ui/src/index.tsx b/ui/src/index.tsx index 30a58ed391..e41d6a5403 100644 --- a/ui/src/index.tsx +++ b/ui/src/index.tsx @@ -20,6 +20,7 @@ import GetOrganizations from 'src/shared/containers/GetOrganizations' import Setup from 'src/Setup' import Signin from 'src/Signin' import SigninPage from 'src/onboarding/containers/SigninPage' +import {LoginPage} from 'src/onboarding/containers/LoginPage' import Logout from 'src/Logout' import TaskPage from 'src/tasks/containers/TaskPage' import TasksPage from 'src/tasks/containers/TasksPage' @@ -191,6 +192,7 @@ class Root extends PureComponent { component={OnboardingWizardPage} /> + diff --git a/ui/src/onboarding/components/LoginForm.tsx b/ui/src/onboarding/components/LoginForm.tsx new file mode 100644 index 0000000000..a197e6c653 --- /dev/null +++ b/ui/src/onboarding/components/LoginForm.tsx @@ -0,0 +1,104 @@ +// Libraries +import React, {FC, useState, ChangeEvent} from 'react' +import { + Button, + ButtonShape, + ButtonType, + Columns, + ComponentColor, + ComponentSize, + ComponentStatus, + Form, + Grid, + Input, + InputType, + VisibilityInput, +} from '@influxdata/clockface' + +// Types +import {FormFieldValidation} from 'src/types' + +interface Props { + buttonStatus: ComponentStatus + emailValidation: FormFieldValidation + email: string + passwordValidation: FormFieldValidation + password: string + handleInputChange: (event: ChangeEvent) => void + handleForgotPasswordClick: () => void +} + +export const LoginForm: FC = ({ + buttonStatus, + emailValidation, + email, + passwordValidation, + password, + handleInputChange, + handleForgotPasswordClick, +}) => { + const [isVisible, toggleVisibility] = useState(false) + return ( + <> + + + + + + + + + + + + toggleVisibility(!isVisible)} + /> + + + + + + Forgot Password? + +