Skip to content

Commit 5fa817a

Browse files
committed
feat: AppListFilters - replace FilterSelectPicker with GroupedFilterSelectPicker
1 parent 71757e1 commit 5fa817a

File tree

6 files changed

+242
-163
lines changed

6 files changed

+242
-163
lines changed

src/components/app/list-new/AppListFilters.tsx

Lines changed: 121 additions & 150 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ import ReactGA from 'react-ga4'
2020
import {
2121
AppListConstants,
2222
ComponentSizeType,
23-
FilterSelectPicker,
23+
GroupedFilterSelectPicker,
24+
GroupedFilterSelectPickerProps,
2425
SearchBar,
2526
SelectPickerOptionType,
2627
SERVER_MODE,
27-
Tooltip,
2828
useGetUserRoles,
2929
} from '@devtron-labs/devtron-fe-common-lib'
3030

@@ -33,8 +33,8 @@ import ExportToCsv from '@Components/common/ExportToCsv/ExportToCsv'
3333

3434
import { getDevtronAppListDataToExport } from './AppListService'
3535
import { AppListFiltersProps, AppListUrlFilters, AppStatuses } from './AppListType'
36-
import { APP_STATUS_FILTER_OPTIONS, SELECT_CLUSTER_TIPPY, TEMPLATE_TYPE_FILTER_OPTIONS } from './Constants'
37-
import { getAppTabNameFromAppType, useFilterOptions } from './list.utils'
36+
import { APP_STATUS_FILTER_OPTIONS, TEMPLATE_TYPE_FILTER_OPTIONS } from './Constants'
37+
import { getAppListFilters, getAppTabNameFromAppType, useFilterOptions } from './list.utils'
3838

