summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/boards/components/modal
diff options
context:
space:
mode:
authorPhil Hughes <me@iamphill.com>2017-02-01 15:23:01 +0000
committerFatih Acet <acetfatih@gmail.com>2017-02-03 17:02:44 +0300
commit4428bb27b78bf8f75d8ff15c227a8dfbb82aaa8e (patch)
treed5cfeca79348d875fe6cb4b6de2b94ed0c1d5bc0 /app/assets/javascripts/boards/components/modal
parentb4113dba0378936024c496b15b3c8a5f1c0a1021 (diff)
downloadgitlab-ce-4428bb27b78bf8f75d8ff15c227a8dfbb82aaa8e.tar.gz
Removed Masonry, instead uses groups of data
Added some error handling which reverts the frontend data changes & notifies the user
Diffstat (limited to 'app/assets/javascripts/boards/components/modal')
-rw-r--r--app/assets/javascripts/boards/components/modal/footer.js.es611
-rw-r--r--app/assets/javascripts/boards/components/modal/header.js.es67
-rw-r--r--app/assets/javascripts/boards/components/modal/index.js.es624
-rw-r--r--app/assets/javascripts/boards/components/modal/list.js.es6117
-rw-r--r--app/assets/javascripts/boards/components/modal/lists_dropdown.js.es62
-rw-r--r--app/assets/javascripts/boards/components/modal/tabs.js.es64
6 files changed, 97 insertions, 68 deletions
diff --git a/app/assets/javascripts/boards/components/modal/footer.js.es6 b/app/assets/javascripts/boards/components/modal/footer.js.es6
index 8883beb1290..4085a22b25a 100644
--- a/app/assets/javascripts/boards/components/modal/footer.js.es6
+++ b/app/assets/javascripts/boards/components/modal/footer.js.es6
@@ -1,5 +1,7 @@
+/* eslint-disable no-new */
//= require ./lists_dropdown
/* global Vue */
+/* global Flash */
(() => {
const ModalStore = gl.issueBoards.ModalStore;
@@ -15,7 +17,7 @@
submitText() {
const count = ModalStore.selectedCount();
- return `Add ${count > 0 ? count : ''} issue${count > 1 || !count ? 's' : ''}`;
+ return `Add ${count > 0 ? count : ''} ${gl.text.pluralize('issue', count)}`;
},
},
methods: {
@@ -27,6 +29,13 @@
// Post the data to the backend
gl.boardService.bulkUpdate(issueIds, {
add_label_ids: [list.label.id],
+ }).catch(() => {
+ new Flash('Failed to update issues, please try again.', 'alert');
+
+ selectedIssues.forEach((issue) => {
+ list.removeIssue(issue);
+ list.issuesSize -= 1;
+ });
});
// Add the issues on the frontend
diff --git a/app/assets/javascripts/boards/components/modal/header.js.es6 b/app/assets/javascripts/boards/components/modal/header.js.es6
index 194d598d42e..dbbcd73f1fe 100644
--- a/app/assets/javascripts/boards/components/modal/header.js.es6
+++ b/app/assets/javascripts/boards/components/modal/header.js.es6
@@ -3,7 +3,7 @@
(() => {
const ModalStore = gl.issueBoards.ModalStore;
- gl.issueBoards.IssuesModalHeader = Vue.extend({
+ gl.issueBoards.ModalHeader = Vue.extend({
mixins: [gl.issueBoards.ModalMixins],
data() {
return ModalStore.store;
@@ -16,6 +16,9 @@
return 'Deselect all';
},
+ showSearch() {
+ return this.activeTab === 'all' && !this.loading && this.issuesCount > 0;
+ },
},
methods: {
toggleAll() {
@@ -45,7 +48,7 @@
<modal-tabs v-if="!loading && issuesCount > 0"></modal-tabs>
<div
class="add-issues-search append-bottom-10"
- v-if="activeTab == 'all' && !loading && issuesCount > 0">
+ v-if="showSearch">
<input
placeholder="Search issues..."
class="form-control"
diff --git a/app/assets/javascripts/boards/components/modal/index.js.es6 b/app/assets/javascripts/boards/components/modal/index.js.es6
index 43d2fa03d92..666f4e16793 100644
--- a/app/assets/javascripts/boards/components/modal/index.js.es6
+++ b/app/assets/javascripts/boards/components/modal/index.js.es6
@@ -53,10 +53,9 @@
},
methods: {
searchOperation: _.debounce(function searchOperationDebounce() {
- this.issues = [];
- this.loadIssues();
+ this.loadIssues(true);
}, 500),
- loadIssues() {
+ loadIssues(clearIssues = false) {
return gl.boardService.getBacklog({
search: this.searchTerm,
page: this.page,
@@ -64,10 +63,14 @@
}).then((res) => {
const data = res.json();
+ if (clearIssues) {
+ this.issues = [];
+ }
+
data.issues.forEach((issueObj) => {
const issue = new ListIssue(issueObj);
const foundSelectedIssue = ModalStore.findSelectedIssue(issue);
- issue.selected = foundSelectedIssue !== undefined;
+ issue.selected = !!foundSelectedIssue;
this.issues.push(issue);
});
@@ -75,7 +78,7 @@
this.loadingNewPage = false;
if (!this.issuesCount) {
- this.issuesCount = this.issues.length;
+ this.issuesCount = data.size;
}
});
},
@@ -88,9 +91,16 @@
return this.issuesCount > 0;
},
+ showEmptyState() {
+ if (!this.loading && this.issuesCount === 0) {
+ return true;
+ }
+
+ return this.activeTab === 'selected' && this.selectedIssues.length === 0;
+ },
},
components: {
- 'modal-header': gl.issueBoards.IssuesModalHeader,
+ 'modal-header': gl.issueBoards.ModalHeader,
'modal-list': gl.issueBoards.ModalList,
'modal-footer': gl.issueBoards.ModalFooter,
'empty-state': gl.issueBoards.ModalEmptyState,
@@ -106,7 +116,7 @@
:root-path="rootPath"
v-if="!loading && showList"></modal-list>
<empty-state
- v-if="(!loading && issuesCount === 0) || (activeTab === 'selected' && selectedIssues.length === 0)"
+ v-if="showEmptyState"
:image="blankStateImage"
:new-issue-path="newIssuePath"></empty-state>
<section
diff --git a/app/assets/javascripts/boards/components/modal/list.js.es6 b/app/assets/javascripts/boards/components/modal/list.js.es6
index ae3e405e70e..d0901219216 100644
--- a/app/assets/javascripts/boards/components/modal/list.js.es6
+++ b/app/assets/javascripts/boards/components/modal/list.js.es6
@@ -1,8 +1,7 @@
/* global Vue */
/* global ListIssue */
-/* global Masonry */
+/* global bp */
(() => {
- let listMasonry;
const ModalStore = gl.issueBoards.ModalStore;
gl.issueBoards.ModalList = Vue.extend({
@@ -21,18 +20,10 @@
},
watch: {
activeTab() {
- this.initMasonry();
-
if (this.activeTab === 'all') {
ModalStore.purgeUnselectedIssues();
}
},
- issues: {
- handler() {
- this.initMasonry();
- },
- deep: true,
- },
},
computed: {
loopIssues() {
@@ -42,8 +33,31 @@
return this.selectedIssues;
},
+ groupedIssues() {
+ const groups = [];
+ this.loopIssues.forEach((issue, i) => {
+ const index = i % this.columns;
+
+ if (!groups[index]) {
+ groups.push([]);
+ }
+
+ groups[index].push(issue);
+ });
+
+ return groups;
+ },
},
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);
@@ -65,40 +79,29 @@
return index !== -1;
},
- initMasonry() {
- const listScrollTop = this.$refs.list.scrollTop;
-
- this.$nextTick(() => {
- this.destroyMasonry();
- listMasonry = new Masonry(this.$refs.list, {
- transitionDuration: 0,
- });
+ setColumnCount() {
+ const breakpoint = bp.getBreakpointSize();
- this.$refs.list.scrollTop = listScrollTop;
- });
- },
- destroyMasonry() {
- if (listMasonry) {
- listMasonry.destroy();
- listMasonry = undefined;
+ if (breakpoint === 'lg' || breakpoint === 'md') {
+ this.columns = 3;
+ } else if (breakpoint === 'sm') {
+ this.columns = 2;
+ } else {
+ this.columns = 1;
}
},
},
mounted() {
- this.initMasonry();
-
- this.$refs.list.onscroll = () => {
- const currentPage = Math.floor(this.issues.length / this.perPage);
+ this.scrollHandlerWrapper = this.scrollHandler.bind(this);
+ this.setColumnCountWrapper = this.setColumnCount.bind(this);
+ this.setColumnCount();
- if ((this.scrollTop() > this.scrollHeight() - 100) && !this.loadingNewPage
- && currentPage === this.page) {
- this.loadingNewPage = true;
- this.page += 1;
- }
- };
+ this.$refs.list.addEventListener('scroll', this.scrollHandlerWrapper);
+ window.addEventListener('resize', this.setColumnCountWrapper);
},
- destroyed() {
- this.destroyMasonry();
+ beforeDestroy() {
+ this.$refs.list.removeEventListener('scroll', this.scrollHandlerWrapper);
+ window.removeEventListener('resize', this.setColumnCountWrapper);
},
components: {
'issue-card-inner': gl.issueBoards.IssueCardInner,
@@ -108,25 +111,29 @@
class="add-issues-list add-issues-list-columns"
ref="list">
<div
- v-for="issue in loopIssues"
- v-if="showIssue(issue)"
- class="card-parent">
+ v-for="group in groupedIssues"
+ class="add-issues-list-column">
<div
- class="card"
- :class="{ 'is-active': issue.selected }"
- @click="toggleIssue($event, issue)">
- <issue-card-inner
- :issue="issue"
- :issue-link-base="issueLinkBase"
- :root-path="rootPath">
- </issue-card-inner>
- <span
- :aria-label="'Issue #' + issue.id + ' selected'"
- aria-checked="true"
- v-if="issue.selected"
- class="issue-card-selected text-center">
- <i class="fa fa-check"></i>
- </span>
+ v-for="issue in group"
+ v-if="showIssue(issue)"
+ class="card-parent">
+ <div
+ class="card"
+ :class="{ 'is-active': issue.selected }"
+ @click="toggleIssue($event, issue)">
+ <issue-card-inner
+ :issue="issue"
+ :issue-link-base="issueLinkBase"
+ :root-path="rootPath">
+ </issue-card-inner>
+ <span
+ :aria-label="'Issue #' + issue.id + ' selected'"
+ aria-checked="true"
+ v-if="issue.selected"
+ class="issue-card-selected text-center">
+ <i class="fa fa-check"></i>
+ </span>
+ </div>
</div>
</div>
</section>
diff --git a/app/assets/javascripts/boards/components/modal/lists_dropdown.js.es6 b/app/assets/javascripts/boards/components/modal/lists_dropdown.js.es6
index bb2d43c4a21..96f12da3753 100644
--- a/app/assets/javascripts/boards/components/modal/lists_dropdown.js.es6
+++ b/app/assets/javascripts/boards/components/modal/lists_dropdown.js.es6
@@ -37,7 +37,7 @@
href="#"
role="button"
:class="{ 'is-active': list.id == selected.id }"
- @click="modal.selectedList = list">
+ @click.prevent="modal.selectedList = list">
<span
class="dropdown-label-box"
:style="{ backgroundColor: list.label.color }">
diff --git a/app/assets/javascripts/boards/components/modal/tabs.js.es6 b/app/assets/javascripts/boards/components/modal/tabs.js.es6
index d556c6d3e04..e8cb43f3503 100644
--- a/app/assets/javascripts/boards/components/modal/tabs.js.es6
+++ b/app/assets/javascripts/boards/components/modal/tabs.js.es6
@@ -23,7 +23,7 @@
href="#"
role="button"
@click.prevent="changeTab('all')">
- <span>All issues</span>
+ All issues
<span class="badge">
{{ issuesCount }}
</span>
@@ -34,7 +34,7 @@
href="#"
role="button"
@click.prevent="changeTab('selected')">
- <span>Selected issues</span>
+ Selected issues
<span class="badge">
{{ selectedCount }}
</span>