diff --git a/ui/src/components/JobStatus/job-status-pin.jsx b/ui/src/components/JobStatus/job-status-pin.jsx
index 9d3341bb..0dc72cb5 100644
--- a/ui/src/components/JobStatus/job-status-pin.jsx
+++ b/ui/src/components/JobStatus/job-status-pin.jsx
@@ -1,16 +1,7 @@
import { JOB_STATUS } from '@Src/constants';
-import { useGetCurrentDataQualityQueryWithPolling, useGetReferenceDataQualityQueryWithPolling } from '@Src/store/state/models/polling-hook';
import { Pin, Spinner } from '@radicalbit/radicalbit-design-system';
-function JobStatusPin({ modelUUID }) {
- const { data: referenceData } = useGetReferenceDataQualityQueryWithPolling(modelUUID);
- const referenceJobStatus = referenceData?.jobStatus;
-
- const { data: currentData } = useGetCurrentDataQualityQueryWithPolling(modelUUID);
- const currentJobStatus = currentData?.jobStatus;
-
- const jobStatus = (referenceJobStatus === JOB_STATUS.SUCCEEDED) ? currentJobStatus : referenceJobStatus;
-
+function JobStatusPin({ jobStatus }) {
switch (jobStatus) {
case JOB_STATUS.IMPORTING: {
return (
diff --git a/ui/src/container/models/Details/secondary-column/content.jsx b/ui/src/container/models/Details/secondary-column/content.jsx
index e1d68310..73440b9b 100644
--- a/ui/src/container/models/Details/secondary-column/content.jsx
+++ b/ui/src/container/models/Details/secondary-column/content.jsx
@@ -1,19 +1,14 @@
-import { modelsApiSlice } from '@Src/store/state/models/api';
+import JobStatusPin from '@Components/JobStatus/job-status-pin';
+import { MODEL_TABS_ENUM } from '@Container/models/Details/constants';
+import { JOB_STATUS } from '@Src/constants';
+import { useGetModelQueryWithPolling } from '@Src/store/state/models/polling-hook';
+import { selectors as layoutSelectors } from '@State/layout';
import { Menu, Truncate } from '@radicalbit/radicalbit-design-system';
import { useEffect, useState } from 'react';
+import { useSelector } from 'react-redux';
import {
useNavigate, useParams, useSearchParams,
} from 'react-router-dom';
-import { selectors as layoutSelectors } from '@State/layout';
-import { useSelector } from 'react-redux';
-import JobStatusPin from '@Components/JobStatus/job-status-pin';
-import { selectors as contextConfigurationSelectors } from '@State/context-configuration';
-import { NamespaceEnum } from '@Src/constants';
-import { MODEL_TABS_ENUM } from '@Container/models/Details/constants';
-
-const { useGetModelsQuery } = modelsApiSlice;
-
-const { selectQueryParamsSelector } = contextConfigurationSelectors;
const commonChildrenMenu = [
{ label: 'Overview', key: MODEL_TABS_ENUM.OVERVIEW },
@@ -30,23 +25,24 @@ export default function SecondaryColumnModelsContent() {
const isSecondaryColumnCollapsed = useSelector(selectHasSecondaryColumnCollapsed);
- const queryParams = useSelector((state) => selectQueryParamsSelector(state, NamespaceEnum.MODELS));
-
- const { data } = useGetModelsQuery({ queryParams });
+ const { data } = useGetModelQueryWithPolling();
const modelList = data?.items ?? [];
- const modelListMenuItem = modelList.map(({ uuid: modelUUID, name }) => (
- {
+ const modelListMenuItem = modelList.map(({
+ uuid: modelUUID, name, latestReferenceJobStatus, latestCurrentJobStatus,
+ }) => {
+ const jobStatus = latestReferenceJobStatus === JOB_STATUS.SUCCEEDED ? latestCurrentJobStatus : latestReferenceJobStatus;
+ return {
label: (
{name}
-
+
),
key: modelUUID,
children: commonChildrenMenu,
className: uuid === modelUUID ? Menu.HIDE_EXPAND_ICON : '',
- }
- ));
+ };
+ });
const [openKeys, setOpenKeys] = useState([uuid]);
const rootSubmenuKeys = modelListMenuItem.map(({ key }) => (key));
diff --git a/ui/src/container/models/List/columns.jsx b/ui/src/container/models/List/columns.jsx
index 4e19f8fc..e38624eb 100644
--- a/ui/src/container/models/List/columns.jsx
+++ b/ui/src/container/models/List/columns.jsx
@@ -1,4 +1,6 @@
+import JobStatusPin from '@Components/JobStatus/job-status-pin';
import { columnFactory } from '@Src/components/smart-table/utils';
+import { JOB_STATUS } from '@Src/constants';
import { DataTypeEnumLabel, ModelTypeEnumLabel } from '@Src/store/state/models/constants';
import { RelativeDateTime } from '@radicalbit/radicalbit-design-system';
@@ -6,14 +8,25 @@ export const getColumns = (
activeFilters,
activeSorter,
) => [
+ columnFactory({
+ title: 'S',
+ key: 'name',
+ width: '3rem',
+ align: 'center',
+ render: ({ latestCurrentJobStatus, latestReferenceJobStatus }) => {
+ const jobStatus = latestReferenceJobStatus === JOB_STATUS.SUCCEEDED ? latestCurrentJobStatus : latestReferenceJobStatus;
+ return (
+
+ );
+ },
+ }),
columnFactory({
title: 'Name',
- dataIndex: 'name',
key: 'name',
activeFilters,
activeSorter,
width: 250,
- render: (name) => ({name}
),
+ render: ({ name }) => ({name}
),
}),
columnFactory({
diff --git a/ui/src/container/models/List/index.jsx b/ui/src/container/models/List/index.jsx
index 75a1d497..0fffd3e9 100644
--- a/ui/src/container/models/List/index.jsx
+++ b/ui/src/container/models/List/index.jsx
@@ -1,26 +1,18 @@
+import SomethingWentWrong from '@Components/ErrorPage/something-went-wrong';
import SmartTable from '@Components/smart-table';
import LogoSquared from '@Img/logo-collapsed.svg';
import { ModalsEnum, NamespaceEnum } from '@Src/constants';
import useModals from '@Src/hooks/use-modals';
-import { modelsApiSlice } from '@Src/store/state/models/api';
+import { useGetModelQueryWithPolling } from '@Src/store/state/models/polling-hook';
import { Button, Spinner, Void } from '@radicalbit/radicalbit-design-system';
import { useLocation, useNavigate } from 'react-router-dom';
-import SomethingWentWrong from '@Components/ErrorPage/something-went-wrong';
-import { useSelector } from 'react-redux';
-import { selectors as contextConfigurationSelectors } from '@State/context-configuration';
import { getColumns } from './columns';
-const { useGetModelsQuery } = modelsApiSlice;
-
-const { selectQueryParamsSelector } = contextConfigurationSelectors;
-
export function ModelsList() {
const navigate = useNavigate();
const { search } = useLocation();
- const queryParams = useSelector((state) => selectQueryParamsSelector(state, NamespaceEnum.MODELS));
-
- const { data, isLoading, isError } = useGetModelsQuery({ queryParams });
+ const { data, isLoading, isError } = useGetModelQueryWithPolling();
const models = data?.items || [];
const count = data?.total || 0;
diff --git a/ui/src/store/state/models/api.js b/ui/src/store/state/models/api.js
index 7284c82a..4fc7846d 100644
--- a/ui/src/store/state/models/api.js
+++ b/ui/src/store/state/models/api.js
@@ -107,6 +107,8 @@ export const modelsApiSlice = apiService.injectEndpoints({
if (result) {
return [
{ type: API_TAGS.REFERENCE_IMPORT, id: modelUUID },
+ { type: API_TAGS.MODEL, id: modelUUID },
+ { type: API_TAGS.MODELS },
];
}
return [];
@@ -178,6 +180,7 @@ export const modelsApiSlice = apiService.injectEndpoints({
return [
{ type: API_TAGS.CURRENT_IMPORT, id: modelUUID },
{ type: API_TAGS.MODEL, id: modelUUID },
+ { type: API_TAGS.MODELS },
];
}
return [];
diff --git a/ui/src/store/state/models/polling-hook.js b/ui/src/store/state/models/polling-hook.js
index 3f999a0f..0f6c49f7 100644
--- a/ui/src/store/state/models/polling-hook.js
+++ b/ui/src/store/state/models/polling-hook.js
@@ -5,6 +5,8 @@ import { useParams } from 'react-router';
import useModals from '@Hooks/use-modals';
import { modelsApiSlice } from './api';
+const { selectQueryParamsSelector } = contextConfigurationSelectors;
+
const {
useGetReferenceImportsQuery,
useGetReferenceDataQualityQuery,
@@ -16,6 +18,7 @@ const {
useGetCurrentStatisticsByUUIDQuery,
useGetCurrentDriftQuery,
useGetModelByUUIDQuery,
+ useGetModelsQuery,
} = modelsApiSlice;
const useGetReferenceImportsQueryWithPolling = () => {
@@ -153,6 +156,19 @@ const useGetCurrentDriftQueryWithPolling = () => {
return result;
};
+const useGetModelQueryWithPolling = () => {
+ const queryParams = useSelector((state) => selectQueryParamsSelector(state, NamespaceEnum.MODELS));
+ const result = useGetModelsQuery({ queryParams });
+
+ const isReferencePending = result.data?.items.every((d) => d.latestReferenceJobStatus === JOB_STATUS.SUCCEEDED);
+ const isCurrentPending = result.data?.items.every((d) => d.latestCurrentJobStatus === JOB_STATUS.SUCCEEDED);
+ const isOperationCompleted = isReferencePending && isCurrentPending;
+
+ useGetModelsQuery({ queryParams }, { pollingInterval: DEFAULT_POLLING_INTERVAL, skip: isOperationCompleted });
+
+ return result;
+};
+
export {
useGetCurrentDataQualityQueryWithPolling,
useGetCurrentDriftQueryWithPolling,
@@ -163,4 +179,5 @@ export {
useGetReferenceImportsQueryWithPolling,
useGetReferenceModelQualityQueryWithPolling,
useGetReferenceStatisticsQueryWithPolling,
+ useGetModelQueryWithPolling,
};