Skip to content

Commit

Permalink
Merge pull request #1733 from devtron-labs/feat/bulk-restart-workload
Browse files Browse the repository at this point in the history
feat: App Group Restart Workload modal
  • Loading branch information
shivani170 authored May 6, 2024
2 parents 77cb5e1 + f76b611 commit 3da3de4
Show file tree
Hide file tree
Showing 12 changed files with 1,128 additions and 10 deletions.
3 changes: 3 additions & 0 deletions src/assets/icons/ic-expand.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
90 changes: 88 additions & 2 deletions src/components/ApplicationGroup/AppGroup.types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
ACTION_STATE,
CDModalTabType,
CHECKBOX_VALUE,
DeploymentNodeType,
FilterConditionsListType,
KeyValueListType,
Expand All @@ -12,8 +13,10 @@ import {
} from '@devtron-labs/devtron-fe-common-lib'
import { MultiValue } from 'react-select'
import { WebhookPayloads } from '../app/details/triggerView/types'
import { EditDescRequest, OptionType } from '../app/types'
import { EditDescRequest, NodeType, Nodes, OptionType } from '../app/types'
import { AppFilterTabs, BulkResponseStatus } from './Constants'
import { GVKType } from '../ResourceBrowser/Types'
import { WorkloadCheckType } from '../v2/appDetails/sourceInfo/scaleWorkloads/scaleWorkloadsModal.type'

