Commit a766c12a authored by Mike Greiling's avatar Mike Greiling

Merge branch '287978_05_5-geo-beta-progress-bars' into 'master'

Geo Node Status 2.0 - Progress Bar

See merge request gitlab-org/gitlab!56990
parents 2b25e9ad 9bb3b515
<script>
import { GlPopover, GlSprintf } from '@gitlab/ui';
import { toNumber } from 'lodash';
import { __, s__ } from '~/locale';
import StackedProgressBar from '~/vue_shared/components/stacked_progress_bar.vue';
export default {
name: 'GeoNodeSyncProgress',
i18n: {
unavailableLabel: s__('Geo|Nothing to synchronize'),
popoverTitle: s__('Geo|Number of %{title}'),
total: __('Total'),
synced: s__('Geo|Synced'),
queued: s__('Geo|Queued'),
failed: __('Failed'),
},
components: {
GlPopover,
GlSprintf,
StackedProgressBar,
},
props: {
title: {
type: String,
required: true,
},
values: {
type: Object,
required: true,
},
},
computed: {
queuedCount() {
return this.totalCount - this.successCount - this.failureCount;
},
totalCount() {
return toNumber(this.values.total) || 0;
},
failureCount() {
return toNumber(this.values.failed) || 0;
},
successCount() {
return toNumber(this.values.success) || 0;
},
},
};
</script>
<template>
<div>
<stacked-progress-bar
:id="`syncProgress-${title}`"
tabindex="0"
hide-tooltips
:unavailable-label="$options.i18n.unavailableLabel"
:success-count="successCount"
:failure-count="failureCount"
:total-count="totalCount"
/>
<gl-popover
:target="`syncProgress-${title}`"
placement="right"
triggers="hover focus"
:css-classes="['w-100']"
>
<template #title>
<gl-sprintf :message="$options.i18n.popoverTitle">
<template #title>
{{ title }}
</template>
</gl-sprintf>
</template>
<section>
<div class="gl-display-flex gl-align-items-center gl-my-3">
<div class="gl-mr-3 gl-bg-transparent gl-w-5 gl-h-2"></div>
<span class="gl-flex-fill-1 gl-mr-4">{{ $options.i18n.total }}</span>
<span class="gl-font-weight-bold">{{ totalCount.toLocaleString() }}</span>
</div>
<div class="gl-display-flex gl-align-items-center gl-my-3">
<div class="gl-mr-3 gl-bg-green-500 gl-w-5 gl-h-2"></div>
<span class="gl-flex-fill-1 gl-mr-4">{{ $options.i18n.synced }}</span>
<span class="gl-font-weight-bold">{{ successCount.toLocaleString() }}</span>
</div>
<div class="gl-display-flex gl-align-items-center gl-my-3">
<div class="gl-mr-3 gl-bg-gray-200 gl-w-5 gl-h-2"></div>
<span class="gl-flex-fill-1 gl-mr-4">{{ $options.i18n.queued }}</span>
<span class="gl-font-weight-bold">{{ queuedCount.toLocaleString() }}</span>
</div>
<div class="gl-display-flex gl-align-items-center gl-my-3">
<div class="gl-mr-3 gl-bg-red-500 gl-w-5 gl-h-2"></div>
<span class="gl-flex-fill-1 gl-mr-4">{{ $options.i18n.failed }}</span>
<span class="gl-font-weight-bold">{{ failureCount.toLocaleString() }}</span>
</div>
</section>
</gl-popover>
</div>
</template>
...@@ -2,16 +2,17 @@ ...@@ -2,16 +2,17 @@
import { GlCard } from '@gitlab/ui'; import { GlCard } from '@gitlab/ui';
import { numberToHumanSize } from '~/lib/utils/number_utils'; import { numberToHumanSize } from '~/lib/utils/number_utils';
import { __, s__ } from '~/locale'; import { __, s__ } from '~/locale';
import GeoNodeProgressBar from '../geo_node_progress_bar.vue';
export default { export default {
name: 'GeoNodePrimaryOtherInfo', name: 'GeoNodePrimaryOtherInfo',
i18n: { i18n: {
otherInformation: __('Other information'), otherInformation: __('Other information'),
progressBarPlaceholder: s__('Geo|Progress Bar Placeholder'),
replicationSlotWAL: s__('Geo|Replication slot WAL'), replicationSlotWAL: s__('Geo|Replication slot WAL'),
}, },
components: { components: {
GlCard, GlCard,
GeoNodeProgressBar,
}, },
props: { props: {
node: { node: {
...@@ -43,7 +44,11 @@ export default { ...@@ -43,7 +44,11 @@ export default {
</template> </template>
<div class="gl-mb-5"> <div class="gl-mb-5">
<span>{{ replicationSlots.title }}</span> <span>{{ replicationSlots.title }}</span>
<p data-testid="replication-progress-bar">{{ $options.i18n.progressBarPlaceholder }}</p> <geo-node-progress-bar
class="gl-mt-3"
:title="replicationSlots.title"
:values="replicationSlots.values"
/>
</div> </div>
<div <div
v-if="node.replicationSlotsMaxRetainedWalBytes" v-if="node.replicationSlotsMaxRetainedWalBytes"
......
...@@ -2,7 +2,8 @@ ...@@ -2,7 +2,8 @@
import { GlCard, GlIcon, GlPopover, GlLink } from '@gitlab/ui'; import { GlCard, GlIcon, GlPopover, GlLink } from '@gitlab/ui';
import { mapGetters } from 'vuex'; import { mapGetters } from 'vuex';
import { HELP_INFO_URL } from 'ee/geo_nodes_beta/constants'; import { HELP_INFO_URL } from 'ee/geo_nodes_beta/constants';
import { sprintf, s__, __ } from '~/locale'; import { s__, __ } from '~/locale';
import GeoNodeProgressBar from '../geo_node_progress_bar.vue';
export default { export default {
name: 'GeoNodeVerificationInfo', name: 'GeoNodeVerificationInfo',
...@@ -12,13 +13,14 @@ export default { ...@@ -12,13 +13,14 @@ export default {
'Geo|Replicated data is verified with the secondary node(s) using checksums.', 'Geo|Replicated data is verified with the secondary node(s) using checksums.',
), ),
learnMore: __('Learn more'), learnMore: __('Learn more'),
progressBarPlaceholder: s__('Geo|Progress Bar Placeholder'), progressBarTitle: s__('Geo|%{title} checksum progress'),
}, },
components: { components: {
GlCard, GlCard,
GlIcon, GlIcon,
GlPopover, GlPopover,
GlLink, GlLink,
GeoNodeProgressBar,
}, },
props: { props: {
node: { node: {
...@@ -32,11 +34,6 @@ export default { ...@@ -32,11 +34,6 @@ export default {
return this.verificationInfo(this.node.id); return this.verificationInfo(this.node.id);
}, },
}, },
methods: {
buildTitle(title) {
return sprintf(s__('Geo|%{title} checksum progress'), { title });
},
},
HELP_INFO_URL, HELP_INFO_URL,
}; };
</script> </script>
...@@ -60,8 +57,14 @@ export default { ...@@ -60,8 +57,14 @@ export default {
</gl-popover> </gl-popover>
</template> </template>
<div v-for="bar in verificationInfoBars" :key="bar.title" class="gl-mb-5"> <div v-for="bar in verificationInfoBars" :key="bar.title" class="gl-mb-5">
<span data-testid="verification-bar-title">{{ buildTitle(bar.title) }}</span> <span data-testid="verification-bar-title">{{
<p data-testid="verification-progress-bar">{{ $options.i18n.progressBarPlaceholder }}</p> sprintf($options.i18n.progressBarTitle, { title: bar.title })
}}</span>
<geo-node-progress-bar
class="gl-mt-3"
:title="sprintf($options.i18n.progressBarTitle, { title: bar.title })"
:values="bar.values"
/>
</div> </div>
</gl-card> </gl-card>
</template> </template>
import { GlPopover } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import GeoNodeProgressBar from 'ee/geo_nodes_beta/components/details/geo_node_progress_bar.vue';
import { MOCK_PRIMARY_VERIFICATION_INFO } from 'ee_jest/geo_nodes_beta/mock_data';
import StackedProgressBar from '~/vue_shared/components/stacked_progress_bar.vue';
describe('GeoNodeProgressBar', () => {
let wrapper;
const defaultProps = {
title: MOCK_PRIMARY_VERIFICATION_INFO[0].title,
values: MOCK_PRIMARY_VERIFICATION_INFO[0].values,
};
const createComponent = (props) => {
wrapper = shallowMount(GeoNodeProgressBar, {
propsData: {
...defaultProps,
...props,
},
});
};
afterEach(() => {
wrapper.destroy();
});
const findStackedProgressBar = () => wrapper.findComponent(StackedProgressBar);
const findGlPopover = () => wrapper.findComponent(GlPopover);
const findCounts = () => findGlPopover().findAll('section > div');
describe('template', () => {
describe('always', () => {
beforeEach(() => {
createComponent();
});
it('renders the stacked progress bar', () => {
expect(findStackedProgressBar().exists()).toBe(true);
});
it('renders the GlPopover', () => {
expect(findGlPopover().exists()).toBe(true);
});
it('renders a popover count for total, successful, queued, and failed', () => {
expect(findCounts()).toHaveLength(4);
});
});
describe.each`
values | expectedUiCounts
${{ success: 5, failed: 3, total: 10 }} | ${['Total 10', 'Synced 5', 'Queued 2', 'Failed 3']}
${{ success: '5', failed: '3', total: '10' }} | ${['Total 10', 'Synced 5', 'Queued 2', 'Failed 3']}
${{ success: null, failed: null, total: null }} | ${['Total 0', 'Synced 0', 'Queued 0', 'Failed 0']}
${{ success: 'abc', failed: 'def', total: 'ghi' }} | ${['Total 0', 'Synced 0', 'Queued 0', 'Failed 0']}
`(`status counts`, ({ values, expectedUiCounts }) => {
beforeEach(() => {
createComponent({ values });
});
describe(`when values are { total: ${values.total}, success: ${values.success}, failed: ${values.failed}} `, () => {
it(`should render the ui counts as ${expectedUiCounts}`, () => {
expect(findCounts().wrappers.map((w) => w.text())).toStrictEqual(expectedUiCounts);
});
});
});
});
});
import { GlCard } from '@gitlab/ui'; import { GlCard } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import GeoNodeProgressBar from 'ee/geo_nodes_beta/components/details/geo_node_progress_bar.vue';
import GeoNodePrimaryOtherInfo from 'ee/geo_nodes_beta/components/details/primary_node/geo_node_primary_other_info.vue'; import GeoNodePrimaryOtherInfo from 'ee/geo_nodes_beta/components/details/primary_node/geo_node_primary_other_info.vue';
import { MOCK_NODES } from 'ee_jest/geo_nodes_beta/mock_data'; import { MOCK_NODES } from 'ee_jest/geo_nodes_beta/mock_data';
import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import { extendedWrapper } from 'helpers/vue_test_utils_helper';
...@@ -28,7 +29,7 @@ describe('GeoNodePrimaryOtherInfo', () => { ...@@ -28,7 +29,7 @@ describe('GeoNodePrimaryOtherInfo', () => {
}); });
const findGlCard = () => wrapper.findComponent(GlCard); const findGlCard = () => wrapper.findComponent(GlCard);
const findGeoNodeProgressBar = () => wrapper.findByTestId('replication-progress-bar'); const findGeoNodeProgressBar = () => wrapper.findComponent(GeoNodeProgressBar);
const findReplicationSlotWAL = () => wrapper.findByTestId('replication-slot-wal'); const findReplicationSlotWAL = () => wrapper.findByTestId('replication-slot-wal');
describe('template', () => { describe('template', () => {
......
...@@ -2,6 +2,7 @@ import { GlCard, GlIcon, GlPopover, GlLink } from '@gitlab/ui'; ...@@ -2,6 +2,7 @@ import { GlCard, GlIcon, GlPopover, GlLink } from '@gitlab/ui';
import { mount } from '@vue/test-utils'; import { mount } from '@vue/test-utils';
import Vue from 'vue'; import Vue from 'vue';
import Vuex from 'vuex'; import Vuex from 'vuex';
import GeoNodeProgressBar from 'ee/geo_nodes_beta/components/details/geo_node_progress_bar.vue';
import GeoNodeVerificationInfo from 'ee/geo_nodes_beta/components/details/primary_node/geo_node_verification_info.vue'; import GeoNodeVerificationInfo from 'ee/geo_nodes_beta/components/details/primary_node/geo_node_verification_info.vue';
import { HELP_INFO_URL } from 'ee/geo_nodes_beta/constants'; import { HELP_INFO_URL } from 'ee/geo_nodes_beta/constants';
import { MOCK_NODES, MOCK_PRIMARY_VERIFICATION_INFO } from 'ee_jest/geo_nodes_beta/mock_data'; import { MOCK_NODES, MOCK_PRIMARY_VERIFICATION_INFO } from 'ee_jest/geo_nodes_beta/mock_data';
...@@ -43,7 +44,7 @@ describe('GeoNodeVerificationInfo', () => { ...@@ -43,7 +44,7 @@ describe('GeoNodeVerificationInfo', () => {
const findGlPopover = () => wrapper.findComponent(GlPopover); const findGlPopover = () => wrapper.findComponent(GlPopover);
const findGlPopoverLink = () => findGlPopover().findComponent(GlLink); const findGlPopoverLink = () => findGlPopover().findComponent(GlLink);
const findGeoNodeProgressBarTitles = () => wrapper.findAllByTestId('verification-bar-title'); const findGeoNodeProgressBarTitles = () => wrapper.findAllByTestId('verification-bar-title');
const findGeoNodeProgressBars = () => wrapper.findAllByTestId('verification-progress-bar'); const findGeoNodeProgressBars = () => wrapper.findAllComponents(GeoNodeProgressBar);
describe('template', () => { describe('template', () => {
describe('always', () => { describe('always', () => {
......
...@@ -13960,6 +13960,12 @@ msgstr "" ...@@ -13960,6 +13960,12 @@ msgstr ""
msgid "Geo|Not synced yet" msgid "Geo|Not synced yet"
msgstr "" msgstr ""
msgid "Geo|Nothing to synchronize"
msgstr ""
msgid "Geo|Number of %{title}"
msgstr ""
msgid "Geo|Pending synchronization" msgid "Geo|Pending synchronization"
msgstr "" msgstr ""
...@@ -13975,9 +13981,6 @@ msgstr "" ...@@ -13975,9 +13981,6 @@ msgstr ""
msgid "Geo|Primary site" msgid "Geo|Primary site"
msgstr "" msgstr ""
msgid "Geo|Progress Bar Placeholder"
msgstr ""
msgid "Geo|Project" msgid "Geo|Project"
msgstr "" msgstr ""
...@@ -13990,6 +13993,9 @@ msgstr "" ...@@ -13990,6 +13993,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards" msgid "Geo|Projects in certain storage shards"
msgstr "" msgstr ""
msgid "Geo|Queued"
msgstr ""
msgid "Geo|Redownload" msgid "Geo|Redownload"
msgstr "" msgstr ""
......
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