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(ui): allow sorting the application list (#4060) #11645

Merged
merged 10 commits into from
Jan 25, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -516,6 +517,18 @@ export const ApplicationsList = (props: RouteComponentProps<{}>) => {
</h5>
</EmptyState>
)}
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',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you want to change Synchronized to App Health?

Copy link
Member Author

@alexef alexef Dec 12, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I would keep Synchronized as it is (it's the last time the sync operation finished - either successfully or not).

But an App Health sort order option makes sense as well: show Unknown,Out of sync, Synced in this order!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated

compare: (a, b) =>
a.status.operationState?.finishedAt?.localeCompare(b.status.operationState?.finishedAt)
}
]}
data={filteredApps}
onPageChange={page => ctx.navigation.goto('.', {page})}>
{data =>
Expand Down
40 changes: 38 additions & 2 deletions ui/src/app/shared/components/paginate/paginate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ import {services} from '../../services';

require('./paginate.scss');

export interface SortOption<T> {
title: string;
compare: (a: T, b: T) => number;
}

export interface PaginateProps<T> {
page: number;
onPageChange: (page: number) => any;
Expand All @@ -15,14 +20,16 @@ export interface PaginateProps<T> {
preferencesKey?: string;
header?: React.ReactNode;
showHeader?: boolean;
sortOptions?: SortOption<T>[];
}

export function Paginate<T>({page, onPageChange, children, data, emptyState, preferencesKey, header, showHeader}: PaginateProps<T>) {
export function Paginate<T>({page, onPageChange, children, data, emptyState, preferencesKey, header, showHeader, sortOptions}: PaginateProps<T>) {
return (
<DataLoader load={() => 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;
Expand All @@ -43,6 +50,29 @@ export function Paginate<T>({page, onPageChange, children, data, emptyState, pre
/>
)}
<div className='paginate__size-menu'>
{sortOptions && (
<DropDownMenu
anchor={() => (
<>
<a>
Sort: {sortOption.toLowerCase()} <i className='fa fa-caret-down' />
</a>
&nbsp;
</>
)}
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);
}
}))}
/>
)}
<DropDownMenu
anchor={() => (
<a>
Expand All @@ -63,7 +93,13 @@ export function Paginate<T>({page, onPageChange, children, data, emptyState, pre
</div>
);
}

if (sortOption) {
sortOptions
.filter(o => o.title === sortOption)
.map(so => {
data.sort(so.compare);
});
}
return (
<React.Fragment>
<div className='paginate'>{paginator()}</div>
Expand Down
1 change: 1 addition & 0 deletions ui/src/app/shared/services/view-preferences-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down