Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: persist app group and env group filter in local storage #2209

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/components/ApplicationGroup/AppGroup.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,7 @@ export interface CIConfigListType {
}

export interface AppGroupAppFilterContextType {
resourceId: string
appListOptions: OptionType[]
selectedAppList: MultiValue<OptionType>
setSelectedAppList: React.Dispatch<React.SetStateAction<MultiValue<OptionType>>>
Expand Down
28 changes: 27 additions & 1 deletion src/components/ApplicationGroup/AppGroup.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
* limitations under the License.
*/

import React from 'react'
import {
ServerErrors,
showError,
Expand All @@ -24,6 +23,7 @@ import {
WorkflowType,
getIsRequestAborted,
CIMaterialType,
OptionType,
} from '@devtron-labs/devtron-fe-common-lib'
import { DEFAULT_GIT_BRANCH_VALUE, DOCKER_FILE_ERROR_TITLE, SOURCE_NOT_CONFIGURED } from '../../config'
import { getEnvAppList } from './AppGroup.service'
Expand All @@ -32,8 +32,12 @@ import {
CDWorkflowStatusType,
CIWorkflowStatusType,
ProcessWorkFlowStatusType,
FilterParentType,
GroupOptionType,
} from './AppGroup.types'
import { getParsedBranchValuesForPlugin } from '@Components/common'
import { MultiValue } from 'react-select'
import { APP_GROUP_LOCAL_STORAGE_KEY, ENV_GROUP_LOCAL_STORAGE_KEY } from './Constants'

let timeoutId

Expand Down Expand Up @@ -290,3 +294,25 @@ export const processConsequenceData = (data: BlockedStateData): ConsequenceType
export const parseSearchParams = (searchParams: URLSearchParams) => ({
[AppGroupUrlFilters.cluster]: searchParams.getAll(AppGroupUrlFilters.cluster),
})

export const setFilterInLocalStorage = (
filterParentType: FilterParentType,
resourceId: string,
resourceList: MultiValue<OptionType>,
groupList: MultiValue<GroupOptionType>,
) => {
const localStorageKey =
filterParentType === FilterParentType.app ? ENV_GROUP_LOCAL_STORAGE_KEY : APP_GROUP_LOCAL_STORAGE_KEY
const localStorageValue = localStorage.getItem(localStorageKey)
if (!localStorageValue) {
const resourceIdVsValuesMap = new Map()
resourceIdVsValuesMap.set(resourceId, [resourceList, groupList])
// Set filter in local storage as Array from Map of resourceId vs [selectedAppList, selectedGroupFilter]
localStorage.setItem(localStorageKey, JSON.stringify(Array.from(resourceIdVsValuesMap)))
} else {
// update or set value for current resource
const localStoredMap = new Map(JSON.parse(localStorageValue))
localStoredMap.set(resourceId, [resourceList, groupList])
localStorage.setItem(localStorageKey, JSON.stringify(Array.from(localStoredMap)))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import { ReactComponent as Edit } from '../../assets/icons/ic-pencil.svg'
import { ReactComponent as Trash } from '../../assets/icons/ic-delete-interactive.svg'
import { ReactComponent as CheckIcon } from '../../assets/icons/ic-check.svg'
import { AppGroupAppFilterContextType, FilterParentType } from './AppGroup.types'
import { AppFilterTabs } from './Constants'
import { APP_GROUP_LOCAL_STORAGE_KEY, AppFilterTabs, ENV_GROUP_LOCAL_STORAGE_KEY } from './Constants'
import { ShortcutKeyBadge } from '@Components/common/formFields/Widgets/Widgets'

export const ValueContainer = (props): JSX.Element => {
Expand Down Expand Up @@ -182,6 +182,11 @@ export const MenuList = (props: any): JSX.Element => {
const clearSelection = (): void => {
setSelectedAppList([])
setSelectedGroupFilter([])
if (filterParentType === FilterParentType.app) {
localStorage.setItem(ENV_GROUP_LOCAL_STORAGE_KEY, '')
} else {
localStorage.setItem(APP_GROUP_LOCAL_STORAGE_KEY, '')
}
}
const onTabChange = (e): void => {
setSelectedFilterTab(e.currentTarget.dataset.selectedTab)
Expand Down
55 changes: 52 additions & 3 deletions src/components/ApplicationGroup/AppGroupAppFilter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,15 @@
import { useEffect, useRef, useState } from 'react'
import ReactSelect, { SelectInstance } from 'react-select'
import { useAppGroupAppFilterContext } from './AppGroupDetailsRoute'
import { appGroupAppSelectorStyle } from './AppGroup.utils'
import { appGroupAppSelectorStyle, setFilterInLocalStorage } from './AppGroup.utils'
import { AppGroupAppFilterContextType, FilterParentType } from './AppGroup.types'
import { AppFilterTabs } from './Constants'
import { APP_GROUP_LOCAL_STORAGE_KEY, AppFilterTabs, ENV_GROUP_LOCAL_STORAGE_KEY } from './Constants'
import { MenuList, Option, ValueContainer } from './AppGroupAppFilter.components'
import { OptionType, ReactSelectInputAction, useRegisterShortcut } from '@devtron-labs/devtron-fe-common-lib'

export default function AppGroupAppFilter() {
const {
resourceId,
appListOptions,
selectedAppList,
setSelectedAppList,
Expand Down Expand Up @@ -87,11 +88,14 @@ export default function AppGroupAppFilter() {
if (selectedFilterTab === AppFilterTabs.APP_FILTER) {
setSelectedAppList(selectedValue)
setSelectedGroupFilter([])
setFilterInLocalStorage(filterParentType, resourceId, selectedValue, [])
} else {
const _selectedGroup = selectedValue.pop()
setSelectedGroupFilter([_selectedGroup])
if (_selectedGroup) {
setSelectedAppList(appListOptions.filter((app) => _selectedGroup.appIds.indexOf(+app.value) >= 0))
const updatedAppList = appListOptions.filter((app) => _selectedGroup.appIds.indexOf(+app.value) >= 0)
setSelectedAppList(updatedAppList)
setFilterInLocalStorage(filterParentType, resourceId, updatedAppList, [_selectedGroup])
}
}
}
Expand All @@ -108,6 +112,51 @@ export default function AppGroupAppFilter() {
appGroupFilterRef.current.onMenuOpen()
}

useEffect(() => {
if (!appListOptions || !groupFilterOptions) {
return
}

const getAndSetItem = (localStorageKey: `${string}__filter`) => {
const localStorageValue = localStorage.getItem(localStorageKey)
if (!localStorageValue) {
return
}
const valueForCurrentResource = new Map(JSON.parse(localStorageValue)).get(resourceId)
// local storage value for app list/ env list
const localStorageResourceList = valueForCurrentResource?.[0]
// local storage value for group filter
const localStorageGroupList = valueForCurrentResource?.[1]

const appListOptionsMap = appListOptions.reduce<Record<string, true>>((agg, curr) => {
agg[curr.value] = true
return agg
}, {})

const groupFilterOptionsMap = groupFilterOptions.reduce<Record<string, true>>((agg, curr) => {
agg[curr.value] = true
return agg
}, {})

// filtering local storage lists acc to new appList/ envList or groupFilterList as local values might be deleted or does not exist anymore
const filteredLocalStorageResourceList = localStorageResourceList?.filter(({value}) => appListOptionsMap[value])
const filteredLocalStorageGroupList = localStorageGroupList?.filter(({value}) => groupFilterOptionsMap[value])

if (filteredLocalStorageResourceList) {
setSelectedAppList(filteredLocalStorageResourceList)
}
if (filteredLocalStorageGroupList) {
setSelectedGroupFilter(filteredLocalStorageGroupList)
}
}

if (filterParentType === FilterParentType.app) {
getAndSetItem(ENV_GROUP_LOCAL_STORAGE_KEY)
} else {
getAndSetItem(APP_GROUP_LOCAL_STORAGE_KEY)
}
}, [appListOptions, groupFilterOptions])

useEffect(() => {
registerShortcut({ keys: ['F'], callback: handleFilterFocus })

Expand Down
2 changes: 2 additions & 0 deletions src/components/ApplicationGroup/AppGroupDetailsRoute.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,7 @@ export const EnvHeader = ({

const contextValue = useMemo(
() => ({
resourceId: envId,
appListOptions,
isMenuOpen,
setMenuOpen,
Expand All @@ -528,6 +529,7 @@ export const EnvHeader = ({
groupFilterOptions,
selectedGroupFilter,
isSuperAdmin,
envId,
],
)

Expand Down
3 changes: 3 additions & 0 deletions src/components/ApplicationGroup/Constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -229,3 +229,6 @@ export const BULK_CI_BUILD_STATUS = (noOfApps) => ({
title: `Verifying selected code sources for ${noOfApps} Applications & initiating build pipelines Applications`,
subTitle: 'It might take some time depending upon the number of applications',
})

export const ENV_GROUP_LOCAL_STORAGE_KEY: `${string}__filter` = 'envGroup__filter'
export const APP_GROUP_LOCAL_STORAGE_KEY: `${string}__filter` = 'appGroup__filter'
2 changes: 2 additions & 0 deletions src/components/app/details/AppHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ export const AppHeader = ({

const contextValue = useMemo(
() => ({
resourceId: appId,
appListOptions,
isMenuOpen,
setMenuOpen,
Expand All @@ -82,6 +83,7 @@ export const AppHeader = ({
groupFilterOptions,
selectedGroupFilter,
isSuperAdmin,
appId,
],
)

Expand Down
Loading