From d1d47e2772f03fddb83327c8a6ab6bf1300fa12d Mon Sep 17 00:00:00 2001 From: David Sharp <34074888+davidsharp7@users.noreply.github.com> Date: Thu, 14 Sep 2023 11:24:27 +1200 Subject: [PATCH] Adding tag descriptions to tooltips (#2612) * add tag descriptions to tooltips Signed-off-by: sharpd * remove tag import after linting Signed-off-by: sharpd * remove comments Signed-off-by: sharpd * ran linter over impacted files and changed code based on feedback Signed-off-by: sharpd * add [run] as dependency based on feedback Signed-off-by: sharpd --------- Signed-off-by: sharpd Co-authored-by: sharpd --- web/src/components/datasets/DatasetInfo.tsx | 57 ++++++++++++++------- web/src/store/actionCreators/actionTypes.ts | 4 ++ web/src/store/actionCreators/index.ts | 12 +++++ web/src/store/reducers/index.ts | 5 +- web/src/store/reducers/tags.ts | 27 ++++++++++ web/src/store/requests/index.ts | 1 + web/src/store/requests/tags.ts | 10 ++++ web/src/store/sagas/index.ts | 24 ++++++++- web/src/types/api.ts | 5 ++ 9 files changed, 123 insertions(+), 22 deletions(-) create mode 100644 web/src/store/reducers/tags.ts create mode 100644 web/src/store/requests/tags.ts diff --git a/web/src/components/datasets/DatasetInfo.tsx b/web/src/components/datasets/DatasetInfo.tsx index ac717ee7f3..c84022cb03 100644 --- a/web/src/components/datasets/DatasetInfo.tsx +++ b/web/src/components/datasets/DatasetInfo.tsx @@ -3,20 +3,21 @@ import * as Redux from 'redux' import { Box, Table, TableBody, TableCell, TableHead, TableRow } from '@mui/material' -import { Field, Run } from '../../types/api' +import { Chip } from '@mui/material' +import { Field, Run, Tag } from '../../types/api' import { IState } from '../../store/reducers' -import { connect } from 'react-redux' -import { fetchJobFacets, resetFacets } from '../../store/actionCreators' +import { connect, useSelector } from 'react-redux' +import { createTheme } from '@mui/material/styles' +import { fetchJobFacets, fetchTags, resetFacets } from '../../store/actionCreators' import { stopWatchDuration } from '../../helpers/time' +import { useTheme } from '@emotion/react' +import MQTooltip from '../core/tooltip/MQTooltip' import MqCode from '../core/code/MqCode' import MqEmpty from '../core/empty/MqEmpty' import MqJsonView from '../core/json-view/MqJsonView' import MqText from '../core/text/MqText' import React, { FunctionComponent, useEffect } from 'react' import RunStatus from '../jobs/RunStatus' -import { Chip } from '@mui/material' -import { createTheme } from '@mui/material/styles' -import { useTheme } from '@emotion/react' export interface DispatchProps { fetchJobFacets: typeof fetchJobFacets @@ -42,18 +43,26 @@ type DatasetInfoProps = { } & JobFacetsProps & DispatchProps -const formatColumnTags = (tags: string[]) => { +const formatColumnTags = (tags: string[], tag_desc: Tag[]) => { const theme = createTheme(useTheme()) return ( <> - {tags.map((tag, index) => ( - - ))} + {tags.map((tag, index) => { + const tagDescription = tag_desc.find((tagItem) => tagItem.name === tag) + const tooltipTitle = tagDescription?.description || 'No Tag Description' + return ( + + + + ) + })} ) } @@ -64,7 +73,8 @@ const DatasetInfo: FunctionComponent = (props) => { useEffect(() => { run && fetchJobFacets(run.id) - }, []) + run && fetchTags() + }, [run]) // unmounting useEffect( @@ -74,6 +84,8 @@ const DatasetInfo: FunctionComponent = (props) => { [] ) + const tagData = useSelector((state: IState) => state.tags.tags) + return ( {datasetFields.length === 0 && ( @@ -103,7 +115,7 @@ const DatasetInfo: FunctionComponent = (props) => { - {i18next.t('dataset_info_columns.tags')} + {i18next.t('dataset_info_columns.tags')} @@ -115,7 +127,7 @@ const DatasetInfo: FunctionComponent = (props) => { {field.name} {field.type} {field.description || 'no description'} - {formatColumnTags(field.tags)} + {formatColumnTags(field.tags, tagData)} ) })} @@ -127,7 +139,13 @@ const DatasetInfo: FunctionComponent = (props) => { {i18next.t('dataset_info.facets_subhead')} - + )} {run && ( @@ -161,6 +179,7 @@ const mapDispatchToProps = (dispatch: Redux.Dispatch) => { fetchJobFacets: fetchJobFacets, resetFacets: resetFacets, + fetchTags: fetchTags, }, dispatch ) diff --git a/web/src/store/actionCreators/actionTypes.ts b/web/src/store/actionCreators/actionTypes.ts index 43d78959ff..5e40a21362 100644 --- a/web/src/store/actionCreators/actionTypes.ts +++ b/web/src/store/actionCreators/actionTypes.ts @@ -57,3 +57,7 @@ export const FETCH_RUN_FACETS = 'FETCH_RUN_FACETS' export const FETCH_JOB_FACETS = 'FETCH_JOB_FACETS' export const FETCH_FACETS_SUCCESS = 'FETCH_FACETS_SUCCESS' export const RESET_FACETS = 'RESET_FACETS' + +// tags +export const FETCH_TAGS = 'FETCH_TAGS' +export const FETCH_TAGS_SUCCESS = 'FETCH_TAGS_SUCCESS' diff --git a/web/src/store/actionCreators/index.ts b/web/src/store/actionCreators/index.ts index 09564ceb27..951bcae5d2 100644 --- a/web/src/store/actionCreators/index.ts +++ b/web/src/store/actionCreators/index.ts @@ -13,6 +13,7 @@ import { Namespace, Run, Search, + Tag, } from '../../types/api' import { JobOrDataset } from '../../components/lineage/types' @@ -194,6 +195,17 @@ export const fetchNamespacesSuccess = (namespaces: Namespace[]) => ({ }, }) +export const fetchTags = () => ({ + type: actionTypes.FETCH_TAGS, +}) + +export const fetchTagsSuccess = (tags: Tag[]) => ({ + type: actionTypes.FETCH_TAGS_SUCCESS, + payload: { + tags, + }, +}) + export const applicationError = (message: string) => ({ type: actionTypes.APPLICATION_ERROR, payload: { diff --git a/web/src/store/reducers/index.ts b/web/src/store/reducers/index.ts index 6bd430823c..7ef58d39d5 100644 --- a/web/src/store/reducers/index.ts +++ b/web/src/store/reducers/index.ts @@ -15,8 +15,10 @@ import lineage, { ILineageState } from './lineage' import namespaces, { INamespacesState } from './namespaces' import runs, { IRunsState } from './runs' import search, { ISearchState } from './search' +import tags, { ITagsState } from './tags' export interface IState { + tags: ITagsState datasets: IDatasetsState dataset: IDatasetState datasetVersions: IDatasetVersionsState @@ -44,5 +46,6 @@ export default (history: History): Reducer => display, lineage, search, - facets + facets, + tags, }) diff --git a/web/src/store/reducers/tags.ts b/web/src/store/reducers/tags.ts new file mode 100644 index 0000000000..d4bf54583d --- /dev/null +++ b/web/src/store/reducers/tags.ts @@ -0,0 +1,27 @@ +// Copyright 2018-2023 contributors to the Marquez project +// SPDX-License-Identifier: Apache-2.0 +import { FETCH_TAGS, FETCH_TAGS_SUCCESS } from '../actionCreators/actionTypes' +import { Tag } from '../../types/api' +import { fetchTagsSuccess } from '../actionCreators' + +export type ITagsState = { isLoading: boolean; tags: Tag[]; init: boolean } + +export const initialState: ITagsState = { + isLoading: false, + init: false, + tags: [], +} + +type ITagsAction = ReturnType + +export default (state: ITagsState = initialState, action: ITagsAction): ITagsState => { + const { type, payload } = action + switch (type) { + case FETCH_TAGS: + return { ...state, isLoading: true } + case FETCH_TAGS_SUCCESS: + return { ...state, isLoading: false, init: true, tags: payload.tags } + default: + return state + } +} diff --git a/web/src/store/requests/index.ts b/web/src/store/requests/index.ts index b75c745887..f9f08b8f70 100644 --- a/web/src/store/requests/index.ts +++ b/web/src/store/requests/index.ts @@ -45,3 +45,4 @@ export * from './events' export * from './facets' export * from './namespaces' export * from './jobs' +export * from './tags' diff --git a/web/src/store/requests/tags.ts b/web/src/store/requests/tags.ts new file mode 100644 index 0000000000..a4345e9e59 --- /dev/null +++ b/web/src/store/requests/tags.ts @@ -0,0 +1,10 @@ +// Copyright 2018-2023 contributors to the Marquez project +// SPDX-License-Identifier: Apache-2.0 + +import { API_URL } from '../../globals' +import { genericFetchWrapper } from './index' + +export const getTags = async () => { + const url = `${API_URL}/tags` + return genericFetchWrapper(url, { method: 'GET' }, 'fetchTags') +} diff --git a/web/src/store/sagas/index.ts b/web/src/store/sagas/index.ts index d8a47559ca..16dcbed6be 100644 --- a/web/src/store/sagas/index.ts +++ b/web/src/store/sagas/index.ts @@ -16,7 +16,15 @@ import { FETCH_RUN_FACETS, FETCH_SEARCH, } from '../actionCreators/actionTypes' -import { Dataset, DatasetVersion, Events, Facets, LineageGraph, Namespaces } from '../../types/api' +import { + Dataset, + DatasetVersion, + Events, + Facets, + LineageGraph, + Namespaces, + Tags, +} from '../../types/api' import { all, put, take } from 'redux-saga/effects' const call: any = Effects.call @@ -37,6 +45,7 @@ import { fetchNamespacesSuccess, fetchRunsSuccess, fetchSearchSuccess, + fetchTagsSuccess, } from '../actionCreators' import { deleteDataset, @@ -50,10 +59,21 @@ import { getNamespaces, getRunFacets, getRuns, + getTags, } from '../requests' import { getLineage } from '../requests/lineage' import { getSearch } from '../requests/search' +export function* fetchTags() { + try { + const response: Tags = yield call(getTags) + const { tags } = response + yield put(fetchTagsSuccess(tags)) + } catch (e) { + yield put(applicationError('Something went wrong while fetching initial data.')) + } +} + export function* fetchNamespaces() { try { const response: Namespaces = yield call(getNamespaces) @@ -226,7 +246,7 @@ export function* fetchRunFacetsSaga() { } export default function* rootSaga(): Generator { - const sagasThatAreKickedOffImmediately = [fetchNamespaces()] + const sagasThatAreKickedOffImmediately = [fetchNamespaces(), fetchTags()] const sagasThatWatchForAction = [ fetchJobsSaga(), fetchRunsSaga(), diff --git a/web/src/types/api.ts b/web/src/types/api.ts index 96ff73b858..458e7070a0 100644 --- a/web/src/types/api.ts +++ b/web/src/types/api.ts @@ -7,6 +7,11 @@ export interface Tag { name: string description: string } + +export interface Tags { + tags: Tag[] +} + export interface Runs { runs: Run[] }