Commit d2fcec7d authored by Phil Hughes's avatar Phil Hughes
Browse files

Merge branch 'cleanup-geo_node-nodes-css' into 'master'

Cleanup styles for Geo Node Items

See merge request gitlab-org/gitlab!21269
parents c7fc256d 079d4b89
......@@ -79,53 +79,49 @@ export default {
</script>
 
<template>
<div class="geo-node-actions">
<div v-if="isSecondaryNode" class="node-action-container">
<a :href="node.geoProjectsUrl" class="btn btn-sm btn-node-action" target="_blank">
<icon v-if="!node.current" name="external-link" /> {{ __('Open projects') }}
</a>
</div>
<div class="d-flex align-items-center justify-content-end geo-node-actions">
<a v-if="isSecondaryNode" :href="node.geoProjectsUrl" class="btn btn-sm mx-1 " target="_blank">
<icon v-if="!node.current" name="external-link" /> {{ __('Open projects') }}
</a>
<template v-if="nodeActionsAllowed">
<div v-if="nodeMissingOauth" class="node-action-container">
<button type="button" class="btn btn-default btn-sm btn-node-action" @click="onRepairNode">
{{ s__('Repair authentication') }}
</button>
</div>
<div v-if="isToggleAllowed" class="node-action-container">
<button
:class="{
'btn-warning': node.enabled,
'btn-success': !node.enabled,
}"
type="button"
class="btn btn-sm btn-node-action"
@click="onToggleNode"
>
<icon :name="nodeToggleIcon" />
{{ nodeToggleLabel }}
</button>
</div>
<div v-if="nodeEditAllowed" class="node-action-container">
<a :href="node.editPath" class="btn btn-sm btn-node-action"> {{ __('Edit') }} </a>
</div>
<div class="node-action-container">
<button
v-if="isSecondaryNode"
type="button"
class="btn btn-sm btn-node-action btn-danger"
@click="onRemoveSecondaryNode"
>
{{ __('Remove') }}
</button>
<button
v-else
type="button"
class="btn btn-sm btn-node-action btn-danger"
@click="onRemovePrimaryNode"
>
{{ __('Remove') }}
</button>
</div>
<button
v-if="nodeMissingOauth"
type="button"
class="btn btn-sm btn-default mx-1"
@click="onRepairNode"
>
{{ s__('Repair authentication') }}
</button>
<button
v-if="isToggleAllowed"
:class="{
'btn-warning': node.enabled,
'btn-success': !node.enabled,
}"
type="button"
class="btn btn-sm mx-1"
@click="onToggleNode"
>
<icon :name="nodeToggleIcon" />
{{ nodeToggleLabel }}
</button>
<a v-if="nodeEditAllowed" :href="node.editPath" class="btn btn-sm mx-1"> {{ __('Edit') }} </a>
<button
v-if="isSecondaryNode"
type="button"
class="btn btn-sm btn-danger mx-1"
@click="onRemoveSecondaryNode"
>
{{ __('Remove') }}
</button>
<button
v-if="!isSecondaryNode"
type="button"
class="btn btn-sm btn-danger mx-1"
@click="onRemovePrimaryNode"
>
{{ __('Remove') }}
</button>
</template>
</div>
</template>
......@@ -126,19 +126,21 @@ export default {
</script>
 
<template>
<div v-if="!featureDisabled" class="prepend-top-15 prepend-left-10 node-detail-item">
<div class="node-detail-title">
<span>{{ itemTitle }}</span>
<div v-if="!featureDisabled" class="mt-2 ml-2 node-detail-item">
<div class="d-flex align-items-center text-secondary-700">
<span class="node-detail-title">{{ itemTitle }}</span>
<icon
v-if="hasHelpInfo"
v-popover="popoverConfig"
:size="12"
class="node-detail-help-text prepend-left-5"
class="text-primary-600 ml-1 node-detail-help-text"
name="question"
/>
</div>
<div v-if="isValueTypePlain" :class="cssClass" class="node-detail-value">{{ itemValue }}</div>
<div v-if="isValueTypeGraph" :class="{ 'd-flex': itemValueStale }" class="node-detail-value">
<div v-if="isValueTypePlain" :class="cssClass" class="mt-1 node-detail-value">
{{ itemValue }}
</div>
<div v-if="isValueTypeGraph" :class="{ 'd-flex': itemValueStale }" class="mt-1">
<stacked-progress-bar
:css-class="itemValueStale ? 'flex-fill' : ''"
:success-label="successLabel"
......@@ -153,7 +155,7 @@ export default {
v-tooltip
:title="itemValueStaleTooltip"
name="time-out"
class="prepend-left-10 detail-value-stale-icon"
class="ml-2 text-warning-500"
data-container="body"
/>
</div>
......
......@@ -66,7 +66,7 @@ export default {
</script>
 
<template>
<div class="card-body">
<div class="card-body p-0">
<node-details-section-main
:node="node"
:node-details="nodeDetails"
......@@ -85,8 +85,8 @@ export default {
:node-details="nodeDetails"
:node-type-primary="node.primary"
/>
<div v-if="hasError || hasVersionMismatch" class="node-health-message-container">
<p class="node-health-message">
<div v-if="hasError || hasVersionMismatch">
<p class="p-3 mb-0 bg-danger-100 text-danger-500">
{{ errorMessage }}
<gl-link :href="geoTroubleshootingHelpPath">{{
s__('Geo|Please refer to Geo Troubleshooting.')
......
......@@ -39,7 +39,7 @@ export default {
</script>
 
<template>
<div class="node-detail-value">
<div class="mt-1 node-detail-value">
<template v-if="eventTimeStamp">
<strong> {{ eventString }} </strong>
<span
......
......@@ -42,11 +42,10 @@ export default {
return this.isNodeHTTP || this.nodeDetailsFailed;
},
nodeStatusIconClass() {
const iconClasses = 'prepend-left-10 node-status-icon';
if (this.nodeDetailsFailed) {
return `${iconClasses} status-icon-failure`;
}
return `${iconClasses} status-icon-warning`;
return [
'ml-2',
{ 'text-danger-500': this.nodeDetailsFailed, 'text-warning-500': !this.nodeDetailsFailed },
];
},
nodeStatusIconName() {
if (this.nodeDetailsFailed) {
......@@ -70,7 +69,7 @@ export default {
<div class="card-header">
<div class="row">
<div class="col-md-8 clearfix">
<span class="d-flex float-left append-right-10">
<span class="d-flex align-items-center float-left append-right-10">
<strong class="node-url"> {{ node.url }} </strong>
<gl-loading-icon
v-if="nodeDetailsLoading || node.nodeActionActive"
......@@ -87,11 +86,17 @@ export default {
data-placement="bottom"
/>
</span>
<span class="inline node-type-badges">
<span v-if="node.current" class="node-badge current-node">
<span class="inline">
<span
v-if="node.current"
class="rounded-pill gl-font-size-12 p-1 text-white bg-success-400"
>
{{ s__('Current node') }}
</span>
<span v-if="node.primary" class="prepend-left-5 node-badge primary-node">
<span
v-if="node.primary"
class="ml-1 rounded-pill gl-font-size-12 p-1 text-white bg-primary-600"
>
{{ s__('Primary') }}
</span>
</span>
......
<script>
import icon from '~/vue_shared/components/icon.vue';
import { HEALTH_STATUS_ICON } from '../constants';
import { HEALTH_STATUS_ICON, HEALTH_STATUS_CLASS } from '../constants';
 
export default {
components: {
......@@ -14,7 +14,7 @@ export default {
},
computed: {
healthCssClass() {
return `geo-node-${this.status.toLowerCase()}`;
return HEALTH_STATUS_CLASS[this.status.toLowerCase()];
},
statusIconName() {
return HEALTH_STATUS_ICON[this.status.toLowerCase()];
......@@ -24,11 +24,11 @@ export default {
</script>
 
<template>
<div class="prepend-top-15 detail-section-item">
<div class="node-detail-title">{{ s__('GeoNodes|Health status') }}</div>
<div :class="healthCssClass" class="node-detail-value node-health-status">
<div class="mt-2 detail-section-item">
<div class="text-secondary-700 node-detail-title">{{ s__('GeoNodes|Health status') }}</div>
<div :class="healthCssClass" class="mt-1 d-flex align-items-center node-health-status">
<icon :size="16" :name="statusIconName" />
<span class="status-text prepend-left-5"> {{ status }} </span>
<span class="status-text ml-2"> {{ status }} </span>
</div>
</div>
</template>
......@@ -78,7 +78,7 @@ export default {
</script>
 
<template>
<div :class="{ 'node-action-active': node.nodeActionActive }" class="card geo-node-item">
<div :class="{ 'node-action-active': node.nodeActionActive }" class="card">
<geo-node-header
:node="node"
:node-details="nodeDetails"
......@@ -93,8 +93,8 @@ export default {
:node-actions-allowed="nodeActionsAllowed"
:geo-troubleshooting-help-path="geoTroubleshootingHelpPath"
/>
<div v-if="isNodeDetailsFailed" class="node-health-message-container">
<p class="node-health-message">
<div v-if="isNodeDetailsFailed">
<p class="p-3 mb-0 bg-danger-100 text-danger-500">
{{ errorMessage
}}<gl-link :href="geoTroubleshootingHelpPath">{{
s__('Geo|Please refer to Geo Troubleshooting.')
......
......@@ -108,18 +108,18 @@ export default {
</script>
 
<template>
<div class="node-detail-value">
<span v-if="syncStatusUnavailable" class="node-detail-value-bold"> {{ __('Unknown') }} </span>
<div class="mt-1 node-sync-settings">
<strong v-if="syncStatusUnavailable"> {{ __('Unknown') }} </strong>
<span
v-else
v-tooltip
:title="syncStatusTooltip"
class="node-sync-settings"
class="d-flex align-items-center"
data-placement="bottom"
>
<strong>{{ syncType }}</strong>
<icon name="retry" class="sync-status-icon prepend-left-5" />
<span v-if="!eventTimestampEmpty" class="sync-status-event-info prepend-left-5">
<icon name="retry" class="ml-2" />
<span v-if="!eventTimestampEmpty" class="ml-2">
{{ syncStatusEventInfo }}
</span>
</span>
......
......@@ -46,13 +46,13 @@ export default {
</script>
 
<template>
<div class="row-fluid clearfix node-detail-section primary-section">
<div class="col-md-8 section-items-container">
<div class="detail-section-item node-version">
<div class="node-detail-title">{{ s__('GeoNodes|GitLab version') }}</div>
<div class="row-fluid clearfix py-3 primary-section">
<div class="col-md-8">
<div>
<div class="text-secondary-700 node-detail-title">{{ s__('GeoNodes|GitLab version') }}</div>
<div
:class="{ 'node-detail-value-error': versionMismatch }"
class="node-detail-value node-detail-value-bold"
:class="{ 'text-danger-500': versionMismatch }"
class="mt-1 font-weight-bold node-detail-value"
>
{{ nodeVersion }}
</div>
......
......@@ -54,7 +54,7 @@ export default {
itemTitle: s__('GeoNodes|Replication slot WAL'),
itemValue: numberToHumanSize(this.nodeDetails.replicationSlotWAL),
itemValueType: VALUE_TYPE.PLAIN,
cssClass: 'node-detail-value-bold',
cssClass: 'font-weight-bold',
});
}
 
......@@ -63,7 +63,7 @@ export default {
itemTitle: s__('GeoNodes|Internal URL'),
itemValue: this.node.internalUrl,
itemValueType: VALUE_TYPE.PLAIN,
cssClass: 'node-detail-value-bold',
cssClass: 'font-weight-bold',
});
}
 
......@@ -76,7 +76,7 @@ export default {
itemTitle: s__('GeoNodes|Storage config'),
itemValue: this.storageShardsStatus,
itemValueType: VALUE_TYPE.PLAIN,
cssClass: this.storageShardsCssClass,
cssClass: this.storageShardsCssClass.join(' '),
},
];
},
......@@ -89,10 +89,7 @@ export default {
: s__('GeoNodes|Does not match the primary storage configuration');
},
storageShardsCssClass() {
const cssClass = 'node-detail-value-bold';
return !this.nodeDetails.storageShardsMatch
? `${cssClass} node-detail-value-error`
: cssClass;
return ['font-weight-bold', { 'text-danger-500': !this.nodeDetails.storageShardsMatch }];
},
},
methods: {
......@@ -104,17 +101,14 @@ export default {
</script>
 
<template>
<div class="row-fluid clearfix node-detail-section other-section">
<div class="row-fluid clearfix py-3 border-top border-color-default other-section">
<div class="col-md-12">
<section-reveal-button
:button-title="__('Other information')"
@toggleButton="handleSectionToggle"
/>
</div>
<div
v-show="showSectionItems"
class="col-md-6 prepend-left-15 prepend-top-10 section-items-container"
>
<div v-if="showSectionItems" class="col-md-6 ml-2 mt-2 section-items-container">
<geo-node-detail-item
v-for="(nodeDetailItem, index) in nodeDetailItems"
:key="index"
......
......@@ -130,17 +130,14 @@ export default {
</script>
 
<template>
<div class="row-fluid clearfix node-detail-section sync-section">
<div class="row-fluid clearfix py-3 border-top border-color-default sync-section">
<div class="col-md-12">
<section-reveal-button
:button-title="__('Sync information')"
@toggleButton="handleSectionToggle"
/>
</div>
<div
v-show="showSectionItems"
class="col-md-6 prepend-left-15 prepend-top-10 section-items-container"
>
<div v-if="showSectionItems" class="col-md-6 ml-2 mt-2 section-items-container">
<geo-node-detail-item
v-for="(nodeDetailItem, index) in nodeDetailItems"
:key="index"
......
......@@ -113,7 +113,7 @@ export default {
</script>
 
<template>
<div class="row-fluid clearfix node-detail-section verification-section">
<div class="row-fluid clearfix py-3 border-top border-color-default verification-section">
<div class="col-md-12">
<section-reveal-button
:button-title="__('Verification information')"
......@@ -121,7 +121,7 @@ export default {
/>
</div>
<template v-if="showSectionItems">
<div class="col-md-6 prepend-left-15 prepend-top-10 section-items-container">
<div class="col-md-6 ml-2 mt-2 section-items-container">
<geo-node-detail-item
v-for="(nodeDetailItem, index) in nodeDetailItems"
:key="index"
......
......@@ -31,7 +31,7 @@ export default {
</script>
 
<template>
<button class="btn-link btn-show-section" type="button" @click="onClickButton">
<button class="btn-link d-flex align-items-center" type="button" @click="onClickButton">
<icon :size="16" :name="toggleButtonIcon" />
<span class="prepend-left-8">{{ buttonTitle }}</span>
</button>
......
......@@ -23,6 +23,14 @@ export const HEALTH_STATUS_ICON = {
offline: 'status_canceled',
};
 
export const HEALTH_STATUS_CLASS = {
healthy: 'text-success-500',
unhealthy: 'text-danger-500',
disabled: 'text-secondary-950',
unknown: 'cdark',
offline: 'cdark',
};
export const TIME_DIFF = {
FIVE_MINS: 300,
HOUR: 3600,
......
.node-badge {
color: $white-light;
padding: 1px $gl-padding-8;
font-size: $label-font-size;
border-radius: $label-border-radius;
@media (max-width: map-get($grid-breakpoints, sm)) {
.geo-node-actions {
flex-direction: column;
margin: 0 1rem;
 
&.primary-node {
background-color: $blue-600;
}
&.current-node {
background-color: $green-400;
}
}
.geo-node-healthy {
color: $green-500;
}
.geo-node-unhealthy {
color: $red-500;
}
.geo-node-offline {
color: $gray-950;
}
.geo-node-disabled {
color: $gray-darkest;
}
.geo-node-unknown {
color: $gray-darkest;
}
.geo-node-item {
.node-status-icon {
height: 35px;
}
.status-icon-warning {
fill: $orange-500;
}
.status-icon-failure {
fill: $red-500;
}
.card-body {
padding: 0;
.node-detail-section {
padding: $gl-padding 0;
&.sync-section,
&.verification-section,
&.other-section {
border-top: 1px solid $border-color;
}
.btn-show-section {
padding: 0;
}
}
}
.node-health-message-container {
max-height: $dropdown-max-height;
overflow-y: auto;
.node-health-message {
margin-bottom: 0;
padding: $gl-padding;
background-color: $red-100;
color: $red-500;
}
}
}
.node-detail-section {
.detail-section-item,
.section-items-container {
.node-detail-title {
color: $gray-700;
.node-detail-help-text {
color: $blue-600;
}
.tooltip .tooltip-inner {
text-align: left;
}
}
.node-detail-value {
margin-top: 4px;
}
.detail-value-stale-icon {
color: $orange-500;
}
.node-detail-value-bold {
font-weight: $gl-font-weight-bold;
}
.node-detail-value-error {
color: $red-500;
}
}
.section-items-container {
display: inline-block;
.node-detail-item {
&:first-child {
margin-top: 0;
}
}
@include media-breakpoint-down(sm) {
width: 95%;
}
}
}
.node-detail-title,
.node-health-status,
.node-sync-settings,
.node-detail-section .btn-show-section {
display: flex;
align-items: center;
}
.geo-node-actions {
display: inline-flex;
justify-content: center;
float: right;
.node-action-container {
margin: 0 5px;
&:last-child {
margin-right: $gl-padding;
}
}
@include media-breakpoint-down(sm) {
display: block;
width: 100%;
.node-action-container {
width: 100%;
margin: 0;
margin-top: 10px;
padding: 0 10px;
}
.btn-node-action {
.btn-sm {
width: 100%;
margin-top: 1rem;
}