summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/assets/javascripts/boards/components/modal/footer.js.es627
-rw-r--r--app/assets/javascripts/boards/components/modal/list.js.es629
-rw-r--r--app/assets/javascripts/boards/components/modal/search.js.es642
-rw-r--r--app/assets/javascripts/boards/components/modal/tabs.js.es613
-rw-r--r--app/assets/javascripts/boards/stores/boards_store.js.es613
-rw-r--r--app/assets/stylesheets/pages/boards.scss41
6 files changed, 141 insertions, 24 deletions
diff --git a/app/assets/javascripts/boards/components/modal/footer.js.es6 b/app/assets/javascripts/boards/components/modal/footer.js.es6
index 9cb48448a87..dec0196a32c 100644
--- a/app/assets/javascripts/boards/components/modal/footer.js.es6
+++ b/app/assets/javascripts/boards/components/modal/footer.js.es6
@@ -7,19 +7,40 @@
gl.issueBoards.ModalFooter = Vue.extend({
data() {
- return Store.modal;
+ return Object.assign({}, Store.modal, {
+ disabled: false,
+ });
+ },
+ computed: {
+ submitDisabled() {
+ if (this.disabled) return true;
+
+ return !Store.modalSelectedCount();
+ },
+ submitText() {
+ const count = Store.modalSelectedCount();
+
+ return `Add ${count} issue${count > 1 || !count ? 's' : ''}`;
+ },
},
methods: {
hideModal() {
this.showAddIssuesModal = false;
},
+ addIssues() {
+ const issueIds = this.issues.filter(issue => issue.selected).map(issue => issue.id);
+
+ this.disabled = true;
+ },
},
template: `
<footer class="form-actions add-issues-footer">
<button
class="btn btn-success pull-left"
- type="button">
- Add issues
+ type="button"
+ :disabled="submitDisabled"
+ @click="addIssues">
+ {{ submitText }}
</button>
<button
class="btn btn-default pull-right"
diff --git a/app/assets/javascripts/boards/components/modal/list.js.es6 b/app/assets/javascripts/boards/components/modal/list.js.es6
index e06fa58b3b6..e700161f642 100644
--- a/app/assets/javascripts/boards/components/modal/list.js.es6
+++ b/app/assets/javascripts/boards/components/modal/list.js.es6
@@ -1,6 +1,8 @@
/* global Vue */
/* global ListIssue */
+/* global Masonry */
(() => {
+ let listMasonry;
const Store = gl.issueBoards.BoardsStore;
window.gl = window.gl || {};
@@ -22,9 +24,14 @@
loading() {
return this.issues.length === 0;
},
+ selectedCount() {
+ return Store.modalSelectedCount();
+ },
},
methods: {
- toggleIssue(issue) {
+ toggleIssue(issueObj) {
+ const issue = issueObj;
+
issue.selected = !issue.selected;
},
showIssue(issue) {
@@ -41,7 +48,7 @@
if (listMasonry) {
listMasonry.destroy();
}
- }
+ },
},
mounted() {
gl.boardService.getBacklog()
@@ -66,9 +73,11 @@
},
template: `
<section class="add-issues-list">
- <i
- class="fa fa-spinner fa-spin"
- v-if="loading"></i>
+ <div
+ class="add-issues-list-loading"
+ v-if="loading">
+ <i class="fa fa-spinner fa-spin"></i>
+ </div>
<div
class="add-issues-list-columns list-unstyled"
ref="list"
@@ -85,9 +94,19 @@
:issue="issue"
:issue-link-base="'/'">
</issue-card-inner>
+ <span
+ v-if="issue.selected"
+ class="issue-card-selected">
+ <i class="fa fa-check"></i>
+ </span>
</div>
</div>
</div>
+ <p
+ class="all-issues-selected-empty"
+ v-if="activeTab == 'selected' && selectedCount == 0">
+ You don't have any issues selected, <a href="#" @click="activeTab = 'all'">select some</a>.
+ </p>
</section>
`,
});
diff --git a/app/assets/javascripts/boards/components/modal/search.js.es6 b/app/assets/javascripts/boards/components/modal/search.js.es6
index 714c9240d4d..59aeb17baa5 100644
--- a/app/assets/javascripts/boards/components/modal/search.js.es6
+++ b/app/assets/javascripts/boards/components/modal/search.js.es6
@@ -1,14 +1,48 @@
/* global Vue */
(() => {
+ const Store = gl.issueBoards.BoardsStore;
+
window.gl = window.gl || {};
window.gl.issueBoards = window.gl.issueBoards || {};
gl.issueBoards.ModalSearch = Vue.extend({
+ data() {
+ return Store.modal;
+ },
+ computed: {
+ selectAllText() {
+ if (Store.modalSelectedCount() !== this.issues.length || this.issues.length === 0) {
+ return 'Select all';
+ }
+
+ return 'Un-select all';
+ },
+ },
+ methods: {
+ toggleAll() {
+ const select = Store.modalSelectedCount() !== this.issues.length;
+
+ this.issues.forEach((issue) => {
+ const issueUpdate = issue;
+ issueUpdate.selected = select;
+ });
+ },
+ },
template: `
- <input
- placeholder="Search issues..."
- class="form-control"
- type="search" />
+ <div
+ class="add-issues-search"
+ v-if="activeTab == 'all'">
+ <input
+ placeholder="Search issues..."
+ class="form-control"
+ type="search" />
+ <button
+ type="button"
+ class="btn btn-success btn-inverted"
+ @click="toggleAll">
+ {{ selectAllText }}
+ </button>
+ </div>
`,
});
})();
diff --git a/app/assets/javascripts/boards/components/modal/tabs.js.es6 b/app/assets/javascripts/boards/components/modal/tabs.js.es6
index 58fb75f839f..a1da7840036 100644
--- a/app/assets/javascripts/boards/components/modal/tabs.js.es6
+++ b/app/assets/javascripts/boards/components/modal/tabs.js.es6
@@ -16,17 +16,12 @@
},
computed: {
selectedCount() {
- let count = 0;
-
- this.issues.forEach((issue) => {
- if (issue.selected) {
- count += 1;
- }
- });
-
- return count;
+ return Store.modalSelectedCount();
},
},
+ destroyed() {
+ this.activeTab = 'all';
+ },
template: `
<div class="top-area">
<ul class="nav-links issues-state-filters">
diff --git a/app/assets/javascripts/boards/stores/boards_store.js.es6 b/app/assets/javascripts/boards/stores/boards_store.js.es6
index 42216d429c6..4c5eb57f5c9 100644
--- a/app/assets/javascripts/boards/stores/boards_store.js.es6
+++ b/app/assets/javascripts/boards/stores/boards_store.js.es6
@@ -125,6 +125,17 @@
},
updateFiltersUrl () {
history.pushState(null, null, `?${$.param(this.state.filters)}`);
- }
+ },
+ modalSelectedCount() {
+ let count = 0;
+
+ this.modal.issues.forEach((issue) => {
+ if (issue.selected) {
+ count += 1;
+ }
+ });
+
+ return count;
+ },
};
})();
diff --git a/app/assets/stylesheets/pages/boards.scss b/app/assets/stylesheets/pages/boards.scss
index f41d4cdd45d..73ed8dd8ab1 100644
--- a/app/assets/stylesheets/pages/boards.scss
+++ b/app/assets/stylesheets/pages/boards.scss
@@ -390,19 +390,34 @@
.top-area {
margin-bottom: 10px;
}
+}
- .form-control {
- margin-bottom: 10px;
+.add-issues-search {
+ display: flex;
+ margin-bottom: 10px;
+
+ .btn {
+ margin-left: 10px;
}
}
.add-issues-list {
+ display: flex;
flex: 1;
margin-left: -$gl-vert-padding;
margin-right: -$gl-vert-padding;
overflow-y: scroll;
}
+.add-issues-list-loading {
+ align-self: center;
+ width: 100%;
+ padding-left: $gl-vert-padding;
+ padding-right: $gl-vert-padding;
+ font-size: 35px;
+ text-align: center;
+}
+
.add-issues-footer {
margin-top: auto;
margin-left: -15px;
@@ -412,6 +427,9 @@
}
.add-issues-list-columns {
+ width: 100%;
+ padding-top: 3px;
+
.card-parent {
width: (100% / 3);
padding: 0 $gl-vert-padding ($gl-vert-padding * 2);
@@ -421,3 +439,22 @@
cursor: pointer;
}
}
+
+.all-issues-selected-empty {
+ align-self: center;
+ margin-bottom: 0;
+}
+
+.issue-card-selected {
+ position: absolute;
+ right: -3px;
+ top: -3px;
+ width: 20px;
+ height: 20px;
+ background-color: $blue-dark;
+ color: $white-light;
+ font-size: 12px;
+ text-align: center;
+ line-height: 20px;
+ border-radius: 50%;
+}