From 44f746533d20ff9449111d540962445c85c9476c Mon Sep 17 00:00:00 2001 From: Alex Eftimie Date: Wed, 25 Jan 2023 19:17:49 +0100 Subject: [PATCH] feat(ui): allow sorting the application list (#11645) Signed-off-by: Alex Eftimie Co-authored-by: Remington Breeze Signed-off-by: schakrad --- .../applications-list/applications-list.tsx | 13 ++++++ .../shared/components/paginate/paginate.tsx | 40 ++++++++++++++++++- .../services/view-preferences-service.ts | 1 + 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/ui/src/app/applications/components/applications-list/applications-list.tsx b/ui/src/app/applications/components/applications-list/applications-list.tsx index 42ee2da8a6899..36e75aaa0810b 100644 --- a/ui/src/app/applications/components/applications-list/applications-list.tsx +++ b/ui/src/app/applications/components/applications-list/applications-list.tsx @@ -43,6 +43,7 @@ const APP_FIELDS = [ 'status.sync.revision', 'status.health', 'status.operationState.phase', + 'status.operationState.finishedAt', 'status.operationState.operation.sync', 'status.summary', 'status.resources' @@ -516,6 +517,18 @@ export const ApplicationsList = (props: RouteComponentProps<{}>) => { )} + sortOptions={[ + {title: 'Name', compare: (a, b) => a.metadata.name.localeCompare(b.metadata.name)}, + { + title: 'Created At', + compare: (a, b) => a.metadata.creationTimestamp.localeCompare(b.metadata.creationTimestamp) + }, + { + title: 'Synchronized', + compare: (a, b) => + a.status.operationState?.finishedAt?.localeCompare(b.status.operationState?.finishedAt) + } + ]} data={filteredApps} onPageChange={page => ctx.navigation.goto('.', {page})}> {data => diff --git a/ui/src/app/shared/components/paginate/paginate.tsx b/ui/src/app/shared/components/paginate/paginate.tsx index 7c55ec779bfe2..8b70cc02535d0 100644 --- a/ui/src/app/shared/components/paginate/paginate.tsx +++ b/ui/src/app/shared/components/paginate/paginate.tsx @@ -6,6 +6,11 @@ import {services} from '../../services'; require('./paginate.scss'); +export interface SortOption { + title: string; + compare: (a: T, b: T) => number; +} + export interface PaginateProps { page: number; onPageChange: (page: number) => any; @@ -15,14 +20,16 @@ export interface PaginateProps { preferencesKey?: string; header?: React.ReactNode; showHeader?: boolean; + sortOptions?: SortOption[]; } -export function Paginate({page, onPageChange, children, data, emptyState, preferencesKey, header, showHeader}: PaginateProps) { +export function Paginate({page, onPageChange, children, data, emptyState, preferencesKey, header, showHeader, sortOptions}: PaginateProps) { return ( services.viewPreferences.getPreferences()}> {pref => { preferencesKey = preferencesKey || 'default'; const pageSize = pref.pageSizes[preferencesKey] || 10; + const sortOption = sortOptions ? (pref.sortOptions && pref.sortOptions[preferencesKey]) || sortOptions[0].title : ''; const pageCount = pageSize === -1 ? 1 : Math.ceil(data.length / pageSize); if (pageCount <= page) { page = pageCount - 1; @@ -43,6 +50,29 @@ export function Paginate({page, onPageChange, children, data, emptyState, pre /> )}
+ {sortOptions && ( + ( + <> + + Sort: {sortOption.toLowerCase()} + +   + + )} + items={sortOptions.map(so => ({ + title: so.title, + action: () => { + // sortOptions might not be set in the browser storage + if (!pref.sortOptions) { + pref.sortOptions = {}; + } + pref.sortOptions[preferencesKey] = so.title; + services.viewPreferences.updatePreferences(pref); + } + }))} + /> + )} ( @@ -63,7 +93,13 @@ export function Paginate({page, onPageChange, children, data, emptyState, pre
); } - + if (sortOption) { + sortOptions + .filter(o => o.title === sortOption) + .map(so => { + data.sort(so.compare); + }); + } return (
{paginator()}
diff --git a/ui/src/app/shared/services/view-preferences-service.ts b/ui/src/app/shared/services/view-preferences-service.ts index e1b4c134a7a83..2d0608356cd88 100644 --- a/ui/src/app/shared/services/view-preferences-service.ts +++ b/ui/src/app/shared/services/view-preferences-service.ts @@ -91,6 +91,7 @@ export interface ViewPreferences { appDetails: AppDetailsPreferences; appList: AppsListPreferences; pageSizes: {[key: string]: number}; + sortOptions: {[key: string]: string}; hideBannerContent: string; hideSidebar: boolean; position: string;