diff --git a/src/components/ApplicationGroup/AppGroup.service.ts b/src/components/ApplicationGroup/AppGroup.service.ts index a39cd3e813..b0d27060c7 100644 --- a/src/components/ApplicationGroup/AppGroup.service.ts +++ b/src/components/ApplicationGroup/AppGroup.service.ts @@ -68,7 +68,7 @@ export function getCIConfig(envID: string, appIds: string): Promise { - return get(`${Routes.ENV_WORKFLOW}/${envID}/${URLS.APP_CI_CONFIG}/min${getFilteredAppQueryString(appIds)}`) + return get(`${Routes.ENV_WORKFLOW}/${envID}/${Routes.APP_CI_PIPELINE}${getFilteredAppQueryString(appIds)}`) } export function getCDConfig(envID: string, appIds: string): Promise { diff --git a/src/components/ApplicationGroup/AppGroup.types.ts b/src/components/ApplicationGroup/AppGroup.types.ts index 994b549623..2e5afd5314 100644 --- a/src/components/ApplicationGroup/AppGroup.types.ts +++ b/src/components/ApplicationGroup/AppGroup.types.ts @@ -321,6 +321,7 @@ export interface AppGroupDetailDefaultType { description?: string getAppListData?: () => Promise handleSaveDescription?: (description: string) => Promise + clearAppListSelection?: () => void } interface CIPipeline { diff --git a/src/components/ApplicationGroup/AppGroupAppFilter.tsx b/src/components/ApplicationGroup/AppGroupAppFilter.tsx index c585235b75..53a033d6d9 100644 --- a/src/components/ApplicationGroup/AppGroupAppFilter.tsx +++ b/src/components/ApplicationGroup/AppGroupAppFilter.tsx @@ -16,6 +16,7 @@ import { useEffect, useRef, useState } from 'react' import ReactSelect, { SelectInstance } from 'react-select' +import ReactGA from 'react-ga4' import { useAppGroupAppFilterContext } from './AppGroupDetailsRoute' import { appGroupAppSelectorStyle } from './AppGroup.utils' import { AppGroupAppFilterContextType, FilterParentType } from './AppGroup.types' @@ -52,7 +53,15 @@ export default function AppGroupAppFilter() { setSelectedFilterTab(_filterTab) } + const handleFilterGAEvent = (isItemClick?: boolean) => { + ReactGA.event({ + category: 'Group filter', + action: `${filterParentType} filter ${isItemClick ? 'item' : ''} clicked`, + }) + } + const handleOpenFilter = (): void => { + handleFilterGAEvent() selectDefaultFilterTab() setMenuOpen(true) } @@ -86,6 +95,7 @@ export default function AppGroupAppFilter() { } const onChangeFilter = (selectedValue): void => { + handleFilterGAEvent(true) if (selectedFilterTab === AppFilterTabs.APP_FILTER) { setSelectedAppList(selectedValue) setSelectedGroupFilter([]) @@ -119,6 +129,7 @@ export default function AppGroupAppFilter() { } const handleFilterFocus = () => { + handleFilterGAEvent() appGroupFilterRef.current.focus() appGroupFilterRef.current.onMenuOpen() } diff --git a/src/components/ApplicationGroup/AppGroupDetailsRoute.tsx b/src/components/ApplicationGroup/AppGroupDetailsRoute.tsx index b80a33413e..fd3078c7f8 100644 --- a/src/components/ApplicationGroup/AppGroupDetailsRoute.tsx +++ b/src/components/ApplicationGroup/AppGroupDetailsRoute.tsx @@ -425,6 +425,17 @@ export default function AppGroupDetailsRoute({ isSuperAdmin }: AppGroupAdminType return _appListData }, [selectedAppList, appGroupListData?.apps, appGroupListData?.description]) + const clearAppListSelection = () => { + setSelectedAppList([]) + setSelectedGroupFilter([]) + setAppGroupFilterInLocalStorage({ + filterParentType: FilterParentType.env, + resourceId: envId, + resourceList: [], + groupList: [], + }) + } + const renderRoute = () => { if (initLoading || loading || appListLoading) { return @@ -454,15 +465,25 @@ export default function AppGroupDetailsRoute({ isSuperAdmin }: AppGroupAdminType - + - + - + diff --git a/src/components/ApplicationGroup/Details/EnvCDDetails/EnvCDDetails.tsx b/src/components/ApplicationGroup/Details/EnvCDDetails/EnvCDDetails.tsx index 57e6113942..44bf2f91e7 100644 --- a/src/components/ApplicationGroup/Details/EnvCDDetails/EnvCDDetails.tsx +++ b/src/components/ApplicationGroup/Details/EnvCDDetails/EnvCDDetails.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { useState, useEffect } from 'react' +import { useState, useEffect, useRef } from 'react' import { Progressing, showError, @@ -56,13 +56,14 @@ import { renderVirtualHistoryArtifacts, } from '../../../app/details/cdDetails/utils' -export default function EnvCDDetails({ filteredAppIds }: AppGroupDetailDefaultType) { +export default function EnvCDDetails({ filteredAppIds, clearAppListSelection }: AppGroupDetailDefaultType) { const { appId, envId, triggerId, pipelineId } = useParams<{ appId: string envId: string triggerId: string pipelineId: string }>() + const isMounted = useRef(false) const [pagination, setPagination] = useState<{ offset: number; size: number }>({ offset: 0, size: 20 }) const [hasMore, setHasMore] = useState(false) const [hasMoreLoading, setHasMoreLoading] = useState(false) @@ -79,6 +80,13 @@ export default function EnvCDDetails({ filteredAppIds }: AppGroupDetailDefaultTy autoBottomScroll: triggerDetails && TRIGGER_STATUS_PROGRESSING.includes(triggerDetails.status.toLowerCase()), }) + useEffect(() => { + if (appId && !isMounted.current) { + clearAppListSelection() + } + isMounted.current = true + }, []) + const [loading, result] = useAsync( () => Promise.allSettled([ @@ -86,6 +94,7 @@ export default function EnvCDDetails({ filteredAppIds }: AppGroupDetailDefaultTy getModuleConfigured(ModuleNameMap.BLOB_STORAGE), ]), [filteredAppIds], + isMounted.current, ) const [loadingDeploymentHistory, deploymentHistoryResult, , , , dependencyState] = useAsync( () => getTriggerHistory({ appId: Number(appId), envId: Number(envId), pagination }), @@ -97,7 +106,6 @@ export default function EnvCDDetails({ filteredAppIds }: AppGroupDetailDefaultTy const { currentEnvironmentName } = useAppContext() useInterval(pollHistory, 30000) - useEffect(() => { if (result?.[0]?.['value']?.result?.length) { const selectedPipelineExist = result[0]['value'].result.some((pipeline) => pipeline.id === +pipelineId) diff --git a/src/components/ApplicationGroup/Details/EnvCIDetails/EnvCIDetails.tsx b/src/components/ApplicationGroup/Details/EnvCIDetails/EnvCIDetails.tsx index d72374e532..5578502c17 100644 --- a/src/components/ApplicationGroup/Details/EnvCIDetails/EnvCIDetails.tsx +++ b/src/components/ApplicationGroup/Details/EnvCIDetails/EnvCIDetails.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { useEffect, useState } from 'react' +import { useEffect, useRef, useState } from 'react' import { generatePath, Route, useHistory, useParams, useRouteMatch } from 'react-router-dom' import { Progressing, @@ -44,12 +44,15 @@ import { getCIConfigList } from '../../AppGroup.service' import { AppGroupDetailDefaultType } from '../../AppGroup.types' import { CIPipelineBuildType } from '../../../ciPipeline/types' -export default function EnvCIDetails({ filteredAppIds }: AppGroupDetailDefaultType) { +export default function EnvCIDetails({ filteredAppIds, clearAppListSelection }: AppGroupDetailDefaultType) { const { envId, pipelineId, buildId } = useParams<{ pipelineId: string buildId: string envId: string }>() + const { path } = useRouteMatch() + const { replace } = useHistory() + const isMounted = useRef(false) const [pagination, setPagination] = useState<{ offset: number; size: number }>({ offset: 0, size: 20 }) const [hasMore, setHasMore] = useState(false) const [triggerHistory, setTriggerHistory] = useState>(new Map()) @@ -71,8 +74,11 @@ export default function EnvCIDetails({ filteredAppIds }: AppGroupDetailDefaultTy autoBottomScroll: triggerDetails && TRIGGER_STATUS_PROGRESSING.includes(triggerDetails.status.toLowerCase()), }) - useEffect(() => { + if (pipelineId && !isMounted.current) { + clearAppListSelection() + } + isMounted.current = true try { setCiGroupLoading(true) getCIConfigList(envId, filteredAppIds).then((result) => { @@ -120,8 +126,6 @@ export default function EnvCIDetails({ filteredAppIds }: AppGroupDetailDefaultTy [pipelineId, pagination], !!pipelineId, ) - const { path } = useRouteMatch() - const { replace } = useHistory() useInterval(pollHistory, 30000) useEffect(() => { diff --git a/src/components/ApplicationGroup/Details/EnvironmentConfig/EnvConfig.tsx b/src/components/ApplicationGroup/Details/EnvironmentConfig/EnvConfig.tsx index ce25277878..06f2bfd897 100644 --- a/src/components/ApplicationGroup/Details/EnvironmentConfig/EnvConfig.tsx +++ b/src/components/ApplicationGroup/Details/EnvironmentConfig/EnvConfig.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { useEffect, useMemo } from 'react' +import { useEffect, useMemo, useRef } from 'react' import { generatePath, Route, Switch, useHistory, useLocation, useRouteMatch } from 'react-router-dom' import { @@ -41,12 +41,20 @@ import ApplicationRoute from './ApplicationRoutes' const getApprovalPolicyConfigForEnv: (envId: number) => Promise = importComponentFromFELibrary('getApprovalPolicyConfigForEnv', null, 'function') -const EnvConfig = ({ filteredAppIds, envName }: AppGroupDetailDefaultType) => { +const EnvConfig = ({ filteredAppIds, envName, clearAppListSelection }: AppGroupDetailDefaultType) => { // HOOKS const { path, params } = useRouteMatch<{ envId: string; appId: string }>() const { appId, envId } = params const { pathname } = useLocation() const { replace } = useHistory() + const isMounted = useRef(false) + + useEffect(() => { + if (appId && !isMounted.current) { + clearAppListSelection() + } + isMounted.current = true + }, []) // ASYNC CALLS const [loading, initDataResults] = useAsync( @@ -58,6 +66,7 @@ const EnvConfig = ({ filteredAppIds, envName }: AppGroupDetailDefaultType) => { : null, ]), [filteredAppIds], + isMounted.current, ) const [envConfigLoading, envConfigRes, , refetch] = useAsync( () => (appId ? getEnvConfig(+appId, +envId) : null), diff --git a/src/components/app/details/appDetails/AppDetails.tsx b/src/components/app/details/appDetails/AppDetails.tsx index 5a224be318..fd9c717612 100644 --- a/src/components/app/details/appDetails/AppDetails.tsx +++ b/src/components/app/details/appDetails/AppDetails.tsx @@ -20,7 +20,6 @@ import { Progressing, noop, stopPropagation, - multiSelectStyles, DeploymentAppTypes, useSearchString, useAsync, @@ -37,6 +36,7 @@ import { ConfirmationModalVariantType, ServerErrors, getIsRequestAborted, + stringComparatorBySortOrder, } from '@devtron-labs/devtron-fe-common-lib' import { Link, useParams, useHistory, useRouteMatch, generatePath, Route, useLocation } from 'react-router-dom' import { fetchAppDetailsInTime, fetchResourceTreeInTime } from '../../service' @@ -53,7 +53,6 @@ import { DEFAULT_STATUS_TEXT, } from '../../../../config' import { NavigationArrow, useAppContext, FragmentHOC } from '../../../common' -import { groupHeaderStyle, Option } from '../../../v2/common/ReactSelect.utils' import { getAppConfigStatus, getAppOtherEnvironmentMin, stopStartApp } from '../../../../services/service' import AppNotDeployedIcon from '@Images/app-not-deployed.svg' import AppNotConfiguredIcon from '@Images/app-not-configured.png' @@ -61,10 +60,8 @@ import { ReactComponent as ICHibernate } from '@Icons/ic-medium-hibernate.svg' import { ReactComponent as ICUnhibernate } from '@Icons/ic-medium-unhibernate.svg' import { ReactComponent as ForwardArrow } from '@Icons/ic-arrow-forward.svg' import { ReactComponent as Trash } from '../../../../assets/icons/ic-delete-dots.svg' - import { SourceInfo } from './SourceInfo' import { Application, Nodes, AggregatedNodes, NodeDetailTabs } from '../../types' -import { NoParamsNoEnvContext, NoParamsWithEnvContext, ParamsNoEnvContext, ParamsAndEnvContext } from './utils' import { AppMetrics } from './AppMetrics' import IndexStore from '../../../v2/appDetails/index.store' import { @@ -82,6 +79,7 @@ import { AppType, EnvType } from '../../../v2/appDetails/appDetails.type' import DeploymentStatusDetailModal from './DeploymentStatusDetailModal' import { getDeploymentStatusDetail } from './appDetails.service' import { + AppDetailsProps, DeletedAppComponentType, DeploymentStatusDetailsBreakdownDataType, DeploymentStatusDetailsType, @@ -116,9 +114,9 @@ const getDeploymentWindowProfileMetaData = importComponentFromFELibrary( 'function', ) -export default function AppDetail({ filteredEnvIds }: { filteredEnvIds?: string }) { +export default function AppDetail({ selectedEnvList, clearEnvListSelection }: Readonly) { const params = useParams<{ appId: string; envId?: string }>() - const { push } = useHistory() + const { replace } = useHistory() const { path } = useRouteMatch() const { environmentId, setEnvironmentId } = useAppContext() // global state for app to synchronise environments const [isAppDeleted, setIsAppDeleted] = useState(false) @@ -128,45 +126,44 @@ export default function AppDetail({ filteredEnvIds }: { filteredEnvIds?: string const isVirtualEnvRef = useRef(false) const [showDeploymentWindowConfirmation, setShowDeploymentWindowConfirmation] = useState(false) - const envList = useMemo(() => { - if (otherEnvsResult?.result?.length > 0) { - const filteredEnvMap = filteredEnvIds?.split(',').reduce((agg, curr) => agg.set(+curr, true), new Map()) - const _envList = - otherEnvsResult.result - .filter((env) => !filteredEnvMap || filteredEnvMap.get(env.environmentId)) - ?.sort((a, b) => (a.environmentName > b.environmentName ? 1 : -1)) || [] - - if (_envList.length > 0) { - let selector - if (!params.envId && !environmentId) { - selector = new NoParamsNoEnvContext() - } else if (!params.envId && environmentId) { - selector = new NoParamsWithEnvContext() - } else if (params.envId && !environmentId) { - selector = new ParamsNoEnvContext() - } else if (params.envId && environmentId) { - selector = new ParamsAndEnvContext() - } + const selectedEnvsMap = new Map(selectedEnvList.map((env) => [+env.value, true])) + const envList = ( + (selectedEnvList.length + ? otherEnvsResult?.result?.filter((env) => selectedEnvsMap.get(env.environmentId)) + : otherEnvsResult?.result) || [] + ).sort((a, b) => stringComparatorBySortOrder(a.environmentName, b.environmentName)) - const selectedEnvId = selector.resolveEnvironmentId(params, environmentId, _envList, setEnvironmentId) + useEffect(() => { + if (params.envId) { + clearEnvListSelection() + } + }, []) - // Set the URL and push to navigation stack - if (selectedEnvId) { - if (String(selectedEnvId) !== String(params.envId)) { - const newUrl = getAppDetailsURL(params.appId, selectedEnvId) - push(newUrl) - } - } else { - setEnvironmentId(null) + useEffect(() => { + if (envList.length > 0) { + const userDefinedEnvId: number = params.envId && !isNaN(+params.envId) ? +params.envId : environmentId + const selectedEnvId: number = + userDefinedEnvId && envList.some((env) => env.environmentId === userDefinedEnvId) + ? userDefinedEnvId + : envList[0].environmentId + + if (selectedEnvId !== +params.envId) { + setEnvironmentId(+params.envId) + } + + // Set the URL and push to navigation stack + if (selectedEnvId) { + if (String(selectedEnvId) !== String(params.envId)) { + const newUrl = getAppDetailsURL(params.appId, selectedEnvId) + replace(newUrl) } } else { setEnvironmentId(null) } - // Return the filtered and sorted environment list - return _envList + } else { + setEnvironmentId(null) } - return [] - }, [filteredEnvIds, otherEnvsResult]) + }, [selectedEnvList, otherEnvsResult]) useEffect(() => { if (!params.envId) { @@ -230,7 +227,6 @@ export default function AppDetail({ filteredEnvIds }: { filteredEnvIds?: string isAppDeleted={isAppDeleted} isVirtualEnvRef={isVirtualEnvRef} isDeploymentBlocked={showDeploymentWindowConfirmation} - filteredEnvIds={filteredEnvIds} deploymentUserActionState={deploymentUserActionState} /> @@ -888,17 +884,6 @@ export const EnvSelector = ({ environments }: { environments: any }) => { ? sortObjectArrayAlphabetically(environments, 'environmentName') : environments - const formatOptionLabel = (option): JSX.Element => { - return ( -
-
{option.label}
- {option.description && ( - {option.description} - )} -
- ) - } - const groupList = sortedEnvironments?.reduce((acc, env) => { const Option = { diff --git a/src/components/app/details/appDetails/appDetails.type.ts b/src/components/app/details/appDetails/appDetails.type.ts index 55f9e4fc83..083dd5c20b 100644 --- a/src/components/app/details/appDetails/appDetails.type.ts +++ b/src/components/app/details/appDetails/appDetails.type.ts @@ -16,6 +16,7 @@ import { ACTION_STATE, ResponseType, ScanResultDTO, ServerErrors } from '@devtron-labs/devtron-fe-common-lib' import { fetchAppDetailsInTime } from '@Components/app/service' +import { MultiValue } from 'react-select' import { AggregatedNodes, OptionType } from '../../types' import { SyncErrorType, AppDetails } from '../../../v2/appDetails/appDetails.type' @@ -53,6 +54,11 @@ export interface AppDetailsPathParams { envId?: string } +export interface AppDetailsProps { + selectedEnvList?: MultiValue + clearEnvListSelection?: () => void +} + export interface SyncStageResourceDetail { id: number cdWorkflowRunnerId: number @@ -191,7 +197,6 @@ export interface DetailsType { showCommitInfo?: React.Dispatch> isVirtualEnvRef?: React.MutableRefObject isDeploymentBlocked?: boolean - filteredEnvIds?: string deploymentUserActionState?: ACTION_STATE onCloseHideDeploymentWindowConfirmationModal?: () => void } diff --git a/src/components/app/details/appDetails/utils.tsx b/src/components/app/details/appDetails/utils.tsx index 29bf5afdb9..52348d2f89 100644 --- a/src/components/app/details/appDetails/utils.tsx +++ b/src/components/app/details/appDetails/utils.tsx @@ -220,17 +220,6 @@ export function getGrafanaBaseURL(chartName: ChartTypes): string { return url } -export function getPodNameSuffix(nodeName: string, isAppDeployment: boolean, nodesMap: any, kind: string): string { - if (Nodes.Pod !== kind || !isAppDeployment) { - return '' - } - if (!nodesMap.has(nodeName)) { - return '' - } - const pod = nodesMap.get(nodeName) - return pod.isNew ? '(new)' : '(old)' -} - interface NodeItems { label: string value: string @@ -241,33 +230,6 @@ interface SelectedNodeItems { value: string } -export function getSelectedNodeItems( - selectedNodes: string, - nodeItems: NodeItems[], - isAppDeployment: boolean, - nodesMap: any, - kind: string, -): SelectedNodeItems[] { - let selectedNodeItems = [] - if (selectedNodes == 'All pods') { - selectedNodeItems = nodeItems - } else if (selectedNodes == 'All new pods') { - const result = nodeItems.filter((item) => item.label.includes('(new)')) - selectedNodeItems = result - } else if (selectedNodes == 'All old pods') { - const result = nodeItems.filter((item) => item.label.includes('(old)')) - selectedNodeItems = result - } else { - const initialNode = { - label: selectedNodes + getPodNameSuffix(selectedNodes, isAppDeployment, nodesMap, kind), - value: selectedNodes, - } - selectedNodeItems.push(initialNode) - } - - return selectedNodeItems -} - export function addChartNameExtensionToBaseURL( url: string, k8sVersion: string, @@ -372,49 +334,6 @@ export const validateMomentDate = (date: string, format: string): string => { return moment(date, format).fromNow() } -class EnvironmentSelection { - resolveEnvironmentId(params, environmentId, _envList, setEnvironmentId) { - throw new Error('This method should be overridden by concrete classes.') - } -} - -export class NoParamsNoEnvContext extends EnvironmentSelection { - resolveEnvironmentId(params, environmentId, _envList, setEnvironmentId) { - return _envList[0].environmentId - } -} - -export class NoParamsWithEnvContext extends EnvironmentSelection { - resolveEnvironmentId(params, environmentId, _envList, setEnvironmentId) { - if (environmentId && _envList.map((env) => env.environmentId).includes(environmentId)) { - return environmentId - } - return _envList[0].environmentId - } -} - -export class ParamsNoEnvContext extends EnvironmentSelection { - resolveEnvironmentId(params, environmentId, _envList, setEnvironmentId) { - if (params.envId && _envList.map((env) => env.environmentId).includes(+params.envId)) { - return +params.envId - } - return _envList[0].environmentId - } -} - -export class ParamsAndEnvContext extends EnvironmentSelection { - resolveEnvironmentId(params, environmentId, _envList, setEnvironmentId) { - if (params.envId && _envList.map((env) => env.environmentId).includes(+params.envId)) { - // If environmentId is present and different from params.envContext, set environmentId - if (environmentId && +environmentId !== +params.envId) { - setEnvironmentId(+params.envId) - } - return +params.envId - } - return _envList[0].environmentId - } -} - export const getDeployButtonStyle = (actionState: ACTION_STATE): ButtonStyleType => { switch (actionState) { case ACTION_STATE.BLOCKED: diff --git a/src/components/app/details/cIDetails/CIDetails.tsx b/src/components/app/details/cIDetails/CIDetails.tsx index 8c6ddbae71..cafc55e5a9 100644 --- a/src/components/app/details/cIDetails/CIDetails.tsx +++ b/src/components/app/details/cIDetails/CIDetails.tsx @@ -54,7 +54,7 @@ import { getArtifactForJobCi, } from '../../service' import { URLS, Routes } from '../../../../config' -import { BuildDetails, CIPipeline, HistoryLogsType, SecurityTabType } from './types' +import { BuildDetails, CIDetailsProps, CIPipeline, HistoryLogsType, SecurityTabType } from './types' import { ImageNotScannedView, CIRunningView } from './cIDetails.util' import './ciDetails.scss' import { getModuleInfo } from '../../../v2/devtronStackManager/DevtronStackManager.service' @@ -69,7 +69,11 @@ const SecurityModalSidebar = importComponentFromFELibrary('SecurityModalSidebar' const terminalStatus = new Set(['succeeded', 'failed', 'error', 'cancelled', 'nottriggered', 'notbuilt']) const statusSet = new Set(['starting', 'running', 'pending']) -export default function CIDetails({ isJobView, filteredEnvIds }: { isJobView?: boolean; filteredEnvIds?: string }) { +export default function CIDetails({ + isJobView, + filteredEnvIds, + clearEnvListSelection, +}: CIDetailsProps) { const { appId, pipelineId, buildId } = useParams<{ appId: string pipelineId: string @@ -100,6 +104,7 @@ export default function CIDetails({ isJobView, filteredEnvIds }: { isJobView?: b ]), [appId, filteredEnvIds], ) + const [loading, triggerHistoryResult, , , , dependencyState] = useAsync( () => getTriggerHistory(+pipelineId, pagination), [pipelineId, pagination], @@ -206,10 +211,15 @@ export default function CIDetails({ isJobView, filteredEnvIds }: { isJobView?: b ) // external and LINKED_CD pipelines not visible in dropdown const selectedPipelineExist = !pipelineId || pipelines.find((pipeline) => pipeline.id === +pipelineId) - if (!pipelines.length && pipelineId) { + if ((!pipelines.length || !selectedPipelineExist) && filteredEnvIds) { + clearEnvListSelection() + } else if (!pipelines.length && pipelineId && !filteredEnvIds) { // reason is un-required params like logs were leaking replace(generatePath(path, { appId })) - } else if ((pipelines.length === 1 && !pipelineId) || (!selectedPipelineExist && pipelines.length)) { + } else if ( + (pipelines.length === 1 && !pipelineId) || + (!selectedPipelineExist && pipelines.length && !filteredEnvIds) + ) { replace(generatePath(path, { appId, pipelineId: pipelines[0].id })) } const pipelineOptions: CICDSidebarFilterOptionType[] = (pipelines || []).map((item) => { diff --git a/src/components/app/details/cIDetails/types.tsx b/src/components/app/details/cIDetails/types.tsx index 3b3e574c1f..532d28b5dc 100644 --- a/src/components/app/details/cIDetails/types.tsx +++ b/src/components/app/details/cIDetails/types.tsx @@ -61,3 +61,9 @@ export interface SecurityTabType { status: string appIdFromParent?: string } + +export interface CIDetailsProps { + isJobView?: boolean + filteredEnvIds?: string + clearEnvListSelection?: () => void +} diff --git a/src/components/app/details/cdDetails/CDDetails.tsx b/src/components/app/details/cdDetails/CDDetails.tsx index 5ec74d1ea3..b211283740 100644 --- a/src/components/app/details/cdDetails/CDDetails.tsx +++ b/src/components/app/details/cdDetails/CDDetails.tsx @@ -44,7 +44,7 @@ import { useAppContext } from '@Components/common' import { getAppOtherEnvironmentMin, getCDConfig as getCDPipelines } from '../../../../services/service' import { AppNotConfigured } from '../appDetails/AppDetails' import './cdDetail.scss' -import { DeploymentTemplateList } from './cd.type' +import { CDDetailsProps } from './cd.type' import { getModuleConfigured } from '../appDetails/appDetails.service' import { EMPTY_STATE_STATUS } from '../../../../config/constantMessaging' import { @@ -57,7 +57,10 @@ import { renderVirtualHistoryArtifacts, } from './utils' -export default function CDDetails({ filteredEnvIds }: { filteredEnvIds: string }) { +export default function CDDetails({ + filteredEnvIds, + clearEnvListSelection, +}: CDDetailsProps) { const location = useLocation() const { appId, envId, triggerId, pipelineId } = useParams<{ appId: string @@ -160,8 +163,12 @@ export default function CDDetails({ filteredEnvIds }: { filteredEnvIds: string } setTriggerHistory(new Map(newTriggerHistory)) }, [deploymentHistoryResult, loading]) + const filteredEnvMap = filteredEnvIds?.split(',').reduce((agg, curr) => agg.set(curr, true), new Map()) //Result Typing to be fixed here useEffect(() => { + if (envId && filteredEnvIds && !filteredEnvMap.get(envId)) { + clearEnvListSelection() + } if (result) { if (result[1]) { setDeploymentAppType( @@ -170,7 +177,6 @@ export default function CDDetails({ filteredEnvIds }: { filteredEnvIds: string } ) } if (result[0]) { - const filteredEnvMap = filteredEnvIds?.split(',').reduce((agg, curr) => agg.set(curr, true), new Map()) const _selectedEnvironment = (result[0]['value']?.result || []) .filter((env) => { return !filteredEnvMap || filteredEnvMap.get(env.environmentId) @@ -199,7 +205,6 @@ export default function CDDetails({ filteredEnvIds }: { filteredEnvIds: string } const cdPipelinesMap = mapByKey(pipelines, 'environmentId') let _selectedEnvironment let isEnvDeleted = false - const filteredEnvMap = filteredEnvIds?.split(',').reduce((agg, curr) => agg.set(+curr, true), new Map()) const envOptions: CICDSidebarFilterOptionType[] = (result[0]['value']?.result || []) .filter((env) => { return !filteredEnvMap || filteredEnvMap.get(env.environmentId) diff --git a/src/components/app/details/cdDetails/cd.type.ts b/src/components/app/details/cdDetails/cd.type.ts index 11c9644c0d..da0a732275 100644 --- a/src/components/app/details/cdDetails/cd.type.ts +++ b/src/components/app/details/cdDetails/cd.type.ts @@ -71,3 +71,8 @@ export interface DeploymentDetailStepsType { userApprovalMetadata?: UserApprovalMetadataType isVirtualEnvironment?: boolean } + +export interface CDDetailsProps { + filteredEnvIds: string + clearEnvListSelection: () => void +} diff --git a/src/components/app/details/main.tsx b/src/components/app/details/main.tsx index b42be062af..199d1138dc 100644 --- a/src/components/app/details/main.tsx +++ b/src/components/app/details/main.tsx @@ -332,6 +332,17 @@ export default function AppDetailsPage({ isV2 }: AppDetailsProps) { getPermissionCheck({ resourceIds: selectedGroupId.appIds, groupType: FilterParentType.app }, false, true) } + const clearEnvListSelection = () => { + setSelectedAppList([]) + setGroupFilterOptions([]) + setAppGroupFilterInLocalStorage({ + filterParentType: FilterParentType.app, + resourceId: appId, + resourceList: [], + groupList: [], + }) + } + if (appListLoading || initLoading) { return } @@ -389,7 +400,12 @@ export default function AppDetailsPage({ isV2 }: AppDetailsProps) { ) : ( } + render={(props) => ( + + )} /> )} @@ -405,7 +421,11 @@ export default function AppDetailsPage({ isV2 }: AppDetailsProps) { render={(props) => } /> - + - + { <> {securityScansResult.result.securityScans.map((scan) => (
handleOpenScanDetailsModal(event, scan)} key={`${scan.name}-${scan.environment}`} role="button" @@ -355,7 +355,7 @@ export const SecurityScansTab = () => { ))} {securityScansResult.result.totalCount > DEFAULT_BASE_PAGE_SIZE && (