From ac8d3da0b9f7451e0863718dc1a6fc894de73883 Mon Sep 17 00:00:00 2001 From: mariana-furyk Date: Fri, 3 Nov 2023 22:16:30 +0200 Subject: [PATCH] Impl [Models] Metrics new look and feel in the table --- src/common/Download/DownloadItem.js | 2 +- src/common/Download/downloadContainer.scss | 2 +- src/components/Datasets/Datasets.js | 17 +- src/components/Datasets/DatasetsView.js | 8 +- .../DetailsResults/DetailsResults.js | 2 +- src/components/Files/Files.js | 17 +- src/components/Files/FilesView.js | 9 +- src/components/ModelsPage/Models/Models.js | 19 +- .../ModelsPage/Models/ModelsView.js | 4 +- src/components/Table/TableHead.js | 25 +- src/components/Table/TableView.js | 14 +- src/components/Table/table.scss | 4 +- .../JobsFunctionsTableRow.js | 2 +- .../ArtifactsTableRow/ArtifactsTableRow.js | 12 +- .../FeatureStoreTableRow.js | 18 +- .../FunctionsTableRow/FunctionsTableRow.js | 18 +- src/elements/JobsTableRow/JobsTableRow.js | 2 +- src/elements/TableCell/TableCell.js | 25 +- src/elements/TableLinkCell/TableLinkCell.js | 7 +- .../TableProducerCell/TableProducerCell.js | 4 +- src/elements/TableTypeCell/TableTypeCell.js | 4 +- src/hooks/groupContent.hook.js | 14 +- src/scss/main.scss | 180 +++++++----- src/utils/createArtifactsContent.js | 270 +++++++++--------- src/utils/createConsumerGroupContent.js | 8 +- src/utils/createConsumerGroupsContent.js | 6 +- src/utils/createFeatureStoreContent.js | 48 ++-- src/utils/createFunctionsContent.js | 26 +- src/utils/createJobsContent.js | 58 ++-- src/utils/generateTableHeaders.js | 30 ++ 30 files changed, 512 insertions(+), 343 deletions(-) create mode 100644 src/utils/generateTableHeaders.js diff --git a/src/common/Download/DownloadItem.js b/src/common/Download/DownloadItem.js index c474e30c55..77a568a0ae 100644 --- a/src/common/Download/DownloadItem.js +++ b/src/common/Download/DownloadItem.js @@ -99,7 +99,7 @@ const DownloadItem = ({ downloadItem }) => { timeoutRef.current = setTimeout(() => { dispatch(removeDownloadItem(downloadItem.id)) - }, 1000) + }, 2000) }) } }, [ diff --git a/src/common/Download/downloadContainer.scss b/src/common/Download/downloadContainer.scss index 88d9d55e66..5b64eddaad 100644 --- a/src/common/Download/downloadContainer.scss +++ b/src/common/Download/downloadContainer.scss @@ -6,7 +6,7 @@ right: 24px; bottom: -115px; opacity: 0; - z-index: 1000; + z-index: 9; width: 220px; min-height: 90px; max-height: 200px; diff --git a/src/components/Datasets/Datasets.js b/src/components/Datasets/Datasets.js index 9371724f5b..ff5018afd0 100644 --- a/src/components/Datasets/Datasets.js +++ b/src/components/Datasets/Datasets.js @@ -65,6 +65,8 @@ import { getViewMode } from '../../utils/helper' import { copyToClipboard } from '../../utils/copyToClipboard' import { generateUri } from '../../utils/resources' import { setDownloadItem, setShowDownloadsList } from '../../reducers/downloadReducer' +import { useSortTable } from '../../hooks/useSortTable.hook' +import { generateTableHeaders } from '../../utils/generateTableHeaders' import { ReactComponent as TagIcon } from 'igz-controls/images/tag-icon.svg' import { ReactComponent as YamlIcon } from 'igz-controls/images/yaml.svg' @@ -291,6 +293,17 @@ const Datasets = () => { ) }, [datasets, filtersStore.groupBy, frontendSpec, latestItems, params.projectName]) + const tableHeaders = useMemo(() => { + return generateTableHeaders(tableContent[0]?.content ?? []) + }, [tableContent]) + + const { sortTable, selectedColumnName, getSortingIcon, sortedTableContent, sortedTableHeaders } = + useSortTable({ + headers: tableHeaders, + content: tableContent, + sortConfig: { excludeSortBy: 'labels', defaultSortBy: 'updated', defaultDirection: 'desc' } + }) + useEffect(() => { if (params.name && params.tag && pageData.details.menu.length > 0) { isDetailsTabExists(params.tab, pageData.details.menu, navigate, location) @@ -369,7 +382,9 @@ const Datasets = () => { setDatasets={setDatasets} setSelectedDataset={setSelectedDataset} setSelectedRowData={setSelectedRowData} - tableContent={tableContent} + sortProps={{ sortTable, selectedColumnName, getSortingIcon }} + tableContent={sortedTableContent} + tableHeaders={sortedTableHeaders} toggleConvertedYaml={toggleConvertedYaml} viewMode={viewMode} urlTagOption={urlTagOption} diff --git a/src/components/Datasets/DatasetsView.js b/src/components/Datasets/DatasetsView.js index 364dfde616..e4070baf5b 100644 --- a/src/components/Datasets/DatasetsView.js +++ b/src/components/Datasets/DatasetsView.js @@ -36,6 +36,7 @@ import { registerDatasetTitle, filters } from './datasets.util' import { removeDataSet } from '../../reducers/artifactsReducer' import { ACTIONS_MENU } from '../../types' import { SECONDARY_BUTTON } from 'igz-controls/constants' +import { SORT_PROPS } from 'igz-controls/types' const DatasetsView = React.forwardRef( ( @@ -57,7 +58,9 @@ const DatasetsView = React.forwardRef( setDatasets, setSelectedDataset, setSelectedRowData, + sortProps, tableContent, + tableHeaders, toggleConvertedYaml, viewMode, urlTagOption @@ -113,7 +116,8 @@ const DatasetsView = React.forwardRef( pageData={pageData} retryRequest={handleRefresh} selectedItem={selectedDataset} - tableHeaders={tableContent[0]?.content ?? []} + sortProps={sortProps} + tableHeaders={tableHeaders ?? []} > {tableContent.map((tableItem, index) => ( classNames( - 'table-header-item', + 'table-header__cell', isSortable && 'sortable-header-cell', isSortable && selectedColumnName === headerId && 'sortable-header-cell_active' ) diff --git a/src/components/Files/Files.js b/src/components/Files/Files.js index 9b9b031e20..620f5b4c83 100644 --- a/src/components/Files/Files.js +++ b/src/components/Files/Files.js @@ -65,6 +65,8 @@ import { getViewMode } from '../../utils/helper' import { copyToClipboard } from '../../utils/copyToClipboard' import { generateUri } from '../../utils/resources' import { setDownloadItem, setShowDownloadsList } from '../../reducers/downloadReducer' +import { useSortTable } from '../../hooks/useSortTable.hook' +import { generateTableHeaders } from '../../utils/generateTableHeaders' import { ReactComponent as TagIcon } from 'igz-controls/images/tag-icon.svg' import { ReactComponent as YamlIcon } from 'igz-controls/images/yaml.svg' @@ -249,6 +251,17 @@ const Files = () => { : files.map(contentItem => createFilesRowData(contentItem, params.projectName, frontendSpec)) }, [files, filtersStore.groupBy, frontendSpec, latestItems, params.projectName]) + const tableHeaders = useMemo(() => { + return generateTableHeaders(tableContent[0]?.content ?? []) + }, [tableContent]) + + const { sortTable, selectedColumnName, getSortingIcon, sortedTableContent, sortedTableHeaders } = + useSortTable({ + headers: tableHeaders, + content: tableContent, + sortConfig: { excludeSortBy: 'labels', defaultSortBy: 'updated', defaultDirection: 'desc' } + }) + const applyDetailsChanges = useCallback( changes => { return handleApplyDetailsChanges( @@ -357,7 +370,9 @@ const Files = () => { setFiles={setFiles} setSelectedFile={setSelectedFile} setSelectedRowData={setSelectedRowData} - tableContent={tableContent} + sortProps={{ sortTable, selectedColumnName, getSortingIcon }} + tableContent={sortedTableContent} + tableHeaders={sortedTableHeaders} toggleConvertedYaml={toggleConvertedYaml} viewMode={viewMode} urlTagOption={urlTagOption} diff --git a/src/components/Files/FilesView.js b/src/components/Files/FilesView.js index 34ab14a34f..b1cfe1a797 100644 --- a/src/components/Files/FilesView.js +++ b/src/components/Files/FilesView.js @@ -36,6 +36,7 @@ import { registerArtifactTitle, filters } from './files.util' import { removeFile } from '../../reducers/artifactsReducer' import { ACTIONS_MENU } from '../../types' import { SECONDARY_BUTTON } from 'igz-controls/constants' +import { SORT_PROPS } from 'igz-controls/types' const FilesView = React.forwardRef( ( @@ -57,7 +58,9 @@ const FilesView = React.forwardRef( setFiles, setSelectedFile, setSelectedRowData, + sortProps, tableContent, + tableHeaders, toggleConvertedYaml, viewMode, urlTagOption @@ -106,8 +109,8 @@ const FilesView = React.forwardRef( handleCancel={() => setSelectedFile({})} pageData={pageData} retryRequest={handleRefresh} - selectedItem={selectedFile} - tableHeaders={tableContent[0]?.content ?? []} + sortProps={sortProps} + tableHeaders={tableHeaders ?? []} > {tableContent.map((tableItem, index) => ( { const [models, setModels] = useState([]) @@ -274,11 +275,16 @@ const Models = ({ fetchModelFeatureVector }) => { ) }, [filtersStore.groupBy, frontendSpec, latestItems, models, params.projectName]) - const { sortTable, selectedColumnName, getSortingIcon, sortedTableContent } = useSortTable({ - headers: tableContent[0]?.content, - content: tableContent, - sortConfig: { defaultSortBy: 'updated', defaultDirection: 'desc' } - }) + const tableHeaders = useMemo(() => { + return generateTableHeaders(tableContent[0]?.content ?? []) + }, [tableContent]) + + const { sortTable, selectedColumnName, getSortingIcon, sortedTableContent, sortedTableHeaders } = + useSortTable({ + headers: tableHeaders, + content: tableContent, + sortConfig: { excludeSortBy: 'labels', defaultSortBy: 'updated', defaultDirection: 'desc' } + }) const applyDetailsChanges = useCallback( changes => { @@ -402,6 +408,7 @@ const Models = ({ fetchModelFeatureVector }) => { setSelectedRowData={setSelectedRowData} sortProps={{ sortTable, selectedColumnName, getSortingIcon }} tableContent={sortedTableContent} + tableHeaders={sortedTableHeaders} viewMode={viewMode} urlTagOption={urlTagOption} /> diff --git a/src/components/ModelsPage/Models/ModelsView.js b/src/components/ModelsPage/Models/ModelsView.js index 24f2aa2c50..5b9e5b0b1f 100644 --- a/src/components/ModelsPage/Models/ModelsView.js +++ b/src/components/ModelsPage/Models/ModelsView.js @@ -58,6 +58,7 @@ const ModelsView = React.forwardRef( setSelectedRowData, sortProps, tableContent, + tableHeaders, viewMode, urlTagOption }, @@ -113,7 +114,7 @@ const ModelsView = React.forwardRef( selectedItem={selectedModel} sortProps={sortProps} tab={MODELS_TAB} - tableHeaders={tableContent[0]?.content ?? []} + tableHeaders={tableHeaders ?? []} > {tableContent.map((tableItem, index) => { return ( @@ -178,6 +179,7 @@ ModelsView.propTypes = { setSelectedRowData: PropTypes.func.isRequired, sortProps: SORT_PROPS, tableContent: PropTypes.arrayOf(PropTypes.object).isRequired, + tableHeaders: PropTypes.arrayOf(PropTypes.object).isRequired, viewMode: PropTypes.string, urlTagOption: PropTypes.string } diff --git a/src/components/Table/TableHead.js b/src/components/Table/TableHead.js index 5c69237955..1390291824 100644 --- a/src/components/Table/TableHead.js +++ b/src/components/Table/TableHead.js @@ -28,10 +28,17 @@ import { SORT_PROPS } from 'igz-controls/types' const TableHead = React.forwardRef( ({ content, hideActionsMenu, mainRowItemsCount, selectedItem, sortProps }, ref) => { - const getHeaderCellClasses = (headerId, isSortable, tableItemClass, index) => + const getHeaderCellClasses = ( + headerId, + isSortable, + tableItemClassName, + headerCellClassName, + index + ) => classNames( - 'table-header-item', - tableItemClass, + 'table-header__cell', + tableItemClassName, + headerCellClassName, isSortable && 'sortable-header-cell', isSortable && sortProps?.selectedColumnName === headerId && 'sortable-header-cell_active', !isEmpty(selectedItem) && index >= mainRowItemsCount && 'table-body__cell_hidden' @@ -39,11 +46,17 @@ const TableHead = React.forwardRef( return ( - + {content.map(({ headerLabel, headerId, isSortable, ...tableItem }, index) => { return tableItem.type !== 'hidden' && !tableItem.hidden ? ( sortProps.sortTable(headerId) : null} > @@ -58,7 +71,7 @@ const TableHead = React.forwardRef( ) : null })} - {!hideActionsMenu && } + {!hideActionsMenu && } ) diff --git a/src/components/Table/TableView.js b/src/components/Table/TableView.js index bd711bdde2..fa10eaf75b 100644 --- a/src/components/Table/TableView.js +++ b/src/components/Table/TableView.js @@ -20,6 +20,7 @@ such restriction. import React from 'react' import PropTypes from 'prop-types' import { isEmpty } from 'lodash' +import classnames from 'classnames' import ArtifactsTableRow from '../../elements/ArtifactsTableRow/ArtifactsTableRow' import ConsumerGroupShardLagTableRow from '../../elements/ConsumerGroupShardLagTableRow/ConsumerGroupShardLagTableRow' @@ -85,11 +86,15 @@ const TableView = ({ <> - {pageData.tableHeaders?.map( - (item, index) => + {pageData.tableHeaders?.map((item, index) => { + const headerClassNames = classnames( + `table-header__cell ${item.className} ${item.headerCellClassName}` + ) + + return ( !item.hidden && ( @@ -98,7 +103,8 @@ const TableView = ({ ) - )} + ) + })} diff --git a/src/components/Table/table.scss b/src/components/Table/table.scss index 28ac73eb56..3956278c0d 100644 --- a/src/components/Table/table.scss +++ b/src/components/Table/table.scss @@ -95,7 +95,7 @@ } } - .parent-row-expanded { + .parent-row_expanded { .row_grouped-by { .table-cell-name { border-right: none; @@ -144,7 +144,7 @@ .table { &-header { - &-item { + &__cell { &.buttonPopout, &.buttonDownload { @include tableColumnFlex(0.5, 80px); diff --git a/src/components/Workflow/JobsFunctionsTableRow/JobsFunctionsTableRow.js b/src/components/Workflow/JobsFunctionsTableRow/JobsFunctionsTableRow.js index c8cfacf0fa..64b9c65e09 100644 --- a/src/components/Workflow/JobsFunctionsTableRow/JobsFunctionsTableRow.js +++ b/src/components/Workflow/JobsFunctionsTableRow/JobsFunctionsTableRow.js @@ -32,7 +32,7 @@ const JobsFunctionsTableRow = ({ handleSelectItem, rowItem, selectedItem }) => { const rowClassNames = classnames( 'table-row', 'parent-row', - isWorkflowJobSelected(rowItem.data, selectedItem) && 'row_active' + isWorkflowJobSelected(rowItem.data, selectedItem) && 'table-row_active' ) return ( diff --git a/src/elements/ArtifactsTableRow/ArtifactsTableRow.js b/src/elements/ArtifactsTableRow/ArtifactsTableRow.js index 0ae3f69b72..996c007db3 100644 --- a/src/elements/ArtifactsTableRow/ArtifactsTableRow.js +++ b/src/elements/ArtifactsTableRow/ArtifactsTableRow.js @@ -51,19 +51,19 @@ const ArtifactsTableRow = ({ 'parent-row', (selectedItem.db_key || selectedItem?.spec?.model) && getArtifactIdentifier(selectedItem, true) === rowItem.data.ui.identifierUnique && - !parent.current?.classList.value.includes('parent-row-expanded') && - 'row_active', - parent.current?.classList.value.includes('parent-row-expanded') && 'parent-row-expanded' + !parent.current?.classList.value.includes('parent-row_expanded') && + 'table-row_active', + parent.current?.classList.value.includes('parent-row_expanded') && 'parent-row_expanded' ) return ( - {parent.current?.classList.contains('parent-row-expanded') ? ( + {parent.current?.classList.contains('parent-row_expanded') ? ( <> @@ -102,7 +102,7 @@ const ArtifactsTableRow = ({ selectedItem.key && tableContentItem.data.ui.identifierUnique === getArtifactIdentifier(selectedItem, true) && - 'row_active' + 'table-row_active' ) return ( diff --git a/src/elements/FeatureStoreTableRow/FeatureStoreTableRow.js b/src/elements/FeatureStoreTableRow/FeatureStoreTableRow.js index 5e68331abe..4d709cc9fd 100644 --- a/src/elements/FeatureStoreTableRow/FeatureStoreTableRow.js +++ b/src/elements/FeatureStoreTableRow/FeatureStoreTableRow.js @@ -54,19 +54,19 @@ const FeatureStoreTableRow = ({ 'parent-row', selectedItem?.name && getIdentifier(selectedItem, true) === rowItem.data.ui.identifierUnique && - !parent.current?.classList.value.includes('parent-row-expanded') && - 'row_active', - parent.current?.classList.value.includes('parent-row-expanded') && 'parent-row-expanded' + !parent.current?.classList.value.includes('parent-row_expanded') && + 'table-row_active', + parent.current?.classList.value.includes('parent-row_expanded') && 'parent-row_expanded' ) return ( - {parent.current?.classList.contains('parent-row-expanded') ? ( + {parent.current?.classList.contains('parent-row_expanded') ? ( <>
@@ -116,11 +116,15 @@ const FeatureStoreTableRow = ({ 'table-row', selectedItem.name && getIdentifier(selectedItem, true) === tableContentItem.data.ui.identifierUnique && - 'row_active' + 'table-row_active' ) return ( -
+ diff --git a/src/elements/FunctionsTableRow/FunctionsTableRow.js b/src/elements/FunctionsTableRow/FunctionsTableRow.js index b7efc96f7c..27d3e6f2b7 100644 --- a/src/elements/FunctionsTableRow/FunctionsTableRow.js +++ b/src/elements/FunctionsTableRow/FunctionsTableRow.js @@ -46,19 +46,19 @@ const FunctionsTableRow = ({ 'table-row', 'parent-row', getFunctionIdentifier(selectedItem, true) === rowItem.data?.ui?.identifierUnique && - !parent.current?.classList.value.includes('parent-row-expanded') && - 'row_active', - parent.current?.classList.value.includes('parent-row-expanded') && 'parent-row-expanded' + !parent.current?.classList.value.includes('parent-row_expanded') && + 'table-row_active', + parent.current?.classList.value.includes('parent-row_expanded') && 'parent-row_expanded' ) return ( - {parent.current?.classList.contains('parent-row-expanded') ? ( + {parent.current?.classList.contains('parent-row_expanded') ? ( <>
@@ -95,11 +95,15 @@ const FunctionsTableRow = ({ 'table-row', selectedItem.name && getFunctionIdentifier(selectedItem, true) === func.data.ui.identifierUnique && - 'row_active' + 'table-row_active' ) return ( -
+ diff --git a/src/elements/JobsTableRow/JobsTableRow.js b/src/elements/JobsTableRow/JobsTableRow.js index e126588e50..02d748a353 100644 --- a/src/elements/JobsTableRow/JobsTableRow.js +++ b/src/elements/JobsTableRow/JobsTableRow.js @@ -34,7 +34,7 @@ const JobsTableRow = ({ actionsMenu, handleSelectJob, rowItem, selectedJob }) => const rowClassNames = classnames( 'table-row', 'parent-row', - getJobIdentifier(selectedJob, true) === rowItem.data.ui.identifierUnique && 'row_active' + getJobIdentifier(selectedJob, true) === rowItem.data.ui.identifierUnique && 'table-row_active' ) return ( diff --git a/src/elements/TableCell/TableCell.js b/src/elements/TableCell/TableCell.js index 60c4b5c1ab..fd4b0cd30b 100644 --- a/src/elements/TableCell/TableCell.js +++ b/src/elements/TableCell/TableCell.js @@ -20,6 +20,7 @@ such restriction. import React from 'react' import PropTypes from 'prop-types' import { useDispatch } from 'react-redux' +import classnames from 'classnames' import ChipCell from '../../common/ChipCell/ChipCell' import CopyToClipboard from '../../common/CopyToClipboard/CopyToClipboard' @@ -50,6 +51,12 @@ const TableCell = ({ }) => { const dispatch = useDispatch() const { value: stateValue, label: stateLabel, className: stateClassName } = item.state ?? {} + const cellClassNames = classnames( + 'table-body__cell', + data.className, + className, + data.bodyCellClassName + ) if (link && data.type !== 'hidden') { return ( @@ -66,7 +73,7 @@ const TableCell = ({ ) } else if (firstCell && !link) { return ( - ) @@ -114,7 +121,7 @@ const TableCell = ({ return } else if (data.type === 'buttonPopout') { return ( - + return } else { return ( -
+
{data && ( }> @@ -93,7 +100,7 @@ const TableCell = ({ return } else if (data.type === 'icons') { return ( -
+ {data.value.map((valueItem, index) => ( + + + + + }> {truncateUid(data.value)} @@ -171,10 +178,10 @@ const TableCell = ({ } else if (data.type === 'hidden') { return null } else if (data.type === 'component') { - return {data.value}{data.value} + } diff --git a/src/elements/TableLinkCell/TableLinkCell.js b/src/elements/TableLinkCell/TableLinkCell.js index 91def5cf84..942f32b796 100644 --- a/src/elements/TableLinkCell/TableLinkCell.js +++ b/src/elements/TableLinkCell/TableLinkCell.js @@ -40,7 +40,12 @@ const TableLinkCell = ({ selectedItem, showExpandButton }) => { - const tableCellClassNames = classnames('table-body__cell', data.class, className) + const tableCellClassNames = classnames( + 'table-body__cell', + data.className, + className, + data.bodyCellClassName + ) const itemNameClassNames = classnames('item-name') const { value: stateValue, label: stateLabel, className: stateClassName } = item.state ?? {} diff --git a/src/elements/TableProducerCell/TableProducerCell.js b/src/elements/TableProducerCell/TableProducerCell.js index 07d011f423..0a9bec61ff 100644 --- a/src/elements/TableProducerCell/TableProducerCell.js +++ b/src/elements/TableProducerCell/TableProducerCell.js @@ -20,6 +20,7 @@ such restriction. import React from 'react' import { Link } from 'react-router-dom' import PropTypes from 'prop-types' +import classnames from 'classnames' import ProducerTooltipTemplate from '../TooltipTemplate/ProducerTooltipTemplate' import { Tooltip, TextTooltipTemplate } from 'igz-controls/components' @@ -32,9 +33,10 @@ const TableProducerCell = ({ data }) => { const [project, uid] = data.value.uri?.split('/') || [] const { name } = data.value const overviewTab = getJobsDetailsMenu().find(tab => tab.id === DETAILS_OVERVIEW_TAB) || {} + const cellClassNames = classnames('table-body__cell', data.className, data.bodyCellClassName) return ( - + {data.value.name && uid && ( { [JOB_KIND_SPARK]: { label: 'Spark', icon: }, [JOB_KIND_WORKFLOW]: { label: 'Workflow', icon: } } + const cellClassNames = classnames('table-body__cell', data.className, data.bodyCellClassName) return ( - + { const rows = [...document.getElementsByClassName('parent-row')] - rows.forEach(row => row.classList.remove('parent-row-expanded')) + rows.forEach(row => row.classList.remove('parent-row_expanded')) setExpand(false) setGroupedContent({}) @@ -66,14 +66,14 @@ export const useGroupContent = ( const handleExpandRow = (e, item) => { const parentRow = e.target.closest('.parent-row') - if (parentRow.classList.contains('parent-row-expanded')) { - parentRow.classList.remove('parent-row-expanded') + if (parentRow.classList.contains('parent-row_expanded')) { + parentRow.classList.remove('parent-row_expanded') handleRemoveRequestData && handleRemoveRequestData(item) setExpandedItems(prev => --prev) } else { - parentRow.classList.remove('row_active') - parentRow.classList.add('parent-row-expanded') + parentRow.classList.remove('table-row_active') + parentRow.classList.add('parent-row_expanded') handleRequestOnExpand && handleRequestOnExpand(item, groupedContent) setExpandedItems(prev => ++prev) @@ -86,12 +86,12 @@ export const useGroupContent = ( const rows = [...document.getElementsByClassName('parent-row')] if (collapseRows || expand) { - rows.forEach(row => row.classList.remove('parent-row-expanded')) + rows.forEach(row => row.classList.remove('parent-row_expanded')) setExpandedItems(0) handleExpandAllCallback && handleExpandAllCallback(true) } else { - rows.forEach(row => row.classList.add('parent-row-expanded')) + rows.forEach(row => row.classList.add('parent-row_expanded')) setExpandedItems(Object.keys(groupedContent).length) handleExpandAllCallback && handleExpandAllCallback(false, groupedContent) diff --git a/src/scss/main.scss b/src/scss/main.scss index 0effce3737..0e692478c7 100644 --- a/src/scss/main.scss +++ b/src/scss/main.scss @@ -5,36 +5,6 @@ @import '~igz-controls/scss/borders'; @import '~igz-controls/scss/fonts'; -*, -::after, -::before { - box-sizing: border-box; -} - -* { - scrollbar-color: rgba($black, 0.25) rgba($black, 0.1); - scrollbar-width: thin; -} - -::-webkit-scrollbar { - width: 8px; - height: 8px; -} - -::-webkit-scrollbar-track { - background-color: rgba($black, 0.1); - border-radius: 10px; -} - -::-webkit-scrollbar-thumb { - background-color: rgba($black, 0.25); - border-radius: 10px; - - &:hover { - background-color: rgba($black, 0.4); - } -} - body { display: flex; flex: 1; @@ -69,6 +39,8 @@ body { } } +//=======================================CONTENT======================================= + .content { position: relative; flex-direction: column; @@ -137,6 +109,8 @@ body { } } +//=======================================MAIN======================================= + main { position: relative; z-index: 1; @@ -166,6 +140,8 @@ main { } } +//=======================================PAGE======================================= + .page { flex: 1 1; min-width: 100%; @@ -193,7 +169,7 @@ main { .table { border-top: none; - .table-header-item, + .table-header__cell, .table-body__cell { color: $primaryTextColor; } @@ -207,6 +183,8 @@ main { } } +//=======================================TABLE======================================= + .table { display: flex; flex-flow: column nowrap; @@ -224,11 +202,7 @@ main { background-color: inherit; border-bottom: $tableRowBorder; - &_header { - min-height: 40px; - } - - &:not(.parent-row-expanded) > * { + &:not(.parent-row_expanded) > * { position: relative; display: inline-flex; flex: 1; @@ -270,7 +244,7 @@ main { } &.parent-row { - &:not(.parent-row-expanded) { + &:not(.parent-row_expanded) { &:not(.parent-row_without-actions) { .table-cell-icon { .actions-menu { @@ -335,7 +309,7 @@ main { margin-top: 3px; } - &-expanded { + &_expanded { flex-direction: column; border: 0; @@ -353,7 +327,7 @@ main { .row_grouped-by { position: sticky; - top: 50px; + top: 40px; background-color: $white; padding: 0; z-index: 3; @@ -378,7 +352,11 @@ main { min-width: 100%; z-index: 3; - &-item { + &-row { + min-height: 40px; + } + + &__cell { min-width: 75px; @include tableHeader; @@ -416,7 +394,7 @@ main { background-color: $white; &:hover, - &.row_active { + &_active { background-color: $ghostWhite; } @@ -424,10 +402,20 @@ main { background-color: inherit; } } + + .metrics-cell { + font-weight: bold; + + &_with-border { + border-left: 1px solid $titanWhite; + } + } } } } +//=======================================SORT======================================= + .sortable-header { &-cell { position: relative; @@ -470,10 +458,7 @@ main { } } -a { - color: inherit; - text-decoration: none; -} +//=======================================STATE======================================= [class^='state-active'], [class^='state-completed'], @@ -528,10 +513,7 @@ a { @include statusState($topaz); } -iframe { - width: 100%; - height: 100%; -} +//=======================================ERROR======================================= .error-container { margin: auto; @@ -548,23 +530,7 @@ iframe { } } -.data-ellipsis { - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; -} - -.cursor-pointer { - cursor: pointer; -} - -.capitalize { - text-transform: capitalize; -} - -.wrap { - white-space: pre-wrap; -} +//=======================================ACTIONS======================================= .actions { display: flex; @@ -590,6 +556,8 @@ iframe { } } +//=======================================INPUT======================================= + .auto-resizable-input { position: relative; display: inline-grid; @@ -620,6 +588,9 @@ iframe { } } + +//=======================================COMBOBOX======================================= + .combobox { .path-type { &-store { @@ -644,13 +615,7 @@ iframe { } } -.visibility-hidden { - visibility: hidden; -} - -.pointer { - cursor: pointer; -} +//=======================================GRAPH======================================= .graph-container { display: flex; @@ -688,6 +653,8 @@ iframe { } } +//=======================================FORM======================================= + .form { color: $primary; @@ -779,6 +746,8 @@ iframe { } } + +//=======================================SORT ICON======================================= .sort-icon { width: 20px; transition: transform 0.3s ease-in-out; @@ -813,6 +782,71 @@ iframe { } } + +//=======================================GENERAL======================================= + +.visibility-hidden { + visibility: hidden; +} + +.data-ellipsis { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} + +.cursor-pointer { + cursor: pointer; +} + +.capitalize { + text-transform: capitalize; +} + +.wrap { + white-space: pre-wrap; +} + +iframe { + width: 100%; + height: 100%; +} + +a { + color: inherit; + text-decoration: none; +} + +*, +::after, +::before { + box-sizing: border-box; +} + +* { + scrollbar-color: rgba($black, 0.25) rgba($black, 0.1); + scrollbar-width: thin; +} + +::-webkit-scrollbar { + width: 8px; + height: 8px; +} + +::-webkit-scrollbar-track { + background-color: rgba($black, 0.1); + border-radius: 10px; +} + +::-webkit-scrollbar-thumb { + background-color: rgba($black, 0.25); + border-radius: 10px; + + &:hover { + background-color: rgba($black, 0.4); + } +} + //TODO: Delete after removing Textarea and Input and using DRC components @mixin fieldWrapperOld { position: relative; diff --git a/src/utils/createArtifactsContent.js b/src/utils/createArtifactsContent.js index 32e440cad8..b4f187a3a3 100644 --- a/src/utils/createArtifactsContent.js +++ b/src/utils/createArtifactsContent.js @@ -18,7 +18,8 @@ under the Apache 2.0 license is conditioned upon your compliance with such restriction. */ import React from 'react' -import { isNumber } from 'lodash' +import { isEmpty, isNumber } from 'lodash' +import classnames from 'classnames' import { ARTIFACTS_PAGE, @@ -112,113 +113,124 @@ export const getIsTargetPathValid = (artifact, frontendSpec) => export const createModelsRowData = (artifact, project, frontendSpec, showExpandButton) => { const iter = getIter(artifact) - - return { - data: { - ...artifact - }, - content: [ - { - id: `key.${artifact.ui.identifierUnique}`, - headerId: 'name', - headerLabel: 'Name', - value: artifact.db_key, - class: 'table-cell-name', - getLink: tab => - validateArguments(artifact.db_key, tab, artifact.tree) - ? generateLinkToDetailsPanel( - project, - MODELS_TAB, - MODELS_TAB, - artifact.db_key, - artifact.tag, - tab, - artifact.tree, - artifact.iter - ) - : '', - expandedCellContent: { - class: 'table-cell-name', - showTag: true, - tooltip: artifact.tag ? `${artifact.tag}${iter}` : `${artifact.tree}${iter}`, - type: 'date', - value: formatDatetime(artifact.updated, 'N/A') - }, - rowExpanded: { - getLink: false - }, + const content = [ + { + id: `key.${artifact.ui.identifierUnique}`, + headerId: 'name', + headerLabel: 'Name', + value: artifact.db_key, + className: 'table-cell-name', + getLink: tab => + validateArguments(artifact.db_key, tab, artifact.tree) + ? generateLinkToDetailsPanel( + project, + MODELS_TAB, + MODELS_TAB, + artifact.db_key, + artifact.tag, + tab, + artifact.tree, + artifact.iter + ) + : '', + expandedCellContent: { + className: 'table-cell-name', showTag: true, - showExpandButton - }, - { - id: `labels.${artifact.ui.identifierUnique}`, - headerId: 'labels', - headerLabel: 'Labels', - value: parseKeyValues(artifact.labels), - class: 'table-cell-1', - type: 'labels' + tooltip: artifact.tag ? `${artifact.tag}${iter}` : `${artifact.tree}${iter}`, + type: 'date', + value: formatDatetime(artifact.updated, 'N/A') }, - { - id: `producer.${artifact.ui.identifierUnique}`, - headerId: 'producer', - headerLabel: 'Producer', - value: artifact.producer, - class: 'table-cell-1', - type: 'producer' + rowExpanded: { + getLink: false }, - { - id: `owner.${artifact.ui.identifierUnique}`, - headerId: 'owner', - headerLabel: 'Owner', - value: artifact.producer?.owner, - class: 'table-cell-1', - type: 'owner' - }, - { - id: `updated.${artifact.ui.identifierUnique}`, - headerId: 'updated', - headerLabel: 'Updated', - value: formatDatetime(artifact.updated, 'N/A'), - class: 'table-cell-1' - }, - { - id: `metrics.${artifact.ui.identifierUnique}`, - headerId: 'metrics', - headerLabel: 'Metrics', - value: parseKeyValues(artifact.metrics), - class: 'table-cell-1', - type: 'metrics' - }, - { - id: `frameWorkAndAlgorithm.${artifact.ui.identifierUnique}`, - headerId: 'frameWorkAndAlgorithm', - headerLabel: ( + showTag: true, + showExpandButton + }, + { + id: `labels.${artifact.ui.identifierUnique}`, + headerId: 'labels', + headerLabel: 'Labels', + value: parseKeyValues(artifact.labels), + className: 'table-cell-1', + type: 'labels' + }, + { + id: `producer.${artifact.ui.identifierUnique}`, + headerId: 'producer', + headerLabel: 'Producer', + value: artifact.producer, + className: 'table-cell-1', + type: 'producer' + }, + { + id: `owner.${artifact.ui.identifierUnique}`, + headerId: 'owner', + headerLabel: 'Owner', + value: artifact.producer?.owner, + className: 'table-cell-1', + type: 'owner' + }, + { + id: `updated.${artifact.ui.identifierUnique}`, + headerId: 'updated', + headerLabel: 'Updated', + value: formatDatetime(artifact.updated, 'N/A'), + className: 'table-cell-1' + }, + { + id: `frameWorkAndAlgorithm.${artifact.ui.identifierUnique}`, + headerId: 'frameWorkAndAlgorithm', + headerLabel: ( + + Framework & +
+ Algorithm +
+ ), + value: + artifact.framework || artifact.algorithm ? ( - Framework & + {artifact.framework}
- Algorithm + {artifact.algorithm}
+ ) : ( + '' ), - value: - artifact.framework || artifact.algorithm ? ( - - {artifact.framework} -
- {artifact.algorithm} -
- ) : ( - '' - ), - class: 'table-cell-1' - }, - { - id: `version.${artifact.ui.identifierUnique}`, - headerId: 'tag', - value: artifact.tag, - class: 'table-cell-1', - type: 'hidden' - } - ] + className: 'table-cell-1' + }, + { + id: `version.${artifact.ui.identifierUnique}`, + headerId: 'tag', + value: artifact.tag, + className: 'table-cell-1', + type: 'hidden' + } + ] + + if (artifact.metrics && !isEmpty(artifact.metrics)) { + Object.entries(artifact.metrics).forEach(([key, value], index) => { + const bodyCellClassName = classnames( + 'metrics-cell', + index === 0 && 'metrics-cell_with-border' + ) + + content.push({ + id: `${key}.${artifact.ui.identifierUnique}`, + headerId: key, + headerLabel: key, + value: parseFloat(value), + className: 'table-cell-1', + bodyCellClassName + }) + }) + } + + return { + data: { + ...artifact + }, + content } } @@ -235,7 +247,7 @@ export const createFilesRowData = (artifact, project, frontendSpec, showExpandBu headerId: 'name', headerLabel: 'Name', value: artifact.db_key, - class: 'table-cell-name', + className: 'table-cell-name', getLink: tab => validateArguments(artifact.db_key, tab, artifact.tree) ? generateLinkToDetailsPanel( @@ -250,7 +262,7 @@ export const createFilesRowData = (artifact, project, frontendSpec, showExpandBu ) : '', expandedCellContent: { - class: 'table-cell-name', + className: 'table-cell-name', showTag: true, tooltip: artifact.tag ? `${artifact.tag}${iter}` : `${artifact.tree}${iter}`, type: 'date', @@ -266,7 +278,7 @@ export const createFilesRowData = (artifact, project, frontendSpec, showExpandBu id: `version.${artifact.ui.identifierUnique}`, headerId: 'tag', value: artifact.tag, - class: 'table-cell-1', + className: 'table-cell-1', type: 'hidden' }, { @@ -274,14 +286,14 @@ export const createFilesRowData = (artifact, project, frontendSpec, showExpandBu headerId: 'type', headerLabel: 'Type', value: artifact.kind, - class: 'table-cell-small' + className: 'table-cell-small' }, { id: `labels.${artifact.ui.identifierUnique}`, headerId: 'labels', headerLabel: 'Labels', value: parseKeyValues(artifact.labels), - class: 'table-cell-1', + className: 'table-cell-1', type: 'labels' }, { @@ -289,7 +301,7 @@ export const createFilesRowData = (artifact, project, frontendSpec, showExpandBu headerId: 'producer', headerLabel: 'Producer', value: artifact.producer || {}, - class: 'table-cell-1', + className: 'table-cell-1', type: 'producer' }, { @@ -297,7 +309,7 @@ export const createFilesRowData = (artifact, project, frontendSpec, showExpandBu headerId: 'owner', headerLabel: 'Owner', value: artifact.producer?.owner, - class: 'table-cell-1', + className: 'table-cell-1', type: 'owner' }, { @@ -305,14 +317,14 @@ export const createFilesRowData = (artifact, project, frontendSpec, showExpandBu headerId: 'updated', headerLabel: 'Updated', value: formatDatetime(artifact.updated, 'N/A'), - class: 'table-cell-1' + className: 'table-cell-1' }, { id: `size.${artifact.ui.identifierUnique}`, headerId: 'size', headerLabel: 'Size', value: isNumber(artifact.size) && artifact.size >= 0 ? convertBytes(artifact.size) : 'N/A', - class: 'table-cell-1' + className: 'table-cell-1' } ] } @@ -352,7 +364,7 @@ export const createModelEndpointsRowData = (artifact, project) => { headerId: 'name', headerLabel: 'Name', value: name, - class: 'table-cell-name', + className: 'table-cell-name', getLink: tab => validateArguments(artifact.metadata?.uid, name) ? generateLinkToDetailsPanel( @@ -372,7 +384,7 @@ export const createModelEndpointsRowData = (artifact, project) => { headerId: 'function', headerLabel: 'Function', value: functionName, - class: 'table-cell-1', + className: 'table-cell-1', getLink: () => generateFunctionDetailsLink(artifact.spec?.function_uri), tooltip: functionUri }, @@ -380,7 +392,7 @@ export const createModelEndpointsRowData = (artifact, project) => { id: `state.${artifact.ui.identifierUnique}`, headerId: 'state', value: artifact.status?.state, - class: 'table-cell-small', + className: 'table-cell-small', type: 'hidden' }, { @@ -388,21 +400,21 @@ export const createModelEndpointsRowData = (artifact, project) => { headerId: 'version', headerLabel: 'Version', value: artifact?.status?.children ? 'Router' : tag, - class: 'table-cell-small' + className: 'table-cell-small' }, { id: `modelClass.${artifact.ui.identifierUnique}`, headerId: 'class', headerLabel: 'Class', value: artifact.spec?.model_class, - class: 'table-cell-1' + className: 'table-cell-1' }, { id: `labels.${artifact.ui.identifierUnique}`, headerId: 'labels', headerLabel: 'Labels', value: parseKeyValues(artifact.metadata?.labels), - class: 'table-cell-1', + className: 'table-cell-1', type: 'labels' }, { @@ -410,35 +422,35 @@ export const createModelEndpointsRowData = (artifact, project) => { headerId: 'uptime', headerLabel: 'Uptime', value: formatDatetime(artifact.status?.first_request, '-'), - class: 'table-cell-1' + className: 'table-cell-1' }, { id: `lastRequest.${artifact.ui.identifierUnique}`, headerId: 'lastprediction', headerLabel: 'Last prediction', value: formatDatetime(artifact.status?.last_request, '-'), - class: 'table-cell-1' + className: 'table-cell-1' }, { id: `averageLatency.${artifact.ui.identifierUnique}`, headerId: 'averagelatency', headerLabel: 'Average latency', value: averageLatency ? `${(averageLatency / 1000).toFixed(2)}ms` : '-', - class: 'table-cell-1' + className: 'table-cell-1' }, { id: `errorCount.${artifact.ui.identifierUnique}`, headerId: 'errorcount', headerLabel: 'Error count', value: artifact.status?.error_count ?? '-', - class: 'table-cell-1' + className: 'table-cell-1' }, { id: `driftStatus.${artifact.ui.identifierUnique}`, headerId: 'drift', headerLabel: 'Drift', value: driftStatusIcons[artifact.status?.drift_status]?.value, - class: 'table-cell-small', + className: 'table-cell-small', tooltip: driftStatusIcons[artifact.status?.drift_status]?.tooltip } ] @@ -458,7 +470,7 @@ export const createDatasetsRowData = (artifact, project, frontendSpec, showExpan headerId: 'name', headerLabel: 'Name', value: artifact.db_key, - class: 'table-cell-name', + className: 'table-cell-name', getLink: tab => validateArguments(artifact.db_key, tab, artifact.tree) ? generateLinkToDetailsPanel( @@ -473,7 +485,7 @@ export const createDatasetsRowData = (artifact, project, frontendSpec, showExpan ) : '', expandedCellContent: { - class: 'table-cell-name', + className: 'table-cell-name', showTag: true, tooltip: artifact.tag ? `${artifact.tag}${iter}` : `${artifact.tree}${iter}`, type: 'date', @@ -490,7 +502,7 @@ export const createDatasetsRowData = (artifact, project, frontendSpec, showExpan headerId: 'labels', headerLabel: 'Labels', value: parseKeyValues(artifact.labels), - class: 'table-cell-1', + className: 'table-cell-1', type: 'labels' }, { @@ -498,7 +510,7 @@ export const createDatasetsRowData = (artifact, project, frontendSpec, showExpan headerId: 'producer', headerLabel: 'Producer', value: artifact.producer, - class: 'table-cell-1', + className: 'table-cell-1', type: 'producer' }, { @@ -506,7 +518,7 @@ export const createDatasetsRowData = (artifact, project, frontendSpec, showExpan headerId: 'owner', headerLabel: 'Owner', value: artifact.producer?.owner, - class: 'table-cell-1', + className: 'table-cell-1', type: 'owner' }, { @@ -514,20 +526,20 @@ export const createDatasetsRowData = (artifact, project, frontendSpec, showExpan headerId: 'updated', headerLabel: 'Updated', value: formatDatetime(artifact.updated, 'N/A'), - class: 'table-cell-1' + className: 'table-cell-1' }, { id: `size.${artifact.ui.identifierUnique}`, headerId: 'size', headerLabel: 'Size', value: isNumber(artifact.size) && artifact.size >= 0 ? convertBytes(artifact.size) : 'N/A', - class: 'table-cell-1' + className: 'table-cell-1' }, { id: `version.${artifact.ui.identifierUnique}`, headerId: 'tag', value: artifact.tag, - class: 'table-cell-1', + className: 'table-cell-1', type: 'hidden' } ] diff --git a/src/utils/createConsumerGroupContent.js b/src/utils/createConsumerGroupContent.js index b151c9c9c6..59e36641e9 100644 --- a/src/utils/createConsumerGroupContent.js +++ b/src/utils/createConsumerGroupContent.js @@ -28,24 +28,24 @@ const createConsumerGroupsContent = content => { shardLagId: { id: `shardLagId.${identifier}`, value: contentItem.shardLagId, - class: 'table-cell-1', + className: 'table-cell-1', identifier: identifier, identifierUnique: identifier }, lagMsgBehind: { id: `lagMsgBehind.${identifier}`, value: contentItem.lag, - class: 'table-cell-1' + className: 'table-cell-1' }, lastSequence: { id: `lastSequence.${identifier}`, value: contentItem.current, - class: 'table-cell-1' + className: 'table-cell-1' }, committedOffset: { id: `committedOffset.${identifier}`, value: contentItem.committed, - class: 'table-cell-1' + className: 'table-cell-1' } } } diff --git a/src/utils/createConsumerGroupsContent.js b/src/utils/createConsumerGroupsContent.js index de3ebfe8cd..db9ea22f54 100644 --- a/src/utils/createConsumerGroupsContent.js +++ b/src/utils/createConsumerGroupsContent.js @@ -29,7 +29,7 @@ const createConsumerGroupsContent = (content, params) => { consumerGroup: { id: `consumerGroup.${identifier}`, value: contentItem?.consumerGroup, - class: 'table-cell-1 text-bold', + className: 'table-cell-1 text-bold', identifier: identifier, identifierUnique: identifier, getLink: () => { @@ -39,7 +39,7 @@ const createConsumerGroupsContent = (content, params) => { streamPath: { id: `streamPath.${identifier}`, value: contentItem?.containerName + contentItem?.streamPath, - class: 'table-cell-1' + className: 'table-cell-1' }, realTimeFunction: { id: `realTimeFunction.${identifier}`, @@ -50,7 +50,7 @@ const createConsumerGroupsContent = (content, params) => { ) }, linkIsExternal: true, - class: 'table-cell-1' + className: 'table-cell-1' } } } diff --git a/src/utils/createFeatureStoreContent.js b/src/utils/createFeatureStoreContent.js index d4a9ecb1dc..1a2707777b 100644 --- a/src/utils/createFeatureStoreContent.js +++ b/src/utils/createFeatureStoreContent.js @@ -63,7 +63,7 @@ export const createFeatureSetsRowData = (featureSet, pageTab, project, showExpan headerId: 'name', headerLabel: 'Name', value: featureSet.name, - class: 'table-cell-name', + className: 'table-cell-name', getLink: tab => validateArguments(featureSet.name, featureSet.tag, tab) ? generateLinkToDetailsPanel( @@ -92,21 +92,21 @@ export const createFeatureSetsRowData = (featureSet, pageTab, project, showExpan headerId: 'description', headerLabel: 'Description', value: featureSet.description, - class: 'table-cell-2' + className: 'table-cell-2' }, { id: `labels.${featureSet.ui.identifierUnique}`, headerId: 'labels', headerLabel: 'Labels', value: parseKeyValues(featureSet.labels), - class: 'table-cell-4', + className: 'table-cell-4', type: 'labels' }, { id: `version.${featureSet.ui.identifierUnique}`, headerId: 'tag', value: featureSet.tag, - class: 'table-cell-2', + className: 'table-cell-2', type: 'hidden' }, { @@ -115,14 +115,14 @@ export const createFeatureSetsRowData = (featureSet, pageTab, project, showExpan headerLabel: 'Entities', value: featureSet.entities?.slice(0, 2).map(entity => entity.name) || '', type: 'labels', - class: 'table-cell-2' + className: 'table-cell-2' }, { ...getFeatureSetTargetCellValue(featureSet.targets) }, { id: `buttonCopy.${featureSet.ui.identifierUnique}`, headerId: 'copy', value: '', - class: 'table-cell-icon', + className: 'table-cell-icon', type: BUTTON_COPY_URI_CELL_TYPE, actionHandler: item => generateUri(item, pageTab) } @@ -142,7 +142,7 @@ export const createFeaturesRowData = (feature, isTablePanelOpen, showExpandButto headerLabel: 'Feature Name', type: feature.ui.type, value: feature.name, - class: 'table-cell-name', + className: 'table-cell-name', expandedCellContent: { class: 'table-cell-name', value: feature.metadata?.tag @@ -154,7 +154,7 @@ export const createFeaturesRowData = (feature, isTablePanelOpen, showExpandButto headerId: 'featureset', headerLabel: 'Feature set', value: feature.metadata?.name, - class: 'table-cell-2', + className: 'table-cell-2', getLink: tab => validateArguments(feature.metadata?.name, feature.metadata?.tag, tab) ? generateLinkToDetailsPanel( @@ -167,7 +167,7 @@ export const createFeaturesRowData = (feature, isTablePanelOpen, showExpandButto ) : '', expandedCellContent: { - class: 'table-cell-2', + className: 'table-cell-2', value: '' }, rowExpanded: { @@ -189,7 +189,7 @@ export const createFeaturesRowData = (feature, isTablePanelOpen, showExpandButto headerId: 'type', headerLabel: 'Type', value: feature.value_type, - class: 'table-cell-1' + className: 'table-cell-1' }, { id: `entity.${feature.ui.identifierUnique}`, @@ -197,21 +197,21 @@ export const createFeaturesRowData = (feature, isTablePanelOpen, showExpandButto headerLabel: 'Entities', type: 'labels', value: feature.spec?.entities.map(entity => entity.name) || '', - class: 'table-cell-2' + className: 'table-cell-2' }, { id: `description.${feature.ui.identifierUnique}`, headerId: 'description', headerLabel: 'Description', value: feature?.description ?? '', - class: 'table-cell-2' + className: 'table-cell-2' }, { id: `labels.${feature.ui.identifierUnique}`, headerId: 'labels', headerLabel: 'Labels', value: parseKeyValues(feature.labels), - class: 'table-cell-4', + className: 'table-cell-4', type: 'labels', hidden: isTablePanelOpen }, @@ -224,7 +224,7 @@ export const createFeaturesRowData = (feature, isTablePanelOpen, showExpandButto headerId: 'validator', headerLabel: 'Validator', value: , - class: 'table-cell-2', + className: 'table-cell-2', type: 'component', hidden: isTablePanelOpen }, @@ -232,7 +232,7 @@ export const createFeaturesRowData = (feature, isTablePanelOpen, showExpandButto id: `addFeature.${feature.ui.identifierUnique}`, headerId: 'addfeature', value: feature.ui.type === 'feature' && , - class: 'table-cell-2 align-right', + className: 'table-cell-2 align-right', type: 'component', hidden: !isTablePanelOpen } @@ -268,7 +268,7 @@ const getFeatureSetTargetCellValue = (targets, identifierUnique) => ({ ) .sort((icon, otherIcon) => (icon.tooltip < otherIcon.tooltip ? -1 : 1)), id: `targets.${identifierUnique}`, - class: 'targets-cell table-cell-2', + className: 'targets-cell table-cell-2', type: 'icons' }) @@ -283,7 +283,7 @@ export const createFeatureVectorsRowData = (featureVector, pageTab, project, sho headerId: 'name', headerLabel: 'Name', value: featureVector.name, - class: 'table-cell-name', + className: 'table-cell-name', getLink: tab => validateArguments(featureVector.name, featureVector.tag, tab) ? generateLinkToDetailsPanel( @@ -312,21 +312,21 @@ export const createFeatureVectorsRowData = (featureVector, pageTab, project, sho headerId: 'description', headerLabel: 'Description', value: featureVector.description, - class: 'table-cell-3' + className: 'table-cell-3' }, { id: `labels.${featureVector.ui.identifierUnique}`, headerId: 'labels', headerLabel: 'Labels', value: parseKeyValues(featureVector.labels), - class: 'table-cell-4', + className: 'table-cell-4', type: 'labels' }, { id: `version.${featureVector.ui.identifierUnique}`, headerId: 'tag', value: featureVector.tag, - class: 'table-cell-2', + className: 'table-cell-2', type: 'hidden' }, { @@ -334,14 +334,14 @@ export const createFeatureVectorsRowData = (featureVector, pageTab, project, sho headerId: 'entities', headerLabel: 'Entities', value: featureVector.index_keys?.join(', ') ?? '', - class: 'table-cell-2' + className: 'table-cell-2' }, { id: `updated.${featureVector.ui.identifierUnique}`, headerId: 'updated', headerLabel: 'Updated', value: featureVector.updated ? formatDatetime(featureVector.updated, 'N/A') : 'N/A', - class: 'table-cell-2', + className: 'table-cell-2', showTag: true, showStatus: true }, @@ -349,7 +349,7 @@ export const createFeatureVectorsRowData = (featureVector, pageTab, project, sho id: `buttonCopy.${featureVector.ui.identifierUnique}`, headerId: 'copy', value: '', - class: 'table-cell-icon', + className: 'table-cell-icon', type: BUTTON_COPY_URI_CELL_TYPE, actionHandler: item => generateUri(item, pageTab) }, @@ -357,7 +357,7 @@ export const createFeatureVectorsRowData = (featureVector, pageTab, project, sho id: `uid.${featureVector.ui.identifierUnique}`, headerId: 'featurevectoruid', value: featureVector.uid, - class: 'table-cell-2', + className: 'table-cell-2', type: 'hidden' } ] diff --git a/src/utils/createFunctionsContent.js b/src/utils/createFunctionsContent.js index a837220d60..8f2918ff3a 100644 --- a/src/utils/createFunctionsContent.js +++ b/src/utils/createFunctionsContent.js @@ -36,7 +36,7 @@ const createFunctionsContent = (functions, pageTab, projectName, showExpandButto headerId: 'name', headerLabel: 'Name', value: func.name, - class: 'table-cell-name', + className: 'table-cell-name', getLink: hash => { return `/projects/${projectName}/${MODELS_PAGE.toLowerCase()}/${REAL_TIME_PIPELINES_TAB}/pipeline/${hash}` }, @@ -44,7 +44,7 @@ const createFunctionsContent = (functions, pageTab, projectName, showExpandButto showStatus: true, expandedCellContent: { value: formatDatetime(func.updated, 'N/A'), - class: 'table-cell-name', + className: 'table-cell-name', type: 'date', showTag: true, showStatus: true @@ -56,7 +56,7 @@ const createFunctionsContent = (functions, pageTab, projectName, showExpandButto headerId: 'type', headerLabel: 'Type', value: func.graph?.kind === 'router' ? 'Router' : 'Flow', - class: 'table-cell-small', + className: 'table-cell-small', type: 'type' }, { @@ -64,7 +64,7 @@ const createFunctionsContent = (functions, pageTab, projectName, showExpandButto headerId: 'function', headerLabel: 'Function', value: func.name, - class: 'table-cell-2', + className: 'table-cell-2', getLink: tab => validateArguments(func.hash, tab) ? generateLinkToDetailsPanel( @@ -81,7 +81,7 @@ const createFunctionsContent = (functions, pageTab, projectName, showExpandButto id: `updated.${func.ui.identifierUnique}`, headerId: 'updated', value: formatDatetime(func.updated, 'N/A'), - class: 'table-cell-2', + className: 'table-cell-2', type: 'date', showTag: true, showStatus: true, @@ -99,13 +99,13 @@ const createFunctionsContent = (functions, pageTab, projectName, showExpandButto headerId: 'name', headerLabel: 'Name', value: func.name, - class: 'table-cell-name', + className: 'table-cell-name', getLink: (hash, tab) => { return `/projects/${projectName}/functions/${hash}${`/${tab}`}` }, expandedCellContent: { value: formatDatetime(func.updated, 'N/A'), - class: 'table-cell-name', + className: 'table-cell-name', type: 'date', showTag: true, showStatus: true @@ -119,7 +119,7 @@ const createFunctionsContent = (functions, pageTab, projectName, showExpandButto headerId: 'kind', headerLabel: 'Kind', value: func.type, - class: 'table-cell-small', + className: 'table-cell-small', type: 'type' }, { @@ -127,7 +127,7 @@ const createFunctionsContent = (functions, pageTab, projectName, showExpandButto headerId: 'hash', headerLabel: 'Hash', value: func.hash, - class: 'table-cell-1', + className: 'table-cell-1', type: 'hash' }, { @@ -135,7 +135,7 @@ const createFunctionsContent = (functions, pageTab, projectName, showExpandButto headerId: 'updated', headerLabel: 'Updated', value: formatDatetime(func.updated, 'N/A'), - class: 'table-cell-2', + className: 'table-cell-2', type: 'date', showTag: true, showStatus: true @@ -145,21 +145,21 @@ const createFunctionsContent = (functions, pageTab, projectName, showExpandButto headerId: 'command', headerLabel: 'Command', value: func.command, - class: 'table-cell-1' + className: 'table-cell-1' }, { id: `image.${func.ui.identifierUnique}`, headerId: 'image', headerLabel: 'Image', value: getFunctionImage(func), - class: 'table-cell-1' + className: 'table-cell-1' }, { id: `description.${func.ui.identifierUnique}`, headerId: 'description', headerLabel: 'Description', value: func.description, - class: 'table-cell-2' + className: 'table-cell-2' }, { id: `tag.${func.ui.identifierUnique}`, diff --git a/src/utils/createJobsContent.js b/src/utils/createJobsContent.js index fa29e5b9ec..738187c94f 100644 --- a/src/utils/createJobsContent.js +++ b/src/utils/createJobsContent.js @@ -72,7 +72,7 @@ export const createJobsMonitorTabContent = (jobs, jobName, isStagingMode) => { headerLabel: jobName ? 'UID' : 'Name', id: `name.${identifierUnique}`, value: jobName ? job.uid || job.id : job.name, - class: 'table-cell-name', + className: 'table-cell-name', type: type === JOB_KIND_WORKFLOW && !isStagingMode ? 'hidden' : 'link', getLink, showStatus: true @@ -82,14 +82,14 @@ export const createJobsMonitorTabContent = (jobs, jobName, isStagingMode) => { headerLabel: 'Type', id: `type.${identifierUnique}`, value: type, - class: 'table-cell-1', + className: 'table-cell-1', type: 'type' }, { headerId: 'job.uid', id: `uid.${identifierUnique}`, value: job.uid || job.id, - class: 'table-cell-1', + className: 'table-cell-1', type: 'hidden' }, { @@ -101,7 +101,7 @@ export const createJobsMonitorTabContent = (jobs, jobName, isStagingMode) => { (job.state?.value !== 'running' && job.updated) || (job.state?.value !== 'error' && new Date(job.finished_at)) ), - class: 'table-cell-1', + className: 'table-cell-1', type: 'duration' }, { @@ -109,14 +109,14 @@ export const createJobsMonitorTabContent = (jobs, jobName, isStagingMode) => { headerLabel: 'Owner', id: `owner.${identifierUnique}`, value: job.owner, - class: 'table-cell-1' + className: 'table-cell-1' }, { headerId: 'labels', headerLabel: 'Labels', id: `labels.${identifierUnique}`, value: job.labels, - class: 'table-cell-1', + className: 'table-cell-1', type: 'labels' }, { @@ -124,7 +124,7 @@ export const createJobsMonitorTabContent = (jobs, jobName, isStagingMode) => { headerLabel: 'Parameters', id: `parameters.${identifierUnique}`, value: job.parametersChips, - class: 'table-cell-1', + className: 'table-cell-1', type: 'parameters' }, { @@ -132,14 +132,14 @@ export const createJobsMonitorTabContent = (jobs, jobName, isStagingMode) => { headerLabel: 'Results', id: `resultsChips.${identifierUnique}`, value: job.resultsChips, - class: 'table-cell-3', + className: 'table-cell-3', type: 'results' }, { headerId: 'updated', id: `updated.${identifierUnique}`, value: job.updated || new Date(job.finished_at), - class: 'table-cell-1', + className: 'table-cell-1', type: 'hidden' } ] @@ -174,7 +174,7 @@ export const createJobsScheduleTabContent = jobs => { headerLabel: 'Name', id: `name.${identifierUnique}`, value: job.name, - class: 'table-cell-name', + className: 'table-cell-name', showStatus: true, getLink: tab => validateArguments(scheduleJobFunctionUid, tab) @@ -194,7 +194,7 @@ export const createJobsScheduleTabContent = jobs => { headerLabel: 'Type', id: `type.${identifierUnique}`, value: job.type, - class: 'table-cell-small', + className: 'table-cell-small', type: 'type' }, { @@ -202,7 +202,7 @@ export const createJobsScheduleTabContent = jobs => { headerLabel: 'Next run (Local TZ)', id: `nextRun.${identifierUnique}`, value: formatDatetime(job.nextRun), - class: 'table-cell-1', + className: 'table-cell-1', type: 'date' }, { @@ -210,7 +210,7 @@ export const createJobsScheduleTabContent = jobs => { headerLabel: 'Schedule (UTC)', id: `schedule.${identifierUnique}`, value: job.scheduled_object?.schedule || null, - class: 'table-cell-1', + className: 'table-cell-1', tip: 'The first day of the week (0) is Monday, and not Sunday.' }, { @@ -218,7 +218,7 @@ export const createJobsScheduleTabContent = jobs => { headerLabel: 'Labels', id: `labels.${identifierUnique}`, value: parseKeyValues(job.scheduled_object?.task.metadata.labels || {}), - class: 'table-cell-1', + className: 'table-cell-1', type: 'labels' }, { @@ -226,7 +226,7 @@ export const createJobsScheduleTabContent = jobs => { headerLabel: 'Last run (Local TZ)', id: `lastRun.${identifierUnique}`, value: formatDatetime(job.startTime), - class: 'table-cell-1', + className: 'table-cell-1', getLink: lastRunLink }, { @@ -234,14 +234,14 @@ export const createJobsScheduleTabContent = jobs => { headerLabel: 'Created time (Local TZ)', id: `createdTime.${identifierUnique}`, value: formatDatetime(job.createdTime, 'Not yet started'), - class: 'table-cell-1', + className: 'table-cell-1', type: 'date' }, { headerId: 'function', id: `func.${identifierUnique}`, value: job.func, - class: '', + className: '', type: 'hidden' } ] @@ -269,7 +269,7 @@ export const createJobsWorkflowsTabContent = (jobs, projectName, isStagingMode, headerLabel: 'Name', id: `name.${identifierUnique}`, value: jobName, - class: 'table-cell-name', + className: 'table-cell-name', type: 'link', getLink: () => { return getWorkflowDetailsLink(projectName, job.id, null, null, MONITOR_WORKFLOWS_TAB) @@ -280,7 +280,7 @@ export const createJobsWorkflowsTabContent = (jobs, projectName, isStagingMode, headerId: 'uid', id: `uid.${identifierUnique}`, value: job?.id, - class: 'table-cell-1', + className: 'table-cell-1', type: 'hidden', hidden: isSelectedItem }, @@ -289,7 +289,7 @@ export const createJobsWorkflowsTabContent = (jobs, projectName, isStagingMode, headerLabel: 'Created at', id: `createdAt.${identifierUnique}`, value: formatDatetime(job.created_at, 'N/A'), - class: 'table-cell-1', + className: 'table-cell-1', hidden: isSelectedItem }, { @@ -297,7 +297,7 @@ export const createJobsWorkflowsTabContent = (jobs, projectName, isStagingMode, headerLabel: 'Finished at', id: `finishedAt.${identifierUnique}`, value: formatDatetime(job.finished_at, 'N/A'), - class: 'table-cell-1', + className: 'table-cell-1', hidden: isSelectedItem }, { @@ -309,7 +309,7 @@ export const createJobsWorkflowsTabContent = (jobs, projectName, isStagingMode, (job.state?.value !== 'running' && job.updated) || (job.state?.value !== 'error' && new Date(job.finished_at)) ), - class: 'table-cell-1', + className: 'table-cell-1', type: 'duration', hidden: isSelectedItem }, @@ -317,7 +317,7 @@ export const createJobsWorkflowsTabContent = (jobs, projectName, isStagingMode, headerId: 'updated', id: `updated.${identifierUnique}`, value: job.updated || new Date(job.finished_at), - class: 'table-cell-1', + className: 'table-cell-1', type: 'hidden', hidden: isSelectedItem } @@ -352,7 +352,7 @@ export const createJobsWorkflowContent = ( headerLabel: 'Name', id: `name.${identifierUnique}`, value: jobName, - class: 'table-cell-name', + className: 'table-cell-name', type: 'link', getLink: tab => { return getWorkflowDetailsLink( @@ -370,7 +370,7 @@ export const createJobsWorkflowContent = ( headerLabel: 'Kind', id: `kind.${identifierUnique}`, value: job.run_type, - class: 'table-cell-1', + className: 'table-cell-1', type: 'type', hidden: isSelectedItem }, @@ -378,7 +378,7 @@ export const createJobsWorkflowContent = ( headerId: 'uid', id: `uid.${identifierUnique}`, value: job.uid || job.id, - class: 'table-cell-1', + className: 'table-cell-1', type: 'hidden', hidden: isSelectedItem }, @@ -387,7 +387,7 @@ export const createJobsWorkflowContent = ( headerLabel: 'Started at', id: `startedAt.${identifierUnique}`, value: formatDatetime(job.startedAt, 'N/A'), - class: 'table-cell-1', + className: 'table-cell-1', hidden: isSelectedItem }, { @@ -395,7 +395,7 @@ export const createJobsWorkflowContent = ( headerLabel: 'Finished at', id: `finishedAt.${identifierUnique}`, value: formatDatetime(job.finishedAt, 'N/A'), - class: 'table-cell-1', + className: 'table-cell-1', hidden: isSelectedItem }, { @@ -406,7 +406,7 @@ export const createJobsWorkflowContent = ( new Date(job.startedAt), job.state?.value !== 'error' && new Date(job.finishedAt) ), - class: 'table-cell-1', + className: 'table-cell-1', type: 'duration', hidden: isSelectedItem } diff --git a/src/utils/generateTableHeaders.js b/src/utils/generateTableHeaders.js new file mode 100644 index 0000000000..cb63371b2a --- /dev/null +++ b/src/utils/generateTableHeaders.js @@ -0,0 +1,30 @@ +/* +Copyright 2019 Iguazio Systems Ltd. + +Licensed under the Apache License, Version 2.0 (the "License") with +an addition restriction as set forth herein. 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. + +In addition, you may not use the software for any purposes that are +illegal under applicable law, and the grant of the foregoing license +under the Apache 2.0 license is conditioned upon your compliance with +such restriction. +*/ + +export const generateTableHeaders = tableContent => { + return tableContent + .filter(tableItem => tableItem.type !== 'hidden') + .map(tableItem => ({ + headerId: tableItem.headerId, + headerLabel: tableItem.headerLabel, + className: tableItem.className, + headerCellClassName: tableItem.headerCellClassName + })) +}