Skip to content
Snippets Groups Projects
Unverified Commit 160157a9 authored by Mike Greiling's avatar Mike Greiling
Browse files

Prettify remaining files with differences in CE and EE

parent ed816c3d
No related branches found
No related tags found
No related merge requests found
Showing
with 637 additions and 618 deletions
Loading
@@ -13,7 +13,7 @@ export default () => {
Loading
@@ -13,7 +13,7 @@ export default () => {
if (editBlobForm.length) { if (editBlobForm.length) {
const urlRoot = editBlobForm.data('relativeUrlRoot'); const urlRoot = editBlobForm.data('relativeUrlRoot');
const assetsPath = editBlobForm.data('assetsPrefix'); const assetsPath = editBlobForm.data('assetsPrefix');
const filePath = editBlobForm.data('blobFilename') const filePath = editBlobForm.data('blobFilename');
const currentAction = $('.js-file-title').data('currentAction'); const currentAction = $('.js-file-title').data('currentAction');
const projectId = editBlobForm.data('project-id'); const projectId = editBlobForm.data('project-id');
   
Loading
Loading
Loading
@@ -42,7 +42,7 @@ export default Vue.extend({
Loading
@@ -42,7 +42,7 @@ export default Vue.extend({
required: true, required: true,
}, },
}, },
data () { data() {
return { return {
detailIssue: boardsStore.detail, detailIssue: boardsStore.detail,
filter: boardsStore.filter, filter: boardsStore.filter,
Loading
@@ -55,27 +55,26 @@ export default Vue.extend({
Loading
@@ -55,27 +55,26 @@ export default Vue.extend({
}, },
isNewIssueShown() { isNewIssueShown() {
return this.list.type === 'backlog' || (!this.disabled && this.list.type !== 'closed'); return this.list.type === 'backlog' || (!this.disabled && this.list.type !== 'closed');
} },
}, },
watch: { watch: {
filter: { filter: {
handler() { handler() {
this.list.page = 1; this.list.page = 1;
this.list.getIssues(true) this.list.getIssues(true).catch(() => {
.catch(() => { // TODO: handle request error
// TODO: handle request error });
});
}, },
deep: true, deep: true,
} },
}, },
mounted () { mounted() {
this.sortableOptions = getBoardSortableDefaultOptions({ this.sortableOptions = getBoardSortableDefaultOptions({
disabled: this.disabled, disabled: this.disabled,
group: 'boards', group: 'boards',
draggable: '.is-draggable', draggable: '.is-draggable',
handle: '.js-board-handle', handle: '.js-board-handle',
onEnd: (e) => { onEnd: e => {
sortableEnd(); sortableEnd();
   
if (e.newIndex !== undefined && e.oldIndex !== e.newIndex) { if (e.newIndex !== undefined && e.oldIndex !== e.newIndex) {
Loading
@@ -86,14 +85,15 @@ export default Vue.extend({
Loading
@@ -86,14 +85,15 @@ export default Vue.extend({
boardsStore.moveList(list, order); boardsStore.moveList(list, order);
}); });
} }
} },
}); });
   
this.sortable = Sortable.create(this.$el.parentNode, this.sortableOptions); this.sortable = Sortable.create(this.$el.parentNode, this.sortableOptions);
}, },
created() { created() {
if (this.list.isExpandable && AccessorUtilities.isLocalStorageAccessSafe()) { if (this.list.isExpandable && AccessorUtilities.isLocalStorageAccessSafe()) {
const isCollapsed = localStorage.getItem(`boards.${this.boardId}.${this.list.type}.expanded`) === 'false'; const isCollapsed =
localStorage.getItem(`boards.${this.boardId}.${this.list.type}.expanded`) === 'false';
   
this.list.isExpanded = !isCollapsed; this.list.isExpanded = !isCollapsed;
} }
Loading
@@ -107,7 +107,10 @@ export default Vue.extend({
Loading
@@ -107,7 +107,10 @@ export default Vue.extend({
this.list.isExpanded = !this.list.isExpanded; this.list.isExpanded = !this.list.isExpanded;
   
if (AccessorUtilities.isLocalStorageAccessSafe()) { if (AccessorUtilities.isLocalStorageAccessSafe()) {
localStorage.setItem(`boards.${this.boardId}.${this.list.type}.expanded`, this.list.isExpanded); localStorage.setItem(
`boards.${this.boardId}.${this.list.type}.expanded`,
this.list.isExpanded,
);
} }
} }
}, },
Loading
Loading
Loading
@@ -32,18 +32,18 @@ export default {
Loading
@@ -32,18 +32,18 @@ export default {
boardsStore.state.lists = _.sortBy(boardsStore.state.lists, 'position'); boardsStore.state.lists = _.sortBy(boardsStore.state.lists, 'position');
   
// Save the labels // Save the labels
gl.boardService.generateDefaultLists() gl.boardService
.generateDefaultLists()
.then(res => res.data) .then(res => res.data)
.then((data) => { .then(data => {
data.forEach((listObj) => { data.forEach(listObj => {
const list = boardsStore.findList('title', listObj.title); const list = boardsStore.findList('title', listObj.title);
   
list.id = listObj.id; list.id = listObj.id;
list.label.id = listObj.label.id; list.label.id = listObj.label.id;
list.getIssues() list.getIssues().catch(() => {
.catch(() => { // TODO: handle request error
// TODO: handle request error });
});
}); });
}) })
.catch(() => { .catch(() => {
Loading
@@ -57,7 +57,6 @@ export default {
Loading
@@ -57,7 +57,6 @@ export default {
clearBlankState: boardsStore.removeBlankState.bind(boardsStore), clearBlankState: boardsStore.removeBlankState.bind(boardsStore),
}, },
}; };
</script> </script>
   
<template> <template>
Loading
Loading
<script> <script>
/* eslint-disable vue/require-default-prop */ /* eslint-disable vue/require-default-prop */
import IssueCardInner from './issue_card_inner.vue'; import IssueCardInner from './issue_card_inner.vue';
import eventHub from '../eventhub'; import eventHub from '../eventhub';
import boardsStore from '../stores/boards_store'; import boardsStore from '../stores/boards_store';
   
export default { export default {
name: 'BoardsIssueCard', name: 'BoardsIssueCard',
components: { components: {
IssueCardInner, IssueCardInner,
},
props: {
list: {
type: Object,
default: () => ({}),
}, },
props: { issue: {
list: { type: Object,
type: Object, default: () => ({}),
default: () => ({}),
},
issue: {
type: Object,
default: () => ({}),
},
issueLinkBase: {
type: String,
default: '',
},
disabled: {
type: Boolean,
default: false,
},
index: {
type: Number,
default: 0,
},
rootPath: {
type: String,
default: '',
},
groupId: {
type: Number,
},
}, },
data() { issueLinkBase: {
return { type: String,
showDetail: false, default: '',
detailIssue: boardsStore.detail,
};
}, },
computed: { disabled: {
issueDetailVisible() { type: Boolean,
return this.detailIssue.issue && this.detailIssue.issue.id === this.issue.id; default: false,
},
}, },
methods: { index: {
mouseDown() { type: Number,
this.showDetail = true; default: 0,
}, },
mouseMove() { rootPath: {
this.showDetail = false; type: String,
}, default: '',
showIssue(e) { },
if (e.target.classList.contains('js-no-trigger')) return; groupId: {
type: Number,
},
},
data() {
return {
showDetail: false,
detailIssue: boardsStore.detail,
};
},
computed: {
issueDetailVisible() {
return this.detailIssue.issue && this.detailIssue.issue.id === this.issue.id;
},
},
methods: {
mouseDown() {
this.showDetail = true;
},
mouseMove() {
this.showDetail = false;
},
showIssue(e) {
if (e.target.classList.contains('js-no-trigger')) return;
   
if (this.showDetail) { if (this.showDetail) {
this.showDetail = false; this.showDetail = false;
   
if (boardsStore.detail.issue && boardsStore.detail.issue.id === this.issue.id) { if (boardsStore.detail.issue && boardsStore.detail.issue.id === this.issue.id) {
eventHub.$emit('clearDetailIssue'); eventHub.$emit('clearDetailIssue');
} else { } else {
eventHub.$emit('newDetailIssue', this.issue); eventHub.$emit('newDetailIssue', this.issue);
boardsStore.detail.list = this.list; boardsStore.detail.list = this.list;
}
} }
}, }
}, },
}; },
};
</script> </script>
   
<template> <template>
Loading
Loading
Loading
@@ -62,7 +62,8 @@ export default {
Loading
@@ -62,7 +62,8 @@ export default {
eventHub.$emit(`scroll-board-list-${this.list.id}`); eventHub.$emit(`scroll-board-list-${this.list.id}`);
this.cancel(); this.cancel();
   
return this.list.newIssue(issue) return this.list
.newIssue(issue)
.then(() => { .then(() => {
// Need this because our jQuery very kindly disables buttons on ALL form submissions // Need this because our jQuery very kindly disables buttons on ALL form submissions
$(this.$refs.submitButton).enable(); $(this.$refs.submitButton).enable();
Loading
Loading
Loading
@@ -38,7 +38,7 @@ export default Vue.extend({
Loading
@@ -38,7 +38,7 @@ export default Vue.extend({
}; };
}, },
computed: { computed: {
showSidebar () { showSidebar() {
return Object.keys(this.issue).length; return Object.keys(this.issue).length;
}, },
milestoneTitle() { milestoneTitle() {
Loading
@@ -51,18 +51,20 @@ export default Vue.extend({
Loading
@@ -51,18 +51,20 @@ export default Vue.extend({
return this.issue.labels && this.issue.labels.length; return this.issue.labels && this.issue.labels.length;
}, },
labelDropdownTitle() { labelDropdownTitle() {
return this.hasLabels ? sprintf(__('%{firstLabel} +%{labelCount} more'), { return this.hasLabels
firstLabel: this.issue.labels[0].title, ? sprintf(__('%{firstLabel} +%{labelCount} more'), {
labelCount: this.issue.labels.length - 1 firstLabel: this.issue.labels[0].title,
}) : __('Label'); labelCount: this.issue.labels.length - 1,
})
: __('Label');
}, },
selectedLabels() { selectedLabels() {
return this.hasLabels ? this.issue.labels.map(l => l.title).join(',') : ''; return this.hasLabels ? this.issue.labels.map(l => l.title).join(',') : '';
} },
}, },
watch: { watch: {
detail: { detail: {
handler () { handler() {
if (this.issue.id !== this.detail.issue.id) { if (this.issue.id !== this.detail.issue.id) {
$('.block.assignee') $('.block.assignee')
.find('input:not(.js-vue)[name="issue[assignee_ids][]"]') .find('input:not(.js-vue)[name="issue[assignee_ids][]"]')
Loading
@@ -71,17 +73,19 @@ export default Vue.extend({
Loading
@@ -71,17 +73,19 @@ export default Vue.extend({
}); });
   
$('.js-issue-board-sidebar', this.$el).each((i, el) => { $('.js-issue-board-sidebar', this.$el).each((i, el) => {
$(el).data('glDropdown').clearMenu(); $(el)
.data('glDropdown')
.clearMenu();
}); });
} }
   
this.issue = this.detail.issue; this.issue = this.detail.issue;
this.list = this.detail.list; this.list = this.detail.list;
}, },
deep: true deep: true,
}, },
}, },
created () { created() {
// Get events from glDropdown // Get events from glDropdown
eventHub.$on('sidebar.removeAssignee', this.removeAssignee); eventHub.$on('sidebar.removeAssignee', this.removeAssignee);
eventHub.$on('sidebar.addAssignee', this.addAssignee); eventHub.$on('sidebar.addAssignee', this.addAssignee);
Loading
@@ -94,7 +98,7 @@ export default Vue.extend({
Loading
@@ -94,7 +98,7 @@ export default Vue.extend({
eventHub.$off('sidebar.removeAllAssignees', this.removeAllAssignees); eventHub.$off('sidebar.removeAllAssignees', this.removeAllAssignees);
eventHub.$off('sidebar.saveAssignees', this.saveAssignees); eventHub.$off('sidebar.saveAssignees', this.saveAssignees);
}, },
mounted () { mounted() {
new IssuableContext(this.currentUser); new IssuableContext(this.currentUser);
new MilestoneSelect(); new MilestoneSelect();
new DueDateSelectors(); new DueDateSelectors();
Loading
@@ -102,29 +106,30 @@ export default Vue.extend({
Loading
@@ -102,29 +106,30 @@ export default Vue.extend({
new Sidebar(); new Sidebar();
}, },
methods: { methods: {
closeSidebar () { closeSidebar() {
this.detail.issue = {}; this.detail.issue = {};
}, },
assignSelf () { assignSelf() {
// Notify gl dropdown that we are now assigning to current user // Notify gl dropdown that we are now assigning to current user
this.$refs.assigneeBlock.dispatchEvent(new Event('assignYourself')); this.$refs.assigneeBlock.dispatchEvent(new Event('assignYourself'));
   
this.addAssignee(this.currentUser); this.addAssignee(this.currentUser);
this.saveAssignees(); this.saveAssignees();
}, },
removeAssignee (a) { removeAssignee(a) {
boardsStore.detail.issue.removeAssignee(a); boardsStore.detail.issue.removeAssignee(a);
}, },
addAssignee (a) { addAssignee(a) {
boardsStore.detail.issue.addAssignee(a); boardsStore.detail.issue.addAssignee(a);
}, },
removeAllAssignees () { removeAllAssignees() {
boardsStore.detail.issue.removeAllAssignees(); boardsStore.detail.issue.removeAllAssignees();
}, },
saveAssignees () { saveAssignees() {
this.loadingAssignees = true; this.loadingAssignees = true;
   
boardsStore.detail.issue.update() boardsStore.detail.issue
.update()
.then(() => { .then(() => {
this.loadingAssignees = false; this.loadingAssignees = false;
}) })
Loading
Loading
<script> <script>
import $ from 'jquery'; import $ from 'jquery';
import Icon from '~/vue_shared/components/icon.vue'; import Icon from '~/vue_shared/components/icon.vue';
import UserAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue'; import UserAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
import eventHub from '../eventhub'; import eventHub from '../eventhub';
import tooltip from '../../vue_shared/directives/tooltip'; import tooltip from '../../vue_shared/directives/tooltip';
import boardsStore from '../stores/boards_store'; import boardsStore from '../stores/boards_store';
   
export default { export default {
components: { components: {
UserAvatarLink, UserAvatarLink,
Icon, Icon,
}, },
directives: { directives: {
tooltip, tooltip,
}, },
props: { props: {
issue: { issue: {
type: Object, type: Object,
required: true, required: true,
},
issueLinkBase: {
type: String,
required: true,
},
list: {
type: Object,
required: false,
default: () => ({}),
},
rootPath: {
type: String,
required: true,
},
updateFilters: {
type: Boolean,
required: false,
default: false,
},
groupId: {
type: Number,
required: false,
default: null,
},
},
data() {
return {
limitBeforeCounter: 3,
maxRender: 4,
maxCounter: 99,
};
}, },
computed: { issueLinkBase: {
numberOverLimit() { type: String,
return this.issue.assignees.length - this.limitBeforeCounter; required: true,
}, },
assigneeCounterTooltip() { list: {
return `${this.assigneeCounterLabel} more`; type: Object,
}, required: false,
assigneeCounterLabel() { default: () => ({}),
if (this.numberOverLimit > this.maxCounter) { },
return `${this.maxCounter}+`; rootPath: {
} type: String,
required: true,
return `+${this.numberOverLimit}`; },
}, updateFilters: {
shouldRenderCounter() { type: Boolean,
if (this.issue.assignees.length <= this.maxRender) { required: false,
return false; default: false,
} },
groupId: {
type: Number,
required: false,
default: null,
},
},
data() {
return {
limitBeforeCounter: 3,
maxRender: 4,
maxCounter: 99,
};
},
computed: {
numberOverLimit() {
return this.issue.assignees.length - this.limitBeforeCounter;
},
assigneeCounterTooltip() {
return `${this.assigneeCounterLabel} more`;
},
assigneeCounterLabel() {
if (this.numberOverLimit > this.maxCounter) {
return `${this.maxCounter}+`;
}
   
return this.issue.assignees.length > this.numberOverLimit; return `+${this.numberOverLimit}`;
}, },
issueId() { shouldRenderCounter() {
if (this.issue.iid) { if (this.issue.assignees.length <= this.maxRender) {
return `#${this.issue.iid}`;
}
return false; return false;
}, }
showLabelFooter() {
return this.issue.labels.find(l => this.showLabel(l)) !== undefined;
},
},
methods: {
isIndexLessThanlimit(index) {
return index < this.limitBeforeCounter;
},
shouldRenderAssignee(index) {
// Eg. maxRender is 4,
// Render up to all 4 assignees if there are only 4 assigness
// Otherwise render up to the limitBeforeCounter
if (this.issue.assignees.length <= this.maxRender) {
return index < this.maxRender;
}
   
return index < this.limitBeforeCounter; return this.issue.assignees.length > this.numberOverLimit;
}, },
assigneeUrl(assignee) { issueId() {
return `${this.rootPath}${assignee.username}`; if (this.issue.iid) {
}, return `#${this.issue.iid}`;
assigneeUrlTitle(assignee) { }
return `Assigned to ${assignee.name}`; return false;
}, },
avatarUrlTitle(assignee) { showLabelFooter() {
return `Avatar for ${assignee.name}`; return this.issue.labels.find(l => this.showLabel(l)) !== undefined;
}, },
showLabel(label) { },
if (!label.id) return false; methods: {
return true; isIndexLessThanlimit(index) {
}, return index < this.limitBeforeCounter;
filterByLabel(label, e) { },
if (!this.updateFilters) return; shouldRenderAssignee(index) {
// Eg. maxRender is 4,
// Render up to all 4 assignees if there are only 4 assigness
// Otherwise render up to the limitBeforeCounter
if (this.issue.assignees.length <= this.maxRender) {
return index < this.maxRender;
}
return index < this.limitBeforeCounter;
},
assigneeUrl(assignee) {
return `${this.rootPath}${assignee.username}`;
},
assigneeUrlTitle(assignee) {
return `Assigned to ${assignee.name}`;
},
avatarUrlTitle(assignee) {
return `Avatar for ${assignee.name}`;
},
showLabel(label) {
if (!label.id) return false;
return true;
},
filterByLabel(label, e) {
if (!this.updateFilters) return;
   
const filterPath = boardsStore.filter.path.split('&'); const filterPath = boardsStore.filter.path.split('&');
const labelTitle = encodeURIComponent(label.title); const labelTitle = encodeURIComponent(label.title);
const param = `label_name[]=${labelTitle}`; const param = `label_name[]=${labelTitle}`;
const labelIndex = filterPath.indexOf(param); const labelIndex = filterPath.indexOf(param);
$(e.currentTarget).tooltip('hide'); $(e.currentTarget).tooltip('hide');
   
if (labelIndex === -1) { if (labelIndex === -1) {
filterPath.push(param); filterPath.push(param);
} else { } else {
filterPath.splice(labelIndex, 1); filterPath.splice(labelIndex, 1);
} }
   
boardsStore.filter.path = filterPath.join('&'); boardsStore.filter.path = filterPath.join('&');
   
boardsStore.updateFiltersUrl(); boardsStore.updateFiltersUrl();
   
eventHub.$emit('updateTokens'); eventHub.$emit('updateTokens');
}, },
labelStyle(label) { labelStyle(label) {
return { return {
backgroundColor: label.color, backgroundColor: label.color,
color: label.textColor, color: label.textColor,
}; };
}, },
}, },
}; };
</script> </script>
<template> <template>
<div> <div>
Loading
Loading
Loading
@@ -20,7 +20,7 @@ export default {
Loading
@@ -20,7 +20,7 @@ export default {
computed: { computed: {
contents() { contents() {
const obj = { const obj = {
title: 'You haven\'t added any issues to your project yet', title: "You haven't added any issues to your project yet",
content: ` content: `
An issue can be a bug, a todo or a feature request that needs to be An issue can be a bug, a todo or a feature request that needs to be
discussed in a project. Besides, issues are searchable and filterable. discussed in a project. Besides, issues are searchable and filterable.
Loading
@@ -28,7 +28,7 @@ export default {
Loading
@@ -28,7 +28,7 @@ export default {
}; };
   
if (this.activeTab === 'selected') { if (this.activeTab === 'selected') {
obj.title = 'You haven\'t selected any issues yet'; obj.title = "You haven't selected any issues yet";
obj.content = ` obj.content = `
Go back to <strong>Open issues</strong> and select some issues Go back to <strong>Open issues</strong> and select some issues
to add to your board. to add to your board.
Loading
Loading
Loading
@@ -42,19 +42,17 @@ export default {
Loading
@@ -42,19 +42,17 @@ export default {
const req = this.buildUpdateRequest(list); const req = this.buildUpdateRequest(list);
   
// Post the data to the backend // Post the data to the backend
gl.boardService gl.boardService.bulkUpdate(issueIds, req).catch(() => {
.bulkUpdate(issueIds, req) Flash(__('Failed to update issues, please try again.'));
.catch(() => {
Flash(__('Failed to update issues, please try again.'));
   
selectedIssues.forEach((issue) => { selectedIssues.forEach(issue => {
list.removeIssue(issue); list.removeIssue(issue);
list.issuesSize -= 1; list.issuesSize -= 1;
});
}); });
});
   
// Add the issues on the frontend // Add the issues on the frontend
selectedIssues.forEach((issue) => { selectedIssues.forEach(issue => {
list.addIssue(issue); list.addIssue(issue);
list.issuesSize += 1; list.issuesSize += 1;
}); });
Loading
Loading
<script> <script>
import ModalFilters from './filters'; import ModalFilters from './filters';
import ModalTabs from './tabs.vue'; import ModalTabs from './tabs.vue';
import ModalStore from '../../stores/modal_store'; import ModalStore from '../../stores/modal_store';
import modalMixin from '../../mixins/modal_mixins'; import modalMixin from '../../mixins/modal_mixins';
   
export default { export default {
components: { components: {
ModalTabs, ModalTabs,
ModalFilters, ModalFilters,
},
mixins: [modalMixin],
props: {
projectId: {
type: Number,
required: true,
}, },
mixins: [modalMixin], milestonePath: {
props: { type: String,
projectId: { required: true,
type: Number,
required: true,
},
milestonePath: {
type: String,
required: true,
},
labelPath: {
type: String,
required: true,
},
}, },
data() { labelPath: {
return ModalStore.store; type: String,
required: true,
}, },
computed: { },
selectAllText() { data() {
if (ModalStore.selectedCount() !== this.issues.length || this.issues.length === 0) { return ModalStore.store;
return 'Select all'; },
} computed: {
selectAllText() {
if (ModalStore.selectedCount() !== this.issues.length || this.issues.length === 0) {
return 'Select all';
}
   
return 'Deselect all'; return 'Deselect all';
},
showSearch() {
return this.activeTab === 'all' && !this.loading && this.issuesCount > 0;
},
}, },
methods: { showSearch() {
toggleAll() { return this.activeTab === 'all' && !this.loading && this.issuesCount > 0;
this.$refs.selectAllBtn.blur(); },
},
methods: {
toggleAll() {
this.$refs.selectAllBtn.blur();
   
ModalStore.toggleAll(); ModalStore.toggleAll();
},
}, },
}; },
};
</script> </script>
<template> <template>
<div> <div>
Loading
Loading
<script> <script>
/* global ListIssue */ /* global ListIssue */
import { urlParamsToObject } from '~/lib/utils/common_utils'; import { urlParamsToObject } from '~/lib/utils/common_utils';
import ModalHeader from './header.vue'; import ModalHeader from './header.vue';
import ModalList from './list.vue'; import ModalList from './list.vue';
import ModalFooter from './footer.vue'; import ModalFooter from './footer.vue';
import EmptyState from './empty_state.vue'; import EmptyState from './empty_state.vue';
import ModalStore from '../../stores/modal_store'; import ModalStore from '../../stores/modal_store';
   
export default { export default {
components: { components: {
EmptyState, EmptyState,
ModalHeader, ModalHeader,
ModalList, ModalList,
ModalFooter, ModalFooter,
},
props: {
newIssuePath: {
type: String,
required: true,
}, },
props: { emptyStateSvg: {
newIssuePath: { type: String,
type: String, required: true,
required: true,
},
emptyStateSvg: {
type: String,
required: true,
},
issueLinkBase: {
type: String,
required: true,
},
rootPath: {
type: String,
required: true,
},
projectId: {
type: Number,
required: true,
},
milestonePath: {
type: String,
required: true,
},
labelPath: {
type: String,
required: true,
},
}, },
data() { issueLinkBase: {
return ModalStore.store; type: String,
required: true,
}, },
computed: { rootPath: {
showList() { type: String,
if (this.activeTab === 'selected') { required: true,
return this.selectedIssues.length > 0; },
} projectId: {
type: Number,
required: true,
},
milestonePath: {
type: String,
required: true,
},
labelPath: {
type: String,
required: true,
},
},
data() {
return ModalStore.store;
},
computed: {
showList() {
if (this.activeTab === 'selected') {
return this.selectedIssues.length > 0;
}
   
return this.issuesCount > 0; return this.issuesCount > 0;
}, },
showEmptyState() { showEmptyState() {
if (!this.loading && this.issuesCount === 0) { if (!this.loading && this.issuesCount === 0) {
return true; return true;
} }
   
return this.activeTab === 'selected' && this.selectedIssues.length === 0; return this.activeTab === 'selected' && this.selectedIssues.length === 0;
},
}, },
watch: { },
page() { watch: {
this.loadIssues(); page() {
}, this.loadIssues();
showAddIssuesModal() { },
if (this.showAddIssuesModal && !this.issues.length) { showAddIssuesModal() {
this.loading = true; if (this.showAddIssuesModal && !this.issues.length) {
this.loading = true;
const loadingDone = () => {
this.loading = false;
};
this.loadIssues()
.then(loadingDone)
.catch(loadingDone);
} else if (!this.showAddIssuesModal) {
this.issues = [];
this.selectedIssues = [];
this.issuesCount = false;
}
},
filter: {
handler() {
if (this.$el.tagName) {
this.page = 1;
this.filterLoading = true;
const loadingDone = () => { const loadingDone = () => {
this.loading = false; this.filterLoading = false;
}; };
   
this.loadIssues() this.loadIssues(true)
.then(loadingDone) .then(loadingDone)
.catch(loadingDone); .catch(loadingDone);
} else if (!this.showAddIssuesModal) {
this.issues = [];
this.selectedIssues = [];
this.issuesCount = false;
} }
}, },
filter: { deep: true,
handler() {
if (this.$el.tagName) {
this.page = 1;
this.filterLoading = true;
const loadingDone = () => {
this.filterLoading = false;
};
this.loadIssues(true)
.then(loadingDone)
.catch(loadingDone);
}
},
deep: true,
},
}, },
created() { },
this.page = 1; created() {
}, this.page = 1;
methods: { },
loadIssues(clearIssues = false) { methods: {
if (!this.showAddIssuesModal) return false; loadIssues(clearIssues = false) {
if (!this.showAddIssuesModal) return false;
   
return gl.boardService.getBacklog({ return gl.boardService
.getBacklog({
...urlParamsToObject(this.filter.path), ...urlParamsToObject(this.filter.path),
page: this.page, page: this.page,
per: this.perPage, per: this.perPage,
}) })
.then(res => res.data) .then(res => res.data)
.then(data => { .then(data => {
if (clearIssues) { if (clearIssues) {
this.issues = []; this.issues = [];
} }
   
data.issues.forEach(issueObj => { data.issues.forEach(issueObj => {
const issue = new ListIssue(issueObj); const issue = new ListIssue(issueObj);
const foundSelectedIssue = ModalStore.findSelectedIssue(issue); const foundSelectedIssue = ModalStore.findSelectedIssue(issue);
issue.selected = !!foundSelectedIssue; issue.selected = !!foundSelectedIssue;
   
this.issues.push(issue); this.issues.push(issue);
}); });
   
this.loadingNewPage = false; this.loadingNewPage = false;
   
if (!this.issuesCount) { if (!this.issuesCount) {
this.issuesCount = data.size; this.issuesCount = data.size;
} }
}) })
.catch(() => { .catch(() => {
// TODO: handle request error // TODO: handle request error
}); });
},
}, },
}; },
};
</script> </script>
<template> <template>
<div <div
Loading
Loading
<script> <script>
import Icon from '~/vue_shared/components/icon.vue'; import Icon from '~/vue_shared/components/icon.vue';
import bp from '../../../breakpoints'; import bp from '../../../breakpoints';
import ModalStore from '../../stores/modal_store'; import ModalStore from '../../stores/modal_store';
import IssueCardInner from '../issue_card_inner.vue'; import IssueCardInner from '../issue_card_inner.vue';
   
export default { export default {
components: { components: {
IssueCardInner, IssueCardInner,
Icon, Icon,
},
props: {
issueLinkBase: {
type: String,
required: true,
}, },
props: { rootPath: {
issueLinkBase: { type: String,
type: String, required: true,
required: true,
},
rootPath: {
type: String,
required: true,
},
emptyStateSvg: {
type: String,
required: true,
},
}, },
data() { emptyStateSvg: {
return ModalStore.store; type: String,
required: true,
}, },
computed: { },
loopIssues() { data() {
if (this.activeTab === 'all') { return ModalStore.store;
return this.issues; },
} computed: {
loopIssues() {
if (this.activeTab === 'all') {
return this.issues;
}
   
return this.selectedIssues; return this.selectedIssues;
}, },
groupedIssues() { groupedIssues() {
const groups = []; const groups = [];
this.loopIssues.forEach((issue, i) => { this.loopIssues.forEach((issue, i) => {
const index = i % this.columns; const index = i % this.columns;
   
if (!groups[index]) { if (!groups[index]) {
groups.push([]); groups.push([]);
} }
   
groups[index].push(issue); groups[index].push(issue);
}); });
   
return groups; return groups;
},
}, },
watch: { },
activeTab() { watch: {
if (this.activeTab === 'all') { activeTab() {
ModalStore.purgeUnselectedIssues(); if (this.activeTab === 'all') {
} ModalStore.purgeUnselectedIssues();
}, }
}, },
mounted() { },
this.scrollHandlerWrapper = this.scrollHandler.bind(this); mounted() {
this.setColumnCountWrapper = this.setColumnCount.bind(this); this.scrollHandlerWrapper = this.scrollHandler.bind(this);
this.setColumnCount(); this.setColumnCountWrapper = this.setColumnCount.bind(this);
this.setColumnCount();
   
this.$refs.list.addEventListener('scroll', this.scrollHandlerWrapper); this.$refs.list.addEventListener('scroll', this.scrollHandlerWrapper);
window.addEventListener('resize', this.setColumnCountWrapper); window.addEventListener('resize', this.setColumnCountWrapper);
},
beforeDestroy() {
this.$refs.list.removeEventListener('scroll', this.scrollHandlerWrapper);
window.removeEventListener('resize', this.setColumnCountWrapper);
},
methods: {
scrollHandler() {
const currentPage = Math.floor(this.issues.length / this.perPage);
if (
this.scrollTop() > this.scrollHeight() - 100 &&
!this.loadingNewPage &&
currentPage === this.page
) {
this.loadingNewPage = true;
this.page += 1;
}
}, },
beforeDestroy() { toggleIssue(e, issue) {
this.$refs.list.removeEventListener('scroll', this.scrollHandlerWrapper); if (e.target.tagName !== 'A') {
window.removeEventListener('resize', this.setColumnCountWrapper); ModalStore.toggleIssue(issue);
}
}, },
methods: { listHeight() {
scrollHandler() { return this.$refs.list.getBoundingClientRect().height;
const currentPage = Math.floor(this.issues.length / this.perPage); },
scrollHeight() {
if ( return this.$refs.list.scrollHeight;
this.scrollTop() > this.scrollHeight() - 100 && },
!this.loadingNewPage && scrollTop() {
currentPage === this.page return this.$refs.list.scrollTop + this.listHeight();
) { },
this.loadingNewPage = true; showIssue(issue) {
this.page += 1; if (this.activeTab === 'all') return true;
}
},
toggleIssue(e, issue) {
if (e.target.tagName !== 'A') {
ModalStore.toggleIssue(issue);
}
},
listHeight() {
return this.$refs.list.getBoundingClientRect().height;
},
scrollHeight() {
return this.$refs.list.scrollHeight;
},
scrollTop() {
return this.$refs.list.scrollTop + this.listHeight();
},
showIssue(issue) {
if (this.activeTab === 'all') return true;
   
const index = ModalStore.selectedIssueIndex(issue); const index = ModalStore.selectedIssueIndex(issue);
   
return index !== -1; return index !== -1;
}, },
setColumnCount() { setColumnCount() {
const breakpoint = bp.getBreakpointSize(); const breakpoint = bp.getBreakpointSize();
   
if (breakpoint === 'lg' || breakpoint === 'md') { if (breakpoint === 'lg' || breakpoint === 'md') {
this.columns = 3; this.columns = 3;
} else if (breakpoint === 'sm') { } else if (breakpoint === 'sm') {
this.columns = 2; this.columns = 2;
} else { } else {
this.columns = 1; this.columns = 1;
} }
},
}, },
}; },
};
</script> </script>
<template> <template>
<section <section
Loading
Loading
<script> <script>
import ModalStore from '../../stores/modal_store'; import ModalStore from '../../stores/modal_store';
import modalMixin from '../../mixins/modal_mixins'; import modalMixin from '../../mixins/modal_mixins';
   
export default { export default {
mixins: [modalMixin], mixins: [modalMixin],
data() { data() {
return ModalStore.store; return ModalStore.store;
},
computed: {
selectedCount() {
return ModalStore.selectedCount();
}, },
computed: { },
selectedCount() { destroyed() {
return ModalStore.selectedCount(); this.activeTab = 'all';
}, },
}, };
destroyed() {
this.activeTab = 'all';
},
};
</script> </script>
<template> <template>
<div class="top-area prepend-top-10 append-bottom-10"> <div class="top-area prepend-top-10 append-bottom-10">
Loading
Loading
Loading
@@ -6,36 +6,41 @@ import _ from 'underscore';
Loading
@@ -6,36 +6,41 @@ import _ from 'underscore';
import CreateLabelDropdown from '../../create_label'; import CreateLabelDropdown from '../../create_label';
import boardsStore from '../stores/boards_store'; import boardsStore from '../stores/boards_store';
   
$(document).off('created.label').on('created.label', (e, label) => { $(document)
boardsStore.new({ .off('created.label')
title: label.title, .on('created.label', (e, label) => {
position: boardsStore.state.lists.length - 2, boardsStore.new({
list_type: 'label',
label: {
id: label.id,
title: label.title, title: label.title,
color: label.color, position: boardsStore.state.lists.length - 2,
}, list_type: 'label',
label: {
id: label.id,
title: label.title,
color: label.color,
},
});
}); });
});
   
export default function initNewListDropdown() { export default function initNewListDropdown() {
$('.js-new-board-list').each(function () { $('.js-new-board-list').each(function() {
const $this = $(this); const $this = $(this);
new CreateLabelDropdown($this.closest('.dropdown').find('.dropdown-new-label'), $this.data('namespacePath'), $this.data('projectPath')); new CreateLabelDropdown(
$this.closest('.dropdown').find('.dropdown-new-label'),
$this.data('namespacePath'),
$this.data('projectPath'),
);
   
$this.glDropdown({ $this.glDropdown({
data(term, callback) { data(term, callback) {
axios.get($this.attr('data-list-labels-path')) axios.get($this.attr('data-list-labels-path')).then(({ data }) => {
.then(({ data }) => { callback(data);
callback(data); });
});
}, },
renderRow (label) { renderRow(label) {
const active = boardsStore.findList('title', label.title); const active = boardsStore.findList('title', label.title);
const $li = $('<li />'); const $li = $('<li />');
const $a = $('<a />', { const $a = $('<a />', {
class: (active ? `is-active js-board-list-${active.id}` : ''), class: active ? `is-active js-board-list-${active.id}` : '',
text: label.title, text: label.title,
href: '#', href: '#',
}); });
Loading
@@ -53,7 +58,7 @@ export default function initNewListDropdown() {
Loading
@@ -53,7 +58,7 @@ export default function initNewListDropdown() {
selectable: true, selectable: true,
multiSelect: true, multiSelect: true,
containerSelector: '.js-tab-container-labels .dropdown-page-one .dropdown-content', containerSelector: '.js-tab-container-labels .dropdown-page-one .dropdown-content',
clicked (options) { clicked(options) {
const { e } = options; const { e } = options;
const label = options.selectedObj; const label = options.selectedObj;
e.preventDefault(); e.preventDefault();
Loading
Loading
Loading
@@ -46,7 +46,7 @@ export default {
Loading
@@ -46,7 +46,7 @@ export default {
selectable: true, selectable: true,
data: (term, callback) => { data: (term, callback) => {
this.loading = true; this.loading = true;
return Api.groupProjects(this.groupId, term, {with_issues_enabled: true}, projects => { return Api.groupProjects(this.groupId, term, { with_issues_enabled: true }, projects => {
this.loading = false; this.loading = false;
callback(projects); callback(projects);
}); });
Loading
@@ -54,7 +54,9 @@ export default {
Loading
@@ -54,7 +54,9 @@ export default {
renderRow(project) { renderRow(project) {
return ` return `
<li> <li>
<a href='#' class='dropdown-menu-link' data-project-id="${project.id}" data-project-name="${project.name}"> <a href='#' class='dropdown-menu-link' data-project-id="${
project.id
}" data-project-name="${project.name}">
${_.escape(project.name)} ${_.escape(project.name)}
</a> </a>
</li> </li>
Loading
Loading
<script> <script>
import Vue from 'vue'; import Vue from 'vue';
import Flash from '../../../flash'; import Flash from '../../../flash';
import { __ } from '../../../locale'; import { __ } from '../../../locale';
import boardsStore from '../../stores/boards_store'; import boardsStore from '../../stores/boards_store';
   
export default Vue.extend({ export default Vue.extend({
props: { props: {
issue: { issue: {
type: Object, type: Object,
required: true, required: true,
},
list: {
type: Object,
required: true,
},
}, },
computed: { list: {
updateUrl() { type: Object,
return this.issue.path; required: true,
},
}, },
methods: { },
removeIssue() { computed: {
const { issue } = this; updateUrl() {
const lists = issue.getLists(); return this.issue.path;
const req = this.buildPatchRequest(issue, lists); },
},
const data = { methods: {
issue: this.seedPatchRequest(issue, req), removeIssue() {
}; const { issue } = this;
const lists = issue.getLists();
const req = this.buildPatchRequest(issue, lists);
   
if (data.issue.label_ids.length === 0) { const data = {
data.issue.label_ids = ['']; issue: this.seedPatchRequest(issue, req),
} };
   
// Post the remove data if (data.issue.label_ids.length === 0) {
Vue.http.patch(this.updateUrl, data).catch(() => { data.issue.label_ids = [''];
Flash(__('Failed to remove issue from board, please try again.')); }
   
lists.forEach(list => { // Post the remove data
list.addIssue(issue); Vue.http.patch(this.updateUrl, data).catch(() => {
}); Flash(__('Failed to remove issue from board, please try again.'));
});
   
// Remove from the frontend store
lists.forEach(list => { lists.forEach(list => {
list.removeIssue(issue); list.addIssue(issue);
}); });
});
   
boardsStore.detail.issue = {}; // Remove from the frontend store
}, lists.forEach(list => {
/** list.removeIssue(issue);
* Build the default patch request. });
*/
buildPatchRequest(issue, lists) {
const listLabelIds = lists.map(list => list.label.id);
   
const labelIds = issue.labels boardsStore.detail.issue = {};
.map(label => label.id) },
.filter(id => !listLabelIds.includes(id)); /**
* Build the default patch request.
*/
buildPatchRequest(issue, lists) {
const listLabelIds = lists.map(list => list.label.id);
const labelIds = issue.labels.map(label => label.id).filter(id => !listLabelIds.includes(id));
   
return { return {
label_ids: labelIds, label_ids: labelIds,
}; };
}, },
/** /**
* Seed the given patch request. * Seed the given patch request.
* *
* (This is overridden in EE) * (This is overridden in EE)
*/ */
seedPatchRequest(issue, req) { seedPatchRequest(issue, req) {
return req; return req;
},
}, },
}); },
});
</script> </script>
<template> <template>
<div <div
Loading
Loading
Loading
@@ -32,7 +32,7 @@ export default class FilteredSearchBoards extends FilteredSearchManager {
Loading
@@ -32,7 +32,7 @@ export default class FilteredSearchBoards extends FilteredSearchManager {
const tokens = FilteredSearchContainer.container.querySelectorAll('.js-visual-token'); const tokens = FilteredSearchContainer.container.querySelectorAll('.js-visual-token');
   
// Remove all the tokens as they will be replaced by the search manager // Remove all the tokens as they will be replaced by the search manager
[].forEach.call(tokens, (el) => { [].forEach.call(tokens, el => {
el.parentNode.removeChild(el); el.parentNode.removeChild(el);
}); });
   
Loading
@@ -50,7 +50,10 @@ export default class FilteredSearchBoards extends FilteredSearchManager {
Loading
@@ -50,7 +50,10 @@ export default class FilteredSearchBoards extends FilteredSearchManager {
   
canEdit(tokenName, tokenValue) { canEdit(tokenName, tokenValue) {
if (this.cantEdit.includes(tokenName)) return false; if (this.cantEdit.includes(tokenName)) return false;
return this.cantEditWithValue.findIndex(token => token.name === tokenName && return (
token.value === tokenValue) === -1; this.cantEditWithValue.findIndex(
token => token.name === tokenName && token.value === tokenValue,
) === -1
);
} }
} }
Loading
@@ -32,9 +32,9 @@ export default () => {
Loading
@@ -32,9 +32,9 @@ export default () => {
const $boardApp = document.getElementById('board-app'); const $boardApp = document.getElementById('board-app');
   
// check for browser back and trigger a hard reload to circumvent browser caching. // check for browser back and trigger a hard reload to circumvent browser caching.
window.addEventListener('pageshow', (event) => { window.addEventListener('pageshow', event => {
const isNavTypeBackForward = window.performance && const isNavTypeBackForward =
window.performance.navigation.type === NavigationType.TYPE_BACK_FORWARD; window.performance && window.performance.navigation.type === NavigationType.TYPE_BACK_FORWARD;
   
if (event.persisted || isNavTypeBackForward) { if (event.persisted || isNavTypeBackForward) {
window.location.reload(); window.location.reload();
Loading
Loading
Loading
@@ -4,7 +4,8 @@ import $ from 'jquery';
Loading
@@ -4,7 +4,8 @@ import $ from 'jquery';
import sortableConfig from '../../sortable/sortable_config'; import sortableConfig from '../../sortable/sortable_config';
   
export function sortableStart() { export function sortableStart() {
$('.has-tooltip').tooltip('hide') $('.has-tooltip')
.tooltip('hide')
.tooltip('disable'); .tooltip('disable');
document.body.classList.add('is-dragging'); document.body.classList.add('is-dragging');
} }
Loading
@@ -15,7 +16,8 @@ export function sortableEnd() {
Loading
@@ -15,7 +16,8 @@ export function sortableEnd() {
} }
   
export function getBoardSortableDefaultOptions(obj) { export function getBoardSortableDefaultOptions(obj) {
const touchEnabled = ('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch; const touchEnabled =
'ontouchstart' in window || (window.DocumentTouch && document instanceof DocumentTouch);
   
const defaultSortOptions = Object.assign({}, sortableConfig, { const defaultSortOptions = Object.assign({}, sortableConfig, {
filter: '.board-delete, .btn', filter: '.board-delete, .btn',
Loading
@@ -26,6 +28,8 @@ export function getBoardSortableDefaultOptions(obj) {
Loading
@@ -26,6 +28,8 @@ export function getBoardSortableDefaultOptions(obj) {
onEnd: sortableEnd, onEnd: sortableEnd,
}); });
   
Object.keys(obj).forEach((key) => { defaultSortOptions[key] = obj[key]; }); Object.keys(obj).forEach(key => {
defaultSortOptions[key] = obj[key];
});
return defaultSortOptions; return defaultSortOptions;
} }
Loading
@@ -9,7 +9,7 @@ import IssueProject from './project';
Loading
@@ -9,7 +9,7 @@ import IssueProject from './project';
import boardsStore from '../stores/boards_store'; import boardsStore from '../stores/boards_store';
   
class ListIssue { class ListIssue {
constructor (obj, defaultAvatar) { constructor(obj, defaultAvatar) {
this.id = obj.id; this.id = obj.id;
this.iid = obj.iid; this.iid = obj.iid;
this.title = obj.title; this.title = obj.title;
Loading
@@ -39,54 +39,54 @@ class ListIssue {
Loading
@@ -39,54 +39,54 @@ class ListIssue {
this.milestone = new ListMilestone(obj.milestone); this.milestone = new ListMilestone(obj.milestone);
} }
   
obj.labels.forEach((label) => { obj.labels.forEach(label => {
this.labels.push(new ListLabel(label)); this.labels.push(new ListLabel(label));
}); });
   
this.assignees = obj.assignees.map(a => new ListAssignee(a, defaultAvatar)); this.assignees = obj.assignees.map(a => new ListAssignee(a, defaultAvatar));
} }
   
addLabel (label) { addLabel(label) {
if (!this.findLabel(label)) { if (!this.findLabel(label)) {
this.labels.push(new ListLabel(label)); this.labels.push(new ListLabel(label));
} }
} }
   
findLabel (findLabel) { findLabel(findLabel) {
return this.labels.filter(label => label.title === findLabel.title)[0]; return this.labels.filter(label => label.title === findLabel.title)[0];
} }
   
removeLabel (removeLabel) { removeLabel(removeLabel) {
if (removeLabel) { if (removeLabel) {
this.labels = this.labels.filter(label => removeLabel.title !== label.title); this.labels = this.labels.filter(label => removeLabel.title !== label.title);
} }
} }
   
removeLabels (labels) { removeLabels(labels) {
labels.forEach(this.removeLabel.bind(this)); labels.forEach(this.removeLabel.bind(this));
} }
   
addAssignee (assignee) { addAssignee(assignee) {
if (!this.findAssignee(assignee)) { if (!this.findAssignee(assignee)) {
this.assignees.push(new ListAssignee(assignee)); this.assignees.push(new ListAssignee(assignee));
} }
} }
   
findAssignee (findAssignee) { findAssignee(findAssignee) {
return this.assignees.filter(assignee => assignee.id === findAssignee.id)[0]; return this.assignees.filter(assignee => assignee.id === findAssignee.id)[0];
} }
   
removeAssignee (removeAssignee) { removeAssignee(removeAssignee) {
if (removeAssignee) { if (removeAssignee) {
this.assignees = this.assignees.filter(assignee => assignee.id !== removeAssignee.id); this.assignees = this.assignees.filter(assignee => assignee.id !== removeAssignee.id);
} }
} }
   
removeAllAssignees () { removeAllAssignees() {
this.assignees = []; this.assignees = [];
} }
   
getLists () { getLists() {
return boardsStore.state.lists.filter(list => list.findIssue(this.id)); return boardsStore.state.lists.filter(list => list.findIssue(this.id));
} }
   
Loading
@@ -102,14 +102,14 @@ class ListIssue {
Loading
@@ -102,14 +102,14 @@ class ListIssue {
this.isLoading[key] = value; this.isLoading[key] = value;
} }
   
update () { update() {
const data = { const data = {
issue: { issue: {
milestone_id: this.milestone ? this.milestone.id : null, milestone_id: this.milestone ? this.milestone.id : null,
due_date: this.dueDate, due_date: this.dueDate,
assignee_ids: this.assignees.length > 0 ? this.assignees.map((u) => u.id) : [0], assignee_ids: this.assignees.length > 0 ? this.assignees.map(u => u.id) : [0],
label_ids: this.labels.map((label) => label.id) label_ids: this.labels.map(label => label.id),
} },
}; };
   
if (!data.issue.label_ids.length) { if (!data.issue.label_ids.length) {
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment