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