interface BulkTriggerAppDetailType {
workFlowId: string
Expand Down Expand Up @@ -460,7 +463,7 @@ export interface BaseModalProps {
setShowHibernateStatusDrawer: React.Dispatch<React.SetStateAction<StatusDrawer>>
}

export interface HibernateInfoMapProps {
export interface HibernateInfoMapProps {
type: string
excludedUserEmails: string[]
userActionState: ACTION_STATE
Expand Down Expand Up @@ -509,3 +512,86 @@ export interface ApiQueuingWithBatchResponseItem {
value?: any
reason?: ServerErrors
}

export interface RestartWorkloadModalProps {
selectedAppIds: number[]
envName: string
envId: string
restartLoader: boolean
setRestartLoader: React.Dispatch<React.SetStateAction<boolean>>
hibernateInfoMap: Record<number, HibernateInfoMapProps>
}

export interface RestartStatusListDrawerProps {
bulkRotatePodsMap: BulkRotatePodsMap
statusModalLoading: boolean
envName: string
hibernateInfoMap: Record<number, HibernateInfoMapProps>
}

// ----------------------------Restart Workload DTO--------------------------------------------

export interface ResourceIdentifierDTO extends ResourceErrorMetaData {
name: string
namespace?: string // This is only in the post response structure and not in get api
groupVersionKind: GVKType
}

export interface AppInfoMetaDataDTO {
resourceMetaData: ResourceIdentifierDTO[]
appName: string,
errorResponse?: string
}

export interface RestartPodMapDTO {
[appId: number]: AppInfoMetaDataDTO
}

export interface WorkloadListResultDTO {
environmentId: number
namespace: string
restartPodMap: RestartPodMapDTO
}

// ----------------------------Bulk Restart Data Manipulation-----------------------------------

export interface ResourceErrorMetaData {
containsError?: boolean
errorResponse?: string
}

export interface AppStatusMetaData {
failedCount?: number
successCount?: number
}

export interface ResourceMetaData extends WorkloadCheckType, ResourceErrorMetaData {
group: string
kind: Nodes | NodeType
version: string
name: string
}
export interface ResourcesMetaDataMap {
[kindName: string]: ResourceMetaData
}
export interface BulkRotatePodsMetaData extends WorkloadCheckType, AppStatusMetaData {
appName: string
resources?: ResourcesMetaDataMap
namespace: string
errorResponse?: string
}

export interface BulkRotatePodsMap {
[appId: number]: BulkRotatePodsMetaData
}
export interface AllExpandableDropdownTypes {
expandedAppIds: number[]
setExpandedAppIds: React.Dispatch<React.SetStateAction<number[]>>
bulkRotatePodsMap: BulkRotatePodsMap
SvgImage: React.FunctionComponent<React.SVGProps<SVGSVGElement>>
iconClassName?: string
dropdownLabel?: string
isExpandableButtonClicked: boolean
setExpandableButtonClicked: React.Dispatch<React.SetStateAction<boolean>>
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from 'react'
import { AllExpandableDropdownTypes } from '../../AppGroup.types'

export const AllExpandableDropdown = ({
expandedAppIds,
setExpandedAppIds,
bulkRotatePodsMap,
SvgImage,
iconClassName,
dropdownLabel = '',
isExpandableButtonClicked,
setExpandableButtonClicked,
}: AllExpandableDropdownTypes) => {
const handleAllExpand = () => {
if (expandedAppIds.length === Object.keys(bulkRotatePodsMap).length) {
setExpandedAppIds([])
setExpandableButtonClicked(false)
} else {
setExpandedAppIds(Object.keys(bulkRotatePodsMap).map((appId) => +appId))
setExpandableButtonClicked(!isExpandableButtonClicked)
}
}

return (
<div className="flex dc__gap-4 cursor" onClick={handleAllExpand}>
{dropdownLabel}
<SvgImage className={`rotate fcn-9 flex ${iconClassName}`} onClick={handleAllExpand} />
</div>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ import {
SortingOrder,
useUrlFilters,
EditableTextArea,
useSearchString,
} from '@devtron-labs/devtron-fe-common-lib'
import Tippy from '@tippyjs/react'
import moment from 'moment'
import React, { useEffect, useRef, useState } from 'react'
import { Link, useParams } from 'react-router-dom'
import { Link, useHistory, useParams } from 'react-router-dom'
import { Moment12HourFormat } from '../../../../config'
import CommitChipCell from '../../../../Pages/Shared/CommitChipCell'
import { StatusConstants } from '../../../app/list-new/Constants'
Expand All @@ -30,7 +31,7 @@ import {
StatusDrawer,
} from '../../AppGroup.types'
import { EnvironmentOverviewSortableKeys, GROUP_LIST_HEADER, OVERVIEW_HEADER } from '../../Constants'
import { BIO_MAX_LENGTH, BIO_MAX_LENGTH_ERROR } from './constants'
import { BIO_MAX_LENGTH, BIO_MAX_LENGTH_ERROR, URL_SEARCH_PARAMS } from './constants'
import { ReactComponent as DockerIcon } from '../../../../assets/icons/git/docker.svg'
import { ReactComponent as ActivityIcon } from '../../../../assets/icons/ic-activity.svg'
import { ReactComponent as ArrowLineDown } from '../../../../assets/icons/ic-arrow-line-down.svg'
Expand All @@ -39,6 +40,7 @@ import { ReactComponent as GridIconBlue } from '../../../../assets/icons/ic-grid
import { ReactComponent as GridIcon } from '../../../../assets/icons/ic-grid-view.svg'
import { ReactComponent as HibernateIcon } from '../../../../assets/icons/ic-hibernate-3.svg'
import { ReactComponent as UnhibernateIcon } from '../../../../assets/icons/ic-unhibernate.svg'
import { ReactComponent as RotateIcon } from '../../../../assets/icons/ic-arrows_clockwise.svg'

const processDeploymentWindowAppGroupOverviewMap = importComponentFromFELibrary(
'processDeploymentWindowAppGroupOverviewMap',
Expand All @@ -49,6 +51,7 @@ import './envOverview.scss'
import { HibernateModal } from './HibernateModal'
import HibernateStatusListDrawer from './HibernateStatusListDrawer'
import { UnhibernateModal } from './UnhibernateModal'
import { RestartWorkloadModal } from './RestartWorkloadModal'

export default function EnvironmentOverview({
appGroupListData,
Expand Down Expand Up @@ -82,11 +85,15 @@ export default function EnvironmentOverview({
const [hibernateInfoMap, setHibernateInfoMap] = useState<
Record<string, { type: string; excludedUserEmails: string[], userActionState: ACTION_STATE }>
>({})
const [restartLoader, setRestartLoader] = useState<boolean>(false)

const { sortBy, sortOrder, handleSorting } = useUrlFilters({
initialSortKey: EnvironmentOverviewSortableKeys.application,
})

const { searchParams } = useSearchString()
const history = useHistory()

useEffect(() => {
return () => {
if (timerId.current) {
Expand All @@ -109,11 +116,10 @@ export default function EnvironmentOverview({
}

useEffect(() => {
if (processDeploymentWindowAppGroupOverviewMap && (openHiberateModal || openUnhiberateModal || showHibernateStatusDrawer.showStatus)) {
if (processDeploymentWindowAppGroupOverviewMap && (openHiberateModal || openUnhiberateModal || showHibernateStatusDrawer.showStatus || location.search.includes(URL_SEARCH_PARAMS.BULK_RESTART_WORKLOAD))) {
getDeploymentWindowEnvOverrideMetaData()
}
}, [openHiberateModal, openUnhiberateModal, showHibernateStatusDrawer.showStatus])

}, [openHiberateModal, openUnhiberateModal, showHibernateStatusDrawer.showStatus, location.search])
useEffect(() => {
setLoading(true)
fetchDeployments()
Expand Down Expand Up @@ -247,6 +253,14 @@ export default function EnvironmentOverview({
setOpenUnhiberateModal(true)
}

const onClickShowBulkRestartModal = () => {
const newParams = {
...searchParams,
modal: URL_SEARCH_PARAMS.BULK_RESTART_WORKLOAD,
}
history.push({ search: new URLSearchParams(newParams).toString() })
}

const closeCommitInfoModal = () => {
setCommitInfoModalConfig(null)
}
Expand Down Expand Up @@ -431,7 +445,7 @@ export default function EnvironmentOverview({
)
}

return appListData ? (
return appListData?.appInfoList?.length > 0 ? (
<div className="env-overview-container dc__content-center bcn-0 pt-20 pb-20 pl-20 pr-20">
<div>{renderSideInfoColumn()}</div>
<div className="dc__h-fit-content">
Expand All @@ -456,6 +470,13 @@ export default function EnvironmentOverview({
<UnhibernateIcon className="icon-dim-12 mr-4" />
Unhibernate
</button>
<button
onClick={onClickShowBulkRestartModal}
className="bcn-0 fs-12 dc__border dc__border-radius-4-imp flex h-28"
>
<RotateIcon className="icon-dim-12 mr-4 scn-9" />
Restart Workload
</button>
</div>
)}
</div>
Expand Down Expand Up @@ -540,6 +561,16 @@ export default function EnvironmentOverview({
showDefaultDrawer={showDefaultDrawer}
/>
)}
{location.search?.includes(URL_SEARCH_PARAMS.BULK_RESTART_WORKLOAD) && (
<RestartWorkloadModal
selectedAppIds={selectedAppIds}
envName={appListData.environment}
envId={envId}
setRestartLoader={setRestartLoader}
restartLoader={restartLoader}
hibernateInfoMap={hibernateInfoMap}
/>
)}
{showHibernateStatusDrawer.showStatus && (
<HibernateStatusListDrawer
closePopup={closePopup}
Expand Down
Loading

0 comments on commit 3da3de4

Please sign in to comment.