Commit 84a7a85f authored by Dallas Reedy's avatar Dallas Reedy Committed by Rémy Coutable

Convert trial status widget from HAML to Vue

- Create a trial-status-widget Vue component
- Within the new component, use existing gl-progress-bar component
  instead of manually recreating its HTML structure
- Add simple test to verify that the component is properly rendered
parent 8589324e
<script>
import { GlLink, GlProgressBar } from '@gitlab/ui';
export default {
components: {
GlLink,
GlProgressBar,
},
props: {
href: {
type: String,
required: true,
},
navIconImagePath: {
type: String,
required: true,
},
percentageComplete: {
type: Number,
required: true,
},
title: {
type: String,
required: true,
},
},
};
</script>
<template>
<gl-link :title="title" :href="href">
<div class="gl-display-flex gl-flex-direction-column gl-align-items-stretch gl-w-full">
<span class="gl-display-flex gl-align-items-center">
<span class="nav-icon-container svg-container">
<img :src="navIconImagePath" width="16" class="svg" />
</span>
<span class="nav-item-name gl-white-space-normal">
{{ title }}
</span>
</span>
<span class="gl-display-flex gl-align-items-stretch gl-mt-3">
<gl-progress-bar :value="percentageComplete" class="gl-flex-grow-1" />
</span>
</div>
</gl-link>
</template>
import Vue from 'vue';
import TrialStatusWidget from './components/trial_status_widget.vue';
export default () => {
const el = document.getElementById('js-trial-status-widget');
if (!el) return undefined;
const { percentageComplete } = el.dataset;
return new Vue({
el,
render: (createElement) =>
createElement(TrialStatusWidget, {
props: {
...el.dataset,
percentageComplete: Number(percentageComplete),
},
}),
});
};
......@@ -3,6 +3,7 @@ import 'bootstrap/js/dist/modal';
import initEETrialBanner from 'ee/ee_trial_banner';
import trackNavbarEvents from 'ee/event_tracking/navbar';
import initNamespaceStorageLimitAlert from 'ee/namespace_storage_limit_alert';
import initTrialStatusWidget from 'ee/contextual_sidebar/group_trial_status_widget';
$(() => {
/**
......@@ -15,4 +16,6 @@ $(() => {
initNamespaceStorageLimitAlert();
trackNavbarEvents();
initTrialStatusWidget();
});
- return unless show_trial_status_widget?(group)
= nav_link do
= link_to group_billings_path(group), title: trial_days_remaining_in_words(group) do
.gl-display-flex.gl-flex-direction-column.gl-align-items-stretch.gl-w-full
%span.gl-display-flex.gl-align-items-center
%span.nav-icon-container.svg-container
= image_tag 'illustrations/golden_tanuki.svg', class: 'svg', size: 16
%span.nav-item-name.gl-white-space-normal
= trial_days_remaining_in_words(group)
%span.gl-display-flex.gl-align-items-stretch.gl-mt-4
.progress.gl-flex-grow-1{ value: trial_percentage_complete(group) }
.progress-bar{ role: 'progressbar', 'aria-valuemin': 0, 'aria-valuemax': 100, 'aria-valuenow': trial_percentage_complete(group), style: "width: #{trial_percentage_complete(group)}%" }
#js-trial-status-widget{ data: { href: group_billings_path(group),
nav_icon_image_path: image_path('illustrations/golden_tanuki.svg'),
title: trial_days_remaining_in_words(group),
percentage_complete: trial_percentage_complete(group) } }
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`TrialStatusWidget component matches the snapshot 1`] = `
<gl-link-stub
href="billing/path-for/group"
title="Gold Trial – 27 days left"
>
<div
class="gl-display-flex gl-flex-direction-column gl-align-items-stretch gl-w-full"
>
<span
class="gl-display-flex gl-align-items-center"
>
<span
class="nav-icon-container svg-container"
>
<img
class="svg"
src="illustrations/golden_tanuki.svg"
width="16"
/>
</span>
<span
class="nav-item-name gl-white-space-normal"
>
Gold Trial – 27 days left
</span>
</span>
<span
class="gl-display-flex gl-align-items-stretch gl-mt-3"
>
<gl-progress-bar-stub
class="gl-flex-grow-1"
value="10"
/>
</span>
</div>
</gl-link-stub>
`;
import { shallowMount } from '@vue/test-utils';
import TrialStatusWidget from 'ee/contextual_sidebar/components/trial_status_widget.vue';
describe('TrialStatusWidget component', () => {
let wrapper;
const createComponent = () => {
return shallowMount(TrialStatusWidget, {
propsData: {
href: 'billing/path-for/group',
navIconImagePath: 'illustrations/golden_tanuki.svg',
percentageComplete: 10,
title: 'Gold Trial – 27 days left',
},
});
};
beforeEach(() => {
wrapper = createComponent();
});
afterEach(() => {
wrapper.destroy();
});
it('matches the snapshot', () => {
expect(wrapper.element).toMatchSnapshot();
});
});
......@@ -16,20 +16,20 @@ RSpec.describe 'layouts/nav/sidebar/_group' do
let!(:gitlab_subscription) { create(:gitlab_subscription, :active_trial, namespace: group) }
context 'when the experiment is off' do
it 'is not visible' do
it 'is not rendered' do
render
expect(rendered).not_to have_text /Gold Trial – \d+ days left/
expect(rendered).not_to have_selector '#js-trial-status-widget'
end
end
context 'when the experiment is on' do
let(:show_trial_status_widget) { true }
it 'is visible' do
it 'is rendered' do
render
expect(rendered).to have_text 'Gold Trial – 15 days left'
expect(rendered).to have_selector '#js-trial-status-widget'
end
end
end
......
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