Commit 8830aa88 authored by Natalia Tepluhina's avatar Natalia Tepluhina

Merge branch 'kpalchyk/fix-project-storage-usage-legend-order-of-items-345190' into 'master'

Fix project storage usage legend order of items

See merge request gitlab-org/gitlab!77106
parents 0bfca6b5 9f243d2d
<script> <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 { numberToHumanSize } from '~/lib/utils/number_utils';
import { thWidthClass } from '~/lib/utils/table_utility'; import { thWidthClass } from '~/lib/utils/table_utility';
import { sprintf } from '~/locale'; import { sprintf } from '~/locale';
import { import {
HELP_LINK_ARIA_LABEL,
PROJECT_TABLE_LABEL_STORAGE_TYPE, PROJECT_TABLE_LABEL_STORAGE_TYPE,
PROJECT_TABLE_LABEL_USAGE, PROJECT_TABLE_LABEL_USAGE,
HELP_LINK_ARIA_LABEL,
} from '../constants'; } from '../constants';
import { descendingStorageUsageSort } from '../utils';
import StorageTypeIcon from './storage_type_icon.vue'; import StorageTypeIcon from './storage_type_icon.vue';
export default { export default {
...@@ -15,7 +16,7 @@ export default { ...@@ -15,7 +16,7 @@ export default {
components: { components: {
GlLink, GlLink,
GlIcon, GlIcon,
GlTable, GlTableLite,
GlSprintf, GlSprintf,
StorageTypeIcon, StorageTypeIcon,
}, },
...@@ -25,6 +26,11 @@ export default { ...@@ -25,6 +26,11 @@ export default {
required: true, required: true,
}, },
}, },
computed: {
sizeSortedStorageTypes() {
return [...this.storageTypes].sort(descendingStorageUsageSort('value'));
},
},
methods: { methods: {
helpLinkAriaLabel(linkTitle) { helpLinkAriaLabel(linkTitle) {
return sprintf(HELP_LINK_ARIA_LABEL, { return sprintf(HELP_LINK_ARIA_LABEL, {
...@@ -37,13 +43,11 @@ export default { ...@@ -37,13 +43,11 @@ export default {
key: 'storageType', key: 'storageType',
label: PROJECT_TABLE_LABEL_STORAGE_TYPE, label: PROJECT_TABLE_LABEL_STORAGE_TYPE,
thClass: thWidthClass(90), thClass: thWidthClass(90),
sortable: true,
}, },
{ {
key: 'value', key: 'value',
label: PROJECT_TABLE_LABEL_USAGE, label: PROJECT_TABLE_LABEL_USAGE,
thClass: thWidthClass(10), thClass: thWidthClass(10),
sortable: true,
formatter: (value) => { formatter: (value) => {
return numberToHumanSize(value, 1); return numberToHumanSize(value, 1);
}, },
...@@ -52,7 +56,7 @@ export default { ...@@ -52,7 +56,7 @@ export default {
}; };
</script> </script>
<template> <template>
<gl-table :items="storageTypes" :fields="$options.projectTableFields"> <gl-table-lite :items="sizeSortedStorageTypes" :fields="$options.projectTableFields">
<template #cell(storageType)="{ item }"> <template #cell(storageType)="{ item }">
<div class="gl-display-flex gl-flex-direction-row"> <div class="gl-display-flex gl-flex-direction-row">
<storage-type-icon <storage-type-icon
...@@ -88,5 +92,5 @@ export default { ...@@ -88,5 +92,5 @@ export default {
</div> </div>
</div> </div>
</template> </template>
</gl-table> </gl-table-lite>
</template> </template>
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
import { GlIcon, GlTooltipDirective } from '@gitlab/ui'; import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
import { numberToHumanSize } from '~/lib/utils/number_utils'; import { numberToHumanSize } from '~/lib/utils/number_utils';
import { PROJECT_STORAGE_TYPES } from '../constants'; import { PROJECT_STORAGE_TYPES } from '../constants';
import { descendingStorageUsageSort } from '../utils';
export default { export default {
components: { components: {
...@@ -84,7 +85,7 @@ export default { ...@@ -84,7 +85,7 @@ export default {
}, },
] ]
.filter((data) => data.size !== 0) .filter((data) => data.size !== 0)
.sort((a, b) => b.size - a.size) .sort(descendingStorageUsageSort('size'))
.map((storageType) => { .map((storageType) => {
const storageTypeExtraData = PROJECT_STORAGE_TYPES.find( const storageTypeExtraData = PROJECT_STORAGE_TYPES.find(
(type) => storageType.id === type.id, (type) => storageType.id === type.id,
......
...@@ -178,3 +178,13 @@ export const parseGetProjectStorageResults = (data, helpLinks) => { ...@@ -178,3 +178,13 @@ export const parseGetProjectStorageResults = (data, helpLinks) => {
statistics: projectStatistics, 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'; ...@@ -2,14 +2,14 @@ import { GlTableLite } from '@gitlab/ui';
import { mount } from '@vue/test-utils'; import { mount } from '@vue/test-utils';
import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import ProjectStorageDetail from 'ee/usage_quotas/storage/components/project_storage_detail.vue'; 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'; import { projectData, projectHelpLinks } from '../mock_data';
describe('ProjectStorageDetail', () => { describe('ProjectStorageDetail', () => {
let wrapper; let wrapper;
const defaultProps = { const { storageTypes } = projectData.storage;
storageTypes: projectData.storage.storageTypes, const defaultProps = { storageTypes };
};
const createComponent = (props = {}) => { const createComponent = (props = {}) => {
wrapper = extendedWrapper( wrapper = extendedWrapper(
...@@ -32,7 +32,7 @@ describe('ProjectStorageDetail', () => { ...@@ -32,7 +32,7 @@ describe('ProjectStorageDetail', () => {
}); });
describe('with storage types', () => { describe('with storage types', () => {
it.each(projectData.storage.storageTypes)( it.each(storageTypes)(
'renders table row correctly %o', 'renders table row correctly %o',
({ storageType: { id, name, description } }) => { ({ storageType: { id, name, description } }) => {
expect(wrapper.findByTestId(`${id}-name`).text()).toBe(name); expect(wrapper.findByTestId(`${id}-name`).text()).toBe(name);
...@@ -43,6 +43,18 @@ describe('ProjectStorageDetail', () => { ...@@ -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', () => { describe('without storage types', () => {
......
...@@ -4,6 +4,7 @@ import { ...@@ -4,6 +4,7 @@ import {
parseProjects, parseProjects,
calculateUsedAndRemStorage, calculateUsedAndRemStorage,
parseGetProjectStorageResults, parseGetProjectStorageResults,
descendingStorageUsageSort,
} from 'ee/usage_quotas/storage/utils'; } from 'ee/usage_quotas/storage/utils';
import { import {
projectData, projectData,
...@@ -120,3 +121,14 @@ describe('parseProjects', () => { ...@@ -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