Commit bd7218f2 authored by Clement Ho's avatar Clement Ho

Backport epic in issue

parent 245fad4d
import Flash from '../../../flash'; import Flash from '../../../flash';
import AssigneeTitle from './assignee_title'; import AssigneeTitle from './assignee_title';
import Assignees from './assignees'; import Assignees from './assignees';
import Store from '../../stores/sidebar_store'; import Store from '../../stores/sidebar_store';
import Mediator from '../../sidebar_mediator';
import eventHub from '../../event_hub'; import eventHub from '../../event_hub';
export default { export default {
name: 'SidebarAssignees', name: 'SidebarAssignees',
data() { data() {
return { return {
mediator: new Mediator(),
store: new Store(), store: new Store(),
loading: false, loading: false,
field: '',
}; };
}, },
props: {
mediator: {
type: Object,
required: true,
},
field: {
type: String,
required: true,
},
signedIn: {
type: Boolean,
required: false,
default: false,
},
},
components: { components: {
'assignee-title': AssigneeTitle, 'assignee-title': AssigneeTitle,
assignees: Assignees, assignees: Assignees,
...@@ -61,10 +71,6 @@ export default { ...@@ -61,10 +71,6 @@ export default {
eventHub.$off('sidebar.removeAllAssignees', this.removeAllAssignees); eventHub.$off('sidebar.removeAllAssignees', this.removeAllAssignees);
eventHub.$off('sidebar.saveAssignees', this.saveAssignees); eventHub.$off('sidebar.saveAssignees', this.saveAssignees);
}, },
beforeMount() {
this.field = this.$el.dataset.field;
this.signedIn = typeof this.$el.dataset.signedIn !== 'undefined';
},
template: ` template: `
<div> <div>
<assignee-title <assignee-title
......
<script> <script>
import Store from '../../stores/sidebar_store'; import Store from '../../stores/sidebar_store';
import Mediator from '../../sidebar_mediator';
import participants from './participants.vue'; import participants from './participants.vue';
export default { export default {
data() { data() {
return { return {
mediator: new Mediator(),
store: new Store(), store: new Store(),
}; };
}, },
props: {
mediator: {
type: Object,
required: true,
},
},
components: { components: {
participants, participants,
}, },
...@@ -21,6 +25,7 @@ export default { ...@@ -21,6 +25,7 @@ export default {
<participants <participants
:loading="store.isFetching.participants" :loading="store.isFetching.participants"
:participants="store.participants" :participants="store.participants"
:number-of-less-participants="7" /> :number-of-less-participants="7"
/>
</div> </div>
</template> </template>
<script> <script>
import Store from '../../stores/sidebar_store'; import Store from '../../stores/sidebar_store';
import Mediator from '../../sidebar_mediator';
import eventHub from '../../event_hub'; import eventHub from '../../event_hub';
import Flash from '../../../flash'; import Flash from '../../../flash';
import { __ } from '../../../locale'; import { __ } from '../../../locale';
...@@ -9,11 +8,15 @@ import subscriptions from './subscriptions.vue'; ...@@ -9,11 +8,15 @@ import subscriptions from './subscriptions.vue';
export default { export default {
data() { data() {
return { return {
mediator: new Mediator(),
store: new Store(), store: new Store(),
}; };
}, },
props: {
mediator: {
type: Object,
required: true,
},
},
components: { components: {
subscriptions, subscriptions,
}, },
......
...@@ -10,6 +10,27 @@ import Translate from '../vue_shared/translate'; ...@@ -10,6 +10,27 @@ import Translate from '../vue_shared/translate';
Vue.use(Translate); Vue.use(Translate);
function mountAssigneesComponent(mediator) {
const el = document.getElementById('js-vue-sidebar-assignees');
if (!el) return;
// eslint-disable-next-line no-new
new Vue({
el,
components: {
SidebarAssignees,
},
render: createElement => createElement('sidebar-assignees', {
props: {
mediator,
field: el.dataset.field,
signedIn: el.hasAttribute('data-signed-in'),
},
}),
});
}
function mountConfidentialComponent(mediator) { function mountConfidentialComponent(mediator) {
const el = document.getElementById('js-confidential-entry-point'); const el = document.getElementById('js-confidential-entry-point');
...@@ -49,9 +70,10 @@ function mountLockComponent(mediator) { ...@@ -49,9 +70,10 @@ function mountLockComponent(mediator) {
}).$mount(el); }).$mount(el);
} }
function mountParticipantsComponent() { function mountParticipantsComponent(mediator) {
const el = document.querySelector('.js-sidebar-participants-entry-point'); const el = document.querySelector('.js-sidebar-participants-entry-point');
// eslint-disable-next-line no-new
if (!el) return; if (!el) return;
// eslint-disable-next-line no-new // eslint-disable-next-line no-new
...@@ -60,11 +82,15 @@ function mountParticipantsComponent() { ...@@ -60,11 +82,15 @@ function mountParticipantsComponent() {
components: { components: {
sidebarParticipants, sidebarParticipants,
}, },
render: createElement => createElement('sidebar-participants', {}), render: createElement => createElement('sidebar-participants', {
props: {
mediator,
},
}),
}); });
} }
function mountSubscriptionsComponent() { function mountSubscriptionsComponent(mediator) {
const el = document.querySelector('.js-sidebar-subscriptions-entry-point'); const el = document.querySelector('.js-sidebar-subscriptions-entry-point');
if (!el) return; if (!el) return;
...@@ -75,22 +101,35 @@ function mountSubscriptionsComponent() { ...@@ -75,22 +101,35 @@ function mountSubscriptionsComponent() {
components: { components: {
sidebarSubscriptions, sidebarSubscriptions,
}, },
render: createElement => createElement('sidebar-subscriptions', {}), render: createElement => createElement('sidebar-subscriptions', {
props: {
mediator,
},
}),
}); });
} }
function mount(mediator) { function mountTimeTrackingComponent() {
const sidebarAssigneesEl = document.getElementById('js-vue-sidebar-assignees'); const el = document.getElementById('issuable-time-tracker');
// Only create the sidebarAssignees vue app if it is found in the DOM
// We currently do not use sidebarAssignees for the MR page
if (sidebarAssigneesEl) {
new Vue(SidebarAssignees).$mount(sidebarAssigneesEl);
}
if (!el) return;
// eslint-disable-next-line no-new
new Vue({
el,
components: {
SidebarTimeTracking,
},
render: createElement => createElement('sidebar-time-tracking', {}),
});
}
export function mountSidebar(mediator) {
mountAssigneesComponent(mediator);
mountConfidentialComponent(mediator); mountConfidentialComponent(mediator);
mountLockComponent(mediator); mountLockComponent(mediator);
mountParticipantsComponent(); mountParticipantsComponent(mediator);
mountSubscriptionsComponent(); mountSubscriptionsComponent(mediator);
new SidebarMoveIssue( new SidebarMoveIssue(
mediator, mediator,
...@@ -98,7 +137,9 @@ function mount(mediator) { ...@@ -98,7 +137,9 @@ function mount(mediator) {
$('.js-move-issue-confirmation-button'), $('.js-move-issue-confirmation-button'),
).init(); ).init();
new Vue(SidebarTimeTracking).$mount('#issuable-time-tracker'); mountTimeTrackingComponent();
} }
export default mount; export function getSidebarOptions() {
return JSON.parse(document.querySelector('.js-sidebar-options').innerHTML);
}
import Mediator from './sidebar_mediator'; import Mediator from './sidebar_mediator';
import mountSidebar from './mount_sidebar'; import { mountSidebar, getSidebarOptions } from './mount_sidebar';
function domContentLoaded() { function domContentLoaded() {
const sidebarOptions = JSON.parse(document.querySelector('.js-sidebar-options').innerHTML); const mediator = new Mediator(getSidebarOptions());
const mediator = new Mediator(sidebarOptions);
mediator.fetch(); mediator.fetch();
mountSidebar(mediator); mountSidebar(mediator);
......
...@@ -7,7 +7,6 @@ export default class SidebarMediator { ...@@ -7,7 +7,6 @@ export default class SidebarMediator {
if (!SidebarMediator.singleton) { if (!SidebarMediator.singleton) {
this.initSingleton(options); this.initSingleton(options);
} }
return SidebarMediator.singleton; return SidebarMediator.singleton;
} }
......
export default class SidebarStore { export default class SidebarStore {
constructor(store) { constructor(options) {
if (!SidebarStore.singleton) { if (!SidebarStore.singleton) {
const { currentUser, rootPath, editable } = store; this.initSingleton(options);
this.currentUser = currentUser;
this.rootPath = rootPath;
this.editable = editable;
this.timeEstimate = 0;
this.totalTimeSpent = 0;
this.humanTimeEstimate = '';
this.humanTimeSpent = '';
this.assignees = [];
this.isFetching = {
assignees: true,
participants: true,
subscriptions: true,
};
this.isLoading = {};
this.autocompleteProjects = [];
this.moveToProjectId = 0;
this.isLockDialogOpen = false;
this.participants = [];
this.subscribed = null;
SidebarStore.singleton = this;
} }
return SidebarStore.singleton; return SidebarStore.singleton;
} }
initSingleton(options) {
const { currentUser, rootPath, editable } = options;
this.currentUser = currentUser;
this.rootPath = rootPath;
this.editable = editable;
this.timeEstimate = 0;
this.totalTimeSpent = 0;
this.humanTimeEstimate = '';
this.humanTimeSpent = '';
this.assignees = [];
this.isFetching = {
assignees: true,
participants: true,
subscriptions: true,
};
this.isLoading = {};
this.autocompleteProjects = [];
this.moveToProjectId = 0;
this.isLockDialogOpen = false;
this.participants = [];
this.subscribed = null;
SidebarStore.singleton = this;
}
setAssigneeData(data) { setAssigneeData(data) {
this.isFetching.assignees = false; this.isFetching.assignees = false;
if (data.assignees) { if (data.assignees) {
......
...@@ -50,6 +50,11 @@ ...@@ -50,6 +50,11 @@
&:not(.disabled) { &:not(.disabled) {
cursor: pointer; cursor: pointer;
} }
svg {
width: $gl-padding;
height: $gl-padding;
}
} }
} }
......
...@@ -470,7 +470,8 @@ ...@@ -470,7 +470,8 @@
} }
} }
.milestone-title span { .milestone-title span,
.collapse-truncated-title {
@include str-truncated(100%); @include str-truncated(100%);
display: block; display: block;
margin: 0 4px; margin: 0 4px;
......
...@@ -4,20 +4,29 @@ import SidebarMediator from '~/sidebar/sidebar_mediator'; ...@@ -4,20 +4,29 @@ import SidebarMediator from '~/sidebar/sidebar_mediator';
import SidebarService from '~/sidebar/services/sidebar_service'; import SidebarService from '~/sidebar/services/sidebar_service';
import SidebarStore from '~/sidebar/stores/sidebar_store'; import SidebarStore from '~/sidebar/stores/sidebar_store';
import Mock from './mock_data'; import Mock from './mock_data';
import mountComponent from '../helpers/vue_mount_component_helper';
describe('sidebar assignees', () => { describe('sidebar assignees', () => {
let component; let vm;
let SidebarAssigneeComponent; let mediator;
let sidebarAssigneesEl;
preloadFixtures('issues/open-issue.html.raw'); preloadFixtures('issues/open-issue.html.raw');
beforeEach(() => { beforeEach(() => {
Vue.http.interceptors.push(Mock.sidebarMockInterceptor); Vue.http.interceptors.push(Mock.sidebarMockInterceptor);
SidebarAssigneeComponent = Vue.extend(SidebarAssignees);
spyOn(SidebarMediator.prototype, 'saveAssignees').and.callThrough();
spyOn(SidebarMediator.prototype, 'assignYourself').and.callThrough();
this.mediator = new SidebarMediator(Mock.mediator);
loadFixtures('issues/open-issue.html.raw'); loadFixtures('issues/open-issue.html.raw');
this.sidebarAssigneesEl = document.querySelector('#js-vue-sidebar-assignees');
mediator = new SidebarMediator(Mock.mediator);
spyOn(mediator, 'saveAssignees').and.callThrough();
spyOn(mediator, 'assignYourself').and.callThrough();
const SidebarAssigneeComponent = Vue.extend(SidebarAssignees);
sidebarAssigneesEl = document.querySelector('#js-vue-sidebar-assignees');
vm = mountComponent(SidebarAssigneeComponent, {
mediator,
field: sidebarAssigneesEl.dataset.field,
}, sidebarAssigneesEl);
}); });
afterEach(() => { afterEach(() => {
...@@ -28,30 +37,24 @@ describe('sidebar assignees', () => { ...@@ -28,30 +37,24 @@ describe('sidebar assignees', () => {
}); });
it('calls the mediator when saves the assignees', () => { it('calls the mediator when saves the assignees', () => {
component = new SidebarAssigneeComponent() vm.saveAssignees();
.$mount(this.sidebarAssigneesEl); expect(mediator.saveAssignees).toHaveBeenCalled();
component.saveAssignees();
expect(SidebarMediator.prototype.saveAssignees).toHaveBeenCalled();
}); });
it('calls the mediator when "assignSelf" method is called', () => { it('calls the mediator when "assignSelf" method is called', () => {
component = new SidebarAssigneeComponent() vm.assignSelf();
.$mount(this.sidebarAssigneesEl);
component.assignSelf();
expect(SidebarMediator.prototype.assignYourself).toHaveBeenCalled(); expect(mediator.assignYourself).toHaveBeenCalled();
expect(this.mediator.store.assignees.length).toEqual(1); expect(mediator.store.assignees.length).toEqual(1);
}); });
it('hides assignees until fetched', (done) => { it('hides assignees until fetched', (done) => {
component = new SidebarAssigneeComponent().$mount(this.sidebarAssigneesEl); const currentAssignee = sidebarAssigneesEl.querySelector('.value');
const currentAssignee = this.sidebarAssigneesEl.querySelector('.value');
expect(currentAssignee).toBe(null); expect(currentAssignee).toBe(null);
component.store.isFetching.assignees = false; vm.store.isFetching.assignees = false;
Vue.nextTick(() => { Vue.nextTick(() => {
expect(component.$el.querySelector('.value')).toBeVisible(); expect(vm.$el.querySelector('.value')).toBeVisible();
done(); done();
}); });
}); });
......
...@@ -26,11 +26,14 @@ describe('Sidebar Subscriptions', function () { ...@@ -26,11 +26,14 @@ describe('Sidebar Subscriptions', function () {
}); });
it('calls the mediator toggleSubscription on event', () => { it('calls the mediator toggleSubscription on event', () => {
spyOn(SidebarMediator.prototype, 'toggleSubscription').and.returnValue(Promise.resolve()); const mediator = new SidebarMediator();
vm = mountComponent(SidebarSubscriptions, {}); spyOn(mediator, 'toggleSubscription').and.returnValue(Promise.resolve());
vm = mountComponent(SidebarSubscriptions, {
mediator,
});
eventHub.$emit('toggleSubscription'); eventHub.$emit('toggleSubscription');
expect(SidebarMediator.prototype.toggleSubscription).toHaveBeenCalled(); expect(mediator.toggleSubscription).toHaveBeenCalled();
}); });
}); });
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