From 109bc75608956a0621d069e3dfdfcea603ff9605 Mon Sep 17 00:00:00 2001 From: Taras Hlukhovetskyi Date: Thu, 6 Nov 2025 15:29:45 +0200 Subject: [PATCH 1/8] =?UTF-8?q?Fix=20UI=20crash=20in=20=E2=80=98Monitoring?= =?UTF-8?q?=20app'=20screen=20upon=20navigate=20to=20app=20and=20select=20?= =?UTF-8?q?=E2=80=9CPast=20month=E2=80=9D=20filter?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MEPsWithDetections.jsx | 2 +- .../MonitoringApplication.jsx | 2 +- .../MonitoringApplications.jsx | 2 +- .../monitoringApplicationsPage.scss | 15 +- src/elements/SectionTable/SectionTable.jsx | 251 ++++++++++-------- src/elements/SectionTable/SectionTable.scss | 203 +++++++------- 6 files changed, 267 insertions(+), 208 deletions(-) diff --git a/src/components/MonitoringApplicationsPage/MonitoringApplications/MEPsWithDetections.jsx b/src/components/MonitoringApplicationsPage/MonitoringApplications/MEPsWithDetections.jsx index 72bab9a527..9a6525b6d7 100644 --- a/src/components/MonitoringApplicationsPage/MonitoringApplications/MEPsWithDetections.jsx +++ b/src/components/MonitoringApplicationsPage/MonitoringApplications/MEPsWithDetections.jsx @@ -125,7 +125,7 @@ const MEPsWithDetections = () => { }, [barConfig, endpointsWithDetectionsData, renderPlugin]) return ( -
+
Model endpoints with suspected/detected issue diff --git a/src/components/MonitoringApplicationsPage/MonitoringApplications/MonitoringApplication/MonitoringApplication.jsx b/src/components/MonitoringApplicationsPage/MonitoringApplications/MonitoringApplication/MonitoringApplication.jsx index e93ce64f8a..08b7f1a6ca 100644 --- a/src/components/MonitoringApplicationsPage/MonitoringApplications/MonitoringApplication/MonitoringApplication.jsx +++ b/src/components/MonitoringApplicationsPage/MonitoringApplications/MonitoringApplication/MonitoringApplication.jsx @@ -75,7 +75,7 @@ const MonitoringApplication = () => { ) : ( <> - + {
-
+
System functions diff --git a/src/components/MonitoringApplicationsPage/monitoringApplicationsPage.scss b/src/components/MonitoringApplicationsPage/monitoringApplicationsPage.scss index db6aeb07b6..b37128ba16 100644 --- a/src/components/MonitoringApplicationsPage/monitoringApplicationsPage.scss +++ b/src/components/MonitoringApplicationsPage/monitoringApplicationsPage.scss @@ -35,6 +35,7 @@ $applicationRowHeightExtended: variables.$rowHeightExtended; .monitoring-app__section-item { display: flex; flex-direction: column; + max-height: 410px; padding: 20px; color: colors.$topaz; background-color: colors.$white; @@ -43,6 +44,10 @@ $applicationRowHeightExtended: variables.$rowHeightExtended; box-shadow: shadows.$previewBoxShadowInit; transition: all 0.3s ease-in-out; + &-small { + max-height: 355px; + } + .section-item_title { display: flex; align-items: center; @@ -59,9 +64,9 @@ $applicationRowHeightExtended: variables.$rowHeightExtended; .applications-table { @include mixins.rowsHeight( - $applicationHeaderRowHeight, - $applicationRowHeight, - $applicationRowHeightExtended + $applicationHeaderRowHeight, + $applicationRowHeight, + $applicationRowHeightExtended ); } @@ -92,8 +97,8 @@ $applicationRowHeightExtended: variables.$rowHeightExtended; left: 50%; font-weight: 500; font-size: 13px; - transform: translate(-50%, 0); - } + transform: translate(-50%, 0); + } &.loading { visibility: hidden; diff --git a/src/elements/SectionTable/SectionTable.jsx b/src/elements/SectionTable/SectionTable.jsx index 0836042da7..0afff97e04 100644 --- a/src/elements/SectionTable/SectionTable.jsx +++ b/src/elements/SectionTable/SectionTable.jsx @@ -17,24 +17,51 @@ 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. */ -import React from 'react' +import React, { useMemo, useState } from 'react' import PropTypes from 'prop-types' import classnames from 'classnames' import { Link } from 'react-router-dom' +import { v4 as uuidv4 } from 'uuid' import { TableTypeCell } from 'igz-controls/elements' import { TextTooltipTemplate, Tooltip, Tip, Loader, ReadOnlyChips } from 'igz-controls/components' +import { isRowRendered, useVirtualization } from '../../hooks/useVirtualization.hook' import './SectionTable.scss' -const SectionTable = ({ loading = false, params, table }) => { +const SectionTable = ({ headerHeight = 41, loading = false, params, rowHeight = 41, table }) => { + const [tableId] = useState(`section-table-${uuidv4()}`) + const [tableBodyId] = useState(`section-table-body-${uuidv4()}`) + + const rowsSizes = useMemo( + () => (table?.body?.length ? new Array(table.body.length).fill(parseInt(rowHeight)) : []), + [rowHeight, table.body.length] + ) + + const heightData = useMemo( + () => ({ + headerRowHeight: headerHeight, + rowHeight: rowHeight, + rowHeightExtended: rowHeight + }), + [headerHeight, rowHeight] + ) + + const virtualizationConfig = useVirtualization({ + renderTriggerItem: table, + heightData, + rowsSizes, + tableBodyId: tableBodyId, + tableId: tableId + }) + return loading ? ( ) : ( - <> - +
+
- + <> {table.header.map( header => @@ -53,94 +80,112 @@ const SectionTable = ({ loading = false, params, table }) => { - + {table.body.map((body, index) => { const extractedItemName = body['name'].value.startsWith(params.projectName) ? body['name'].value.slice(params.projectName.length + 1) : body['name'].value return ( - - <> - {Object.keys(body).map((key, index) => { - const tableValueClassName = classnames( - 'section-table__table-cell', - body[key].className, - key === 'name' && 'name-wrapper', - key === 'status' && 'status-cell', - key === 'status' && - !Array.isArray(body[key].value) && - `status_${body?.[key]?.value?.toLowerCase?.()} capitalize` - ) + isRowRendered(virtualizationConfig, index) && ( + + <> + {Object.keys(body).map((key, index) => { + const tableValueClassName = classnames( + 'section-table__table-cell', + body[key].className, + key === 'name' && 'name-wrapper', + key === 'status' && 'status-cell', + key === 'status' && + !Array.isArray(body[key].value) && + `status_${body?.[key]?.value?.toLowerCase?.()} capitalize` + ) - return ( - !body[key].hidden && - (key === 'type' ? ( - - ) : ( - - )) - ) - })} - - + {body[key].status && ( + } + > + + + )} + + )} + + )) + ) + })} + + + ) ) })}
- {key === 'name' ? ( - <> - {body[key].href ? ( - - } - textShow={true} + return ( + !body[key].hidden && + (key === 'type' ? ( + + ) : ( + + {key === 'name' ? ( + <> + {body[key].href ? ( + - {extractedItemName} - - - ) : body[key].link ? ( - + } + textShow={true} + > + {extractedItemName} + + + ) : body[key].link ? ( + + } + > + {body[key].value} + + + ) : ( } > {body[key].value} - - ) : ( - } - > - {body[key].value} - - )} + )} - {body[key].tag ? ( - } - > - {body[key].tag} - - ) : null} - - ) : key === 'labels' ? ( - - ) : key === 'status' ? ( - <> - {Array.isArray(body.status.value) ? ( - body.status.value.map((status, index) => { - return ( - } - > - - - ) - }) - ) : ( + {body[key].tag ? ( + } + > + {body[key].tag} + + ) : null} + + ) : key === 'labels' ? ( + + ) : key === 'status' ? ( + <> + {Array.isArray(body.status.value) ? ( + body.status.value.map((status, index) => { + return ( + } + > + + + ) + }) + ) : ( + + } + > + {body[key].value} + + )} + + ) : ( + <> { > {body[key].value} - )} - - ) : ( - <> - - } - > - {body[key].value} - - {body[key].status && ( - } - > - - - )} - - )} -
- +
) } SectionTable.propTypes = { + headerHeight: PropTypes.number, loading: PropTypes.bool, params: PropTypes.object.isRequired, + rowHeight: PropTypes.number, table: PropTypes.object.isRequired } diff --git a/src/elements/SectionTable/SectionTable.scss b/src/elements/SectionTable/SectionTable.scss index 2da8cf9e53..92443d4564 100644 --- a/src/elements/SectionTable/SectionTable.scss +++ b/src/elements/SectionTable/SectionTable.scss @@ -18,73 +18,92 @@ } } -.section-table { - min-width: fit-content; +.section-table__wrapper { + display: flex; + flex-direction: column; height: 100%; - border: borders.$dividerBorder; - border-radius: 8px; - - &__table { - &-body { - display: flex; - flex: 1; - flex-direction: column; - } - - &-row { - display: flex; - flex: 1; - flex-direction: row; - border-bottom: borders.$tertiaryBorder; - } + overflow-y: auto; - &-link { + .section-table { + position: relative; + display: flex; + flex: 1; + flex-flow: column nowrap; + min-width: fit-content; + height: 100%; + overflow-y: auto; + border: borders.$dividerBorder; + border-radius: 8px; + will-change: scroll-position; + + thead { + position: sticky; + top: 0; + z-index: 3; min-width: 100%; - max-width: 50px; + background: colors.$white; } - &-cell { - display: flex; - align-items: center; - padding: 8px 5px 8px 0; - color: colors.$primary; - line-height: 24px; - - &.status { - color: colors.$supernova; - text-transform: none; - - &_completed, - &_ready, - &_running { - color: colors.$java; - } + &__table { + &-body { + display: flex; + flex-direction: column; + } + + &-row { + display: flex; + flex-direction: row; + min-width: 100%; + border-bottom: borders.$tertiaryBorder; + } + + &-link { + min-width: 100%; + max-width: 50px; + } - &-nuclio { - &_ready { - color: colors.$brightTurquoise; + &-cell { + display: flex; + align-items: center; + padding: 8px 5px 8px 0; + color: colors.$primary; + line-height: 24px; + + &.status { + color: colors.$supernova; + text-transform: none; + + &_completed, + &_ready, + &_running { + color: colors.$java; + } + + &-nuclio { + &_ready { + color: colors.$brightTurquoise; - &.disabled { + &.disabled { + color: colors.$topaz; + } + } + + &_scaledToZero { color: colors.$topaz; } } - &_scaledToZero { - color: colors.$topaz; + &_failed, + &_error, + &_unhealthy { + color: colors.$amaranth; } - } - &_failed, - &_error, - &_unhealthy { - color: colors.$amaranth; + &_imported { + color: colors.$topaz; + } } - &_imported { - color: colors.$topaz; - } - } - .tooltip-wrapper { min-width: 8px; } @@ -93,60 +112,60 @@ margin-left: 5px; } - &.name-wrapper { - display: flex; - flex-wrap: wrap; + &.name-wrapper { + display: flex; + flex-wrap: wrap; + + &.table-cell_with-tag { + gap: 4px; + height: 57px; + } + + .item-name { + width: 100%; + } - &.table-cell_with-tag { - gap: 4px; - height: 57px; + .item-tag { + display: inline; + max-width: 150px; + color: colors.$topaz; + line-height: 16px; + } } - .item-name { - width: 100%; + .table-body__cell { + &_type { + display: flex; + align-items: center; + padding: 0; + } } - .item-tag { - display: inline; - max-width: 150px; - color: colors.$topaz; - line-height: 16px; + &:first-child { + padding-left: 15px; } } - .table-body__cell { - &_type { - display: flex; - align-items: center; - padding: 0; + &-header { + display: flex; + font-size: 14px; + line-height: 24px; + border-bottom: borders.$tertiaryBorder; + + .table-header-item { + color: colors.$topaz; + font-weight: bold; } } - &:first-child { - padding-left: 15px; + .table-body__cell { + align-items: center; + border: none; } - } - &-header { - display: flex; - flex: 1; - font-size: 14px; - line-height: 24px; - border-bottom: borders.$tertiaryBorder; - - .table-header-item { - color: colors.$topaz; - font-weight: bold; + .tooltip__text { + display: initial; } } - - .table-body__cell { - align-items: center; - border: none; - } - - .tooltip__text { - display: initial; - } } } From 6b017f67d493c55dc1484f6e94818c92d3b70c20 Mon Sep 17 00:00:00 2001 From: Taras Hlukhovetskyi Date: Thu, 6 Nov 2025 18:44:48 +0200 Subject: [PATCH 2/8] =?UTF-8?q?Fix=20UI=20crash=20in=20=E2=80=98Monitoring?= =?UTF-8?q?=20app'=20screen=20upon=20navigate=20to=20app=20and=20select=20?= =?UTF-8?q?=E2=80=9CPast=20month=E2=80=9D=20filter?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MEPsWithDetections.jsx | 2 +- .../MonitoringApplication.jsx | 6 +- .../monitoringApplication.scss | 7 +- .../MonitoringApplications.jsx | 4 +- .../monitoringApplicationsPage.scss | 5 - src/elements/SectionTable/SectionTable.jsx | 297 +++++++++--------- src/elements/SectionTable/SectionTable.scss | 11 +- 7 files changed, 172 insertions(+), 160 deletions(-) diff --git a/src/components/MonitoringApplicationsPage/MonitoringApplications/MEPsWithDetections.jsx b/src/components/MonitoringApplicationsPage/MonitoringApplications/MEPsWithDetections.jsx index 9a6525b6d7..72bab9a527 100644 --- a/src/components/MonitoringApplicationsPage/MonitoringApplications/MEPsWithDetections.jsx +++ b/src/components/MonitoringApplicationsPage/MonitoringApplications/MEPsWithDetections.jsx @@ -125,7 +125,7 @@ const MEPsWithDetections = () => { }, [barConfig, endpointsWithDetectionsData, renderPlugin]) return ( -
+
Model endpoints with suspected/detected issue diff --git a/src/components/MonitoringApplicationsPage/MonitoringApplications/MonitoringApplication/MonitoringApplication.jsx b/src/components/MonitoringApplicationsPage/MonitoringApplications/MonitoringApplication/MonitoringApplication.jsx index 08b7f1a6ca..296451e8c8 100644 --- a/src/components/MonitoringApplicationsPage/MonitoringApplications/MonitoringApplication/MonitoringApplication.jsx +++ b/src/components/MonitoringApplicationsPage/MonitoringApplications/MonitoringApplication/MonitoringApplication.jsx @@ -40,7 +40,7 @@ import './monitoringApplication.scss' const MonitoringApplication = () => { const dispatch = useDispatch() - const { artifacts } = useSelector(store => store.artifactsStore) + const { artifacts, loading: loadingArtifacts } = useSelector(store => store.artifactsStore) const { monitoringApplication, loading } = useSelector(store => store.monitoringApplicationsStore) const params = useParams() @@ -71,11 +71,11 @@ const MonitoringApplication = () => {
Artifacts
- {artifacts.length === 0 && !loading ? ( + {artifacts.length === 0 && !loadingArtifacts ? ( ) : ( <> - + {
-
+
System functions @@ -110,7 +110,7 @@ const MonitoringApplications = () => { } /> ) : ( - + )}
diff --git a/src/components/MonitoringApplicationsPage/monitoringApplicationsPage.scss b/src/components/MonitoringApplicationsPage/monitoringApplicationsPage.scss index b37128ba16..f9f3695da5 100644 --- a/src/components/MonitoringApplicationsPage/monitoringApplicationsPage.scss +++ b/src/components/MonitoringApplicationsPage/monitoringApplicationsPage.scss @@ -35,7 +35,6 @@ $applicationRowHeightExtended: variables.$rowHeightExtended; .monitoring-app__section-item { display: flex; flex-direction: column; - max-height: 410px; padding: 20px; color: colors.$topaz; background-color: colors.$white; @@ -44,10 +43,6 @@ $applicationRowHeightExtended: variables.$rowHeightExtended; box-shadow: shadows.$previewBoxShadowInit; transition: all 0.3s ease-in-out; - &-small { - max-height: 355px; - } - .section-item_title { display: flex; align-items: center; diff --git a/src/elements/SectionTable/SectionTable.jsx b/src/elements/SectionTable/SectionTable.jsx index 0afff97e04..7d8db12512 100644 --- a/src/elements/SectionTable/SectionTable.jsx +++ b/src/elements/SectionTable/SectionTable.jsx @@ -29,7 +29,9 @@ import { isRowRendered, useVirtualization } from '../../hooks/useVirtualization. import './SectionTable.scss' -const SectionTable = ({ headerHeight = 41, loading = false, params, rowHeight = 41, table }) => { +const SPACE_FOR_BORDER = 2 + +const SectionTable = ({ headerHeight = 41, loading = false, params, rowHeight = 41, table, maxTableHeight = 369 }) => { const [tableId] = useState(`section-table-${uuidv4()}`) const [tableBodyId] = useState(`section-table-body-${uuidv4()}`) @@ -47,6 +49,10 @@ const SectionTable = ({ headerHeight = 41, loading = false, params, rowHeight = [headerHeight, rowHeight] ) + const tableContainerHeight = useMemo(() => { + return Math.min(headerHeight + rowHeight * table.body.length + SPACE_FOR_BORDER, maxTableHeight) + }, [headerHeight, maxTableHeight, rowHeight, table]) + const virtualizationConfig = useVirtualization({ renderTriggerItem: table, heightData, @@ -58,121 +64,139 @@ const SectionTable = ({ headerHeight = 41, loading = false, params, rowHeight = return loading ? ( ) : ( -
- - - - <> - {table.header.map( - header => - !header.hidden && ( - - ) - )} - - - - - {table.body.map((body, index) => { - const extractedItemName = body['name'].value.startsWith(params.projectName) - ? body['name'].value.slice(params.projectName.length + 1) - : body['name'].value - - return ( - isRowRendered(virtualizationConfig, index) && ( - - <> - {Object.keys(body).map((key, index) => { - const tableValueClassName = classnames( - 'section-table__table-cell', - body[key].className, - key === 'name' && 'name-wrapper', - key === 'status' && 'status-cell', - key === 'status' && - !Array.isArray(body[key].value) && - `status_${body?.[key]?.value?.toLowerCase?.()} capitalize` - ) - - return ( - !body[key].hidden && - (key === 'type' ? ( - - ) : ( - +
- }> - {header.value} - - {header.tip && } -
- {key === 'name' ? ( - <> - {body[key].href ? ( - - } - textShow={true} +
+
+ + + + <> + {table.header.map( + header => + !header.hidden && ( + + ) + )} + + + + + {table.body.map((body, index) => { + const extractedItemName = body['name'].value.startsWith(params.projectName) + ? body['name'].value.slice(params.projectName.length + 1) + : body['name'].value + + return ( + isRowRendered(virtualizationConfig, index) && ( + + <> + {Object.keys(body).map((key, index) => { + const tableValueClassName = classnames( + 'section-table__table-cell', + body[key].className, + key === 'name' && 'name-wrapper', + key === 'status' && 'status-cell', + key === 'status' && + !Array.isArray(body[key].value) && + `status_${body?.[key]?.value?.toLowerCase?.()} capitalize` + ) + + return ( + !body[key].hidden && + (key === 'type' ? ( + + ) : ( + - )) - ) - })} - - + {body[key].status && ( + } + > + + + )} + + )} + + )) + ) + })} + + + ) ) - ) - })} - -
+ }> + {header.value} + + {header.tip && } +
+ {key === 'name' ? ( + <> + {body[key].href ? ( + - {extractedItemName} - - - ) : body[key].link ? ( - + } + textShow={true} + > + {extractedItemName} + + + ) : body[key].link ? ( + + } + > + {body[key].value} + + + ) : ( } > {body[key].value} - - ) : ( - } - > - {body[key].value} - - )} + )} - {body[key].tag ? ( - } - > - {body[key].tag} - - ) : null} - - ) : key === 'labels' ? ( - - ) : key === 'status' ? ( - <> - {Array.isArray(body.status.value) ? ( - body.status.value.map((status, index) => { - return ( - } - > - - - ) - }) - ) : ( + {body[key].tag ? ( + } + > + {body[key].tag} + + ) : null} + + ) : key === 'labels' ? ( + + ) : key === 'status' ? ( + <> + {Array.isArray(body.status.value) ? ( + body.status.value.map((status, index) => { + return ( + } + > + + + ) + }) + ) : ( + + } + > + {body[key].value} + + )} + + ) : ( + <> {body[key].value} - )} - - ) : ( - <> - - } - > - {body[key].value} - - {body[key].status && ( - } - > - - - )} - - )} -
+ })} +
+
) } @@ -225,7 +237,8 @@ SectionTable.propTypes = { loading: PropTypes.bool, params: PropTypes.object.isRequired, rowHeight: PropTypes.number, - table: PropTypes.object.isRequired + table: PropTypes.object.isRequired, + maxTableHeight: PropTypes.number } export default React.memo(SectionTable) diff --git a/src/elements/SectionTable/SectionTable.scss b/src/elements/SectionTable/SectionTable.scss index 92443d4564..b87bae1bac 100644 --- a/src/elements/SectionTable/SectionTable.scss +++ b/src/elements/SectionTable/SectionTable.scss @@ -18,9 +18,18 @@ } } +.section-table__content { + position: relative; + width: 100%; +} + .section-table__wrapper { + position: absolute; + top: 0; + right: 0; display: flex; flex-direction: column; + width: 100%; height: 100%; overflow-y: auto; @@ -29,7 +38,7 @@ display: flex; flex: 1; flex-flow: column nowrap; - min-width: fit-content; + width: 100%; height: 100%; overflow-y: auto; border: borders.$dividerBorder; From f64fec2c44b83d449bdf33548f6d99590bdc15a4 Mon Sep 17 00:00:00 2001 From: Taras Hlukhovetskyi Date: Thu, 13 Nov 2025 17:27:53 +0200 Subject: [PATCH 3/8] add virtualization for applications table --- .../AllApplicationsTable.jsx | 121 ++++++++++++++++++ .../MonitoringApplications.jsx | 77 +---------- .../monitoringApplicationsPage.scss | 26 ++++ 3 files changed, 151 insertions(+), 73 deletions(-) create mode 100644 src/components/MonitoringApplicationsPage/MonitoringApplications/AllApplicationsTable.jsx diff --git a/src/components/MonitoringApplicationsPage/MonitoringApplications/AllApplicationsTable.jsx b/src/components/MonitoringApplicationsPage/MonitoringApplications/AllApplicationsTable.jsx new file mode 100644 index 0000000000..e5725b7c65 --- /dev/null +++ b/src/components/MonitoringApplicationsPage/MonitoringApplications/AllApplicationsTable.jsx @@ -0,0 +1,121 @@ +import React, { useMemo } from 'react' +import { useNavigate, useParams } from 'react-router-dom' +import PropTypes from 'prop-types' + +import ApplicationTableRow from '../../../elements/ApplicationTableRow/ApplicationTableRow' +import NoData from '../../../common/NoData/NoData' +import Table from '../../Table/Table' +import { Loader } from 'igz-controls/components' +import { MODEL_ENDPOINTS_TAB, MONITORING_APP_PAGE } from '../../../constants' +import { createApplicationContent } from '../../../utils/createApplicationContent' +import { saveAndTransformSearchParams } from 'igz-controls/utils/filter.util' +import { MONITORING_APPLICATIONS_NO_DATA_MESSAGE } from '../MonitoringApplicationsPage.util' + +import PresentMetricsIcon from 'igz-controls/images/present-metrics-icon.svg?react' +import { getScssVariableValue } from 'igz-controls/utils/common.util' +import { isRowRendered, useVirtualization } from '../../../hooks/useVirtualization.hook' + +import '../MonitoringApplicationsPage.scss' + +const AllApplicationsTable = ({ applications, loading, error = null }) => { + const params = useParams() + const navigate = useNavigate() + + const applicationsRowHeight = useMemo(() => getScssVariableValue('--applicationRowHeight'), []) + const applicationRowHeightExtended = useMemo( + () => getScssVariableValue('--applicationRowHeightExtended'), + [] + ) + const applicationsHeaderRowHeight = useMemo( + () => getScssVariableValue('--applicationHeaderRowHeight'), + [] + ) + + const applicationsTableContent = useMemo(() => { + return applications.map(contentItem => + createApplicationContent(contentItem, params.projectName) + ) + }, [applications, params.projectName]) + + const applicationsTableHeaders = useMemo( + () => applicationsTableContent[0]?.content ?? [], + [applicationsTableContent] + ) + + const applicationsTableActionsMenu = useMemo( + () => [ + [], + [ + { + id: 'open-metrics', + label: 'Open metrics', + icon: , + onClick: data => + navigate( + `/projects/${params.projectName}/${MONITORING_APP_PAGE}/${data.name}/${MODEL_ENDPOINTS_TAB}${saveAndTransformSearchParams( + window.location.search, + true + )}` + ) + } + ] + ], + [navigate, params.projectName] + ) + + const virtualizationConfig = useVirtualization({ + rowsData: { + content: applicationsTableContent + }, + heightData: { + headerRowHeight: applicationsHeaderRowHeight, + rowHeight: applicationsRowHeight, + rowHeightExtended: applicationRowHeightExtended + } + }) + + return ( +
+
+ All Applications +
+ {applications.length === 0 && !loading ? ( + + ) : loading ? ( + + ) : ( + + {applicationsTableContent.map((tableItem, index) => ( + isRowRendered(virtualizationConfig, index) && () + ))} +
+ )} +
+ ) +} + +AllApplicationsTable.propTypes = { + applications: PropTypes.array.isRequired, + loading: PropTypes.bool.isRequired, + error: PropTypes.object +} + +export default AllApplicationsTable diff --git a/src/components/MonitoringApplicationsPage/MonitoringApplications/MonitoringApplications.jsx b/src/components/MonitoringApplicationsPage/MonitoringApplications/MonitoringApplications.jsx index acd1ccd558..d2ec45ca86 100644 --- a/src/components/MonitoringApplicationsPage/MonitoringApplications/MonitoringApplications.jsx +++ b/src/components/MonitoringApplicationsPage/MonitoringApplications/MonitoringApplications.jsx @@ -19,71 +19,34 @@ such restriction. */ import React, { useEffect, useMemo } from 'react' import { useDispatch, useSelector } from 'react-redux' -import { useNavigate, useParams } from 'react-router-dom' +import { useParams } from 'react-router-dom' -import ApplicationTableRow from '../../../elements/ApplicationTableRow/ApplicationTableRow' import MEPsWithDetections from './MEPsWithDetections' import NoData from '../../../common/NoData/NoData' import SectionTable from '../../../elements/SectionTable/SectionTable' -import Table from '../../Table/Table' -import { Loader, Tip } from 'igz-controls/components' +import { Tip } from 'igz-controls/components' +import AllApplicationsTable from './AllApplicationsTable' -import { MODEL_ENDPOINTS_TAB, MONITORING_APP_PAGE } from '../../../constants' import { MONITORING_APPLICATIONS_NO_DATA_MESSAGE } from '../MonitoringApplicationsPage.util' -import { createApplicationContent } from '../../../utils/createApplicationContent' import { generateOperatingFunctionsTable } from './monitoringApplications.util' import { removeMonitoringApplications, removeMEPWithDetections } from '../../../reducers/monitoringApplicationsReducer' -import { saveAndTransformSearchParams } from 'igz-controls/utils/filter.util' - -import PresentMetricsIcon from 'igz-controls/images/present-metrics-icon.svg?react' const MonitoringApplications = () => { const dispatch = useDispatch() const params = useParams() - const navigate = useNavigate() const { monitoringApplications: { applications = [], operatingFunctions = [] }, loading, error } = useSelector(store => store.monitoringApplicationsStore) - const applicationsTableActionsMenu = useMemo( - () => [ - [], - [ - { - id: 'open-metrics', - label: 'Open metrics', - icon: , - onClick: data => - navigate( - `/projects/${params.projectName}/${MONITORING_APP_PAGE}/${data.name}/${MODEL_ENDPOINTS_TAB}${saveAndTransformSearchParams( - window.location.search, - true - )}` - ) - } - ] - ], - [navigate, params.projectName] - ) const operatingFunctionsTable = useMemo( () => generateOperatingFunctionsTable(operatingFunctions, params.projectName), [operatingFunctions, params.projectName] ) - const applicationsTableContent = useMemo(() => { - return applications.map(contentItem => - createApplicationContent(contentItem, params.projectName) - ) - }, [applications, params.projectName]) - - const applicationsTableHeaders = useMemo( - () => applicationsTableContent[0]?.content ?? [], - [applicationsTableContent] - ) useEffect(() => { return () => { @@ -115,39 +78,7 @@ const MonitoringApplications = () => {
-
-
- All applications -
- {applications.length === 0 && !loading ? ( - - ) : loading ? ( - - ) : ( - - {applicationsTableContent.map((tableItem, index) => ( - - ))} -
- )} -
+
) diff --git a/src/components/MonitoringApplicationsPage/monitoringApplicationsPage.scss b/src/components/MonitoringApplicationsPage/monitoringApplicationsPage.scss index f9f3695da5..cddb71497e 100644 --- a/src/components/MonitoringApplicationsPage/monitoringApplicationsPage.scss +++ b/src/components/MonitoringApplicationsPage/monitoringApplicationsPage.scss @@ -7,6 +7,32 @@ $applicationRowHeight: variables.$rowHeight; $applicationHeaderRowHeight: variables.$headerRowHeight; $applicationRowHeightExtended: variables.$rowHeightExtended; +:root { + --applicationRowHeight: #{$applicationRowHeight}; + --applicationHeaderRowHeight: #{$applicationHeaderRowHeight}; + --applicationRowHeightExtended: #{$applicationRowHeightExtended}; +} + +.all-applications-table { + max-height: 450px; + + .table__flex { + max-height: calc(100% - 25px); + + .table__content { + height: 100%; + + & > div { + height: 100%; + + table.applications-table { + height: 100%; + } + } + } + } +} + .monitoring-app-content { .monitoring-apps-title { color: colors.$primary; From 305411aba7e4d1a27a0c3978c75ba12b3cf7a700 Mon Sep 17 00:00:00 2001 From: Taras Hlukhovetskyi Date: Mon, 17 Nov 2025 16:43:24 +0200 Subject: [PATCH 4/8] fix PR comments --- .../MonitoringApplications/AllApplicationsTable.jsx | 5 +++-- src/elements/SectionTable/SectionTable.jsx | 13 +++++++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/components/MonitoringApplicationsPage/MonitoringApplications/AllApplicationsTable.jsx b/src/components/MonitoringApplicationsPage/MonitoringApplications/AllApplicationsTable.jsx index e5725b7c65..d82a9407f4 100644 --- a/src/components/MonitoringApplicationsPage/MonitoringApplications/AllApplicationsTable.jsx +++ b/src/components/MonitoringApplicationsPage/MonitoringApplications/AllApplicationsTable.jsx @@ -6,15 +6,16 @@ import ApplicationTableRow from '../../../elements/ApplicationTableRow/Applicati import NoData from '../../../common/NoData/NoData' import Table from '../../Table/Table' import { Loader } from 'igz-controls/components' + import { MODEL_ENDPOINTS_TAB, MONITORING_APP_PAGE } from '../../../constants' import { createApplicationContent } from '../../../utils/createApplicationContent' import { saveAndTransformSearchParams } from 'igz-controls/utils/filter.util' import { MONITORING_APPLICATIONS_NO_DATA_MESSAGE } from '../MonitoringApplicationsPage.util' - -import PresentMetricsIcon from 'igz-controls/images/present-metrics-icon.svg?react' import { getScssVariableValue } from 'igz-controls/utils/common.util' import { isRowRendered, useVirtualization } from '../../../hooks/useVirtualization.hook' +import PresentMetricsIcon from 'igz-controls/images/present-metrics-icon.svg?react' + import '../MonitoringApplicationsPage.scss' const AllApplicationsTable = ({ applications, loading, error = null }) => { diff --git a/src/elements/SectionTable/SectionTable.jsx b/src/elements/SectionTable/SectionTable.jsx index 7d8db12512..4b9f82300b 100644 --- a/src/elements/SectionTable/SectionTable.jsx +++ b/src/elements/SectionTable/SectionTable.jsx @@ -30,8 +30,17 @@ import { isRowRendered, useVirtualization } from '../../hooks/useVirtualization. import './SectionTable.scss' const SPACE_FOR_BORDER = 2 - -const SectionTable = ({ headerHeight = 41, loading = false, params, rowHeight = 41, table, maxTableHeight = 369 }) => { +const DEFAULT_ROW_HEIGHT = 41 +const DEFAULT_MAX_TABLE_HEIGHT = 369 + +const SectionTable = ({ + headerHeight = DEFAULT_ROW_HEIGHT, + loading = false, + params, + rowHeight = DEFAULT_ROW_HEIGHT, + table, + maxTableHeight = DEFAULT_MAX_TABLE_HEIGHT +}) => { const [tableId] = useState(`section-table-${uuidv4()}`) const [tableBodyId] = useState(`section-table-body-${uuidv4()}`) From 3231087c6321b19e35a823e9ce764da000a57bf9 Mon Sep 17 00:00:00 2001 From: Taras Hlukhovetskyi Date: Mon, 17 Nov 2025 18:38:34 +0200 Subject: [PATCH 5/8] fix after resolving conflicts --- .../MonitoringApplications/AllApplicationsTable.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/MonitoringApplicationsPage/MonitoringApplications/AllApplicationsTable.jsx b/src/components/MonitoringApplicationsPage/MonitoringApplications/AllApplicationsTable.jsx index d82a9407f4..1ee30b7164 100644 --- a/src/components/MonitoringApplicationsPage/MonitoringApplications/AllApplicationsTable.jsx +++ b/src/components/MonitoringApplicationsPage/MonitoringApplications/AllApplicationsTable.jsx @@ -78,7 +78,7 @@ const AllApplicationsTable = ({ applications, loading, error = null }) => { return (
- All Applications + All applications
{applications.length === 0 && !loading ? ( Date: Mon, 17 Nov 2025 18:43:20 +0200 Subject: [PATCH 6/8] copyright --- .../AllApplicationsTable.jsx | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/components/MonitoringApplicationsPage/MonitoringApplications/AllApplicationsTable.jsx b/src/components/MonitoringApplicationsPage/MonitoringApplications/AllApplicationsTable.jsx index 1ee30b7164..b98fdc90a5 100644 --- a/src/components/MonitoringApplicationsPage/MonitoringApplications/AllApplicationsTable.jsx +++ b/src/components/MonitoringApplicationsPage/MonitoringApplications/AllApplicationsTable.jsx @@ -1,3 +1,22 @@ +/* +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. +*/ import React, { useMemo } from 'react' import { useNavigate, useParams } from 'react-router-dom' import PropTypes from 'prop-types' From dce308c0431f1bb5b8612d7de00326687ecc87c0 Mon Sep 17 00:00:00 2001 From: Taras Hlukhovetskyi Date: Mon, 1 Dec 2025 14:58:11 +0200 Subject: [PATCH 7/8] formatting --- .../AllApplicationsTable.jsx | 21 +++++++++++-------- .../MonitoringApplication.jsx | 8 ++++++- .../MonitoringApplications.jsx | 9 ++++++-- 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/src/components/MonitoringApplicationsPage/MonitoringApplications/AllApplicationsTable.jsx b/src/components/MonitoringApplicationsPage/MonitoringApplications/AllApplicationsTable.jsx index b98fdc90a5..e856ba9cd2 100644 --- a/src/components/MonitoringApplicationsPage/MonitoringApplications/AllApplicationsTable.jsx +++ b/src/components/MonitoringApplicationsPage/MonitoringApplications/AllApplicationsTable.jsx @@ -92,7 +92,7 @@ const AllApplicationsTable = ({ applications, loading, error = null }) => { rowHeight: applicationsRowHeight, rowHeightExtended: applicationRowHeightExtended } - }) + }) return (
@@ -118,14 +118,17 @@ const AllApplicationsTable = ({ applications, loading, error = null }) => { skipTableWrapper virtualizationConfig={virtualizationConfig} > - {applicationsTableContent.map((tableItem, index) => ( - isRowRendered(virtualizationConfig, index) && () - ))} + {applicationsTableContent.map( + (tableItem, index) => + isRowRendered(virtualizationConfig, index) && ( + + ) + )} )}
diff --git a/src/components/MonitoringApplicationsPage/MonitoringApplications/MonitoringApplication/MonitoringApplication.jsx b/src/components/MonitoringApplicationsPage/MonitoringApplications/MonitoringApplication/MonitoringApplication.jsx index 296451e8c8..fba71215c2 100644 --- a/src/components/MonitoringApplicationsPage/MonitoringApplications/MonitoringApplication/MonitoringApplication.jsx +++ b/src/components/MonitoringApplicationsPage/MonitoringApplications/MonitoringApplication/MonitoringApplication.jsx @@ -75,7 +75,13 @@ const MonitoringApplication = () => { ) : ( <> - + { } /> ) : ( - + )}
- +
) From 73fd2eb350f39ba055144aa5075d79dc2fc48982 Mon Sep 17 00:00:00 2001 From: Taras Hlukhovetskyi Date: Mon, 1 Dec 2025 16:05:10 +0200 Subject: [PATCH 8/8] try to rename import --- .../MonitoringApplications/AllApplicationsTable.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/MonitoringApplicationsPage/MonitoringApplications/AllApplicationsTable.jsx b/src/components/MonitoringApplicationsPage/MonitoringApplications/AllApplicationsTable.jsx index e856ba9cd2..671734358f 100644 --- a/src/components/MonitoringApplicationsPage/MonitoringApplications/AllApplicationsTable.jsx +++ b/src/components/MonitoringApplicationsPage/MonitoringApplications/AllApplicationsTable.jsx @@ -35,7 +35,7 @@ import { isRowRendered, useVirtualization } from '../../../hooks/useVirtualizati import PresentMetricsIcon from 'igz-controls/images/present-metrics-icon.svg?react' -import '../MonitoringApplicationsPage.scss' +import '../monitoringApplicationsPage.scss' const AllApplicationsTable = ({ applications, loading, error = null }) => { const params = useParams()