3939
const AppListFilters = ({
4040
filterConfig,
@@ -44,7 +44,8 @@ const AppListFilters = ({
4444
isExternalArgo,
4545
isExternalFlux,
4646
appListFiltersResponse,
47-
showPulsatingDot,
47+
// TODO: need to handle this
48+
// showPulsatingDot,
4849
appListFiltersError,
4950
reloadAppListFilters,
5051
serverMode,
@@ -122,7 +123,7 @@ const AppListFilters = ({
122123
}
123124
}, [filterConfig])
124125

125-
const appStatusFilters: SelectPickerOptionType[] = structuredClone(APP_STATUS_FILTER_OPTIONS)
126+
const appStatusFilters: typeof APP_STATUS_FILTER_OPTIONS = structuredClone(APP_STATUS_FILTER_OPTIONS)
126127

127128
const showExportCsvButton =
128129
isSuperAdmin && appType === AppListConstants.AppType.DEVTRON_APPS && serverMode !== SERVER_MODE.EA_ONLY
@@ -132,153 +133,123 @@ const AppListFilters = ({
132133
updateSearchParams({ [filterKey]: selectedOptions.map((option) => String(option.value)) })
133134
}
134135

136+
const appListFiltersSelectPickerMap: GroupedFilterSelectPickerProps<AppListUrlFilters>['filterSelectPickerPropsMap'] =
137+
{
138+
[AppListUrlFilters.appStatus]: {
139+
placeholder: 'App Status',
140+
inputId: 'app-list-app-status-select',
141+
options: appStatusFilters,
142+
appliedFilterOptions: selectedAppStatus,
143+
handleApplyFilter: handleUpdateFilters(AppListUrlFilters.appStatus),
144+
isDisabled: false,
145+
isLoading: false,
146+
isOptionDisabled: getIsAppStatusDisabled,
147+
},
148+
[AppListUrlFilters.project]: {
149+
placeholder: 'Project',
150+
inputId: 'app-list-project-select',
151+
options: projectOptions,
152+
appliedFilterOptions: selectedProjects,
153+
handleApplyFilter: handleUpdateFilters(AppListUrlFilters.project),
154+
isDisabled: appListFiltersLoading,
155+
isLoading: appListFiltersLoading,
156+
optionListError: appListFiltersError,
157+
reloadOptionList: reloadAppListFilters,
158+
},
159+
[AppListUrlFilters.environment]: {
160+
placeholder: 'Environment',
161+
inputId: 'app-list-environment-select',
162+
options: environmentOptions,
163+
appliedFilterOptions: selectedEnvironments,
164+
handleApplyFilter: handleUpdateFilters(AppListUrlFilters.environment),
165+
isDisabled: appListFiltersLoading || !!clusterIdsCsv,
166+
isLoading: appListFiltersLoading,
167+
optionListError: appListFiltersError,
168+
reloadOptionList: reloadAppListFilters,
169+
},
170+
[AppListUrlFilters.templateType]: {
171+
placeholder: 'Template Type',
172+
inputId: 'app-list-template-type-filter',
173+
options: TEMPLATE_TYPE_FILTER_OPTIONS,
174+
appliedFilterOptions: selectedTemplateTypes,
175+
handleApplyFilter: handleUpdateFilters(AppListUrlFilters.templateType),
176+
isDisabled: !clusterIdsCsv,
177+
isLoading: false,
178+
},
179+
[AppListUrlFilters.cluster]: {
180+
placeholder: 'Cluster',
181+
inputId: 'app-list-cluster-filter',
182+
options: clusterOptions,
183+
appliedFilterOptions: selectedClusters,
184+
isDisabled: !(isExternalArgo || isExternalFlux) && !!selectedEnvironments.length,
185+
isLoading: appListFiltersLoading,
186+
handleApplyFilter: handleUpdateFilters(AppListUrlFilters.cluster),
187+
optionListError: appListFiltersError,
188+
reloadOptionList: reloadAppListFilters,
189+
isOptionDisabled: getIsClusterOptionDisabled,
190+
},
191+
[AppListUrlFilters.namespace]: {
192+
placeholder: 'Namespace',
193+
inputId: 'app-list-namespace-filter',
194+
options: namespaceOptions,
195+
appliedFilterOptions: selectedNamespaces,
196+
isDisabled: appListFiltersLoading || !clusterIdsCsv,
197+
isLoading: appListFiltersLoading,
198+
handleApplyFilter: handleUpdateFilters(AppListUrlFilters.namespace),
199+
shouldMenuAlignRight: !showExportCsvButton,
200+
optionListError: appListFiltersError,
201+
reloadOptionList: reloadAppListFilters,
202+
},
203+
}
204+
135205
return (
136206
<div className="search-filter-section">
137-
<SearchBar
138-
containerClassName="w-250"
139-
dataTestId="search-by-app-name"
140-
initialSearchText={searchKey}
141-
inputProps={{
142-
placeholder: `${
143-
appType === AppListConstants.AppType.HELM_APPS
144-
? 'Search by app or chart name'
145-
: 'Search by app name'
146-
}`,
147-
}}
148-
handleEnter={handleSearch}
149-
size={ComponentSizeType.medium}
150-
/>
151-
<div className="flexbox dc__gap-8 dc__align-items-center">
152-
{!(isExternalArgo || isExternalFlux) && (
153-
<>
154-
{isArgoInstalled && (
155-
<>
156-
<FilterSelectPicker
157-
placeholder="App Status"
158-
inputId="app-list-app-status-select"
159-
options={appStatusFilters}
160-
appliedFilterOptions={selectedAppStatus}
161-
handleApplyFilter={handleUpdateFilters(AppListUrlFilters.appStatus)}
162-
isDisabled={false}
163-
isLoading={false}
164-
isOptionDisabled={getIsAppStatusDisabled}
165-
/>
166-
<div className="dc__border-right h-16" />
167-
</>
168-
)}
169-
<FilterSelectPicker
170-
placeholder="Project"
171-
inputId="app-list-project-select"
172-
options={projectOptions}
173-
appliedFilterOptions={selectedProjects}
174-
handleApplyFilter={handleUpdateFilters(AppListUrlFilters.project)}
175-
isDisabled={appListFiltersLoading}
176-
isLoading={appListFiltersLoading}
177-
optionListError={appListFiltersError}
178-
reloadOptionList={reloadAppListFilters}
179-
/>
180-
<div className="dc__border-right h-16" />
181-
{serverMode === SERVER_MODE.FULL && (
182-
<>
183-
<Tooltip
184-
content="Remove cluster filters to use environment filter"
185-
alwaysShowTippyOnHover={!!clusterIdsCsv}
186-
wordBreak={false}
187-
>
188-
<div>
189-
<FilterSelectPicker
190-
placeholder="Environment"
191-
inputId="app-list-environment-select"
192-
options={environmentOptions}
193-
appliedFilterOptions={selectedEnvironments}
194-
handleApplyFilter={handleUpdateFilters(AppListUrlFilters.environment)}
195-
isDisabled={appListFiltersLoading || !!clusterIdsCsv}
196-
isLoading={appListFiltersLoading}
197-
optionListError={appListFiltersError}
198-
reloadOptionList={reloadAppListFilters}
199-
/>
200-
</div>
201-
</Tooltip>
202-
<div className="dc__border-right h-16" />
203-
</>
204-
)}
205-
</>
206-
)}
207-
{isExternalFlux && (
208-
<>
209-
<Tooltip content={SELECT_CLUSTER_TIPPY} alwaysShowTippyOnHover={!clusterIdsCsv}>
210-
<div>
211-
<FilterSelectPicker
212-
placeholder="Template Type"
213-
inputId="app-list-template-type-filter"
214-
options={TEMPLATE_TYPE_FILTER_OPTIONS}
215-
appliedFilterOptions={selectedTemplateTypes}
216-
handleApplyFilter={handleUpdateFilters(AppListUrlFilters.templateType)}
217-
isDisabled={!clusterIdsCsv}
218-
isLoading={false}
219-
/>
220-
</div>
221-
</Tooltip>
222-
<div className="dc__border-right h-16" />
223-
</>
224-
)}
225-
<Tooltip
226-
content="Remove environment filters to use cluster filter"
227-
alwaysShowTippyOnHover={!(isExternalArgo || isExternalFlux) && !!selectedEnvironments.length}
228-
wordBreak={false}
229-
>
230-
<div className="flexbox dc__position-rel">
231-
<FilterSelectPicker
232-
placeholder="Cluster"
233-
inputId="app-list-cluster-filter"
234-
options={clusterOptions}
235-
appliedFilterOptions={selectedClusters}
236-
isDisabled={!(isExternalArgo || isExternalFlux) && !!selectedEnvironments.length}
237-
isLoading={appListFiltersLoading}
238-
handleApplyFilter={handleUpdateFilters(AppListUrlFilters.cluster)}
239-
optionListError={appListFiltersError}
240-
reloadOptionList={reloadAppListFilters}
241-
isOptionDisabled={getIsClusterOptionDisabled}
242-
/>
243-
{showPulsatingDot && <div className="dc__pulsating-dot dc__position-abs" />}
244-
</div>
245-
</Tooltip>
246-
<Tooltip content={SELECT_CLUSTER_TIPPY} alwaysShowTippyOnHover={!clusterIdsCsv}>
247-
<div>
248-
<FilterSelectPicker
249-
placeholder="Namespace"
250-
inputId="app-list-namespace-filter"
251-
options={namespaceOptions}
252-
appliedFilterOptions={selectedNamespaces}
253-
isDisabled={appListFiltersLoading || !clusterIdsCsv}
254-
isLoading={appListFiltersLoading}
255-
handleApplyFilter={handleUpdateFilters(AppListUrlFilters.namespace)}
256-
shouldMenuAlignRight={!showExportCsvButton}
257-
optionListError={appListFiltersError}
258-
reloadOptionList={reloadAppListFilters}
259-
/>
260-
</div>
261-
</Tooltip>
262-
{showExportCsvButton && (
263-
<>
264-
<div className="dc__border-right h-16" />
265-
<ExportToCsv
266-
apiPromise={() =>
267-
getDevtronAppListDataToExport(
268-
filterConfig,
269-
appListFiltersResponse?.appListFilters.result.environments,
270-
namespaceListResponse?.result,
271-
appListFiltersResponse?.appListFilters.result.clusters,
272-
appListFiltersResponse?.appListFilters.result.teams,
273-
appCount,
274-
)
275-
}
276-
fileName={FILE_NAMES.Apps}
277-
disabled={!appCount}
278-
/>
279-
</>
280-
)}
207+
<div className="flex left dc__gap-8">
208+
<SearchBar
209+
containerClassName="w-250"
210+
dataTestId="search-by-app-name"
211+
initialSearchText={searchKey}
212+
inputProps={{
213+
placeholder: `${
214+
appType === AppListConstants.AppType.HELM_APPS
215+
? 'Search by app or chart name'
216+
: 'Search by app name'
217+
}`,
218+
}}
219+
handleEnter={handleSearch}
220+
size={ComponentSizeType.medium}
221+
/>
222+
<GroupedFilterSelectPicker<AppListUrlFilters>
223+
id="app-list-filters"
224+
isFilterApplied={!!(selectedAppStatus.length || selectedProjects.length)}
225+
options={getAppListFilters({
226+
clusterIdsCsv,
227+
isExternalArgo,
228+
isExternalFlux,
229+
isArgoInstalled,
230+
serverMode,
231+
selectedEnvironments,
232+
})}
233+
filterSelectPickerPropsMap={appListFiltersSelectPickerMap}
234+
/>
281235
</div>
236+
237+
{showExportCsvButton && (
238+
<ExportToCsv
239+
apiPromise={() =>
240+
getDevtronAppListDataToExport(
241+
filterConfig,
242+
appListFiltersResponse?.appListFilters.result.environments,
243+
namespaceListResponse?.result,
244+
appListFiltersResponse?.appListFilters.result.clusters,
245+
appListFiltersResponse?.appListFilters.result.teams,
246+
appCount,
247+
)
248+
}
249+
fileName={FILE_NAMES.Apps}
250+
disabled={!appCount}
251+
/>
252+
)}
282253
</div>
283254
)
284255
}

src/components/app/list-new/AppListType.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
import {
1818
EnvironmentListHelmResponse,
19+
GroupedFilterSelectPickerProps,
1920
ResponseType,
2021
SERVER_MODE,
2122
SortingOrder,
@@ -210,3 +211,6 @@ export interface GetDevtronHelmAppListParamsType {
210211
export interface AskToClearFiltersProps extends Pick<DevtronAppListProps, 'clearAllFilters'> {
211212
showTipToSelectCluster?: boolean
212213
}
214+
215+
export type AppListFilterMenuItemType =
216+
GroupedFilterSelectPickerProps<AppListUrlFilters>['options'][number]['items'][number]

src/components/app/list-new/Constants.ts

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
* limitations under the License.
1515
*/
1616

17+
import { GroupBase } from 'react-select'
18+
1719
import { OptionType, SelectPickerOptionType, UseUrlFiltersProps } from '@devtron-labs/devtron-fe-common-lib'
1820

1921
import { URLS } from '@Config/routes'
@@ -73,13 +75,18 @@ export const TEMPLATE_TYPE_FILTER_OPTIONS: SelectPickerOptionType[] = [
7375
{ label: FluxCDTemplateType.KUSTOMIZATION, value: FluxCDTemplateType.KUSTOMIZATION },
7476
]
7577

76-
export const APP_STATUS_FILTER_OPTIONS: SelectPickerOptionType[] = [
77-
{ label: AppStatuses.DEGRADED, value: AppStatusesDTO.DEGRADED },
78-
{ label: AppStatuses.HEALTHY, value: AppStatusesDTO.HEALTHY },
79-
{ label: AppStatuses.HIBERNATING, value: AppStatusesDTO.HIBERNATING },
80-
{ label: AppStatuses.MISSING, value: AppStatusesDTO.MISSING },
81-
{ label: AppStatuses.NOT_DEPLOYED, value: AppStatusesDTO.NOT_DEPLOYED },
82-
{ label: AppStatuses.PROGRESSING, value: AppStatusesDTO.PROGRESSING },
78+
export const APP_STATUS_FILTER_OPTIONS: GroupBase<SelectPickerOptionType>[] = [
79+
{
80+
label: 'App Status',
81+
options: [
82+
{ label: AppStatuses.DEGRADED, value: AppStatusesDTO.DEGRADED },
83+
{ label: AppStatuses.HEALTHY, value: AppStatusesDTO.HEALTHY },
84+
{ label: AppStatuses.HIBERNATING, value: AppStatusesDTO.HIBERNATING },
85+
{ label: AppStatuses.MISSING, value: AppStatusesDTO.MISSING },
86+
{ label: AppStatuses.NOT_DEPLOYED, value: AppStatusesDTO.NOT_DEPLOYED },
87+
{ label: AppStatuses.PROGRESSING, value: AppStatusesDTO.PROGRESSING },
88+
],
89+
},
8390
]
8491

8592
export const APPS_WITH_NO_PROJECT_OPTION: OptionType = {

0 commit comments

Comments
 (0)