Commit a898b605 authored by 🤖 GitLab Bot 🤖's avatar 🤖 GitLab Bot 🤖
Browse files

Add latest changes from gitlab-org/gitlab@master

parent 7d5d2381
......@@ -50,11 +50,6 @@
/ee/app/models/project_alias.rb @patrickbajao
/ee/lib/api/project_aliases.rb @patrickbajao
# Code Owners
#
/ee/lib/gitlab/code_owners/ @reprazent @kerrizor @garyh
/doc/user/project/code_owners.md @reprazent @kerrizor @garyh
# Quality owned files
/qa/ @gl-quality
......@@ -78,3 +73,9 @@ Dangerfile @gl-quality/eng-prod
/lib/gitlab/usage_data.rb @gitlab-org/growth/telemetry
/lib/gitlab/cycle_analytics/usage_data.rb @gitlab-org/growth/telemetry
/lib/gitlab/usage_data_counters/ @gitlab-org/growth/telemetry
[Code Owners]
/ee/lib/gitlab/code_owners.rb @reprazent @kerrizor @garyh
/ee/lib/gitlab/code_owners/ @reprazent @kerrizor @garyh
/ee/spec/lib/gitlab/code_owners/ @reprazent @kerrizor @garyh
/doc/user/project/code_owners.md @reprazent @kerrizor @garyh
......@@ -81,7 +81,9 @@ gem 'gitlab_omniauth-ldap', '~> 2.1.1', require: 'omniauth-ldap'
gem 'net-ldap'
# API
gem 'grape', '~> 1.3.3'
# Locked at Grape v1.4.0 until https://github.com/ruby-grape/grape/pull/2088 is merged
# Remove config/initializers/grape_patch.rb
gem 'grape', '= 1.4.0'
gem 'grape-entity', '~> 0.7.1'
gem 'rack-cors', '~> 1.0.6', require: 'rack/cors'
......
......@@ -453,7 +453,7 @@ GEM
signet (~> 0.14)
gpgme (2.0.20)
mini_portile2 (~> 2.3)
grape (1.3.3)
grape (1.4.0)
activesupport
builder
dry-types (>= 1.1)
......@@ -1269,7 +1269,7 @@ DEPENDENCIES
google-api-client (~> 0.33)
google-protobuf (~> 3.8.0)
gpgme (~> 2.0.19)
grape (~> 1.3.3)
grape (= 1.4.0)
grape-entity (~> 0.7.1)
grape-path-helpers (~> 1.3)
grape_logging (~> 1.7)
......
......@@ -233,7 +233,7 @@ export default {
</script>
<template>
<div class="boards-switcher js-boards-selector append-right-10">
<div class="boards-switcher js-boards-selector gl-mr-3">
<span class="boards-selector-wrapper js-boards-selector-wrapper">
<gl-dropdown
data-qa-selector="boards_dropdown"
......
......@@ -112,7 +112,7 @@ export default {
<div v-for="variable in variables" :key="variable.id" class="gl-responsive-table-row">
<div class="table-section section-50">
<div class="table-mobile-header" role="rowheader">{{ s__('Pipeline|Key') }}</div>
<div class="table-mobile-content append-right-10">
<div class="table-mobile-content gl-mr-3">
<input
:ref="`${$options.inputTypes.key}-${variable.id}`"
v-model="variable.key"
......@@ -124,7 +124,7 @@ export default {
<div class="table-section section-50">
<div class="table-mobile-header" role="rowheader">{{ s__('Pipeline|Value') }}</div>
<div class="table-mobile-content append-right-10">
<div class="table-mobile-content gl-mr-3">
<input
:ref="`${$options.inputTypes.value}-${variable.id}`"
v-model="variable.secret_value"
......@@ -149,7 +149,7 @@ export default {
<div class="gl-responsive-table-row">
<div class="table-section section-50">
<div class="table-mobile-header" role="rowheader">{{ s__('Pipeline|Key') }}</div>
<div class="table-mobile-content append-right-10">
<div class="table-mobile-content gl-mr-3">
<input
ref="inputKey"
v-model="key"
......@@ -161,7 +161,7 @@ export default {
<div class="table-section section-50">
<div class="table-mobile-header" role="rowheader">{{ s__('Pipeline|Value') }}</div>
<div class="table-mobile-content append-right-10">
<div class="table-mobile-content gl-mr-3">
<input
ref="inputSecretValue"
v-model="secretValue"
......
......@@ -161,7 +161,6 @@ export default {
...mapState('monitoringDashboard', [
'dashboard',
'emptyState',
'showEmptyState',
'expandedPanel',
'variables',
'links',
......@@ -169,6 +168,9 @@ export default {
'hasDashboardValidationWarnings',
]),
...mapGetters('monitoringDashboard', ['selectedDashboard', 'getMetricStates']),
shouldShowEmptyState() {
return Boolean(this.emptyState);
},
shouldShowVariablesSection() {
return Boolean(this.variables.length);
},
......@@ -277,6 +279,14 @@ export default {
}
return null;
},
/**
* Return true if the entire group is loading.
* @param {String} groupKey - Identifier for group
* @returns {boolean}
*/
isGroupLoading(groupKey) {
return this.groupSingleEmptyState(groupKey) === metricStates.LOADING;
},
/**
* A group should be not collapsed if any metric is loaded (OK)
*
......@@ -412,9 +422,9 @@ export default {
@dateTimePickerInvalid="onDateTimePickerInvalid"
@setRearrangingPanels="onSetRearrangingPanels"
/>
<variables-section v-if="shouldShowVariablesSection && !showEmptyState" />
<links-section v-if="shouldShowLinksSection && !showEmptyState" />
<div v-if="!showEmptyState">
<template v-if="!shouldShowEmptyState">
<variables-section v-if="shouldShowVariablesSection" />
<links-section v-if="shouldShowLinksSection" />
<dashboard-panel
v-show="expandedPanel.panel"
ref="expandedPanel"
......@@ -449,6 +459,7 @@ export default {
:key="`${groupData.group}.${groupData.priority}`"
:name="groupData.group"
:show-panels="showPanels"
:is-loading="isGroupLoading(groupData.key)"
:collapse-group="collapseGroup(groupData.key)"
>
<vue-draggable
......@@ -506,7 +517,7 @@ export default {
</div>
</graph-group>
</div>
</div>
</template>
<empty-state
v-else
:selected-state="emptyState"
......
......@@ -119,10 +119,10 @@ export default {
},
computed: {
...mapState('monitoringDashboard', [
'emptyState',
'environmentsLoading',
'currentEnvironmentName',
'isUpdatingStarredValue',
'showEmptyState',
'dashboardTimezone',
'projectPath',
'canAccessOperationsSettings',
......@@ -132,13 +132,16 @@ export default {
isOutOfTheBoxDashboard() {
return this.selectedDashboard?.out_of_the_box_dashboard;
},
shouldShowEmptyState() {
return Boolean(this.emptyState);
},
shouldShowEnvironmentsDropdownNoMatchedMsg() {
return !this.environmentsLoading && this.filteredEnvironments.length === 0;
},
addingMetricsAvailable() {
return (
this.customMetricsAvailable &&
!this.showEmptyState &&
!this.shouldShowEmptyState &&
// Custom metrics only avaialble on system dashboards because
// they are stored in the database. This can be improved. See:
// https://gitlab.com/gitlab-org/gitlab/-/issues/28241
......@@ -146,7 +149,7 @@ export default {
);
},
showRearrangePanelsBtn() {
return !this.showEmptyState && this.rearrangePanelsAvailable;
return !this.shouldShowEmptyState && this.rearrangePanelsAvailable;
},
displayUtc() {
return this.dashboardTimezone === timezones.UTC;
......
<script>
import { GlEmptyState } from '@gitlab/ui';
import { GlLoadingIcon, GlEmptyState } from '@gitlab/ui';
import { __ } from '~/locale';
import { dashboardEmptyStates } from '../constants';
export default {
components: {
GlLoadingIcon,
GlEmptyState,
},
props: {
selectedState: {
type: String,
required: true,
validator: state => Object.values(dashboardEmptyStates).includes(state),
},
documentationPath: {
type: String,
required: true,
......@@ -22,10 +28,6 @@ export default {
required: false,
default: '',
},
selectedState: {
type: String,
required: true,
},
emptyGettingStartedSvgPath: {
type: String,
required: true,
......@@ -54,52 +56,49 @@ export default {
},
data() {
return {
/**
* Possible empty states.
* Keys in each state must match GlEmptyState props
*/
states: {
[dashboardEmptyStates.GETTING_STARTED]: {
svgUrl: this.emptyGettingStartedSvgPath,
svgPath: this.emptyGettingStartedSvgPath,
title: __('Get started with performance monitoring'),
description: __(`Stay updated about the performance and health
of your environment by configuring Prometheus to monitor your deployments.`),
buttonText: __('Install on clusters'),
buttonPath: this.clustersPath,
primaryButtonText: __('Install on clusters'),
primaryButtonLink: this.clustersPath,
secondaryButtonText: __('Configure existing installation'),
secondaryButtonPath: this.settingsPath,
},
[dashboardEmptyStates.LOADING]: {
svgUrl: this.emptyLoadingSvgPath,
title: __('Waiting for performance data'),
description: __(`Creating graphs uses the data from the Prometheus server.
If this takes a long time, ensure that data is available.`),
buttonText: __('View documentation'),
buttonPath: this.documentationPath,
secondaryButtonText: '',
secondaryButtonPath: '',
secondaryButtonLink: this.settingsPath,
},
[dashboardEmptyStates.NO_DATA]: {
svgUrl: this.emptyNoDataSvgPath,
svgPath: this.emptyNoDataSvgPath,
title: __('No data found'),
description: __(`You are connected to the Prometheus server, but there is currently
no data to display.`),
buttonText: __('Configure Prometheus'),
buttonPath: this.settingsPath,
primaryButtonText: __('Configure Prometheus'),
primaryButtonLink: this.settingsPath,
secondaryButtonText: '',
secondaryButtonPath: '',
secondaryButtonLink: '',
},
[dashboardEmptyStates.UNABLE_TO_CONNECT]: {
svgUrl: this.emptyUnableToConnectSvgPath,
svgPath: this.emptyUnableToConnectSvgPath,
title: __('Unable to connect to Prometheus server'),
description: __(
'Ensure connectivity is available from the GitLab server to the Prometheus server',
),
buttonText: __('View documentation'),
buttonPath: this.documentationPath,
primaryButtonText: __('View documentation'),
primaryButtonLink: this.documentationPath,
secondaryButtonText: __('Configure Prometheus'),
secondaryButtonPath: this.settingsPath,
secondaryButtonLink: this.settingsPath,
},
},
};
},
computed: {
isLoading() {
return this.selectedState === dashboardEmptyStates.LOADING;
},
currentState() {
return this.states[this.selectedState];
},
......@@ -108,14 +107,8 @@ export default {
</script>
<template>
<gl-empty-state
:title="currentState.title"
:description="currentState.description"
:primary-button-text="currentState.buttonText"
:primary-button-link="currentState.buttonPath"
:secondary-button-text="currentState.secondaryButtonText"
:secondary-button-link="currentState.secondaryButtonPath"
:svg-path="currentState.svgUrl"
:compact="compact"
/>
<div>
<gl-loading-icon v-if="isLoading" size="xl" class="gl-my-9" />
<gl-empty-state v-if="currentState" v-bind="currentState" :compact="compact" />
</div>
</template>
<script>
import Icon from '~/vue_shared/components/icon.vue';
import { GlLoadingIcon, GlIcon } from '@gitlab/ui';
export default {
components: {
Icon,
GlLoadingIcon,
GlIcon,
},
props: {
name: {
......@@ -15,6 +16,11 @@ export default {
required: false,
default: true,
},
isLoading: {
type: Boolean,
required: false,
default: false,
},
/**
* Initial value of collapse on mount.
*/
......@@ -55,15 +61,18 @@ export default {
<div v-if="showPanels" ref="graph-group" class="card prometheus-panel">
<div class="card-header d-flex align-items-center">
<h4 class="flex-grow-1">{{ name }}</h4>
<gl-loading-icon v-if="isLoading" name="loading" />
<a
data-testid="group-toggle-button"
:aria-label="__('Toggle collapse')"
:icon="caretIcon"
role="button"
class="js-graph-group-toggle gl-text-gray-900"
class="js-graph-group-toggle gl-display-flex gl-ml-2 gl-text-gray-900"
tabindex="0"
@click="collapse"
@keyup.enter="collapse"
>
<icon :size="16" :aria-label="__('Toggle collapse')" :name="caretIcon" />
<gl-icon :name="caretIcon" />
</a>
</div>
<div
......
......@@ -40,7 +40,6 @@ export const SET_ALL_DASHBOARDS = 'SET_ALL_DASHBOARDS';
export const SET_ENDPOINTS = 'SET_ENDPOINTS';
export const SET_INITIAL_STATE = 'SET_INITIAL_STATE';
export const SET_GETTING_STARTED_EMPTY_STATE = 'SET_GETTING_STARTED_EMPTY_STATE';
export const SET_NO_DATA_EMPTY_STATE = 'SET_NO_DATA_EMPTY_STATE';
export const SET_SHOW_ERROR_BANNER = 'SET_SHOW_ERROR_BANNER';
export const SET_PANEL_GROUP_METRICS = 'SET_PANEL_GROUP_METRICS';
export const SET_ENVIRONMENTS_FILTER = 'SET_ENVIRONMENTS_FILTER';
......
......@@ -59,7 +59,6 @@ export default {
*/
[types.REQUEST_METRICS_DASHBOARD](state) {
state.emptyState = dashboardEmptyStates.LOADING;
state.showEmptyState = true;
},
[types.RECEIVE_METRICS_DASHBOARD_SUCCESS](state, dashboardYML) {
const { dashboard, panelGroups, variables, links } = mapToDashboardViewModel(dashboardYML);
......@@ -72,13 +71,14 @@ export default {
if (!state.dashboard.panelGroups.length) {
state.emptyState = dashboardEmptyStates.NO_DATA;
} else {
state.emptyState = null;
}
},
[types.RECEIVE_METRICS_DASHBOARD_FAILURE](state, error) {
state.emptyState = error
? dashboardEmptyStates.UNABLE_TO_CONNECT
: dashboardEmptyStates.NO_DATA;
state.showEmptyState = true;
},
[types.REQUEST_DASHBOARD_STARRING](state) {
......@@ -152,9 +152,6 @@ export default {
const metric = findMetricInDashboard(metricId, state.dashboard);
metric.loading = false;
state.showEmptyState = false;
state.emptyState = null;
if (!data.result || data.result.length === 0) {
metric.state = metricStates.NO_DATA;
metric.result = null;
......@@ -184,13 +181,8 @@ export default {
state.timeRange = timeRange;
},
[types.SET_GETTING_STARTED_EMPTY_STATE](state) {
state.showEmptyState = true;
state.emptyState = dashboardEmptyStates.GETTING_STARTED;
},
[types.SET_NO_DATA_EMPTY_STATE](state) {
state.showEmptyState = true;
state.emptyState = dashboardEmptyStates.NO_DATA;
},
[types.SET_ALL_DASHBOARDS](state, dashboards) {
state.allDashboards = dashboards || [];
},
......
......@@ -21,8 +21,13 @@ export default () => ({
// Dashboard data
hasDashboardValidationWarnings: false,
/**
* {?String} If set, dashboard should display a global
* empty state, there is no way to interact (yet)
* with the dashboard.
*/
emptyState: dashboardEmptyStates.GETTING_STARTED,
showEmptyState: true,
showErrorBanner: true,
isUpdatingStarredValue: false,
dashboard: {
......
......@@ -419,7 +419,7 @@ export default {
</gl-alert>
<div class="note-form-actions">
<div
class="btn-group append-right-10 comment-type-dropdown js-comment-type-dropdown droplab-dropdown"
class="btn-group gl-mr-3 comment-type-dropdown js-comment-type-dropdown droplab-dropdown"
>
<button
:disabled="isSubmitButtonDisabled"
......
......@@ -410,7 +410,7 @@ export default {
</button>
<button
v-if="discussion.resolvable"
class="btn btn-nr btn-default append-right-10 js-comment-resolve-button"
class="btn btn-nr btn-default gl-mr-3 js-comment-resolve-button"
@click.prevent="handleUpdate(true)"
>
{{ resolveButtonTitle }}
......
......@@ -56,7 +56,7 @@ export default {
v-gl-tooltip
category="primary"
variant="default"
class="append-right-10 js-edit-button ml-2 pb-2"
class="gl-mr-3 js-edit-button ml-2 pb-2"
:title="__('Edit this release')"
:href="editLink"
>
......
......@@ -114,7 +114,12 @@ export default {
class="mr-widget-section grouped-security-reports mr-report"
>
<template v-if="showViewFullReport" #actionButtons>
<gl-button :href="testTabURL" icon="external-link" data-testid="group-test-reports-full-link">
<gl-button
:href="testTabURL"
icon="external-link"
data-testid="group-test-reports-full-link"
class="gl-mr-3"
>
{{ s__('ciReport|View full report') }}
</gl-button>
</template>
......
......@@ -62,7 +62,7 @@ export default {
<template>
<div class="sidebar-item-warning-message-actions">
<button type="button" class="btn btn-default append-right-10" @click="closeForm">
<button type="button" class="btn btn-default gl-mr-3" @click="closeForm">
{{ __('Cancel') }}
</button>
<button
......
......@@ -41,7 +41,7 @@ export default {
<template>
<div class="sidebar-item-warning-message-actions">
<button type="button" class="btn btn-default append-right-10" @click="closeForm">
<button type="button" class="btn btn-default gl-mr-3" @click="closeForm">
{{ __('Cancel') }}
</button>
......
......@@ -87,7 +87,7 @@ export default {
<status-icon status="success" />
<div class="media-body">
<h4 class="d-flex align-items-start">
<span class="append-right-10">
<span class="gl-mr-3">
<span class="js-status-text-before-author">{{ statusTextBeforeAuthor }}</span>
<mr-widget-author :author="mr.setToAutoMergeBy" />
<span class="js-status-text-after-author">{{ statusTextAfterAuthor }}</span>
......@@ -113,9 +113,7 @@ export default {
{{ s__('mrWidget|The source branch will be deleted') }}
</p>
<p v-else class="d-flex align-items-start">
<span class="append-right-10">{{
s__('mrWidget|The source branch will not be deleted')
}}</span>
<span class="gl-mr-3">{{ s__('mrWidget|The source branch will not be deleted') }}</span>
<a
v-if="canRemoveSourceBranch"
:disabled="isRemovingSourceBranch"
......
......@@ -384,7 +384,7 @@ export default {
v-if="mr.testResultsPath"
class="js-reports-container"
:endpoint="mr.testResultsPath"
:pipeline-path="mr.mergeRequestAddCiConfigPath"
:pipeline-path="mr.pipeline.path"
/>
<terraform-plan v-if="mr.terraformReportsPath" :endpoint="mr.terraformReportsPath" />
......
......@@ -56,7 +56,7 @@ export default {
@click="onClick"
>
<icon
class="prepend-left-10 append-right-10 flex-shrink-0 position-top-0 js-selected-icon"
class="prepend-left-10 gl-mr-3 flex-shrink-0 position-top-0 js-selected-icon"
:class="{ 'js-selected visible': selected, 'js-unselected invisible': !selected }"
name="mobile-issue-close"
/>
......
......@@ -404,7 +404,6 @@ img.emoji {
.prepend-left-15 { margin-left: 15px; }
.prepend-left-20 { margin-left: 20px; }
.prepend-left-64 { margin-left: 64px; }
.append-right-10 { margin-right: 10px; }
.append-right-15 { margin-right: 15px; }
.append-right-20 { margin-right: 20px; }
.append-bottom-10 { margin-bottom: 10px; }
......
......@@ -171,7 +171,7 @@ $gray-500: #a7a7a7 !default;
$gray-600: #919191 !default;
$gray-700: #707070 !default;
$gray-800: #4f4f4f !default;
$gray-900: #2e2e2e !default;
$gray-900: #303030 !default;