Commit 7736f145 authored by Phil Hughes's avatar Phil Hughes

Merge branch...

Merge branch '6037-geo-move-out-the-replication-slots-items-from-verification-section-in-geo-admin-screen' into 'master'

Resolve "Geo: Move out the replication slots items from verification section in Geo admin screen"

Closes #6037

See merge request gitlab-org/gitlab-ee!5723
parents ea7efee7 d4d38997
...@@ -71,12 +71,13 @@ ...@@ -71,12 +71,13 @@
:node-details="nodeDetails" :node-details="nodeDetails"
/> />
<node-details-section-verification <node-details-section-verification
v-if="nodeDetails.repositoryVerificationEnabled"
:node-details="nodeDetails" :node-details="nodeDetails"
:node-type-primary="node.primary" :node-type-primary="node.primary"
/> />
<node-details-section-other <node-details-section-other
v-if="!node.primary"
:node-details="nodeDetails" :node-details="nodeDetails"
:node-type-primary="node.primary"
/> />
<div <div
v-if="hasError || hasVersionMismatch" v-if="hasError || hasVersionMismatch"
......
<script> <script>
import { s__, __ } from '~/locale'; import { s__, __ } from '~/locale';
import { numberToHumanSize } from '~/lib/utils/number_utils';
import { VALUE_TYPE } from '../../constants'; import { VALUE_TYPE } from '../../constants';
...@@ -17,6 +18,10 @@ ...@@ -17,6 +18,10 @@
type: Object, type: Object,
required: true, required: true,
}, },
nodeTypePrimary: {
type: Boolean,
required: true,
},
}, },
data() { data() {
return { return {
...@@ -24,6 +29,43 @@ ...@@ -24,6 +29,43 @@
}; };
}, },
computed: { computed: {
nodeDetailItems() {
if (this.nodeTypePrimary) {
// Return primary node detail items
const primaryNodeDetailItems = [
{
itemTitle: s__('GeoNodes|Replication slots'),
itemValue: this.nodeDetails.replicationSlots,
itemValueType: VALUE_TYPE.GRAPH,
successLabel: s__('GeoNodes|Used slots'),
neutraLabel: s__('GeoNodes|Unused slots'),
},
];
if (this.nodeDetails.replicationSlots.totalCount) {
primaryNodeDetailItems.push(
{
itemTitle: s__('GeoNodes|Replication slot WAL'),
itemValue: numberToHumanSize(this.nodeDetails.replicationSlotWAL),
itemValueType: VALUE_TYPE.PLAIN,
cssClass: 'node-detail-value-bold',
},
);
}
return primaryNodeDetailItems;
}
// Return secondary node detail items
return [
{
itemTitle: s__('GeoNodes|Storage config'),
itemValue: this.storageShardsStatus,
itemValueType: VALUE_TYPE.PLAIN,
cssClass: this.storageShardsCssClass,
},
];
},
storageShardsStatus() { storageShardsStatus() {
if (this.nodeDetails.storageShardsMatch == null) { if (this.nodeDetails.storageShardsMatch == null) {
return __('Unknown'); return __('Unknown');
...@@ -56,10 +98,14 @@ ...@@ -56,10 +98,14 @@
class="col-md-6 prepend-left-15 prepend-top-10 section-items-container" class="col-md-6 prepend-left-15 prepend-top-10 section-items-container"
> >
<geo-node-detail-item <geo-node-detail-item
:item-title="s__('GeoNodes|Storage config')" v-for="(nodeDetailItem, index) in nodeDetailItems"
:item-value="storageShardsStatus" :key="index"
:item-value-type="$options.valueType.PLAIN" :css-class="nodeDetailItem.cssClass"
:css-class="storageShardsCssClass" :item-title="nodeDetailItem.itemTitle"
:item-value="nodeDetailItem.itemValue"
:item-value-type="nodeDetailItem.itemValueType"
:success-label="nodeDetailItem.successLabel"
:neutral-label="nodeDetailItem.neutraLabel"
/> />
</div> </div>
</div> </div>
......
<script> <script>
import { s__ } from '~/locale'; import { s__ } from '~/locale';
import { numberToHumanSize } from '~/lib/utils/number_utils';
import { VALUE_TYPE, HELP_INFO_URL } from '../../constants'; import { VALUE_TYPE, HELP_INFO_URL } from '../../constants';
...@@ -30,12 +29,6 @@ ...@@ -30,12 +29,6 @@
}; };
}, },
computed: { computed: {
hasItemsToShow() {
if (!this.nodeTypePrimary) {
return this.nodeDetails.repositoryVerificationEnabled;
}
return true;
},
nodeDetailItems() { nodeDetailItems() {
return this.nodeTypePrimary ? return this.nodeTypePrimary ?
this.getPrimaryNodeDetailItems() : this.getPrimaryNodeDetailItems() :
...@@ -44,64 +37,37 @@ ...@@ -44,64 +37,37 @@
}, },
methods: { methods: {
getPrimaryNodeDetailItems() { getPrimaryNodeDetailItems() {
const primaryNodeDetailItems = []; return [
if (this.nodeDetails.repositoryVerificationEnabled) {
primaryNodeDetailItems.push(
{
itemTitle: s__('GeoNodes|Repository checksum progress'),
itemValue: this.nodeDetails.repositoriesChecksummed,
itemValueType: VALUE_TYPE.GRAPH,
successLabel: s__('GeoNodes|Checksummed'),
neutraLabel: s__('GeoNodes|Not checksummed'),
failureLabel: s__('GeoNodes|Failed'),
helpInfo: {
title: s__('GeoNodes|Repositories checksummed for verification with their counterparts on Secondary nodes'),
url: HELP_INFO_URL,
urlText: s__('GeoNodes|Learn more about Repository checksum progress'),
},
},
{
itemTitle: s__('GeoNodes|Wiki checksum progress'),
itemValue: this.nodeDetails.wikisChecksummed,
itemValueType: VALUE_TYPE.GRAPH,
successLabel: s__('GeoNodes|Checksummed'),
neutraLabel: s__('GeoNodes|Not checksummed'),
failureLabel: s__('GeoNodes|Failed'),
helpInfo: {
title: s__('GeoNodes|Wikis checksummed for verification with their counterparts on Secondary nodes'),
url: HELP_INFO_URL,
urlText: s__('GeoNodes|Learn more about Wiki checksum progress'),
},
},
);
}
primaryNodeDetailItems.push(
{ {
itemTitle: s__('GeoNodes|Replication slots'), itemTitle: s__('GeoNodes|Repository checksum progress'),
itemValue: this.nodeDetails.replicationSlots, itemValue: this.nodeDetails.repositoriesChecksummed,
itemValueType: VALUE_TYPE.GRAPH, itemValueType: VALUE_TYPE.GRAPH,
successLabel: s__('GeoNodes|Used slots'), successLabel: s__('GeoNodes|Checksummed'),
neutraLabel: s__('GeoNodes|Unused slots'), neutraLabel: s__('GeoNodes|Not checksummed'),
failureLabel: s__('GeoNodes|Failed'),
helpInfo: {
title: s__('GeoNodes|Repositories checksummed for verification with their counterparts on Secondary nodes'),
url: HELP_INFO_URL,
urlText: s__('GeoNodes|Learn more about Repository checksum progress'),
},
}, },
); {
itemTitle: s__('GeoNodes|Wiki checksum progress'),
if (this.nodeDetails.replicationSlots.totalCount) { itemValue: this.nodeDetails.wikisChecksummed,
primaryNodeDetailItems.push( itemValueType: VALUE_TYPE.GRAPH,
{ successLabel: s__('GeoNodes|Checksummed'),
itemTitle: s__('GeoNodes|Replication slot WAL'), neutraLabel: s__('GeoNodes|Not checksummed'),
itemValue: numberToHumanSize(this.nodeDetails.replicationSlotWAL), failureLabel: s__('GeoNodes|Failed'),
itemValueType: VALUE_TYPE.PLAIN, helpInfo: {
cssClass: 'node-detail-value-bold', title: s__('GeoNodes|Wikis checksummed for verification with their counterparts on Secondary nodes'),
url: HELP_INFO_URL,
urlText: s__('GeoNodes|Learn more about Wiki checksum progress'),
}, },
); },
} ];
return primaryNodeDetailItems;
}, },
getSecondaryNodeDetailItems() { getSecondaryNodeDetailItems() {
const secondaryNodeDetailItems = [ return [
{ {
itemTitle: s__('GeoNodes|Repository verification progress'), itemTitle: s__('GeoNodes|Repository verification progress'),
itemValue: this.nodeDetails.verifiedRepositories, itemValue: this.nodeDetails.verifiedRepositories,
...@@ -129,8 +95,6 @@ ...@@ -129,8 +95,6 @@
}, },
}, },
]; ];
return secondaryNodeDetailItems;
}, },
handleSectionToggle(toggleState) { handleSectionToggle(toggleState) {
this.showSectionItems = toggleState; this.showSectionItems = toggleState;
...@@ -140,10 +104,7 @@ ...@@ -140,10 +104,7 @@
</script> </script>
<template> <template>
<div <div class="row-fluid clearfix node-detail-section verification-section">
v-if="hasItemsToShow"
class="row-fluid clearfix node-detail-section verification-section"
>
<div class="col-md-12"> <div class="col-md-12">
<section-reveal-button <section-reveal-button
:button-title="__('Verification information')" :button-title="__('Verification information')"
......
...@@ -70,8 +70,9 @@ export default class GeoNodesStore { ...@@ -70,8 +70,9 @@ export default class GeoNodesStore {
primaryRevision: rawNodeDetails.primaryRevision, primaryRevision: rawNodeDetails.primaryRevision,
replicationSlotWAL: rawNodeDetails.replication_slots_max_retained_wal_bytes, replicationSlotWAL: rawNodeDetails.replication_slots_max_retained_wal_bytes,
missingOAuthApplication: rawNodeDetails.missing_oauth_application || false, missingOAuthApplication: rawNodeDetails.missing_oauth_application || false,
storageShardsMatch: rawNodeDetails.storage_shards_match,
syncStatusUnavailable: rawNodeDetails.sync_status_unavailable || false, syncStatusUnavailable: rawNodeDetails.sync_status_unavailable || false,
storageShardsMatch: rawNodeDetails.storage_shards_match,
repositoryVerificationEnabled: rawNodeDetails.repository_verification_enabled,
replicationSlots: { replicationSlots: {
totalCount: rawNodeDetails.replication_slots_count || 0, totalCount: rawNodeDetails.replication_slots_count || 0,
successCount: rawNodeDetails.replication_slots_used_count || 0, successCount: rawNodeDetails.replication_slots_used_count || 0,
...@@ -87,7 +88,6 @@ export default class GeoNodesStore { ...@@ -87,7 +88,6 @@ export default class GeoNodesStore {
successCount: rawNodeDetails.wikis_synced_count || 0, successCount: rawNodeDetails.wikis_synced_count || 0,
failureCount: rawNodeDetails.wikis_failed_count || 0, failureCount: rawNodeDetails.wikis_failed_count || 0,
}, },
repositoryVerificationEnabled: rawNodeDetails.repository_verification_enabled,
repositoriesChecksummed: { repositoriesChecksummed: {
totalCount: rawNodeDetails.repositories_count || 0, totalCount: rawNodeDetails.repositories_count || 0,
successCount: rawNodeDetails.repositories_checksummed_count || 0, successCount: rawNodeDetails.repositories_checksummed_count || 0,
......
---
title: Geo - Move out the replication slots items from verification section in Geo admin screen
merge_request: 5723
author:
type: fixed
...@@ -2,15 +2,18 @@ import Vue from 'vue'; ...@@ -2,15 +2,18 @@ import Vue from 'vue';
import NodeDetailsSectionOtherComponent from 'ee/geo_nodes/components/node_detail_sections/node_details_section_other.vue'; import NodeDetailsSectionOtherComponent from 'ee/geo_nodes/components/node_detail_sections/node_details_section_other.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper'; import mountComponent from 'spec/helpers/vue_mount_component_helper';
import { numberToHumanSize } from '~/lib/utils/number_utils';
import { mockNodeDetails } from '../../mock_data'; import { mockNodeDetails } from '../../mock_data';
const createComponent = ( const createComponent = (
nodeDetails = Object.assign({}, mockNodeDetails), nodeDetails = Object.assign({}, mockNodeDetails),
nodeTypePrimary = false,
) => { ) => {
const Component = Vue.extend(NodeDetailsSectionOtherComponent); const Component = Vue.extend(NodeDetailsSectionOtherComponent);
return mountComponent(Component, { return mountComponent(Component, {
nodeDetails, nodeDetails,
nodeTypePrimary,
}); });
}; };
...@@ -32,6 +35,29 @@ describe('NodeDetailsSectionOther', () => { ...@@ -32,6 +35,29 @@ describe('NodeDetailsSectionOther', () => {
}); });
describe('computed', () => { describe('computed', () => {
describe('nodeDetailItems', () => {
it('returns array containing items to show under primary node when prop `nodeTypePrimary` is true', () => {
const vmNodePrimary = createComponent(mockNodeDetails, true);
const items = vmNodePrimary.nodeDetailItems;
expect(items.length).toBe(2);
expect(items[0].itemTitle).toBe('Replication slots');
expect(items[0].itemValue).toBe(mockNodeDetails.replicationSlots);
expect(items[1].itemTitle).toBe('Replication slot WAL');
expect(items[1].itemValue).toBe(numberToHumanSize(mockNodeDetails.replicationSlotWAL));
vmNodePrimary.$destroy();
});
it('returns array containing items to show under secondary node when prop `nodeTypePrimary` is false', () => {
const items = vm.nodeDetailItems;
expect(items.length).toBe(1);
expect(items[0].itemTitle).toBe('Storage config');
});
});
describe('storageShardsStatus', () => { describe('storageShardsStatus', () => {
it('returns `Unknown` when `nodeDetails.storageShardsMatch` is null', (done) => { it('returns `Unknown` when `nodeDetails.storageShardsMatch` is null', (done) => {
vm.nodeDetails.storageShardsMatch = null; vm.nodeDetails.storageShardsMatch = null;
......
...@@ -37,24 +37,6 @@ describe('NodeDetailsSectionVerification', () => { ...@@ -37,24 +37,6 @@ describe('NodeDetailsSectionVerification', () => {
}); });
}); });
describe('computed', () => {
describe('hasItemsToShow', () => {
it('returns `true` when `nodeTypePrimary` prop is true', (done) => {
vm.nodeTypePrimary = true;
Vue.nextTick()
.then(() => {
expect(vm.hasItemsToShow).toBe(true);
})
.then(done)
.catch(done.fail);
});
it('returns value of `nodeDetails.repositoryVerificationEnabled` when `nodeTypePrimary` prop is false', () => {
expect(vm.hasItemsToShow).toBe(mockNodeDetails.repositoryVerificationEnabled);
});
});
});
describe('methods', () => { describe('methods', () => {
describe('getPrimaryNodeDetailItems', () => { describe('getPrimaryNodeDetailItems', () => {
const primaryItems = [ const primaryItems = [
...@@ -66,10 +48,6 @@ describe('NodeDetailsSectionVerification', () => { ...@@ -66,10 +48,6 @@ describe('NodeDetailsSectionVerification', () => {
title: 'Wiki checksum progress', title: 'Wiki checksum progress',
valueProp: 'wikisChecksummed', valueProp: 'wikisChecksummed',
}, },
{
title: 'Replication slots',
valueProp: 'replicationSlots',
},
]; ];
it('returns array containing items to show under primary node', () => { it('returns array containing items to show under primary node', () => {
......
...@@ -153,8 +153,8 @@ export const mockNodeDetails = { ...@@ -153,8 +153,8 @@ export const mockNodeDetails = {
storageShardsMatch: false, storageShardsMatch: false,
repositoryVerificationEnabled: true, repositoryVerificationEnabled: true,
replicationSlots: { replicationSlots: {
totalCount: null, totalCount: 1,
successCount: null, successCount: 1,
failureCount: 0, failureCount: 0,
}, },
repositories: { repositories: {
......
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