From b269e7a6aa91a98142d9a2b9f9b0a9bf424904a9 Mon Sep 17 00:00:00 2001 From: darth-coder00 <86726556+darth-coder00@users.noreply.github.com> Date: Thu, 12 Aug 2021 21:13:59 +0530 Subject: [PATCH] Updated landing page with stats data (#110) * Updated landing page * Minor change --- .../ui/src/assets/svg/data-assets.svg | 4 + .../resources/ui/src/assets/svg/service.svg | 4 + .../resources/ui/src/assets/svg/terms.svg | 3 + .../main/resources/ui/src/assets/svg/user.svg | 4 + .../ui/src/auth-provider/AuthProvider.tsx | 9 +- .../resources/ui/src/axiosAPIs/userAPI.ts | 9 +- .../AddServiceModal/AddServiceModal.tsx | 8 +- .../src/components/my-data/MyDataHeader.tsx | 105 ++++++++++++++++++ .../resources/ui/src/constants/constants.ts | 1 + .../resources/ui/src/interface/types.d.ts | 13 +++ .../resources/ui/src/pages/my-data/index.tsx | 18 ++- .../resources/ui/src/pages/services/index.tsx | 18 +-- .../resources/ui/src/pages/tags/index.tsx | 4 +- .../resources/ui/src/utils/ServiceUtils.ts | 67 ++++++++++- .../main/resources/ui/src/utils/SvgUtils.tsx | 24 ++++ 15 files changed, 264 insertions(+), 27 deletions(-) create mode 100644 catalog-rest-service/src/main/resources/ui/src/assets/svg/data-assets.svg create mode 100644 catalog-rest-service/src/main/resources/ui/src/assets/svg/service.svg create mode 100644 catalog-rest-service/src/main/resources/ui/src/assets/svg/terms.svg create mode 100644 catalog-rest-service/src/main/resources/ui/src/assets/svg/user.svg create mode 100644 catalog-rest-service/src/main/resources/ui/src/components/my-data/MyDataHeader.tsx diff --git a/catalog-rest-service/src/main/resources/ui/src/assets/svg/data-assets.svg b/catalog-rest-service/src/main/resources/ui/src/assets/svg/data-assets.svg new file mode 100644 index 00000000000..d8ff11ec64f --- /dev/null +++ b/catalog-rest-service/src/main/resources/ui/src/assets/svg/data-assets.svg @@ -0,0 +1,4 @@ + + + + diff --git a/catalog-rest-service/src/main/resources/ui/src/assets/svg/service.svg b/catalog-rest-service/src/main/resources/ui/src/assets/svg/service.svg new file mode 100644 index 00000000000..8cb3fc6cff6 --- /dev/null +++ b/catalog-rest-service/src/main/resources/ui/src/assets/svg/service.svg @@ -0,0 +1,4 @@ + + + + diff --git a/catalog-rest-service/src/main/resources/ui/src/assets/svg/terms.svg b/catalog-rest-service/src/main/resources/ui/src/assets/svg/terms.svg new file mode 100644 index 00000000000..315ba95587f --- /dev/null +++ b/catalog-rest-service/src/main/resources/ui/src/assets/svg/terms.svg @@ -0,0 +1,3 @@ + + + diff --git a/catalog-rest-service/src/main/resources/ui/src/assets/svg/user.svg b/catalog-rest-service/src/main/resources/ui/src/assets/svg/user.svg new file mode 100644 index 00000000000..a5b35445b3e --- /dev/null +++ b/catalog-rest-service/src/main/resources/ui/src/assets/svg/user.svg @@ -0,0 +1,4 @@ + + + + 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 255bb849d2f..6e319d33dc1 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 @@ -38,7 +38,12 @@ import { getUserByName, getUsers, } from '../axiosAPIs/userAPI'; -import { oidcTokenKey, ROUTES, TIMEOUT } from '../constants/constants'; +import { + API_RES_MAX_SIZE, + oidcTokenKey, + ROUTES, + TIMEOUT, +} from '../constants/constants'; import { ClientErrors } from '../enums/axios.enum'; import { useAuth } from '../hooks/authHooks'; import useToastContext from '../hooks/useToastContext'; @@ -94,7 +99,7 @@ const AuthProvider: FunctionComponent = ({ // Moving this code here from App.tsx const getAllUsersList = (): void => { - getUsers().then((res) => { + getUsers('', API_RES_MAX_SIZE).then((res) => { appState.users = res.data.data; }); }; diff --git a/catalog-rest-service/src/main/resources/ui/src/axiosAPIs/userAPI.ts b/catalog-rest-service/src/main/resources/ui/src/axiosAPIs/userAPI.ts index 012a0393e88..2270975aa42 100644 --- a/catalog-rest-service/src/main/resources/ui/src/axiosAPIs/userAPI.ts +++ b/catalog-rest-service/src/main/resources/ui/src/axiosAPIs/userAPI.ts @@ -20,8 +20,13 @@ import { UserProfile } from 'Models'; import { getURLWithQueryFields } from '../utils/APIUtils'; import APIClient from './index'; -export const getUsers = (arrQueryFields?: string): Promise => { - const url = getURLWithQueryFields('/users', arrQueryFields); +export const getUsers = ( + arrQueryFields?: string, + limit?: number +): Promise => { + const url = + `${getURLWithQueryFields('/users', arrQueryFields)}` + + (limit ? `${arrQueryFields?.length ? '&' : '?'}limit=${limit}` : ''); return APIClient.get(url); }; diff --git a/catalog-rest-service/src/main/resources/ui/src/components/Modals/AddServiceModal/AddServiceModal.tsx b/catalog-rest-service/src/main/resources/ui/src/components/Modals/AddServiceModal/AddServiceModal.tsx index 68acf55d0db..7f260da92d9 100644 --- a/catalog-rest-service/src/main/resources/ui/src/components/Modals/AddServiceModal/AddServiceModal.tsx +++ b/catalog-rest-service/src/main/resources/ui/src/components/Modals/AddServiceModal/AddServiceModal.tsx @@ -36,7 +36,7 @@ export type DatabaseObj = { serviceType: string; }; -export type DataObj = { +export type ServiceDataObj = { connectionUrl: string; description: string; driverClass: string; @@ -56,8 +56,8 @@ export type EditObj = { type Props = { header: string; serviceName: string; - serviceList: Array; - data?: DataObj; + serviceList: Array; + data?: ServiceDataObj; onSave: (obj: DatabaseObj, text: string, editData: EditObj) => void; onCancel: () => void; }; @@ -88,7 +88,7 @@ const generateOptions = (count: number, initialValue = 0) => { )); }; -const generateName = (data: Array) => { +const generateName = (data: Array) => { const newArr: string[] = []; data.forEach((d) => { newArr.push(d.name); diff --git a/catalog-rest-service/src/main/resources/ui/src/components/my-data/MyDataHeader.tsx b/catalog-rest-service/src/main/resources/ui/src/components/my-data/MyDataHeader.tsx new file mode 100644 index 00000000000..fb46534a73f --- /dev/null +++ b/catalog-rest-service/src/main/resources/ui/src/components/my-data/MyDataHeader.tsx @@ -0,0 +1,105 @@ +import { observer } from 'mobx-react'; +import React, { FunctionComponent, useEffect, useState } from 'react'; +import AppState from '../../AppState'; +import SVGIcons, { Icons } from '../../utils/SvgUtils'; + +type Props = { + countServices: number; + countAssets: number; +}; + +const LANDING_STATES = [ + { + title: 'Explore Assets', + description: + 'OpenMetadata has {countAssets} Assets. Click Explore on top menu to search, claim or follow your Data Assets', + }, + { + title: 'Register Services', + description: + 'Create a service to bring in metadata. Click Settings -> Services to explore available services.', + }, + { + title: 'Knowledgebase', + description: + 'Donec tempus eu dolor non vehicula. Etiam malesuada, sapien ac euismod condimentum.', + }, +]; + +const MyDataHeader: FunctionComponent = ({ + countAssets, + countServices, +}: Props) => { + const { users, userTeams } = AppState; + const [dataSummary, setdataSummary] = useState({ + asstes: { + icon: Icons.ASSETS, + data: `${countAssets} of Assets`, + }, + service: { + icon: Icons.SERVICE, + data: `${countServices} of Services`, + }, + user: { + icon: Icons.USERS, + data: `${users.length} of Users`, + }, + terms: { + icon: Icons.TERMS, + data: `${userTeams.length} of Teams`, + }, + }); + + const getFormattedDescription = (description: string) => { + return description.replaceAll('{countAssets}', countAssets.toString()); + }; + + useEffect(() => { + setdataSummary({ + asstes: { + icon: Icons.ASSETS, + data: `${countAssets} of Assets`, + }, + service: { + icon: Icons.SERVICE, + data: `${countServices} of Services`, + }, + user: { + icon: Icons.USERS, + data: `${users.length} of Users`, + }, + terms: { + icon: Icons.TERMS, + data: `${userTeams.length} of Teams`, + }, + }); + }, [userTeams, users, countAssets, countServices]); + + return ( +
+

+ Open + Metadata +

+
+ {Object.values(dataSummary).map((data, index) => ( +
+ + +

{data.data}

+
+ ))} +
+
+ {LANDING_STATES.map((d, i) => ( +
+

{d.title}

+

{getFormattedDescription(d.description)}

+
+ ))} +
+
+ ); +}; + +export default observer(MyDataHeader); diff --git a/catalog-rest-service/src/main/resources/ui/src/constants/constants.ts b/catalog-rest-service/src/main/resources/ui/src/constants/constants.ts index 5c0e8cf0b6c..2a4d2c230ff 100644 --- a/catalog-rest-service/src/main/resources/ui/src/constants/constants.ts +++ b/catalog-rest-service/src/main/resources/ui/src/constants/constants.ts @@ -16,6 +16,7 @@ */ export const PAGE_SIZE = 10; +export const API_RES_MAX_SIZE = 100000; export const LIST_SIZE = 5; export const SIDEBAR_WIDTH_COLLAPSED = 290; export const SIDEBAR_WIDTH_EXPANDED = 290; diff --git a/catalog-rest-service/src/main/resources/ui/src/interface/types.d.ts b/catalog-rest-service/src/main/resources/ui/src/interface/types.d.ts index 1d817d9a952..0f37be79829 100644 --- a/catalog-rest-service/src/main/resources/ui/src/interface/types.d.ts +++ b/catalog-rest-service/src/main/resources/ui/src/interface/types.d.ts @@ -281,4 +281,17 @@ declare module 'Models' { aggregations: Record; }; }; + + export type ServiceCollection = { + name: string; + value: string; + }; + + export type ServiceData = { + collection: { + documentation: string; + href: string; + name: string; + }; + }; } diff --git a/catalog-rest-service/src/main/resources/ui/src/pages/my-data/index.tsx b/catalog-rest-service/src/main/resources/ui/src/pages/my-data/index.tsx index c56addd210f..5a5839908e2 100644 --- a/catalog-rest-service/src/main/resources/ui/src/pages/my-data/index.tsx +++ b/catalog-rest-service/src/main/resources/ui/src/pages/my-data/index.tsx @@ -21,12 +21,14 @@ import React, { useEffect, useState } from 'react'; import { searchData } from '../../axiosAPIs/miscAPI'; import Error from '../../components/common/error/Error'; import Loader from '../../components/Loader/Loader'; +import MyDataHeader from '../../components/my-data/MyDataHeader'; import SearchedData from '../../components/searched-data/SearchedData'; import { ERROR404, ERROR500, PAGE_SIZE } from '../../constants/constants'; import { Ownership } from '../../enums/mydata.enum'; import useToastContext from '../../hooks/useToastContext'; import { formatDataResponse } from '../../utils/APIUtils'; import { getCurrentUserId } from '../../utils/CommonUtils'; +import { getAllServices } from '../../utils/ServiceUtils'; const MyDataPage: React.FC = (): React.ReactElement => { const showToast = useToastContext(); @@ -37,6 +39,8 @@ const MyDataPage: React.FC = (): React.ReactElement => { const [currentTab, setCurrentTab] = useState(1); const [error, setError] = useState(''); const [filter, setFilter] = useState(''); + const [countServices, setCountServices] = useState(0); + const [countAssets, setCountAssets] = useState(0); const getActiveTabClass = (tab: number) => { return tab === currentTab ? 'active' : ''; @@ -52,9 +56,11 @@ const MyDataPage: React.FC = (): React.ReactElement => { ) .then((res: SearchResponse) => { const hits = res.data.hits.hits; + const total = res.data.hits.total.value; if (hits.length > 0) { setTotalNumberOfValues(res.data.hits.total.value); setData(formatDataResponse(hits)); + setCountAssets(total); setIsLoading(false); } else { setData([]); @@ -93,7 +99,7 @@ const MyDataPage: React.FC = (): React.ReactElement => { setFilter(Ownership.OWNER); setCurrentPage(1); }}> - Owned + My Data