diff --git a/catalog-rest-service/src/main/resources/ui/src/@types/jpeg.d.ts b/catalog-rest-service/src/main/resources/ui/src/@types/jpeg.d.ts new file mode 100644 index 00000000000..30469029fdd --- /dev/null +++ b/catalog-rest-service/src/main/resources/ui/src/@types/jpeg.d.ts @@ -0,0 +1,19 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +// Module declaration to allow importing JPEG files +declare module '*.jpeg'; diff --git a/catalog-rest-service/src/main/resources/ui/src/assets/img/confetti-bg.jpeg b/catalog-rest-service/src/main/resources/ui/src/assets/img/confetti-bg.jpeg new file mode 100644 index 00000000000..fce092ad36a Binary files /dev/null and b/catalog-rest-service/src/main/resources/ui/src/assets/img/confetti-bg.jpeg differ diff --git a/catalog-rest-service/src/main/resources/ui/src/auth-provider/AuthProvider.tsx b/catalog-rest-service/src/main/resources/ui/src/auth-provider/AuthProvider.tsx index 320c3a33e5a..5b0eef45955 100644 --- a/catalog-rest-service/src/main/resources/ui/src/auth-provider/AuthProvider.tsx +++ b/catalog-rest-service/src/main/resources/ui/src/auth-provider/AuthProvider.tsx @@ -19,7 +19,7 @@ import { AxiosResponse } from 'axios'; import { CookieStorage } from 'cookie-storage'; import { isEmpty, isNil } from 'lodash'; import { observer } from 'mobx-react'; -import { User } from 'Models'; +import { NewUser, User } from 'Models'; import { UserManager, WebStorageStateStore } from 'oidc-client'; import React, { ComponentType, @@ -28,7 +28,13 @@ import React, { useState, } from 'react'; import { Callback, makeAuthenticator, makeUserManager } from 'react-oidc'; -import { Redirect, Route, Switch, useHistory } from 'react-router-dom'; +import { + Redirect, + Route, + Switch, + useHistory, + useLocation, +} from 'react-router-dom'; import appState from '../AppState'; import axiosClient from '../axiosAPIs'; import { fetchAuthorizerConfig } from '../axiosAPIs/miscAPI'; @@ -38,6 +44,7 @@ import { getUserByName, getUsers, } from '../axiosAPIs/userAPI'; +import { FirstTimeUserModal } from '../components/Modals/FirstTimeUserModal/FirstTimeUserModal'; import { API_RES_MAX_SIZE, oidcTokenKey, @@ -72,9 +79,16 @@ const AuthProvider: FunctionComponent = ({ childComponentType, children, }: AuthProviderProps) => { + const location = useLocation(); const history = useHistory(); const showToast = useToastContext(); - const { isSignedIn, isSigningIn, isSignedOut } = useAuth(); + const { + isAuthenticatedRoute, + isFirstTimeUser, + isSignedIn, + isSigningIn, + isSignedOut, + } = useAuth(location.pathname); const oidcUserToken = cookieStorage.getItem(oidcTokenKey); const [loading, setLoading] = useState(true); @@ -82,11 +96,11 @@ const AuthProvider: FunctionComponent = ({ {} as UserManager ); const [userManagerConfig, setUserManagerConfig] = useState< - Record + Record >({}); const clearOidcUserData = ( - userConfig: Record + userConfig: Record ): void => { cookieStorage.removeItem( `oidc.user:${userConfig.authority}:${userConfig.client_id}` @@ -198,6 +212,15 @@ const AuthProvider: FunctionComponent = ({ }); }; + const handleFirstTourModal = (skip: boolean) => { + appState.newUser = {} as NewUser; + if (skip) { + history.push(ROUTES.HOME); + } else { + // TODO: Route to tour page + } + }; + useEffect(() => { fetchAuthConfig(); @@ -241,39 +264,47 @@ const AuthProvider: FunctionComponent = ({ return ( <> {!loading ? ( - - - {!isSignedIn && !isSigningIn ? ( - + <> + + + {!isSignedIn && !isSigningIn ? ( + + ) : ( + + )} + + + {!isSigningIn ? ( + + ) : null} + ( + { + cookieStorage.setItem(oidcTokenKey, user.id_token, { + expires: getOidcExpiry(), + }); + fetchUserByEmail(user as OidcUser); + }} + /> + )} + /> + {isSignedOut ? : null} + {oidcUserToken || !userManagerConfig?.client_id ? ( + children ) : ( - + )} - - - {!isSigningIn ? ( - + + {isAuthenticatedRoute && isFirstTimeUser ? ( + handleFirstTourModal(true)} + onSave={() => handleFirstTourModal(false)} + /> ) : null} - ( - { - cookieStorage.setItem(oidcTokenKey, user.id_token, { - expires: getOidcExpiry(), - }); - fetchUserByEmail(user as OidcUser); - }} - /> - )} - /> - {isSignedOut ? : null} - {oidcUserToken || !userManagerConfig?.client_id ? ( - children - ) : ( - - )} - + ) : null} ); diff --git a/catalog-rest-service/src/main/resources/ui/src/components/Modals/FirstTimeUserModal/FirstTimeUserModal.tsx b/catalog-rest-service/src/main/resources/ui/src/components/Modals/FirstTimeUserModal/FirstTimeUserModal.tsx index 2ddb8420000..4df02e0802d 100644 --- a/catalog-rest-service/src/main/resources/ui/src/components/Modals/FirstTimeUserModal/FirstTimeUserModal.tsx +++ b/catalog-rest-service/src/main/resources/ui/src/components/Modals/FirstTimeUserModal/FirstTimeUserModal.tsx @@ -1,5 +1,6 @@ import classNames from 'classnames'; import React, { FunctionComponent, useState } from 'react'; +import BGConfetti from '../../../assets/img/confetti-bg.jpeg'; import { Button } from '../../buttons/Button/Button'; type Props = { @@ -15,48 +16,44 @@ const description = [ export const FirstTimeUserModal: FunctionComponent = ({ onCancel, + onSave, }: Props) => { const [active, setActive] = useState(0); const [lastSlide, setLastSlide] = useState(false); const previousClick = () => { - if (lastSlide) { - // to somthing - } else { - setActive((pre) => pre - 1); - } + setActive((pre) => pre - 1); + setLastSlide(false); }; const nextClick = () => { - if (lastSlide) { - onCancel(); - } else { - setActive((pre) => { - const newVal = pre + 1; - description.length - 1 === newVal && setLastSlide(true); + setActive((pre) => { + const newVal = pre + 1; + setLastSlide(description.length - 1 === newVal); - return newVal; - }); - } + return newVal; + }); }; return (
-
-
-

