Commit b842d10a authored by Andrei Stoicescu's avatar Andrei Stoicescu

Add metrics settings button to dashboard header

 - add button
 - refactor dashboard header
parent df90c6e4
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
import { debounce } from 'lodash'; import { debounce } from 'lodash';
import { mapActions, mapState, mapGetters } from 'vuex'; import { mapActions, mapState, mapGetters } from 'vuex';
import { import {
GlButton,
GlIcon, GlIcon,
GlDeprecatedButton, GlDeprecatedButton,
GlDropdown, GlDropdown,
...@@ -37,6 +38,7 @@ import { timezones } from '../format_date'; ...@@ -37,6 +38,7 @@ import { timezones } from '../format_date';
export default { export default {
components: { components: {
Icon, Icon,
GlButton,
GlIcon, GlIcon,
GlDeprecatedButton, GlDeprecatedButton,
GlDropdown, GlDropdown,
...@@ -123,6 +125,8 @@ export default { ...@@ -123,6 +125,8 @@ export default {
'showEmptyState', 'showEmptyState',
'dashboardTimezone', 'dashboardTimezone',
'projectPath', 'projectPath',
'canAccessOperationsSettings',
'operationsSettingsPath',
]), ]),
...mapGetters('monitoringDashboard', ['selectedDashboard', 'filteredEnvironments']), ...mapGetters('monitoringDashboard', ['selectedDashboard', 'filteredEnvironments']),
isSystemDashboard() { isSystemDashboard() {
...@@ -150,6 +154,9 @@ export default { ...@@ -150,6 +154,9 @@ export default {
shouldShowActionsMenu() { shouldShowActionsMenu() {
return Boolean(this.projectPath); return Boolean(this.projectPath);
}, },
shouldShowSettingsButton() {
return this.canAccessOperationsSettings && this.operationsSettingsPath;
},
}, },
methods: { methods: {
...mapActions('monitoringDashboard', ['filterEnvironments', 'toggleStarredValue']), ...mapActions('monitoringDashboard', ['filterEnvironments', 'toggleStarredValue']),
...@@ -381,10 +388,14 @@ export default { ...@@ -381,10 +388,14 @@ export default {
</gl-deprecated-button> </gl-deprecated-button>
</div> </div>
<template v-if="shouldShowActionsMenu"> <!-- This separator should be displayed only if at least one of the action menu or settings button are displayed -->
<span aria-hidden="true" class="gl-pl-3 border-left gl-mb-3 d-none d-sm-block"></span> <span
v-if="shouldShowActionsMenu || shouldShowSettingsButton"
aria-hidden="true"
class="gl-pl-3 border-left gl-mb-3 d-none d-sm-block"
></span>
<div class="gl-mb-3 gl-mr-3 d-flex d-sm-block"> <div v-if="shouldShowActionsMenu" class="gl-mb-3 gl-mr-3 d-flex d-sm-block">
<gl-new-dropdown <gl-new-dropdown
v-gl-tooltip v-gl-tooltip
right right
...@@ -418,7 +429,16 @@ export default { ...@@ -418,7 +429,16 @@ export default {
</template> </template>
</gl-new-dropdown> </gl-new-dropdown>
</div> </div>
</template>
<div v-if="shouldShowSettingsButton" class="mb-2 mr-2 d-flex d-sm-block">
<gl-button
v-gl-tooltip
data-testid="metrics-settings-button"
icon="settings"
:href="operationsSettingsPath"
:title="s__('Metrics|Metrics Settings')"
/>
</div>
</div> </div>
<duplicate-dashboard-modal <duplicate-dashboard-modal
:default-branch="defaultBranch" :default-branch="defaultBranch"
......
...@@ -64,8 +64,16 @@ export default () => ({ ...@@ -64,8 +64,16 @@ export default () => ({
// GitLab paths to other pages // GitLab paths to other pages
projectPath: null, projectPath: null,
operationsSettingsPath: '',
logsPath: invalidUrl, logsPath: invalidUrl,
// static paths // static paths
customDashboardBasePath: '', customDashboardBasePath: '',
// current user data
/**
* Flag that denotes if the currently logged user can access
* the project Settings -> Operations
*/
canAccessOperationsSettings: false,
}); });
...@@ -25,6 +25,8 @@ export const stateAndPropsFromDataset = (dataset = {}) => { ...@@ -25,6 +25,8 @@ export const stateAndPropsFromDataset = (dataset = {}) => {
dashboardEndpoint, dashboardEndpoint,
dashboardsEndpoint, dashboardsEndpoint,
dashboardTimezone, dashboardTimezone,
canAccessOperationsSettings,
operationsSettingsPath,
projectPath, projectPath,
logsPath, logsPath,
currentEnvironmentName, currentEnvironmentName,
...@@ -44,6 +46,8 @@ export const stateAndPropsFromDataset = (dataset = {}) => { ...@@ -44,6 +46,8 @@ export const stateAndPropsFromDataset = (dataset = {}) => {
dashboardEndpoint, dashboardEndpoint,
dashboardsEndpoint, dashboardsEndpoint,
dashboardTimezone, dashboardTimezone,
canAccessOperationsSettings,
operationsSettingsPath,
projectPath, projectPath,
logsPath, logsPath,
currentEnvironmentName, currentEnvironmentName,
......
...@@ -84,8 +84,9 @@ module EnvironmentsHelper ...@@ -84,8 +84,9 @@ module EnvironmentsHelper
'metrics-endpoint' => additional_metrics_project_environment_path(project, environment, format: :json), 'metrics-endpoint' => additional_metrics_project_environment_path(project, environment, format: :json),
'dashboard-endpoint' => metrics_dashboard_project_environment_path(project, environment, format: :json), 'dashboard-endpoint' => metrics_dashboard_project_environment_path(project, environment, format: :json),
'deployments-endpoint' => project_environment_deployments_path(project, environment, format: :json), 'deployments-endpoint' => project_environment_deployments_path(project, environment, format: :json),
'alerts-endpoint' => project_prometheus_alerts_path(project, environment_id: environment.id, format: :json) 'alerts-endpoint' => project_prometheus_alerts_path(project, environment_id: environment.id, format: :json),
'operations-settings-path' => project_settings_operations_path(project),
'can-access-operations-settings' => can?(current_user, :admin_operations, project).to_s
} }
end end
......
---
title: Add a metrics settings button to the dashboard header
merge_request: 35848
author:
type: added
...@@ -8,6 +8,10 @@ RSpec.describe EnvironmentsHelper do ...@@ -8,6 +8,10 @@ RSpec.describe EnvironmentsHelper do
let(:user) { create(:user) } let(:user) { create(:user) }
describe '#metrics_data' do describe '#metrics_data' do
before do
allow(helper).to receive(:can?).and_return(false)
end
subject { helper.metrics_data(project, environment) } subject { helper.metrics_data(project, environment) }
context 'user has all accesses' do context 'user has all accesses' do
......
...@@ -14577,6 +14577,9 @@ msgstr "" ...@@ -14577,6 +14577,9 @@ msgstr ""
msgid "Metrics|Max" msgid "Metrics|Max"
msgstr "" msgstr ""
msgid "Metrics|Metrics Settings"
msgstr ""
msgid "Metrics|Min" msgid "Metrics|Min"
msgstr "" msgstr ""
......
...@@ -129,6 +129,10 @@ exports[`Dashboard template matches the default snapshot 1`] = ` ...@@ -129,6 +129,10 @@ exports[`Dashboard template matches the default snapshot 1`] = `
<!----> <!---->
<!----> <!---->
<!---->
<!---->
</div> </div>
<duplicate-dashboard-modal-stub <duplicate-dashboard-modal-stub
......
...@@ -157,4 +157,52 @@ describe('Dashboard header', () => { ...@@ -157,4 +157,52 @@ describe('Dashboard header', () => {
}); });
}); });
}); });
describe('metrics settings button', () => {
const findSettingsButton = () => wrapper.find('[data-testid="metrics-settings-button"]');
const url = 'https://path/to/project/settings';
beforeEach(() => {
createShallowWrapper();
store.state.monitoringDashboard.canAccessOperationsSettings = false;
store.state.monitoringDashboard.operationsSettingsPath = '';
});
it('is rendered when the user can access the project settings and path to settings is available', () => {
store.state.monitoringDashboard.canAccessOperationsSettings = true;
store.state.monitoringDashboard.operationsSettingsPath = url;
return wrapper.vm.$nextTick(() => {
expect(findSettingsButton().exists()).toBe(true);
});
});
it('is not rendered when the user can not access the project settings', () => {
store.state.monitoringDashboard.canAccessOperationsSettings = false;
store.state.monitoringDashboard.operationsSettingsPath = url;
return wrapper.vm.$nextTick(() => {
expect(findSettingsButton().exists()).toBe(false);
});
});
it('is not rendered when the path to settings is unavailable', () => {
store.state.monitoringDashboard.canAccessOperationsSettings = false;
store.state.monitoringDashboard.operationsSettingsPath = '';
return wrapper.vm.$nextTick(() => {
expect(findSettingsButton().exists()).toBe(false);
});
});
it('leads to the project settings page', () => {
store.state.monitoringDashboard.canAccessOperationsSettings = true;
store.state.monitoringDashboard.operationsSettingsPath = url;
return wrapper.vm.$nextTick(() => {
expect(findSettingsButton().attributes('href')).toBe(url);
});
});
});
}); });
...@@ -42,10 +42,26 @@ RSpec.describe EnvironmentsHelper do ...@@ -42,10 +42,26 @@ RSpec.describe EnvironmentsHelper do
'custom-metrics-available' => 'true', 'custom-metrics-available' => 'true',
'alerts-endpoint' => project_prometheus_alerts_path(project, environment_id: environment.id, format: :json), 'alerts-endpoint' => project_prometheus_alerts_path(project, environment_id: environment.id, format: :json),
'prometheus-alerts-available' => 'true', 'prometheus-alerts-available' => 'true',
'custom-dashboard-base-path' => Metrics::Dashboard::CustomDashboardService::DASHBOARD_ROOT 'custom-dashboard-base-path' => Metrics::Dashboard::CustomDashboardService::DASHBOARD_ROOT,
'operations-settings-path' => project_settings_operations_path(project),
'can-access-operations-settings' => 'true'
) )
end end
context 'without admin_operations permission' do
before do
allow(helper).to receive(:can?)
.with(user, :admin_operations, project)
.and_return(false)
end
specify do
expect(metrics_data).to include(
'can-access-operations-settings' => 'false'
)
end
end
context 'without read_prometheus_alerts permission' do context 'without read_prometheus_alerts permission' do
before do before do
allow(helper).to receive(:can?) allow(helper).to receive(:can?)
......
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