Commit 75931feb authored by Andrew Fontaine's avatar Andrew Fontaine

Merge branch 'jswain_whats_new_drawer' into 'master'

Whats new - create vue component and render to dom

See merge request gitlab-org/gitlab!38975
parents d7239da8 48b2efb9
import $ from 'jquery'; import $ from 'jquery';
import ContextualSidebar from './contextual_sidebar'; import ContextualSidebar from './contextual_sidebar';
import initFlyOutNav from './fly_out_nav'; import initFlyOutNav from './fly_out_nav';
import initWhatsNew from '~/whats_new';
function hideEndFade($scrollingTabs) { function hideEndFade($scrollingTabs) {
$scrollingTabs.each(function scrollTabsLoop() { $scrollingTabs.each(function scrollTabsLoop() {
...@@ -20,6 +21,7 @@ export default function initLayoutNav() { ...@@ -20,6 +21,7 @@ export default function initLayoutNav() {
contextualSidebar.bindEvents(); contextualSidebar.bindEvents();
initFlyOutNav(); initFlyOutNav();
initWhatsNew();
// We need to init it on DomContentLoaded as others could also call it // We need to init it on DomContentLoaded as others could also call it
$(document).on('init.scrolling-tabs', () => { $(document).on('init.scrolling-tabs', () => {
......
<script>
import { mapState, mapActions } from 'vuex';
import { GlDrawer } from '@gitlab/ui';
export default {
components: {
GlDrawer,
},
computed: {
...mapState(['open']),
},
methods: {
...mapActions(['closeDrawer']),
},
};
</script>
<template>
<div>
<gl-drawer class="mt-6" :open="open" @close="closeDrawer">
<template #header>
<h4>{{ __("What's new at GitLab") }}</h4>
</template>
<template>
<div></div>
</template>
</gl-drawer>
</div>
</template>
<script>
import { mapActions } from 'vuex';
import { GlButton } from '@gitlab/ui';
export default {
components: {
GlButton,
},
methods: {
...mapActions(['openDrawer']),
},
};
</script>
<template>
<li>
<gl-button variant="link" @click="openDrawer">{{ __("See what's new at GitLab") }}</gl-button>
</li>
</template>
import Vue from 'vue';
import App from './components/app.vue';
import Trigger from './components/trigger.vue';
import store from './store';
export default () => {
// eslint-disable-next-line no-new
new Vue({
el: document.getElementById('whats-new-app'),
store,
components: {
App,
},
render(createElement) {
return createElement('app');
},
});
// eslint-disable-next-line no-new
new Vue({
el: document.getElementById('whats-new-trigger'),
store,
components: {
Trigger,
},
render(createElement) {
return createElement('trigger');
},
});
};
import * as types from './mutation_types';
export default {
closeDrawer({ commit }) {
commit(types.CLOSE_DRAWER);
},
openDrawer({ commit }) {
commit(types.OPEN_DRAWER);
},
};
import Vue from 'vue';
import Vuex from 'vuex';
import actions from './actions';
import mutations from './mutations';
import state from './state';
Vue.use(Vuex);
export default new Vuex.Store({
actions,
mutations,
state,
});
export const CLOSE_DRAWER = 'CLOSE_DRAWER';
export const OPEN_DRAWER = 'OPEN_DRAWER';
import * as types from './mutation_types';
export default {
[types.CLOSE_DRAWER](state) {
state.open = false;
},
[types.OPEN_DRAWER](state) {
state.open = true;
},
};
...@@ -312,6 +312,7 @@ ...@@ -312,6 +312,7 @@
> a, > a,
button, button,
.gl-button.btn-link,
.menu-item { .menu-item {
@include dropdown-link; @include dropdown-link;
} }
......
...@@ -84,5 +84,8 @@ ...@@ -84,5 +84,8 @@
= sprite_icon('ellipsis_h', size: 12, css_class: 'more-icon js-navbar-toggle-right') = sprite_icon('ellipsis_h', size: 12, css_class: 'more-icon js-navbar-toggle-right')
= sprite_icon('close', size: 12, css_class: 'close-icon js-navbar-toggle-left') = sprite_icon('close', size: 12, css_class: 'close-icon js-navbar-toggle-left')
- if ::Feature.enabled?(:whats_new_drawer)
#whats-new-app
- if can?(current_user, :update_user_status, current_user) - if can?(current_user, :update_user_status, current_user)
.js-set-status-modal-wrapper{ data: { current_emoji: current_user.status.present? ? current_user.status.emoji : '', current_message: current_user.status.present? ? current_user.status.message : '' } } .js-set-status-modal-wrapper{ data: { current_emoji: current_user.status.present? ? current_user.status.emoji : '', current_message: current_user.status.present? ? current_user.status.message : '' } }
...@@ -113,10 +113,6 @@ module EE ...@@ -113,10 +113,6 @@ module EE
show show
end end
def show_whats_new_dropdown_item?
::Gitlab.com? && ::Feature.enabled?(:whats_new_dropdown)
end
private private
def appearance def appearance
......
- if show_whats_new_dropdown_item? - if ::Feature.enabled?(:whats_new_dropdown)
%li - if ::Feature.enabled?(:whats_new_drawer)
= link_to _("See what's new at GitLab"), "#{promo_url}/releases/gitlab-com/", target: '_blank', rel: 'noopener noreferrer', data: { track_event: 'click_whats_new', track_property: 'question_menu' } #whats-new-trigger
- else
%li
= link_to _("See what's new at GitLab"), "#{promo_url}/releases/gitlab-com/", target: '_blank', rel: 'noopener noreferrer', data: { track_event: 'click_whats_new', track_property: 'question_menu' }
...@@ -214,26 +214,4 @@ RSpec.describe ApplicationHelper do ...@@ -214,26 +214,4 @@ RSpec.describe ApplicationHelper do
it { is_expected.to be(app_setting && is_admin) } it { is_expected.to be(app_setting && is_admin) }
end end
end end
describe '#show_whats_new_dropdown_item?' do
using RSpec::Parameterized::TableSyntax
subject { helper.show_whats_new_dropdown_item? }
where(:feature_flag, :gitlab_com, :result) do
true | true | true
true | false | false
false | true | false
false | false | false
end
with_them do
before do
stub_feature_flags(whats_new_dropdown: feature_flag)
allow(::Gitlab).to receive(:com?).and_return(gitlab_com)
end
it { is_expected.to be(result) }
end
end
end end
...@@ -27418,6 +27418,9 @@ msgstr "" ...@@ -27418,6 +27418,9 @@ msgstr ""
msgid "What describes you best?" msgid "What describes you best?"
msgstr "" msgstr ""
msgid "What's new at GitLab"
msgstr ""
msgid "What’s your experience level?" msgid "What’s your experience level?"
msgstr "" msgstr ""
......
import { createLocalVue, mount } from '@vue/test-utils';
import Vuex from 'vuex';
import { GlDrawer } from '@gitlab/ui';
import App from '~/whats_new/components/app.vue';
const localVue = createLocalVue();
localVue.use(Vuex);
describe('App', () => {
let wrapper;
let store;
let actions;
let state;
beforeEach(() => {
actions = {
closeDrawer: jest.fn(),
};
state = {
open: true,
};
store = new Vuex.Store({
actions,
state,
});
wrapper = mount(App, {
localVue,
store,
});
});
afterEach(() => {
wrapper.destroy();
});
const getDrawer = () => wrapper.find(GlDrawer);
it('contains a drawer', () => {
expect(getDrawer().exists()).toBe(true);
});
it('dispatches closeDrawer when clicking close', () => {
getDrawer().vm.$emit('close');
expect(actions.closeDrawer).toHaveBeenCalled();
});
it.each([true, false])('passes open property', async openState => {
wrapper.vm.$store.state.open = openState;
await wrapper.vm.$nextTick();
expect(getDrawer().props('open')).toBe(openState);
});
});
import { createLocalVue, mount } from '@vue/test-utils';
import Vuex from 'vuex';
import { GlButton } from '@gitlab/ui';
import Trigger from '~/whats_new/components/trigger.vue';
const localVue = createLocalVue();
localVue.use(Vuex);
describe('Trigger', () => {
let wrapper;
let store;
let actions;
let state;
beforeEach(() => {
actions = {
openDrawer: jest.fn(),
};
state = {
open: true,
};
store = new Vuex.Store({
actions,
state,
});
wrapper = mount(Trigger, {
localVue,
store,
});
});
afterEach(() => {
wrapper.destroy();
});
it('dispatches openDrawer when clicking close', () => {
wrapper.find(GlButton).vm.$emit('click');
expect(actions.openDrawer).toHaveBeenCalled();
});
});
import testAction from 'helpers/vuex_action_helper';
import actions from '~/whats_new/store/actions';
import * as types from '~/whats_new/store/mutation_types';
describe('whats new actions', () => {
describe('openDrawer', () => {
it('should commit openDrawer', () => {
testAction(actions.openDrawer, {}, {}, [{ type: types.OPEN_DRAWER }]);
});
});
describe('closeDrawer', () => {
it('should commit closeDrawer', () => {
testAction(actions.closeDrawer, {}, {}, [{ type: types.CLOSE_DRAWER }]);
});
});
});
import mutations from '~/whats_new/store/mutations';
import createState from '~/whats_new/store/state';
import * as types from '~/whats_new/store/mutation_types';
describe('whats new mutations', () => {
let state;
beforeEach(() => {
state = createState;
});
describe('openDrawer', () => {
it('sets open to true', () => {
mutations[types.OPEN_DRAWER](state);
expect(state.open).toBe(true);
});
});
describe('closeDrawer', () => {
it('sets open to false', () => {
mutations[types.CLOSE_DRAWER](state);
expect(state.open).toBe(false);
});
});
});
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