Commit 04fb74d0 authored by Vitaly Slobodin's avatar Vitaly Slobodin

Merge branch 'storage-inline-alert-integration' into 'master'

Integrate StorageInlineAlert with graphql response

See merge request gitlab-org/gitlab!45051
parents 6d4b6f18 02058f29
...@@ -4,6 +4,7 @@ import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; ...@@ -4,6 +4,7 @@ import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import ProjectsTable from './projects_table.vue'; import ProjectsTable from './projects_table.vue';
import UsageGraph from './usage_graph.vue'; import UsageGraph from './usage_graph.vue';
import UsageStatistics from './usage_statistics.vue'; import UsageStatistics from './usage_statistics.vue';
import StorageInlineAlert from './storage_inline_alert.vue';
import query from '../queries/storage.query.graphql'; import query from '../queries/storage.query.graphql';
import TemporaryStorageIncreaseModal from './temporary_storage_increase_modal.vue'; import TemporaryStorageIncreaseModal from './temporary_storage_increase_modal.vue';
import { parseBoolean } from '~/lib/utils/common_utils'; import { parseBoolean } from '~/lib/utils/common_utils';
...@@ -17,6 +18,7 @@ export default { ...@@ -17,6 +18,7 @@ export default {
GlButton, GlButton,
GlSprintf, GlSprintf,
GlIcon, GlIcon,
StorageInlineAlert,
UsageGraph, UsageGraph,
UsageStatistics, UsageStatistics,
TemporaryStorageIncreaseModal, TemporaryStorageIncreaseModal,
...@@ -72,6 +74,7 @@ export default { ...@@ -72,6 +74,7 @@ export default {
isAdditionalStorageFlagEnabled() { isAdditionalStorageFlagEnabled() {
return this.glFeatures.additionalRepoStorageByNamespace; return this.glFeatures.additionalRepoStorageByNamespace;
}, },
formattedNamespaceLimit() { formattedNamespaceLimit() {
return formatUsageSize(this.namespace.limit); return formatUsageSize(this.namespace.limit);
}, },
...@@ -86,12 +89,25 @@ export default { ...@@ -86,12 +89,25 @@ export default {
additionalPurchasedStorageSize: this.namespace.additionalPurchasedStorageSize, additionalPurchasedStorageSize: this.namespace.additionalPurchasedStorageSize,
}; };
}, },
shouldShowStorageInlineAlert() {
return this.isAdditionalStorageFlagEnabled && !this.$apollo.queries.namespace.loading;
},
}, },
modalId: 'temporary-increase-storage-modal', modalId: 'temporary-increase-storage-modal',
}; };
</script> </script>
<template> <template>
<div> <div>
<storage-inline-alert
v-if="shouldShowStorageInlineAlert"
:contains-locked-projects="namespace.containsLockedProjects"
:repository-size-excess-project-count="namespace.repositorySizeExcessProjectCount"
:total-repository-size-excess="namespace.totalRepositorySizeExcess"
:total-repository-size="namespace.totalRepositorySize"
:additional-purchased-storage-size="namespace.additionalPurchasedStorageSize"
:actual-repository-size-limit="namespace.actualRepositorySizeLimit"
/>
<div v-if="isAdditionalStorageFlagEnabled && storageStatistics"> <div v-if="isAdditionalStorageFlagEnabled && storageStatistics">
<usage-statistics :root-storage-statistics="storageStatistics" /> <usage-statistics :root-storage-statistics="storageStatistics" />
</div> </div>
......
<script> <script>
import { GlAlert } from '@gitlab/ui'; import { GlAlert } from '@gitlab/ui';
import { n__, __ } from '~/locale'; import { n__, __ } from '~/locale';
import { getFormatter, SUPPORTED_FORMATS } from '~/lib/utils/unit_format'; import { formatUsageSize, usageRatioToThresholdLevel } from '../utils';
import { usageRatioToThresholdLevel } from '../utils';
import { ALERT_THRESHOLD, ERROR_THRESHOLD, WARNING_THRESHOLD } from '../constants'; import { ALERT_THRESHOLD, ERROR_THRESHOLD, WARNING_THRESHOLD } from '../constants';
export default { export default {
...@@ -30,7 +29,7 @@ export default { ...@@ -30,7 +29,7 @@ export default {
type: Number, type: Number,
required: true, required: true,
}, },
repositoryFreeSizeLimit: { actualRepositorySizeLimit: {
type: Number, type: Number,
required: true, required: true,
}, },
...@@ -86,14 +85,13 @@ export default { ...@@ -86,14 +85,13 @@ export default {
return this.additionalPurchasedStorageSize > 0; return this.additionalPurchasedStorageSize > 0;
}, },
formatSize(size) { formatSize(size) {
const formatter = getFormatter(SUPPORTED_FORMATS.decimalBytes); return formatUsageSize(size);
return formatter(size);
}, },
hasPurchasedStorageText() { hasPurchasedStorageText() {
if (this.thresholdLevel === ERROR_THRESHOLD) { if (this.thresholdLevel === ERROR_THRESHOLD) {
return __( return __(
`You have consumed all of your additional storage, please purchase more to unlock your projects over the free ${this.formatSize( `You have consumed all of your additional storage, please purchase more to unlock your projects over the free ${this.formatSize(
this.repositoryFreeSizeLimit, this.actualRepositorySizeLimit,
)} limit`, )} limit`,
); );
} else if ( } else if (
...@@ -106,7 +104,7 @@ export default { ...@@ -106,7 +104,7 @@ export default {
} }
return __( return __(
`When you purchase additional storage, we automatically unlock projects that were locked when you reached the ${this.formatSize( `When you purchase additional storage, we automatically unlock projects that were locked when you reached the ${this.formatSize(
this.repositoryFreeSizeLimit, this.actualRepositorySizeLimit,
)} limit.`, )} limit.`,
); );
}, },
...@@ -114,7 +112,7 @@ export default { ...@@ -114,7 +112,7 @@ export default {
if (this.thresholdLevel === ERROR_THRESHOLD) { if (this.thresholdLevel === ERROR_THRESHOLD) {
return __( return __(
`You have reached the free storage limit of ${this.formatSize( `You have reached the free storage limit of ${this.formatSize(
this.repositoryFreeSizeLimit, this.actualRepositorySizeLimit,
)} on ${this.projectsLockedText}. To unlock them, please purchase additional storage.`, )} on ${this.projectsLockedText}. To unlock them, please purchase additional storage.`,
); );
} }
......
import { mount } from '@vue/test-utils'; import { mount } from '@vue/test-utils';
import StorageApp from 'ee/storage_counter/components/app.vue'; import StorageApp from 'ee/storage_counter/components/app.vue';
import Project from 'ee/storage_counter/components/project.vue'; import Project from 'ee/storage_counter/components/project.vue';
import StorageInlineAlert from 'ee/storage_counter/components/storage_inline_alert.vue';
import UsageGraph from 'ee/storage_counter/components/usage_graph.vue'; import UsageGraph from 'ee/storage_counter/components/usage_graph.vue';
import UsageStatistics from 'ee/storage_counter/components/usage_statistics.vue'; import UsageStatistics from 'ee/storage_counter/components/usage_statistics.vue';
import TemporaryStorageIncreaseModal from 'ee/storage_counter/components/temporary_storage_increase_modal.vue'; import TemporaryStorageIncreaseModal from 'ee/storage_counter/components/temporary_storage_increase_modal.vue';
...@@ -19,11 +20,13 @@ describe('Storage counter app', () => { ...@@ -19,11 +20,13 @@ describe('Storage counter app', () => {
wrapper.find("[data-testid='temporary-storage-increase-button']"); wrapper.find("[data-testid='temporary-storage-increase-button']");
const findUsageGraph = () => wrapper.find(UsageGraph); const findUsageGraph = () => wrapper.find(UsageGraph);
const findUsageStatistics = () => wrapper.find(UsageStatistics); const findUsageStatistics = () => wrapper.find(UsageStatistics);
const findStorageInlineAlert = () => wrapper.find(StorageInlineAlert);
const createComponent = ({ const createComponent = ({
props = {}, props = {},
loading = false, loading = false,
additionalRepoStorageByNamespace = false, additionalRepoStorageByNamespace = false,
namespace = {},
} = {}) => { } = {}) => {
const $apollo = { const $apollo = {
queries: { queries: {
...@@ -44,6 +47,11 @@ describe('Storage counter app', () => { ...@@ -44,6 +47,11 @@ describe('Storage counter app', () => {
additionalRepoStorageByNamespace, additionalRepoStorageByNamespace,
}, },
}, },
data() {
return {
namespace,
};
},
}); });
}; };
...@@ -109,14 +117,12 @@ describe('Storage counter app', () => { ...@@ -109,14 +117,12 @@ describe('Storage counter app', () => {
expect(findUsageGraph().exists()).toBe(true); expect(findUsageGraph().exists()).toBe(true);
expect(findUsageStatistics().exists()).toBe(false); expect(findUsageStatistics().exists()).toBe(false);
expect(findStorageInlineAlert().exists()).toBe(false);
}); });
it('usage_statistics component is rendered when flag is true', async () => { it('usage_statistics component is rendered when flag is true', async () => {
createComponent({ createComponent({
additionalRepoStorageByNamespace: true, additionalRepoStorageByNamespace: true,
});
wrapper.setData({
namespace: withRootStorageStatistics, namespace: withRootStorageStatistics,
}); });
...@@ -124,6 +130,7 @@ describe('Storage counter app', () => { ...@@ -124,6 +130,7 @@ describe('Storage counter app', () => {
expect(findUsageStatistics().exists()).toBe(true); expect(findUsageStatistics().exists()).toBe(true);
expect(findUsageGraph().exists()).toBe(false); expect(findUsageGraph().exists()).toBe(false);
expect(findStorageInlineAlert().exists()).toBe(true);
}); });
}); });
......
...@@ -2,7 +2,7 @@ import { shallowMount } from '@vue/test-utils'; ...@@ -2,7 +2,7 @@ import { shallowMount } from '@vue/test-utils';
import StorageInlineAlert from 'ee/storage_counter/components/storage_inline_alert.vue'; import StorageInlineAlert from 'ee/storage_counter/components/storage_inline_alert.vue';
import { GlAlert } from '@gitlab/ui'; import { GlAlert } from '@gitlab/ui';
const GB_IN_BYTES = 1_000_000_000; const GB_IN_BYTES = 1_074_000_000;
const THIRTEEN_GB_IN_BYTES = 13 * GB_IN_BYTES; const THIRTEEN_GB_IN_BYTES = 13 * GB_IN_BYTES;
const TEN_GB_IN_BYTES = 10 * GB_IN_BYTES; const TEN_GB_IN_BYTES = 10 * GB_IN_BYTES;
const FIVE_GB_IN_BYTES = 5 * GB_IN_BYTES; const FIVE_GB_IN_BYTES = 5 * GB_IN_BYTES;
...@@ -27,7 +27,7 @@ describe('StorageInlineAlert', () => { ...@@ -27,7 +27,7 @@ describe('StorageInlineAlert', () => {
totalRepositorySizeExcess: 0, totalRepositorySizeExcess: 0,
totalRepositorySize: FIVE_GB_IN_BYTES, totalRepositorySize: FIVE_GB_IN_BYTES,
additionalPurchasedStorageSize: 0, additionalPurchasedStorageSize: 0,
repositoryFreeSizeLimit: TEN_GB_IN_BYTES, actualRepositorySizeLimit: TEN_GB_IN_BYTES,
}); });
}); });
...@@ -44,7 +44,7 @@ describe('StorageInlineAlert', () => { ...@@ -44,7 +44,7 @@ describe('StorageInlineAlert', () => {
totalRepositorySizeExcess: THREE_GB_IN_BYTES, totalRepositorySizeExcess: THREE_GB_IN_BYTES,
totalRepositorySize: THIRTEEN_GB_IN_BYTES, totalRepositorySize: THIRTEEN_GB_IN_BYTES,
additionalPurchasedStorageSize: 0, additionalPurchasedStorageSize: 0,
repositoryFreeSizeLimit: TEN_GB_IN_BYTES, actualRepositorySizeLimit: TEN_GB_IN_BYTES,
}); });
}); });
...@@ -55,7 +55,7 @@ describe('StorageInlineAlert', () => { ...@@ -55,7 +55,7 @@ describe('StorageInlineAlert', () => {
it('renders human readable repositoryFreeLimit', () => { it('renders human readable repositoryFreeLimit', () => {
expect(findAlert().text()).toBe( expect(findAlert().text()).toBe(
'You have reached the free storage limit of 10GB on 1 project. To unlock them, please purchase additional storage.', 'You have reached the free storage limit of 10.0GiB on 1 project. To unlock them, please purchase additional storage.',
); );
}); });
}); });
...@@ -68,7 +68,7 @@ describe('StorageInlineAlert', () => { ...@@ -68,7 +68,7 @@ describe('StorageInlineAlert', () => {
totalRepositorySizeExcess: THREE_GB_IN_BYTES, totalRepositorySizeExcess: THREE_GB_IN_BYTES,
totalRepositorySize: THIRTEEN_GB_IN_BYTES, totalRepositorySize: THIRTEEN_GB_IN_BYTES,
additionalPurchasedStorageSize: FIVE_GB_IN_BYTES, additionalPurchasedStorageSize: FIVE_GB_IN_BYTES,
repositoryFreeSizeLimit: TEN_GB_IN_BYTES, actualRepositorySizeLimit: TEN_GB_IN_BYTES,
}); });
}); });
...@@ -79,7 +79,7 @@ describe('StorageInlineAlert', () => { ...@@ -79,7 +79,7 @@ describe('StorageInlineAlert', () => {
it('renders text explaining storage', () => { it('renders text explaining storage', () => {
expect(findAlert().text()).toBe( expect(findAlert().text()).toBe(
'When you purchase additional storage, we automatically unlock projects that were locked when you reached the 10GB limit.', 'When you purchase additional storage, we automatically unlock projects that were locked when you reached the 10.0GiB limit.',
); );
}); });
}); });
...@@ -92,7 +92,7 @@ describe('StorageInlineAlert', () => { ...@@ -92,7 +92,7 @@ describe('StorageInlineAlert', () => {
totalRepositorySizeExcess: THREE_GB_IN_BYTES, totalRepositorySizeExcess: THREE_GB_IN_BYTES,
totalRepositorySize: THIRTEEN_GB_IN_BYTES, totalRepositorySize: THIRTEEN_GB_IN_BYTES,
additionalPurchasedStorageSize: THREE_GB_IN_BYTES, additionalPurchasedStorageSize: THREE_GB_IN_BYTES,
repositoryFreeSizeLimit: TEN_GB_IN_BYTES, actualRepositorySizeLimit: TEN_GB_IN_BYTES,
}); });
}); });
......
...@@ -68,6 +68,12 @@ export const withRootStorageStatistics = { ...@@ -68,6 +68,12 @@ export const withRootStorageStatistics = {
projects, projects,
limit: 10000000, limit: 10000000,
totalUsage: 129334601, totalUsage: 129334601,
containsLockedProjects: true,
repositorySizeExcessProjectCount: 1,
totalRepositorySizeExcess: 2321,
totalRepositorySize: 1002321,
additionalPurchasedStorageSize: 321,
actualRepositorySizeLimit: 1002321,
rootStorageStatistics: { rootStorageStatistics: {
storageSize: 129334601, storageSize: 129334601,
repositorySize: 46012030, repositorySize: 46012030,
......
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