Commit 10d18936 authored by Sheldon Led's avatar Sheldon Led Committed by David O'Regan

Allow dismissal of pipeline minutes quota warning

parent 1bd0df77
import Vue from 'vue'; import Vue from 'vue';
import Cookies from 'js-cookie';
import { parseBoolean } from '~/lib/utils/common_utils'; import { parseBoolean } from '~/lib/utils/common_utils';
import DismissibleAlert from '~/vue_shared/components/dismissible_alert.vue'; import DismissibleAlert from '~/vue_shared/components/dismissible_alert.vue';
const getCookieExpirationPeriod = (expirationPeriod) => {
const defaultExpirationPeriod = 30;
const alertExpirationPeriod = Number(expirationPeriod);
return !expirationPeriod || Number.isNaN(alertExpirationPeriod)
? defaultExpirationPeriod
: alertExpirationPeriod;
};
const mountVueAlert = (el) => { const mountVueAlert = (el) => {
const props = { const props = {
html: el.innerHTML, html: el.innerHTML,
...@@ -10,11 +20,25 @@ const mountVueAlert = (el) => { ...@@ -10,11 +20,25 @@ const mountVueAlert = (el) => {
...el.dataset, ...el.dataset,
dismissible: parseBoolean(el.dataset.dismissible), dismissible: parseBoolean(el.dataset.dismissible),
}; };
const { dismissCookieName, dismissCookieExpire } = el.dataset;
return new Vue({ return new Vue({
el, el,
render(h) { render(createElement) {
return h(DismissibleAlert, { props, attrs }); return createElement(DismissibleAlert, {
props,
attrs,
on: {
alertDismissed() {
if (!dismissCookieName) {
return;
}
Cookies.set(dismissCookieName, true, {
expires: getCookieExpirationPeriod(dismissCookieExpire),
});
},
},
});
}, },
}); });
}; };
......
...@@ -24,6 +24,7 @@ export default { ...@@ -24,6 +24,7 @@ export default {
methods: { methods: {
dismiss() { dismiss() {
this.isDismissed = true; this.isDismissed = true;
this.$emit('alertDismissed');
}, },
}, },
}; };
......
...@@ -15,9 +15,10 @@ module Ci ...@@ -15,9 +15,10 @@ module Ci
@stage = calculate_notification_stage if eligible_for_notifications? @stage = calculate_notification_stage if eligible_for_notifications?
end end
def show?(current_user) def show?(current_user, cookies = false)
return false unless @stage return false unless @stage
return false unless @context.level return false unless @context.level
return false if alert_has_been_dismissed?(cookies)
Ability.allowed?(current_user, :read_ci_minutes_quota, @context.level) Ability.allowed?(current_user, :read_ci_minutes_quota, @context.level)
end end
...@@ -46,10 +47,20 @@ module Ci ...@@ -46,10 +47,20 @@ module Ci
context.shared_runners_minutes_limit_enabled? context.shared_runners_minutes_limit_enabled?
end end
def dismiss_cookie_id
"ci_minutes_notification_#{stage_percentage}_stage_percentage"
end
private private
attr_reader :context, :stage attr_reader :context, :stage
def alert_has_been_dismissed?(cookies)
return unless cookies
Gitlab::Utils.to_boolean(cookies[dismiss_cookie_id], default: false)
end
def calculate_notification_stage def calculate_notification_stage
percentage = context.percent_total_minutes_remaining.to_i percentage = context.percent_total_minutes_remaining.to_i
......
- notification = ::Ci::Minutes::Notification.new(local_assigns.dig(:project), local_assigns.dig(:namespace)) - notification = ::Ci::Minutes::Notification.new(local_assigns.dig(:project), local_assigns.dig(:namespace))
- return unless notification.show?(current_user) - return unless notification.show?(current_user, cookies)
%div{ class: [(classes if defined? classes)] } %div{ class: [(classes if defined? classes)] }
.shared-runner-quota-message.gl-pt-5.gl-pb-3 .shared-runner-quota-message.gl-pt-5.gl-pb-3
.js-vue-alert{ 'v-cloak': true, data: { variant: notification.style, .js-vue-alert{ 'v-cloak': true, data: { variant: notification.style,
primary_button_text: _('Buy more Pipeline minutes'), primary_button_text: _('Buy more Pipeline minutes'),
primary_button_link: ::EE::SUBSCRIPTIONS_MORE_MINUTES_URL, primary_button_link: ::EE::SUBSCRIPTIONS_MORE_MINUTES_URL,
dismissible: 'false' } } dismissible: 'true',
dismiss_cookie_name: notification.dismiss_cookie_id,
dismiss_cookie_expire: 30 } }
= notification.text = notification.text
...@@ -34,6 +34,12 @@ RSpec.describe Ci::Minutes::Notification do ...@@ -34,6 +34,12 @@ RSpec.describe Ci::Minutes::Notification do
end end
shared_examples 'has notifications' do shared_examples 'has notifications' do
shared_examples 'aware of dismission cookie' do
it 'does not show when cookie is set' do
expect(subject.show?(user, { subject.dismiss_cookie_id => 'true' })).to be_falsey
end
end
context 'when usage has reached a notification level' do context 'when usage has reached a notification level' do
before do before do
group.shared_runners_minutes_limit = 20 group.shared_runners_minutes_limit = 20
...@@ -48,6 +54,7 @@ RSpec.describe Ci::Minutes::Notification do ...@@ -48,6 +54,7 @@ RSpec.describe Ci::Minutes::Notification do
expect(subject.text).to match(/.*\shas 30% or less Shared Runner Pipeline minutes remaining/) expect(subject.text).to match(/.*\shas 30% or less Shared Runner Pipeline minutes remaining/)
expect(subject.style).to eq :warning expect(subject.style).to eq :warning
end end
it_behaves_like 'aware of dismission cookie'
end end
describe '#running_out?' do describe '#running_out?' do
...@@ -78,6 +85,7 @@ RSpec.describe Ci::Minutes::Notification do ...@@ -78,6 +85,7 @@ RSpec.describe Ci::Minutes::Notification do
expect(subject.text).to match(/.*\shas 5% or less Shared Runner Pipeline minutes remaining/) expect(subject.text).to match(/.*\shas 5% or less Shared Runner Pipeline minutes remaining/)
expect(subject.style).to eq :danger expect(subject.style).to eq :danger
end end
it_behaves_like 'aware of dismission cookie'
end end
describe '#running_out?' do describe '#running_out?' do
...@@ -108,6 +116,7 @@ RSpec.describe Ci::Minutes::Notification do ...@@ -108,6 +116,7 @@ RSpec.describe Ci::Minutes::Notification do
expect(subject.text).to match(/.*\shas 30% or less Shared Runner Pipeline minutes remaining/) expect(subject.text).to match(/.*\shas 30% or less Shared Runner Pipeline minutes remaining/)
expect(subject.style).to eq :warning expect(subject.style).to eq :warning
end end
it_behaves_like 'aware of dismission cookie'
end end
describe '#running_out?' do describe '#running_out?' do
...@@ -138,6 +147,7 @@ RSpec.describe Ci::Minutes::Notification do ...@@ -138,6 +147,7 @@ RSpec.describe Ci::Minutes::Notification do
expect(subject.text).to match(/.*\shas exceeded its pipeline minutes quota/) expect(subject.text).to match(/.*\shas exceeded its pipeline minutes quota/)
expect(subject.style).to eq :danger expect(subject.style).to eq :danger
end end
it_behaves_like 'aware of dismission cookie'
end end
describe '#running_out?' do describe '#running_out?' do
......
...@@ -43,6 +43,10 @@ describe('vue_shared/components/dismissible_alert', () => { ...@@ -43,6 +43,10 @@ describe('vue_shared/components/dismissible_alert', () => {
it('hides the alert', () => { it('hides the alert', () => {
expect(findAlert().exists()).toBe(false); expect(findAlert().exists()).toBe(false);
}); });
it('emmits alertDismissed', () => {
expect(wrapper.emitted('alertDismissed')).toBeTruthy();
});
}); });
}); });
......
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