Commit 9f243d2d authored by Kostia Palchyk's avatar Kostia Palchyk Committed by Kos Palchyk

Sort storage quotas usage list to match graph order

To synchronise sorting in the graph and in the list a reusable sorting
factory was added.
parent 1350874c
<script>
import { GlLink, GlIcon, GlTableLite as GlTable, GlSprintf } from '@gitlab/ui';
import { GlIcon, GlLink, GlSprintf, GlTableLite } from '@gitlab/ui';
import { numberToHumanSize } from '~/lib/utils/number_utils';
import { thWidthClass } from '~/lib/utils/table_utility';
import { sprintf } from '~/locale';
import {
HELP_LINK_ARIA_LABEL,
PROJECT_TABLE_LABEL_STORAGE_TYPE,
PROJECT_TABLE_LABEL_USAGE,
HELP_LINK_ARIA_LABEL,
} from '../constants';
import { descendingStorageUsageSort } from '../utils';
import StorageTypeIcon from './storage_type_icon.vue';
export default {
......@@ -15,7 +16,7 @@ export default {
components: {
GlLink,
GlIcon,
GlTable,
GlTableLite,
GlSprintf,
StorageTypeIcon,
},
......@@ -25,6 +26,11 @@ export default {
required: true,
},
},
computed: {
sizeSortedStorageTypes() {
return [...this.storageTypes].sort(descendingStorageUsageSort('value'));
},
},
methods: {
helpLinkAriaLabel(linkTitle) {
return sprintf(HELP_LINK_ARIA_LABEL, {
......@@ -37,13 +43,11 @@ export default {
key: 'storageType',
label: PROJECT_TABLE_LABEL_STORAGE_TYPE,
thClass: thWidthClass(90),
sortable: true,
},
{
key: 'value',
label: PROJECT_TABLE_LABEL_USAGE,
thClass: thWidthClass(10),
sortable: true,
formatter: (value) => {
return numberToHumanSize(value, 1);
},
......@@ -52,7 +56,7 @@ export default {
};
</script>
<template>
<gl-table :items="storageTypes" :fields="$options.projectTableFields">
<gl-table-lite :items="sizeSortedStorageTypes" :fields="$options.projectTableFields">
<template #cell(storageType)="{ item }">
<div class="gl-display-flex gl-flex-direction-row">
<storage-type-icon
......@@ -88,5 +92,5 @@ export default {
</div>
</div>
</template>
</gl-table>
</gl-table-lite>
</template>
......@@ -2,6 +2,7 @@
import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
import { numberToHumanSize } from '~/lib/utils/number_utils';
import { PROJECT_STORAGE_TYPES } from '../constants';
import { descendingStorageUsageSort } from '../utils';
export default {
components: {
......@@ -84,7 +85,7 @@ export default {
},
]
.filter((data) => data.size !== 0)
.sort((a, b) => b.size - a.size)
.sort(descendingStorageUsageSort('size'))
.map((storageType) => {
const storageTypeExtraData = PROJECT_STORAGE_TYPES.find(
(type) => storageType.id === type.id,
......
......@@ -178,3 +178,13 @@ export const parseGetProjectStorageResults = (data, helpLinks) => {
statistics: projectStatistics,
};
};
/**
* Creates a sorting function to sort storage types by usage in the graph and in the table
*
* @param {string} storageUsageKey key storing value of storage usage
* @returns {Function} sorting function
*/
export function descendingStorageUsageSort(storageUsageKey) {
return (a, b) => b[storageUsageKey] - a[storageUsageKey];
}
......@@ -2,14 +2,14 @@ import { GlTableLite } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import ProjectStorageDetail from 'ee/usage_quotas/storage/components/project_storage_detail.vue';
import { numberToHumanSize } from '~/lib/utils/number_utils';
import { projectData, projectHelpLinks } from '../mock_data';
describe('ProjectStorageDetail', () => {
let wrapper;
const defaultProps = {
storageTypes: projectData.storage.storageTypes,
};
const { storageTypes } = projectData.storage;
const defaultProps = { storageTypes };
const createComponent = (props = {}) => {
wrapper = extendedWrapper(
......@@ -32,7 +32,7 @@ describe('ProjectStorageDetail', () => {
});
describe('with storage types', () => {
it.each(projectData.storage.storageTypes)(
it.each(storageTypes)(
'renders table row correctly %o',
({ storageType: { id, name, description } }) => {
expect(wrapper.findByTestId(`${id}-name`).text()).toBe(name);
......@@ -43,6 +43,18 @@ describe('ProjectStorageDetail', () => {
);
},
);
it('should render items in order from the biggest usage size to the smallest', () => {
const rows = findTable().find('tbody').findAll('tr');
// Cloning array not to mutate the source
const sortedStorageTypes = [...storageTypes].sort((a, b) => b.value - a.value);
sortedStorageTypes.forEach((storageType, i) => {
const rowUsageAmount = rows.wrappers[i].find('td:last-child').text();
const expectedUsageAmount = numberToHumanSize(storageType.value, 1);
expect(rowUsageAmount).toBe(expectedUsageAmount);
});
});
});
describe('without storage types', () => {
......
......@@ -4,6 +4,7 @@ import {
parseProjects,
calculateUsedAndRemStorage,
parseGetProjectStorageResults,
descendingStorageUsageSort,
} from 'ee/usage_quotas/storage/utils';
import {
projectData,
......@@ -120,3 +121,14 @@ describe('parseProjects', () => {
});
});
});
describe('descendingStorageUsageSort', () => {
it('sorts items by a given key in descending order', () => {
const items = [{ k: 1 }, { k: 3 }, { k: 2 }];
const sorted = [...items].sort(descendingStorageUsageSort('k'));
const expectedSorted = [{ k: 3 }, { k: 2 }, { k: 1 }];
expect(sorted).toEqual(expectedSorted);
});
});
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment