Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 38 additions & 19 deletions web/src/components/datasets/DatasetInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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) => (
<Chip
key={tag}
label={tag}
size="small"
style={{display: 'inline', marginRight: index < tags.length - 1 ? theme.spacing(1) : 0}}
/>
))}
{tags.map((tag, index) => {
const tagDescription = tag_desc.find((tagItem) => tagItem.name === tag)
const tooltipTitle = tagDescription?.description || 'No Tag Description'
return (
<MQTooltip title={tooltipTitle} key={tag}>
<Chip
label={tag}
size='small'
style={{
display: 'inline',
marginRight: index < tags.length - 1 ? theme.spacing(1) : 0,
}}
/>
</MQTooltip>
)
})}
</>
)
}
Expand All @@ -64,7 +73,8 @@ const DatasetInfo: FunctionComponent<DatasetInfoProps> = (props) => {

useEffect(() => {
run && fetchJobFacets(run.id)
}, [])
run && fetchTags()
}, [run])

// unmounting
useEffect(
Expand All @@ -74,6 +84,8 @@ const DatasetInfo: FunctionComponent<DatasetInfoProps> = (props) => {
[]
)

const tagData = useSelector((state: IState) => state.tags.tags)

return (
<Box>
{datasetFields.length === 0 && (
Expand Down Expand Up @@ -103,7 +115,7 @@ const DatasetInfo: FunctionComponent<DatasetInfoProps> = (props) => {
</TableCell>
<TableCell align='left'>
<MqText subheading inline>
{i18next.t('dataset_info_columns.tags')}
{i18next.t('dataset_info_columns.tags')}
</MqText>
</TableCell>
</TableRow>
Expand All @@ -115,7 +127,7 @@ const DatasetInfo: FunctionComponent<DatasetInfoProps> = (props) => {
<TableCell align='left'>{field.name}</TableCell>
<TableCell align='left'>{field.type}</TableCell>
<TableCell align='left'>{field.description || 'no description'}</TableCell>
<TableCell align='left'>{formatColumnTags(field.tags)}</TableCell>
<TableCell align='left'>{formatColumnTags(field.tags, tagData)}</TableCell>
</TableRow>
)
})}
Expand All @@ -127,7 +139,13 @@ const DatasetInfo: FunctionComponent<DatasetInfoProps> = (props) => {
<Box mb={1}>
<MqText subheading>{i18next.t('dataset_info.facets_subhead')}</MqText>
</Box>
<MqJsonView data={facets} searchable={true} aria-label={i18next.t('dataset_info.facets_subhead_aria')} aria-required='True' placeholder='Search' />
<MqJsonView
data={facets}
searchable={true}
aria-label={i18next.t('dataset_info.facets_subhead_aria')}
aria-required='True'
placeholder='Search'
/>
</Box>
)}
{run && (
Expand Down Expand Up @@ -161,6 +179,7 @@ const mapDispatchToProps = (dispatch: Redux.Dispatch) =>
{
fetchJobFacets: fetchJobFacets,
resetFacets: resetFacets,
fetchTags: fetchTags,
},
dispatch
)
Expand Down
4 changes: 4 additions & 0 deletions web/src/store/actionCreators/actionTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
12 changes: 12 additions & 0 deletions web/src/store/actionCreators/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
Namespace,
Run,
Search,
Tag,
} from '../../types/api'
import { JobOrDataset } from '../../components/lineage/types'

Expand Down Expand Up @@ -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: {
Expand Down
5 changes: 4 additions & 1 deletion web/src/store/reducers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -44,5 +46,6 @@ export default (history: History): Reducer =>
display,
lineage,
search,
facets
facets,
tags,
})
27 changes: 27 additions & 0 deletions web/src/store/reducers/tags.ts
Original file line number Diff line number Diff line change
@@ -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<typeof fetchTagsSuccess>

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
}
}
1 change: 1 addition & 0 deletions web/src/store/requests/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,4 @@ export * from './events'
export * from './facets'
export * from './namespaces'
export * from './jobs'
export * from './tags'
10 changes: 10 additions & 0 deletions web/src/store/requests/tags.ts
Original file line number Diff line number Diff line change
@@ -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')
}
24 changes: 22 additions & 2 deletions web/src/store/sagas/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -37,6 +45,7 @@ import {
fetchNamespacesSuccess,
fetchRunsSuccess,
fetchSearchSuccess,
fetchTagsSuccess,
} from '../actionCreators'
import {
deleteDataset,
Expand All @@ -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)
Expand Down Expand Up @@ -226,7 +246,7 @@ export function* fetchRunFacetsSaga() {
}

export default function* rootSaga(): Generator {
const sagasThatAreKickedOffImmediately = [fetchNamespaces()]
const sagasThatAreKickedOffImmediately = [fetchNamespaces(), fetchTags()]
const sagasThatWatchForAction = [
fetchJobsSaga(),
fetchRunsSaga(),
Expand Down
5 changes: 5 additions & 0 deletions web/src/types/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ export interface Tag {
name: string
description: string
}

export interface Tags {
tags: Tag[]
}

export interface Runs {
runs: Run[]
}
Expand Down