Skip to content
Merged
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
7 changes: 3 additions & 4 deletions src/gitops/components/imageupdater/ImageUpdaterList.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import * as React from 'react';
import { useTranslation } from 'react-i18next';
import { useLocation } from 'react-router-dom-v5-compat';
import * as YamlFormatter from 'yaml';

import ActionsDropdown from '@gitops/utils/components/ActionDropDown/ActionDropDown';
import { modelToGroupVersionKind } from '@gitops/utils/utils';
Expand Down Expand Up @@ -43,7 +42,7 @@ import {
useGitOpsDataViewSort,
useGitOpsListPagePagination,
} from '../shared/DataView';
import { filterByConsoleNameAndLabels, parseLabelFilterParam } from '../shared/listPageTextFilters';
import { filterByConsoleNameAndLabels, getLabelsSortKey, parseLabelFilterParam } from '../shared/listPageTextFilters';
import MetadataLabels from '../shared/MetadataLabels';

import { useImageUpdaterActionsProvider } from './hooks/useImageUpdaterActionsProvider';
Expand Down Expand Up @@ -269,8 +268,8 @@ export const sortData = (
bValue = b.status?.conditions?.find((c) => c.type === 'Ready')?.status || '';
break;
case 'labels':
aValue = YamlFormatter.stringify(a.metadata?.labels || {});
bValue = YamlFormatter.stringify(b.metadata?.labels || {});
aValue = getLabelsSortKey(a.metadata?.labels);
bValue = getLabelsSortKey(b.metadata?.labels);
break;
default:
return 0;
Expand Down
7 changes: 3 additions & 4 deletions src/gitops/components/project/ProjectList.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import * as React from 'react';
import { useTranslation } from 'react-i18next';
import { useLocation } from 'react-router-dom-v5-compat';
import * as YamlFormatter from 'yaml';

import ActionsDropdown from '@gitops/utils/components/ActionDropDown/ActionDropDown';
import { modelToGroupVersionKind, modelToRef } from '@gitops/utils/utils';
Expand Down Expand Up @@ -41,7 +40,7 @@ import {
useGitOpsDataViewSort,
useGitOpsListPagePagination,
} from '../shared/DataView';
import { filterByConsoleNameAndLabels, parseLabelFilterParam } from '../shared/listPageTextFilters';
import { filterByConsoleNameAndLabels, getLabelsSortKey, parseLabelFilterParam } from '../shared/listPageTextFilters';
import { MetadataLabels } from '../shared/MetadataLabels/MetadataLabels';

import { useProjectActionsProvider } from './hooks/useProjectActionsProvider';
Expand Down Expand Up @@ -375,8 +374,8 @@ export const sortData = (
bValue = getApplicationsCount(b, applications, appsLoaded);
break;
case 'labels':
aValue = YamlFormatter.stringify(a.metadata?.labels || {});
bValue = YamlFormatter.stringify(b.metadata?.labels || {});
aValue = getLabelsSortKey(a.metadata?.labels);
bValue = getLabelsSortKey(b.metadata?.labels);
break;
case 'last-updated':
aValue = getLastUpdateTimestamp(a) || '';
Expand Down
6 changes: 3 additions & 3 deletions src/gitops/components/rollout/RolloutList.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import * as React from 'react';
import { Link } from 'react-router-dom-v5-compat';
import * as YamlFormatter from 'yaml';

import { AppProjectKind } from '@gitops/models/AppProjectModel';
import ActionsDropdown from '@gitops/utils/components/ActionDropDown/ActionDropDown';
Expand Down Expand Up @@ -44,6 +43,7 @@ import {
import {
filterByConsoleNameAndLabels,
filterResourcesByLabelQuery,
getLabelsSortKey,
parseLabelFilterParam,
} from '../shared/listPageTextFilters';
import { MetadataLabels } from '../shared/MetadataLabels/MetadataLabels';
Expand Down Expand Up @@ -265,8 +265,8 @@ export const sortData = (
bValue = b.status?.readyReplicas || '';
break;
case 'labels':
aValue = YamlFormatter.stringify(a.metadata?.labels || {});
bValue = YamlFormatter.stringify(b.metadata?.labels || {});
aValue = getLabelsSortKey(a.metadata?.labels);
bValue = getLabelsSortKey(b.metadata?.labels);
break;
case 'selector':
aValue = a.status?.selector || '';
Expand Down
6 changes: 3 additions & 3 deletions src/gitops/components/shared/ApplicationList.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import * as React from 'react';
import { useTranslation } from 'react-i18next';
import * as YamlFormatter from 'yaml';

import { ApplicationSetKind } from '@gitops/models/ApplicationSetModel';
import {
Expand Down Expand Up @@ -66,6 +65,7 @@ import {
import {
filterByConsoleNameAndLabels,
filterResourcesByLabelQuery,
getLabelsSortKey,
parseLabelFilterParam,
} from './listPageTextFilters';
import MetadataLabels from './MetadataLabels';
Expand Down Expand Up @@ -362,8 +362,8 @@ export const sortData = (
bValue = b.status?.sync?.revision || '';
break;
case 'labels':
aValue = YamlFormatter.stringify(a.metadata?.labels || {});
bValue = YamlFormatter.stringify(b.metadata?.labels || {});
aValue = getLabelsSortKey(a.metadata?.labels);
bValue = getLabelsSortKey(b.metadata?.labels);
break;
case 'project':
aValue = a.spec?.project || '';
Expand Down
6 changes: 3 additions & 3 deletions src/gitops/components/shared/ApplicationSetList.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import * as React from 'react';
import { useTranslation } from 'react-i18next';
import * as YamlFormatter from 'yaml';

import {
K8sResourceCommon,
Expand Down Expand Up @@ -50,6 +49,7 @@ import {
import {
filterByConsoleNameAndLabels,
filterResourcesByLabelQuery,
getLabelsSortKey,
parseLabelFilterParam,
} from './listPageTextFilters';
import MetadataLabels from './MetadataLabels';
Expand Down Expand Up @@ -536,8 +536,8 @@ export const sortData = (
bValue = getAppSetGeneratorCount(b);
break;
case 'labels':
aValue = YamlFormatter.stringify(a.metadata?.labels || {});
bValue = YamlFormatter.stringify(b.metadata?.labels || {});
aValue = getLabelsSortKey(a.metadata?.labels);
bValue = getLabelsSortKey(b.metadata?.labels);
break;
case 'created-at':
aValue = new Date(a.metadata?.creationTimestamp || 0).getTime();
Expand Down
20 changes: 20 additions & 0 deletions src/gitops/components/shared/listPageTextFilters.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
filterByConsoleNameAndLabels,
filterResourcesByLabelQuery,
fuzzySearch,
getLabelsSortKey,
matchesConsoleLabelFilter,
matchesConsoleNameFilter,
matchesLabelSearchQuery,
Expand Down Expand Up @@ -83,6 +84,25 @@ describe('matchesLabelSearchQuery (GitOps q param)', () => {
});
});

describe('getLabelsSortKey', () => {
it('returns the same key regardless of label key insertion order', () => {
const first = { app: 'foo', env: 'prod' };
const second = { env: 'prod', app: 'foo' };
expect(getLabelsSortKey(first)).toBe('app=foo,env=prod');
expect(getLabelsSortKey(second)).toBe('app=foo,env=prod');
expect(getLabelsSortKey(first)).toBe(getLabelsSortKey(second));
});

it('sorts keys alphabetically', () => {
expect(getLabelsSortKey({ z: '1', a: '2', m: '3' })).toBe('a=2,m=3,z=1');
});

it('returns an empty string when labels are missing or empty', () => {
expect(getLabelsSortKey(undefined)).toBe('');
expect(getLabelsSortKey({})).toBe('');
});
});

describe('name and label filters with pagination', () => {
const items = [
resource('app-matrix-2-staging-us-east', { app: 'matrix' }),
Expand Down
6 changes: 6 additions & 0 deletions src/gitops/components/shared/listPageTextFilters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,9 @@ export const filterResourcesByLabelQuery = <T extends LabeledResource>(
}
return (items ?? []).filter((item) => matchesLabelSearchQuery(query, item.metadata?.labels));
};

export const getLabelsSortKey = (labels: Record<string, string> | undefined): string =>
Object.keys(labels ?? {})
.sort()
.map((key) => `${key}=${labels?.[key] ?? ''}`)
.join(',');
Loading