diff options
author | Simon Knox <psimyn@gmail.com> | 2017-09-06 15:02:30 +1000 |
---|---|---|
committer | Simon Knox <psimyn@gmail.com> | 2017-09-06 15:41:00 +1000 |
commit | c28d52a3a5e745d20981151b89bfcad07c68fa9c (patch) | |
tree | d51df26c80701f8e7b8a178119ffd09a895ad063 | |
parent | b9aa55e1ea2ba226bd9bf4c6fb08fdec30e046c5 (diff) | |
download | gitlab-ce-c28d52a3a5e745d20981151b89bfcad07c68fa9c.tar.gz |
FE backport of group boards to reduce CE conflicts
-rw-r--r-- | app/assets/javascripts/api.js | 14 | ||||
-rw-r--r-- | app/assets/javascripts/boards/boards_bundle.js | 51 | ||||
-rw-r--r-- | app/assets/javascripts/boards/components/board_list.js | 10 | ||||
-rw-r--r-- | app/assets/javascripts/boards/components/board_new_issue.js | 5 | ||||
-rw-r--r-- | app/assets/javascripts/boards/components/issue_card_inner.js | 7 | ||||
-rw-r--r-- | app/assets/javascripts/boards/components/modal/footer.js | 2 | ||||
-rw-r--r-- | app/assets/javascripts/boards/components/new_list_dropdown.js | 2 | ||||
-rw-r--r-- | app/assets/javascripts/boards/components/sidebar/remove_issue.js | 23 | ||||
-rw-r--r-- | app/assets/javascripts/boards/models/issue.js | 4 | ||||
-rw-r--r-- | app/assets/javascripts/boards/models/label.js | 1 | ||||
-rw-r--r-- | app/assets/javascripts/boards/models/list.js | 27 | ||||
-rw-r--r-- | spec/javascripts/api_spec.js | 23 |
12 files changed, 116 insertions, 53 deletions
diff --git a/app/assets/javascripts/api.js b/app/assets/javascripts/api.js index 8acddd6194c..501cc43d552 100644 --- a/app/assets/javascripts/api.js +++ b/app/assets/javascripts/api.js @@ -6,7 +6,8 @@ const Api = { namespacesPath: '/api/:version/namespaces.json', groupProjectsPath: '/api/:version/groups/:id/projects.json', projectsPath: '/api/:version/projects.json', - labelsPath: '/:namespace_path/:project_path/labels', + projectLabelsPath: '/:namespace_path/:project_path/labels', + groupLabelsPath: '/groups/:namespace_path/labels', licensePath: '/api/:version/templates/licenses/:key', gitignorePath: '/api/:version/templates/gitignores/:key', gitlabCiYmlPath: '/api/:version/templates/gitlab_ci_ymls/:key', @@ -74,9 +75,14 @@ const Api = { }, newLabel(namespacePath, projectPath, data, callback) { - const url = Api.buildUrl(Api.labelsPath) - .replace(':namespace_path', namespacePath) - .replace(':project_path', projectPath); + let url; + if (projectPath) { + url = Api.buildUrl(Api.projectLabelsPath) + .replace(':namespace_path', namespacePath) + .replace(':project_path', projectPath); + } else { + url = Api.buildUrl(Api.groupLabelsPath).replace(':namespace_path', namespacePath); + } return $.ajax({ url, type: 'POST', diff --git a/app/assets/javascripts/boards/boards_bundle.js b/app/assets/javascripts/boards/boards_bundle.js index 89c14180149..ea00efe4b46 100644 --- a/app/assets/javascripts/boards/boards_bundle.js +++ b/app/assets/javascripts/boards/boards_bundle.js @@ -53,7 +53,8 @@ $(() => { data: { state: Store.state, loading: true, - endpoint: $boardApp.dataset.endpoint, + boardsEndpoint: $boardApp.dataset.boardsEndpoint, + listsEndpoint: $boardApp.dataset.listsEndpoint, boardId: $boardApp.dataset.boardId, disabled: $boardApp.dataset.disabled === 'true', issueLinkBase: $boardApp.dataset.issueLinkBase, @@ -68,7 +69,13 @@ $(() => { }, }, created () { - gl.boardService = new BoardService(this.endpoint, this.bulkUpdatePath, this.boardId); + gl.boardService = new BoardService({ + boardsEndpoint: this.boardsEndpoint, + listsEndpoint: this.listsEndpoint, + bulkUpdatePath: this.bulkUpdatePath, + boardId: this.boardId, + }); + Store.rootPath = this.boardsEndpoint; this.filterManager = new FilteredSearchBoards(Store.filter, true); this.filterManager.setup(); @@ -112,19 +119,21 @@ $(() => { gl.IssueBoardsSearch = new Vue({ el: document.getElementById('js-add-list'), data: { - filters: Store.state.filters + filters: Store.state.filters, }, mounted () { gl.issueBoards.newListDropdownInit(); - } + }, }); gl.IssueBoardsModalAddBtn = new Vue({ mixins: [gl.issueBoards.ModalMixins], el: document.getElementById('js-add-issues-btn'), - data: { - modal: ModalStore.store, - store: Store.state, + data() { + return { + modal: ModalStore.store, + store: Store.state, + }; }, watch: { disabled() { @@ -133,6 +142,9 @@ $(() => { }, computed: { disabled() { + if (!this.store) { + return true; + } return !this.store.lists.filter(list => !list.preset).length; }, tooltipTitle() { @@ -145,7 +157,7 @@ $(() => { }, methods: { updateTooltip() { - const $tooltip = $(this.$el); + const $tooltip = $(this.$refs.addIssuesButton); this.$nextTick(() => { if (this.disabled) { @@ -165,16 +177,19 @@ $(() => { this.updateTooltip(); }, template: ` - <button - class="btn btn-create pull-right prepend-left-10" - type="button" - data-placement="bottom" - :class="{ 'disabled': disabled }" - :title="tooltipTitle" - :aria-disabled="disabled" - @click="openModal"> - Add issues - </button> + <div class="board-extra-actions"> + <button + class="btn btn-create prepend-left-10" + type="button" + data-placement="bottom" + ref="addIssuesButton" + :class="{ 'disabled': disabled }" + :title="tooltipTitle" + :aria-disabled="disabled" + @click="openModal"> + Add issues + </button> + </div> `, }); }); diff --git a/app/assets/javascripts/boards/components/board_list.js b/app/assets/javascripts/boards/components/board_list.js index bebca17fb1e..6159680f1e6 100644 --- a/app/assets/javascripts/boards/components/board_list.js +++ b/app/assets/javascripts/boards/components/board_list.js @@ -77,7 +77,7 @@ export default { this.showIssueForm = !this.showIssueForm; }, onScroll() { - if ((this.scrollTop() > this.scrollHeight() - this.scrollOffset) && !this.list.loadingMore) { + if (!this.loadingMore && (this.scrollTop() > this.scrollHeight() - this.scrollOffset)) { this.loadNextPage(); } }, @@ -165,11 +165,9 @@ export default { v-if="loading"> <loading-icon /> </div> - <transition name="slide-down"> - <board-new-issue - :list="list" - v-if="list.type !== 'closed' && showIssueForm"/> - </transition> + <board-new-issue + :list="list" + v-if="list.type !== 'closed' && showIssueForm"/> <ul class="board-list" v-show="!loading" diff --git a/app/assets/javascripts/boards/components/board_new_issue.js b/app/assets/javascripts/boards/components/board_new_issue.js index 4af8b0c7713..541b8049855 100644 --- a/app/assets/javascripts/boards/components/board_new_issue.js +++ b/app/assets/javascripts/boards/components/board_new_issue.js @@ -6,7 +6,10 @@ const Store = gl.issueBoards.BoardsStore; export default { name: 'BoardNewIssue', props: { - list: Object, + list: { + type: Object, + required: true, + }, }, data() { return { diff --git a/app/assets/javascripts/boards/components/issue_card_inner.js b/app/assets/javascripts/boards/components/issue_card_inner.js index 9a5d87ede7e..26f0a41c0ca 100644 --- a/app/assets/javascripts/boards/components/issue_card_inner.js +++ b/app/assets/javascripts/boards/components/issue_card_inner.js @@ -67,7 +67,10 @@ gl.issueBoards.IssueCardInner = Vue.extend({ return `${this.issueLinkBase}/${this.issue.id}`; }, issueId() { - return `#${this.issue.id}`; + if (this.issue.iid) { + return `#${this.issue.iid}`; + } + return false; }, showLabelFooter() { return this.issue.labels.find(l => this.showLabel(l)) !== undefined; @@ -143,7 +146,7 @@ gl.issueBoards.IssueCardInner = Vue.extend({ :title="issue.title">{{ issue.title }}</a> <span class="card-number" - v-if="issue.id" + v-if="issueId" > {{ issueId }} </span> diff --git a/app/assets/javascripts/boards/components/modal/footer.js b/app/assets/javascripts/boards/components/modal/footer.js index 478a1335b2b..a656f0546c0 100644 --- a/app/assets/javascripts/boards/components/modal/footer.js +++ b/app/assets/javascripts/boards/components/modal/footer.js @@ -29,7 +29,7 @@ gl.issueBoards.ModalFooter = Vue.extend({ const firstListIndex = 1; const list = this.modal.selectedList || this.state.lists[firstListIndex]; const selectedIssues = ModalStore.getSelectedIssues(); - const issueIds = selectedIssues.map(issue => issue.globalId); + const issueIds = selectedIssues.map(issue => issue.id); // Post the data to the backend gl.boardService.bulkUpdate(issueIds, { diff --git a/app/assets/javascripts/boards/components/new_list_dropdown.js b/app/assets/javascripts/boards/components/new_list_dropdown.js index 72bb9e10fbc..d7f203b3f96 100644 --- a/app/assets/javascripts/boards/components/new_list_dropdown.js +++ b/app/assets/javascripts/boards/components/new_list_dropdown.js @@ -27,7 +27,7 @@ gl.issueBoards.newListDropdownInit = () => { $this.glDropdown({ data(term, callback) { - $.get($this.attr('data-labels')) + $.get($this.attr('data-list-labels-path')) .then((resp) => { callback(resp); }); diff --git a/app/assets/javascripts/boards/components/sidebar/remove_issue.js b/app/assets/javascripts/boards/components/sidebar/remove_issue.js index 6a900d4abd0..b44e87b051d 100644 --- a/app/assets/javascripts/boards/components/sidebar/remove_issue.js +++ b/app/assets/javascripts/boards/components/sidebar/remove_issue.js @@ -18,17 +18,32 @@ gl.issueBoards.RemoveIssueBtn = Vue.extend({ type: Object, required: true, }, + issueUpdate: { + type: String, + required: true, + }, + }, + computed: { + updateUrl() { + return this.issueUpdate; + }, }, methods: { removeIssue() { const issue = this.issue; const lists = issue.getLists(); - const labelIds = lists.map(list => list.label.id); + const listLabelIds = lists.map(list => list.label.id); + const labelIds = this.issue.labels + .map(label => label.id) + .filter(id => !listLabelIds.includes(id)); // Post the remove data - gl.boardService.bulkUpdate([issue.globalId], { - remove_label_ids: labelIds, - }).catch(() => { + const data = { + issue: { + label_ids: labelIds, + }, + }; + Vue.http.patch(this.updateUrl, data).catch(() => { new Flash('Failed to remove issue from board, please try again.', 'alert'); lists.forEach((list) => { diff --git a/app/assets/javascripts/boards/models/issue.js b/app/assets/javascripts/boards/models/issue.js index 6c2d8a3781b..407db176446 100644 --- a/app/assets/javascripts/boards/models/issue.js +++ b/app/assets/javascripts/boards/models/issue.js @@ -7,8 +7,8 @@ import Vue from 'vue'; class ListIssue { constructor (obj, defaultAvatar) { - this.globalId = obj.id; - this.id = obj.iid; + this.id = obj.id; + this.iid = obj.iid; this.title = obj.title; this.confidential = obj.confidential; this.dueDate = obj.due_date; diff --git a/app/assets/javascripts/boards/models/label.js b/app/assets/javascripts/boards/models/label.js index 9af88d167d6..98c1ec014c4 100644 --- a/app/assets/javascripts/boards/models/label.js +++ b/app/assets/javascripts/boards/models/label.js @@ -4,6 +4,7 @@ class ListLabel { constructor (obj) { this.id = obj.id; this.title = obj.title; + this.type = obj.type; this.color = obj.color; this.textColor = obj.text_color; this.description = obj.description; diff --git a/app/assets/javascripts/boards/models/list.js b/app/assets/javascripts/boards/models/list.js index 08f7c5ddcd2..787f5eae64d 100644 --- a/app/assets/javascripts/boards/models/list.js +++ b/app/assets/javascripts/boards/models/list.js @@ -110,11 +110,12 @@ class List { return gl.boardService.newIssue(this.id, issue) .then(resp => resp.json()) .then((data) => { - issue.id = data.iid; + issue.id = data.id; + issue.iid = data.iid; if (this.issuesSize > 1) { - const moveBeforeIid = this.issues[1].id; - gl.boardService.moveIssue(issue.id, null, null, null, moveBeforeIid); + const moveBeforeId = this.issues[1].id; + gl.boardService.moveIssue(issue.id, null, null, null, moveBeforeId); } }); } @@ -126,19 +127,19 @@ class List { } addIssue (issue, listFrom, newIndex) { - let moveBeforeIid = null; - let moveAfterIid = null; + let moveBeforeId = null; + let moveAfterId = null; if (!this.findIssue(issue.id)) { if (newIndex !== undefined) { this.issues.splice(newIndex, 0, issue); if (this.issues[newIndex - 1]) { - moveBeforeIid = this.issues[newIndex - 1].id; + moveBeforeId = this.issues[newIndex - 1].id; } if (this.issues[newIndex + 1]) { - moveAfterIid = this.issues[newIndex + 1].id; + moveAfterId = this.issues[newIndex + 1].id; } } else { this.issues.push(issue); @@ -151,30 +152,30 @@ class List { if (listFrom) { this.issuesSize += 1; - this.updateIssueLabel(issue, listFrom, moveBeforeIid, moveAfterIid); + this.updateIssueLabel(issue, listFrom, moveBeforeId, moveAfterId); } } } - moveIssue (issue, oldIndex, newIndex, moveBeforeIid, moveAfterIid) { + moveIssue (issue, oldIndex, newIndex, moveBeforeId, moveAfterId) { this.issues.splice(oldIndex, 1); this.issues.splice(newIndex, 0, issue); - gl.boardService.moveIssue(issue.id, null, null, moveBeforeIid, moveAfterIid) + gl.boardService.moveIssue(issue.id, null, null, moveBeforeId, moveAfterId) .catch(() => { // TODO: handle request error }); } - updateIssueLabel(issue, listFrom, moveBeforeIid, moveAfterIid) { - gl.boardService.moveIssue(issue.id, listFrom.id, this.id, moveBeforeIid, moveAfterIid) + updateIssueLabel(issue, listFrom, moveBeforeId, moveAfterId) { + gl.boardService.moveIssue(issue.id, listFrom.id, this.id, moveBeforeId, moveAfterId) .catch(() => { // TODO: handle request error }); } findIssue (id) { - return this.issues.filter(issue => issue.id === id)[0]; + return this.issues.find(issue => issue.id === id); } removeIssue (removeIssue) { diff --git a/spec/javascripts/api_spec.js b/spec/javascripts/api_spec.js index 2aa4fb1f6c6..72d1b8423ff 100644 --- a/spec/javascripts/api_spec.js +++ b/spec/javascripts/api_spec.js @@ -145,7 +145,7 @@ describe('Api', () => { }); }); - describe('newLabel', () => { + fdescribe('newLabel', () => { it('creates a new label', (done) => { const namespace = 'some namespace'; const project = 'some project'; @@ -167,6 +167,27 @@ describe('Api', () => { done(); }); }); + + it('creates a new group label', (done) => { + const namespace = 'some namespace'; + const labelData = { some: 'data' }; + const expectedUrl = `${dummyUrlRoot}/${namespace}/labels`; + const expectedData = { + label: labelData, + }; + spyOn(jQuery, 'ajax').and.callFake((request) => { + expect(request.url).toEqual(expectedUrl); + expect(request.dataType).toEqual('json'); + expect(request.type).toEqual('POST'); + expect(request.data).toEqual(expectedData); + return sendDummyResponse(); + }); + + Api.newLabel(namespace, null, labelData, (response) => { + expect(response).toBe(dummyResponse); + done(); + }); + }); }); describe('groupProjects', () => { |