+

+
+

Welcome to OpenMetadata

-
+
{description.map((d, i) => (

{d} @@ -66,38 +63,48 @@ export const FirstTimeUserModal: FunctionComponent = ({

- - + {lastSlide ? ( + + + + + ) : ( + + )}
diff --git a/catalog-rest-service/src/main/resources/ui/src/hooks/authHooks.ts b/catalog-rest-service/src/main/resources/ui/src/hooks/authHooks.ts index bea2e0e2bd0..178e541557a 100644 --- a/catalog-rest-service/src/main/resources/ui/src/hooks/authHooks.ts +++ b/catalog-rest-service/src/main/resources/ui/src/hooks/authHooks.ts @@ -38,5 +38,6 @@ export const useAuth = (pathname = '') => { isAuthenticatedRoute: isAuthenticatedRoute, isAuthDisabled: authDisabled, isAdminUser: userDetails?.isAdmin, + isFirstTimeUser: !isEmpty(userDetails) && !isEmpty(newUser), }; }; diff --git a/catalog-rest-service/src/main/resources/ui/src/pages/login/index.tsx b/catalog-rest-service/src/main/resources/ui/src/pages/login/index.tsx index 084e76c7359..247ea0f2fa4 100644 --- a/catalog-rest-service/src/main/resources/ui/src/pages/login/index.tsx +++ b/catalog-rest-service/src/main/resources/ui/src/pages/login/index.tsx @@ -40,7 +40,7 @@ const SigninPage = () => {
-
+
{
Centralized Metadata Store, Discover,
Collaborate and get your Data Right
-
+
{appState.authProvider.provider === AuthTypes.GOOGLE && (