diff --git a/package-lock.json b/package-lock.json index 49a30d9ce..10a366045 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,7 @@ "@module-federation/vite": "^1.2.6", "@monaco-editor/react": "^4.7.0", "@reduxjs/toolkit": "^1.9.5", - "axios": "1.13.5", + "axios": "^1.15.0", "bfj": "^9.1.3", "camelcase": "^6.3.0", "chart.js": "^4.4.2", @@ -30,11 +30,11 @@ "final-form-arrays": "^3.1.0", "fs-extra": "^10.0.0", "identity-obj-proxy": "^3.0.0", - "iguazio.dashboard-react-controls": "3.2.19", + "iguazio.dashboard-react-controls": "3.2.20", "is-wsl": "^1.1.0", "js-base64": "^2.6.4", "js-yaml": "^4.1.0", - "lodash": "^4.17.23", + "lodash": "^4.18.1", "moment": "^2.30.1", "pretty-bytes": "^6.1.1", "prismjs": "^1.29.0", @@ -137,7 +137,7 @@ "stylelint-order": "^4.0.0", "stylelint-scss": "^3.17.2", "url-loader": "4.1.1", - "vite": "^6.2.0", + "vite": "^6.4.2", "vite-plugin-commonjs": "^0.10.4", "vite-plugin-eslint": "^1.8.1", "vite-plugin-svgr": "^4.3.0", @@ -9923,14 +9923,23 @@ } }, "node_modules/axios": { - "version": "1.13.5", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.5.tgz", - "integrity": "sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.15.0.tgz", + "integrity": "sha512-wWyJDlAatxk30ZJer+GeCWS209sA42X+N5jU2jy6oHTp7ufw8uzUTVFBX9+wTfAlhiJXGS0Bq7X6efruWjuK9Q==", "license": "MIT", "dependencies": { "follow-redirects": "^1.15.11", "form-data": "^4.0.5", - "proxy-from-env": "^1.1.0" + "proxy-from-env": "^2.1.0" + } + }, + "node_modules/axios/node_modules/proxy-from-env": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", + "license": "MIT", + "engines": { + "node": ">=10" } }, "node_modules/babel-jest": { @@ -10376,9 +10385,9 @@ } }, "node_modules/basic-ftp": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.1.0.tgz", - "integrity": "sha512-RkaJzeJKDbaDWTIPiJwubyljaEPwpVWkm9Rt5h9Nd6h7tEXTJ3VB4qxdZBioV7JO5yLUaOKwz7vDOzlncUsegw==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.2.2.tgz", + "integrity": "sha512-1tDrzKsdCg70WGvbFss/ulVAxupNauGnOlgpyjKzeQxzyllBLS0CGLV7tjIXTK3ZQA9/FBEm9qyFFN1bciA6pw==", "dev": true, "license": "MIT", "engines": { @@ -14086,15 +14095,15 @@ } }, "node_modules/flatted": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", - "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", "license": "ISC" }, "node_modules/follow-redirects": { - "version": "1.15.11", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", - "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", "funding": [ { "type": "individual", @@ -15203,9 +15212,9 @@ "license": "ISC" }, "node_modules/iguazio.dashboard-react-controls": { - "version": "3.2.19", - "resolved": "https://registry.npmjs.org/iguazio.dashboard-react-controls/-/iguazio.dashboard-react-controls-3.2.19.tgz", - "integrity": "sha512-yGr2O9CrF7xnptGCc5lmXR7Nc3YmRjTmTLjuPuEtKWu7uxPZRxApGu4c3i/CF8hT/Zp7TpSNKEq27MfG50nS6g==", + "version": "3.2.20", + "resolved": "https://registry.npmjs.org/iguazio.dashboard-react-controls/-/iguazio.dashboard-react-controls-3.2.20.tgz", + "integrity": "sha512-cSF6OQ1qRPcIucK1inu17Lsiy9qED2z9Qlq4I39K+MX9q+Qn07s26eA/NTrk1u1acV0CQgTm3iyEH2+1R+QXIQ==", "peerDependencies": { "@reduxjs/toolkit": "*", "classnames": "*", @@ -16651,9 +16660,9 @@ } }, "node_modules/lodash": { - "version": "4.17.23", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", - "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", "license": "MIT" }, "node_modules/lodash.clonedeepwith": { @@ -20271,6 +20280,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true, "license": "MIT" }, "node_modules/pstree.remy": { @@ -21977,9 +21987,9 @@ } }, "node_modules/serialize-javascript": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-7.0.4.tgz", - "integrity": "sha512-DuGdB+Po43Q5Jxwpzt1lhyFSYKryqoNjQSA9M92tyw0lyHIOur+XCalOUe0KTJpyqzT8+fQ5A0Jf7vCx/NKmIg==", + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-7.0.5.tgz", + "integrity": "sha512-F4LcB0UqUl1zErq+1nYEEzSHJnIwb3AF2XWB94b+afhrekOUijwooAYqFyRbjYkm2PAKBabx6oYv/xDxNi8IBw==", "dev": true, "license": "BSD-3-Clause", "peer": true, @@ -24419,9 +24429,9 @@ } }, "node_modules/vite": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz", - "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.2.tgz", + "integrity": "sha512-2N/55r4JDJ4gdrCvGgINMy+HH3iRpNIz8K6SFwVsA+JbQScLiC+clmAxBgwiSPgcG9U15QmvqCGWzMbqda5zGQ==", "license": "MIT", "dependencies": { "esbuild": "^0.25.0", diff --git a/package.json b/package.json index 9a23fc4f2..9b860faf8 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "@module-federation/vite": "^1.2.6", "@monaco-editor/react": "^4.7.0", "@reduxjs/toolkit": "^1.9.5", - "axios": "1.13.5", + "axios": "^1.15.0", "bfj": "^9.1.3", "camelcase": "^6.3.0", "chart.js": "^4.4.2", @@ -25,11 +25,11 @@ "final-form-arrays": "^3.1.0", "fs-extra": "^10.0.0", "identity-obj-proxy": "^3.0.0", - "iguazio.dashboard-react-controls": "3.2.19", + "iguazio.dashboard-react-controls": "3.2.20", "is-wsl": "^1.1.0", "js-base64": "^2.6.4", "js-yaml": "^4.1.0", - "lodash": "^4.17.23", + "lodash": "^4.18.1", "moment": "^2.30.1", "pretty-bytes": "^6.1.1", "prismjs": "^1.29.0", @@ -168,7 +168,7 @@ "stylelint-order": "^4.0.0", "stylelint-scss": "^3.17.2", "url-loader": "4.1.1", - "vite": "^6.2.0", + "vite": "^6.4.2", "vite-plugin-commonjs": "^0.10.4", "vite-plugin-eslint": "^1.8.1", "vite-plugin-svgr": "^4.3.0", diff --git a/src/common/DatePicker/DatePicker.jsx b/src/common/DatePicker/DatePicker.jsx index 85c006f2e..dd27fcc8a 100644 --- a/src/common/DatePicker/DatePicker.jsx +++ b/src/common/DatePicker/DatePicker.jsx @@ -54,14 +54,14 @@ import { isTargetElementInContainerElement } from '../../utils/checkElementsPosi const defaultProps = { date: new Date(), - dateTo: null + setExternalInvalid: () => {} } const DatePicker = ({ className = '', customOptions = null, date = defaultProps.date, - dateTo = defaultProps.dateTo, + dateTo = null, disabled = false, excludeCustomRange = false, externalInvalid = null, @@ -72,7 +72,7 @@ const DatePicker = ({ required = false, requiredText = 'This field is required', selectedOptionId = '', - setExternalInvalid = () => {}, + setExternalInvalid = defaultProps.setExternalInvalid, timeFrameLimit = Infinity, tip = '', type = 'date', diff --git a/src/components/ActionBar/ActionBar.jsx b/src/components/ActionBar/ActionBar.jsx index 92c0b6b68..2a265731d 100644 --- a/src/components/ActionBar/ActionBar.jsx +++ b/src/components/ActionBar/ActionBar.jsx @@ -44,7 +44,13 @@ import { REQUEST_CANCELED, TAG_FILTER_ALL_ITEMS } from '../../constants' -import { CUSTOM_RANGE_DATE_OPTION } from '../../utils/datePicker.util' +import { + ANY_TIME_DATE_OPTION, + CUSTOM_RANGE_DATE_OPTION, + datePickerFutureOptions, + datePickerPastOptions, + getDatePickerFilterValue +} from '../../utils/datePicker.util' import { FILTERS_CONFIG } from '../../types' import { getCloseDetailsLink } from '../../utils/link-helper.util' import { setFieldState } from 'igz-controls/utils/form.util' @@ -189,13 +195,36 @@ const ActionBar = ({ [filtersConfig, setSearchParams, withoutSearchParams] ) + const updateRelativeTimeValue = useCallback( + filters => { + if ( + filters[DATES_FILTER]?.initialSelectedOptionId && + filters[DATES_FILTER].initialSelectedOptionId !== CUSTOM_RANGE_DATE_OPTION && + filters[DATES_FILTER].initialSelectedOptionId !== ANY_TIME_DATE_OPTION + ) { + const isFuture = filtersConfig[DATES_FILTER]?.isFuture + const options = isFuture ? datePickerFutureOptions : datePickerPastOptions + + filters[DATES_FILTER] = getDatePickerFilterValue( + options, + filters[DATES_FILTER].initialSelectedOptionId, + isFuture + ) + formRef.current.change(DATES_FILTER, filters[DATES_FILTER]) + dispatch(setFilters({ relativeDateChange: Date.now() })) + } + }, + [dispatch, filtersConfig] + ) + const applyFilters = useCallback( async (formValues, filters, actionCanBePerformedChecked) => { const actionCanBePerformed = actionCanBePerformedChecked || (await performDetailsActionHelper(changes, dispatch, true)) - const newFilters = { ...filters, ...formValues } if (actionCanBePerformed) { + const newFilters = { ...filters, ...formValues } + if (closeParamName) { navigate(getCloseDetailsLink(closeParamName, true, selectedItemName), { replace: true }) } @@ -216,6 +245,7 @@ const ActionBar = ({ if (withoutSearchParams) { setLocalFilters(newFilters) } else { + updateRelativeTimeValue(newFilters) saveFilters(newFilters) } @@ -228,17 +258,18 @@ const ActionBar = ({ [ changes, dispatch, + updateRelativeTimeValue, closeParamName, filtersStore.groupBy, - saveFilters, + withoutSearchParams, removeSelectedItem, setSelectedRowData, toggleAllRows, handleRefresh, navigate, selectedItemName, - withoutSearchParams, - setLocalFilters + setLocalFilters, + saveFilters ] ) @@ -258,6 +289,7 @@ const ActionBar = ({ if (withoutSearchParams) { setLocalFilters(newFilters) } else { + updateRelativeTimeValue(newFilters) saveFilters(formState.values) } @@ -269,11 +301,12 @@ const ActionBar = ({ changes, dispatch, cancelRequest, - saveFilters, - handleRefresh, filters, + updateRelativeTimeValue, withoutSearchParams, - setLocalFilters + handleRefresh, + setLocalFilters, + saveFilters ] ) diff --git a/src/components/Alerts/Alerts.jsx b/src/components/Alerts/Alerts.jsx index 6324c2a85..1e39b2215 100644 --- a/src/components/Alerts/Alerts.jsx +++ b/src/components/Alerts/Alerts.jsx @@ -57,7 +57,8 @@ const Alerts = () => { const alertsFilters = useFiltersFromSearchParams( alertsFiltersConfig, - parseAlertsQueryParamsCallback + parseAlertsQueryParamsCallback, + params.projectName ) const { diff --git a/src/components/Details/details.util.js b/src/components/Details/details.util.js index 5a67137aa..0a496dad9 100644 --- a/src/components/Details/details.util.js +++ b/src/components/Details/details.util.js @@ -313,10 +313,12 @@ export const generateRealTimePipelinesContent = selectedItem => { rootFunction: { value: selectedItem.name, status: selectedItem.state.value, + statusLabel: selectedItem.state.label, className: selectedItem.state.className, link: generateNuclioLink( `/projects/${selectedItem.project}/real-time-functions/${nuclioFunctionName}` - ) + ), + linkIsExternal: true }, childFunction: { value: selectedItem.childFunctions ?? selectedItem.function_refs ?? [], diff --git a/src/components/FunctionsPage/Functions.jsx b/src/components/FunctionsPage/Functions.jsx index d86b0fc17..19ebe6955 100644 --- a/src/components/FunctionsPage/Functions.jsx +++ b/src/components/FunctionsPage/Functions.jsx @@ -131,7 +131,11 @@ const Functions = ({ isAllVersions = false }) => { } }, [selectedFunction.node_selector]) - const functionsFilters = useFiltersFromSearchParams(functionsFiltersConfig) + const functionsFilters = useFiltersFromSearchParams( + functionsFiltersConfig, + undefined, + params.projectName + ) const terminateDeleteTasksPolling = useCallback(() => { terminatePollRef?.current?.() diff --git a/src/components/FunctionsPageOld/FunctionsOld.jsx b/src/components/FunctionsPageOld/FunctionsOld.jsx index 830a168e0..b56b64d58 100644 --- a/src/components/FunctionsPageOld/FunctionsOld.jsx +++ b/src/components/FunctionsPageOld/FunctionsOld.jsx @@ -123,7 +123,11 @@ const Functions = () => { } }, []) - const functionsFilters = useFiltersFromSearchParams(functionsFiltersConfig) + const functionsFilters = useFiltersFromSearchParams( + functionsFiltersConfig, + undefined, + params.projectName + ) const terminateDeleteTasksPolling = useCallback(() => { terminatePollRef?.current?.() diff --git a/src/components/Jobs/Jobs.jsx b/src/components/Jobs/Jobs.jsx index 89655da76..ee7fb3104 100644 --- a/src/components/Jobs/Jobs.jsx +++ b/src/components/Jobs/Jobs.jsx @@ -92,7 +92,8 @@ const Jobs = () => { parseQueryParamsCallback: parseScheduledQueryParamsCallback } } - }, [params.jobName]) + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [params.jobName, params.projectName, selectedTab]) const { abortControllerRef, @@ -197,7 +198,8 @@ const Jobs = () => { const filters = useFiltersFromSearchParams( initialTabData[selectedTab]?.filtersConfig, - initialTabData[selectedTab]?.parseQueryParamsCallback + initialTabData[selectedTab]?.parseQueryParamsCallback, + `${params.projectName}+${selectedTab}` ) return ( diff --git a/src/components/MonitoringApplicationsPage/MonitoringApplicationsPage.jsx b/src/components/MonitoringApplicationsPage/MonitoringApplicationsPage.jsx index 6e295b3c8..12e61c991 100644 --- a/src/components/MonitoringApplicationsPage/MonitoringApplicationsPage.jsx +++ b/src/components/MonitoringApplicationsPage/MonitoringApplicationsPage.jsx @@ -49,7 +49,7 @@ const MonitoringApplicationsPage = () => { const params = useParams() const navigate = useNavigate() const filtersConfig = useMemo(() => getFiltersConfig(), []) - const filters = useFiltersFromSearchParams(filtersConfig) + const filters = useFiltersFromSearchParams(filtersConfig, undefined, params.projectName) const [, setSearchParams] = useSearchParams() const contentRef = useRef(null) diff --git a/src/elements/DetailsInfoItem/DetailsInfoItem.jsx b/src/elements/DetailsInfoItem/DetailsInfoItem.jsx index a55ace861..1e70d3bcd 100644 --- a/src/elements/DetailsInfoItem/DetailsInfoItem.jsx +++ b/src/elements/DetailsInfoItem/DetailsInfoItem.jsx @@ -233,7 +233,9 @@ const DetailsInfoItem = React.forwardRef( }>{infoItem} {item.status && (
- }> + } + >
@@ -244,7 +246,9 @@ const DetailsInfoItem = React.forwardRef( }>{infoItem} {item.status && (
- }> + } + >
diff --git a/src/hooks/useFiltersFromSearchParams.hook.js b/src/hooks/useFiltersFromSearchParams.hook.js index 4e0d8aea2..4ae07395e 100644 --- a/src/hooks/useFiltersFromSearchParams.hook.js +++ b/src/hooks/useFiltersFromSearchParams.hook.js @@ -19,13 +19,15 @@ such restriction. */ import { useMemo } from 'react' import { mapValues, isNil, pickBy } from 'lodash' +import { useSelector } from 'react-redux' +import { useSearchParams } from 'react-router-dom' + import { DATES_FILTER, ITERATIONS_FILTER, SHOW_ITERATIONS, SHOW_UNTAGGED_FILTER } from '../constants' -import { useSearchParams } from 'react-router-dom' import { datePickerFutureOptions, datePickerPastOptions, @@ -42,7 +44,19 @@ const getFiltersFromSearchParams = (filtersConfig, searchParams, paramsParsingCa return mapValues(filtersConfigToApply, (filterConfig, filterName) => { const searchParamValue = searchParams.get(filterName)?.trim?.() - if (isNil(searchParamValue)) return filterConfig.initialValue + if (isNil(searchParamValue)) { + if (filterName === DATES_FILTER) { + return ( + getDatePickerFilterValue( + filterConfig.isFuture ? datePickerFutureOptions : datePickerPastOptions, + filterConfig.initialValue.initialSelectedOptionId, + filterConfig.isFuture + ) ?? filterConfig.initialValue + ) + } + + return filterConfig.initialValue + } let parsedValue = paramsParsingCallback(filterName, searchParamValue) @@ -78,12 +92,21 @@ export const getInitialFiltersByConfig = (filtersConfig = {}) => { export const useFiltersFromSearchParams = ( filtersConfig = null, - paramsParsingCallback = defaultParamsParsingCallback + paramsParsingCallback = defaultParamsParsingCallback, + triggerKey = '' ) => { + const relativeDateChange = useSelector(store => store.filtersStore.relativeDateChange) const [searchParams] = useSearchParams() const filters = useMemo(() => { - return getFiltersFromSearchParams(filtersConfig, searchParams, paramsParsingCallback) - }, [filtersConfig, paramsParsingCallback, searchParams]) + // triggerKey and relativeDateChange are added to dependencies to trigger date (timestamp for relative time) filter recalculation + return getFiltersFromSearchParams( + filtersConfig, + searchParams, + paramsParsingCallback, + triggerKey, + relativeDateChange + ) + }, [filtersConfig, paramsParsingCallback, searchParams, relativeDateChange, triggerKey]) return filters } diff --git a/src/reducers/filtersReducer.js b/src/reducers/filtersReducer.js index e86a6feb9..93e6e46ea 100644 --- a/src/reducers/filtersReducer.js +++ b/src/reducers/filtersReducer.js @@ -29,7 +29,8 @@ const initialState = { internalAutoRefresh: false, tagOptions: null, projectOptions: [], - [FILTER_MENU_MODAL]: {} + [FILTER_MENU_MODAL]: {}, + relativeDateChange: null } export const getFilterTagOptions = createAsyncThunk(