From 8cf5e4882132c88b8e9ca055674478825a1f030b Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Mon, 16 Jan 2017 09:24:28 -0500 Subject: [PATCH 1/3] Issue boards markup in JS files --- .../javascripts/boards/boards_bundle.js.es6 | 8 +- .../boards/components/board.js.es6 | 41 ++++++-- .../components/board_blank_state.js.es6 | 31 ++++++ .../boards/components/board_card.js.es6 | 27 ++++- .../boards/components/board_delete.js.es6 | 11 +++ .../boards/components/board_header.js.es6 | 60 ++++++++++++ .../boards/components/board_list.js.es6 | 44 ++++++++- .../boards/components/board_new_issue.js.es6 | 39 ++++++++ .../boards/components/board_sidebar.js.es6 | 44 ++++++++- .../boards/components/sidebar/assignee.js.es6 | 98 +++++++++++++++++++ .../javascripts/boards/models/issue.js.es6 | 1 + .../javascripts/boards/models/user.js.es6 | 1 + .../bs_dropdown_menu.js.es6 | 73 ++++++++++++++ app/helpers/boards_helper.rb | 6 ++ app/views/projects/boards/_show.html.haml | 10 +- .../boards/components/_blank_state.html.haml | 15 --- .../boards/components/_board.html.haml | 35 ------- .../boards/components/_board_list.html.haml | 45 --------- .../boards/components/_card.html.haml | 10 -- .../boards/components/_sidebar.html.haml | 26 ----- .../components/sidebar/_assignee.html.haml | 40 -------- 21 files changed, 476 insertions(+), 189 deletions(-) create mode 100644 app/assets/javascripts/boards/components/board_header.js.es6 create mode 100644 app/assets/javascripts/boards/components/sidebar/assignee.js.es6 create mode 100644 app/assets/javascripts/vue_common_component/bs_dropdown_menu.js.es6 delete mode 100644 app/views/projects/boards/components/_blank_state.html.haml delete mode 100644 app/views/projects/boards/components/_board.html.haml delete mode 100644 app/views/projects/boards/components/_board_list.html.haml delete mode 100644 app/views/projects/boards/components/_card.html.haml delete mode 100644 app/views/projects/boards/components/_sidebar.html.haml delete mode 100644 app/views/projects/boards/components/sidebar/_assignee.html.haml diff --git a/app/assets/javascripts/boards/boards_bundle.js.es6 b/app/assets/javascripts/boards/boards_bundle.js.es6 index c345fb6ce14b..05cf70438e33 100644 --- a/app/assets/javascripts/boards/boards_bundle.js.es6 +++ b/app/assets/javascripts/boards/boards_bundle.js.es6 @@ -47,7 +47,13 @@ $(() => { issueLinkBase: $boardApp.dataset.issueLinkBase, rootPath: $boardApp.dataset.rootPath, bulkUpdatePath: $boardApp.dataset.bulkUpdatePath, - detailIssue: Store.detail + canCreateIssue: $boardApp.dataset.canCreateIssue === 'true', + canAdminIssue: $boardApp.dataset.canAdminIssue === 'true', + canAdminList: $boardApp.dataset.canAdminList === 'true', + currentUser: JSON.parse($boardApp.dataset.currentUser), + detailIssue: Store.detail, + closeIconHtml: $boardApp.dataset.closeIconHtml, + projectId: $boardApp.dataset.projectId, }, computed: { detailIssueVisible () { diff --git a/app/assets/javascripts/boards/components/board.js.es6 b/app/assets/javascripts/boards/components/board.js.es6 index 18324de18b3d..82ef7fa0f680 100644 --- a/app/assets/javascripts/boards/components/board.js.es6 +++ b/app/assets/javascripts/boards/components/board.js.es6 @@ -5,6 +5,7 @@ require('./board_blank_state'); require('./board_delete'); require('./board_list'); +require('./board_header'); (() => { const Store = gl.issueBoards.BoardsStore; @@ -13,17 +14,46 @@ require('./board_list'); window.gl.issueBoards = window.gl.issueBoards || {}; gl.issueBoards.Board = Vue.extend({ - template: '#js-board-template', + template: ` +
+
+ + + + + + +
+
+ `, components: { 'board-list': gl.issueBoards.BoardList, - 'board-delete': gl.issueBoards.BoardDelete, - 'board-blank-state': gl.issueBoards.BoardBlankState + 'board-blank-state': gl.issueBoards.BoardBlankState, + 'board-header': gl.issueBoards.BoardHeader, }, props: { list: Object, disabled: Boolean, issueLinkBase: String, rootPath: String, + canCreateIssue: Boolean, + canAdminIssue: Boolean, + canAdminList: Boolean, }, data () { return { @@ -74,11 +104,6 @@ require('./board_list'); deep: true } }, - methods: { - showNewIssueForm() { - this.$refs['board-list'].showIssueForm = !this.$refs['board-list'].showIssueForm; - } - }, mounted () { this.sortableOptions = gl.issueBoards.getBoardSortableDefaultOptions({ disabled: this.disabled, diff --git a/app/assets/javascripts/boards/components/board_blank_state.js.es6 b/app/assets/javascripts/boards/components/board_blank_state.js.es6 index d76314c1892b..f3dce8b1a82c 100644 --- a/app/assets/javascripts/boards/components/board_blank_state.js.es6 +++ b/app/assets/javascripts/boards/components/board_blank_state.js.es6 @@ -9,6 +9,37 @@ window.gl.issueBoards = window.gl.issueBoards || {}; gl.issueBoards.BoardBlankState = Vue.extend({ + template: ` +
+

+ Add the following default lists to your Issue Board with one click: +

+ +

+ Starting out with the default set of lists will get you right on the way to making the most of your board. +

+ + +
+ `, data () { return { predefinedLabels: [ diff --git a/app/assets/javascripts/boards/components/board_card.js.es6 b/app/assets/javascripts/boards/components/board_card.js.es6 index 0ea66bd027c7..da1df2fc0469 100644 --- a/app/assets/javascripts/boards/components/board_card.js.es6 +++ b/app/assets/javascripts/boards/components/board_card.js.es6 @@ -10,10 +10,26 @@ require('./issue_card_inner'); window.gl.issueBoards = window.gl.issueBoards || {}; gl.issueBoards.BoardCard = Vue.extend({ - template: '#js-board-list-card', components: { 'issue-card-inner': gl.issueBoards.IssueCardInner, }, + template: ` +
  • + + +
  • + `, props: { list: Object, issue: Object, @@ -31,6 +47,15 @@ require('./issue_card_inner'); computed: { issueDetailVisible () { return this.detailIssue.issue && this.detailIssue.issue.id === this.issue.id; + }, + userCanDrag() { + return !this.disabled && this.issue.id; + }, + isDisabled() { + return this.disabled || !this.issue.id; + }, + relativeUrl() { + return gon.relative_url_root; } }, methods: { diff --git a/app/assets/javascripts/boards/components/board_delete.js.es6 b/app/assets/javascripts/boards/components/board_delete.js.es6 index 861600424a59..a42361dab125 100644 --- a/app/assets/javascripts/boards/components/board_delete.js.es6 +++ b/app/assets/javascripts/boards/components/board_delete.js.es6 @@ -6,6 +6,17 @@ window.gl.issueBoards = window.gl.issueBoards || {}; gl.issueBoards.BoardDelete = Vue.extend({ + template: ` + + `, props: { list: Object }, diff --git a/app/assets/javascripts/boards/components/board_header.js.es6 b/app/assets/javascripts/boards/components/board_header.js.es6 new file mode 100644 index 000000000000..516e3cae1942 --- /dev/null +++ b/app/assets/javascripts/boards/components/board_header.js.es6 @@ -0,0 +1,60 @@ +(() => { + window.gl = window.gl || {}; + window.gl.issueBoards = window.gl.issueBoards || {}; + + gl.issueBoards.BoardHeader = Vue.extend({ + template: ` +
    +

    + + {{ list.title }} + +
    + + {{ list.issuesSize }} + + +
    + + +

    +
    + `, + components: { + 'board-delete': gl.issueBoards.BoardDelete, + }, + props: [ + 'disabled', 'list', 'canAdminList', 'canAdminIssue' + ], + methods: { + showNewIssueForm() { + this.$parent.$refs['board-list'].showIssueForm = !this.$parent.$refs['board-list'].showIssueForm; + } + }, + }); +})(); diff --git a/app/assets/javascripts/boards/components/board_list.js.es6 b/app/assets/javascripts/boards/components/board_list.js.es6 index 60b0a30af3f6..1e90bff6ed6a 100644 --- a/app/assets/javascripts/boards/components/board_list.js.es6 +++ b/app/assets/javascripts/boards/components/board_list.js.es6 @@ -12,7 +12,48 @@ require('./board_new_issue'); window.gl.issueBoards = window.gl.issueBoards || {}; gl.issueBoards.BoardList = Vue.extend({ - template: '#js-board-list-template', + template: ` +
    +
    + +
    + + + +
    + `, components: { 'board-card': gl.issueBoards.BoardCard, 'board-new-issue': gl.issueBoards.BoardNewIssue @@ -24,6 +65,7 @@ require('./board_new_issue'); loading: Boolean, issueLinkBase: String, rootPath: String, + canCreateIssue: Boolean, }, data () { return { diff --git a/app/assets/javascripts/boards/components/board_new_issue.js.es6 b/app/assets/javascripts/boards/components/board_new_issue.js.es6 index b5c14a198baf..2e1ae64dc814 100644 --- a/app/assets/javascripts/boards/components/board_new_issue.js.es6 +++ b/app/assets/javascripts/boards/components/board_new_issue.js.es6 @@ -8,6 +8,45 @@ window.gl = window.gl || {}; gl.issueBoards.BoardNewIssue = Vue.extend({ + template: ` +
    +
    +
    +
    + An error occured. Please try again. +
    +
    + + +
    + + +
    +
    +
    + `, props: { list: Object, }, diff --git a/app/assets/javascripts/boards/components/board_sidebar.js.es6 b/app/assets/javascripts/boards/components/board_sidebar.js.es6 index dfc6eed785cd..0d5cd2516831 100644 --- a/app/assets/javascripts/boards/components/board_sidebar.js.es6 +++ b/app/assets/javascripts/boards/components/board_sidebar.js.es6 @@ -6,6 +6,7 @@ /* global Sidebar */ require('./sidebar/remove_issue'); +require('./sidebar/assignee'); (() => { const Store = gl.issueBoards.BoardsStore; @@ -14,9 +15,48 @@ require('./sidebar/remove_issue'); window.gl.issueBoards = window.gl.issueBoards || {}; gl.issueBoards.BoardSidebar = Vue.extend({ - props: { - currentUser: Object + template: ` + + + + `, + components: { + 'boards-sidebar-assignee': gl.issueBoards.BoardsSidebarAssignee, }, + props: [ + 'currentUser', 'closeIconHtml', 'canAdminIssue', 'issueLinkBase', 'projectId', + ], data() { return { detail: Store.detail, diff --git a/app/assets/javascripts/boards/components/sidebar/assignee.js.es6 b/app/assets/javascripts/boards/components/sidebar/assignee.js.es6 new file mode 100644 index 000000000000..bdd0ad4dbb91 --- /dev/null +++ b/app/assets/javascripts/boards/components/sidebar/assignee.js.es6 @@ -0,0 +1,98 @@ +/*= require vue_common_component/bs_dropdown_menu */ +/* global Vue */ + +(() => { + window.gl = window.gl || {}; + window.gl.issueBoards = window.gl.issueBoards || {}; + + gl.issueBoards.BoardsSidebarAssignee = Vue.extend({ + template: ` +
    +
    + Assignee + + + Edit + +
    + +
    + + +
    +
    + `, + props: [ + 'currentUser', 'canAdminIssue', 'issue', 'issueLinkBase', 'projectId', + ], + computed: { + assigneeUrl() { + return `${gon.relative_url_root}/${this.issue.assignee.username}` + }, + currentUsername() { + return this.currentUser.username || false; + }, + }, + }); +})(); diff --git a/app/assets/javascripts/boards/models/issue.js.es6 b/app/assets/javascripts/boards/models/issue.js.es6 index 2d0a295ae4d2..2b41860da05b 100644 --- a/app/assets/javascripts/boards/models/issue.js.es6 +++ b/app/assets/javascripts/boards/models/issue.js.es6 @@ -8,6 +8,7 @@ class ListIssue { constructor (obj) { this.globalId = obj.id; this.id = obj.iid; + this.reference = `#${this.id}`; this.title = obj.title; this.confidential = obj.confidential; this.dueDate = obj.due_date; diff --git a/app/assets/javascripts/boards/models/user.js.es6 b/app/assets/javascripts/boards/models/user.js.es6 index 8e9de4d4cbb6..188b65ec101c 100644 --- a/app/assets/javascripts/boards/models/user.js.es6 +++ b/app/assets/javascripts/boards/models/user.js.es6 @@ -5,6 +5,7 @@ class ListUser { this.id = user.id; this.name = user.name; this.username = user.username; + this.reference = `@${this.username}`; this.avatar = user.avatar_url; } } diff --git a/app/assets/javascripts/vue_common_component/bs_dropdown_menu.js.es6 b/app/assets/javascripts/vue_common_component/bs_dropdown_menu.js.es6 new file mode 100644 index 000000000000..d6ba8862b859 --- /dev/null +++ b/app/assets/javascripts/vue_common_component/bs_dropdown_menu.js.es6 @@ -0,0 +1,73 @@ +(() => { + Vue.component('bs-dropdown-menu', { + props: { + classNames: { + type: String, + required: false, + default: '', + }, + title: { + type: String, + required: false, + default: '', + }, + filter: { + type: Boolean, + required: false, + default: false, + }, + filterPlaceholder: { + type: String, + required: false, + default: '', + }, + selectable: { + type: Boolean, + required: false, + default: false, + }, + }, + template: ` + + `, + computed: { + classNamesObject() { + const classNamesObject = { + 'dropdown-menu-selectable': this.selectable, + }; + const splitClassNames = this.classNames.split(' '); + + splitClassNames.forEach((className) => { + classNamesObject[className] = true; + }); + + return classNamesObject; + }, + }, + }) +})(); diff --git a/app/helpers/boards_helper.rb b/app/helpers/boards_helper.rb index f43827da446d..992c50626f98 100644 --- a/app/helpers/boards_helper.rb +++ b/app/helpers/boards_helper.rb @@ -9,6 +9,12 @@ def board_data issue_link_base: namespace_project_issues_path(@project.namespace, @project), root_path: root_path, bulk_update_path: bulk_update_namespace_project_issues_path(@project.namespace, @project), + can_create_issue: "#{can?(current_user, :create_issue, @project)}", + can_admin_issue: "#{can?(current_user, :admin_issue, @project)}", + can_admin_list: "#{can?(current_user, :admin_list, @project)}", + current_user: "#{current_user ? current_user.to_json(only: [:username, :id, :name], methods: [:avatar_url]) : {}}", + close_icon_html: custom_icon("icon_close", size: 15), + project_id: @project.id, } end end diff --git a/app/views/projects/boards/_show.html.haml b/app/views/projects/boards/_show.html.haml index 05fe504d1c9f..d94003192da4 100644 --- a/app/views/projects/boards/_show.html.haml +++ b/app/views/projects/boards/_show.html.haml @@ -6,10 +6,6 @@ = page_specific_javascript_bundle_tag('boards') = page_specific_javascript_bundle_tag('boards_test') if Rails.env.test? - %script#js-board-template{ type: "text/x-template" }= render "projects/boards/components/board" - %script#js-board-list-template{ type: "text/x-template" }= render "projects/boards/components/board_list" - %script#js-board-list-card{ type: "text/x-template" }= render "projects/boards/components/card" - = render "projects/issues/head" = render 'shared/issuable/filter', type: :boards @@ -26,7 +22,6 @@ ":issue-link-base" => "issueLinkBase", ":root-path" => "rootPath", ":key" => "_uid" } - = render "projects/boards/components/sidebar" %board-add-issues-modal{ "blank-state-image" => render('shared/empty_states/icons/issues.svg'), "new-issue-path" => new_namespace_project_issue_path(@project.namespace, @project), "milestone-path" => milestones_filter_dropdown_path, @@ -34,3 +29,8 @@ ":issue-link-base" => "issueLinkBase", ":root-path" => "rootPath", ":project-id" => @project.try(:id) } + %board-sidebar{ ":current-user" => "currentUser", + ":close-icon-html" => "closeIconHtml", + ":can-admin-issue" => "canAdminIssue", + ":issue-link-base" => "issueLinkBase", + ":project-id" => "projectId" } diff --git a/app/views/projects/boards/components/_blank_state.html.haml b/app/views/projects/boards/components/_blank_state.html.haml deleted file mode 100644 index 0af40ddf8fe7..000000000000 --- a/app/views/projects/boards/components/_blank_state.html.haml +++ /dev/null @@ -1,15 +0,0 @@ -%board-blank-state{ "inline-template" => true, - "v-if" => 'list.id == "blank"' } - .board-blank-state - %p - Add the following default lists to your Issue Board with one click: - %ul.board-blank-state-list - %li{ "v-for" => "label in predefinedLabels" } - %span.label-color{ ":style" => "{ backgroundColor: label.color } " } - {{ label.title }} - %p - Starting out with the default set of lists will get you right on the way to making the most of your board. - %button.btn.btn-create.btn-inverted.btn-block{ type: "button", "@click.stop" => "addDefaultLists" } - Add default lists - %button.btn.btn-default.btn-block{ type: "button", "@click.stop" => "clearBlankState" } - Nevermind, I'll use my own diff --git a/app/views/projects/boards/components/_board.html.haml b/app/views/projects/boards/components/_board.html.haml deleted file mode 100644 index 72bce4049de4..000000000000 --- a/app/views/projects/boards/components/_board.html.haml +++ /dev/null @@ -1,35 +0,0 @@ -.board{ ":class" => '{ "is-draggable": !list.preset }', - ":data-id" => "list.id" } - .board-inner - %header.board-header{ ":class" => '{ "has-border": list.label }', ":style" => "{ borderTopColor: (list.label ? list.label.color : null) }" } - %h3.board-title.js-board-handle{ ":class" => '{ "user-can-drag": (!disabled && !list.preset) }' } - %span.has-tooltip{ ":title" => '(list.label ? list.label.description : "")', - data: { container: "body", placement: "bottom" } } - {{ list.title }} - .board-issue-count-holder.pull-right.clearfix{ "v-if" => 'list.type !== "blank"' } - %span.board-issue-count.pull-left{ ":class" => '{ "has-btn": list.type !== "done" && !disabled }' } - {{ list.issuesSize }} - - if can?(current_user, :admin_issue, @project) - %button.btn.btn-small.btn-default.pull-right.has-tooltip{ type: "button", - "@click" => "showNewIssueForm", - "v-if" => 'list.type !== "done"', - "aria-label" => "Add an issue", - "title" => "Add an issue", - data: { placement: "top", container: "body" } } - = icon("plus") - - if can?(current_user, :admin_list, @project) - %board-delete{ "inline-template" => true, - ":list" => "list", - "v-if" => "!list.preset && list.id" } - %button.board-delete.has-tooltip.pull-right{ type: "button", title: "Delete list", "aria-label" => "Delete list", data: { placement: "bottom" }, "@click.stop" => "deleteBoard" } - = icon("trash") - %board-list{ "v-if" => 'list.type !== "blank"', - ":list" => "list", - ":issues" => "list.issues", - ":loading" => "list.loading", - ":disabled" => "disabled", - ":issue-link-base" => "issueLinkBase", - ":root-path" => "rootPath", - "ref" => "board-list" } - - if can?(current_user, :admin_list, @project) - = render "projects/boards/components/blank_state" diff --git a/app/views/projects/boards/components/_board_list.html.haml b/app/views/projects/boards/components/_board_list.html.haml deleted file mode 100644 index f413a5e94c14..000000000000 --- a/app/views/projects/boards/components/_board_list.html.haml +++ /dev/null @@ -1,45 +0,0 @@ -.board-list-component - .board-list-loading.text-center{ "v-if" => "loading" } - = icon("spinner spin") - - if can? current_user, :create_issue, @project - %board-new-issue{ "inline-template" => true, - ":list" => "list", - "v-if" => 'list.type !== "done" && showIssueForm' } - .card.board-new-issue-form - %form{ "@submit" => "submit($event)" } - .flash-container{ "v-if" => "error" } - .flash-alert - An error occured. Please try again. - %label.label-light{ ":for" => 'list.id + "-title"' } - Title - %input.form-control{ type: "text", - "v-model" => "title", - "ref" => "input", - ":id" => 'list.id + "-title"' } - .clearfix.prepend-top-10 - %button.btn.btn-success.pull-left{ type: "submit", - ":disabled" => 'title === ""', - "ref" => "submit-button" } - Submit issue - %button.btn.btn-default.pull-right{ type: "button", - "@click" => "cancel" } - Cancel - %ul.board-list{ "ref" => "list", - "v-show" => "!loading", - ":data-board" => "list.id", - ":class" => '{ "is-smaller": showIssueForm }' } - %board-card{ "v-for" => "(issue, index) in orderedIssues", - "ref" => "issue", - ":index" => "index", - ":list" => "list", - ":issue" => "issue", - ":issue-link-base" => "issueLinkBase", - ":root-path" => "rootPath", - ":disabled" => "disabled", - ":key" => "issue.id" } - %li.board-list-count.text-center{ "v-if" => "showCount" } - = icon("spinner spin", "v-show" => "list.loadingMore" ) - %span{ "v-if" => "list.issues.length === list.issuesSize" } - Showing all issues - %span{ "v-else" => true } - Showing {{ list.issues.length }} of {{ list.issuesSize }} issues diff --git a/app/views/projects/boards/components/_card.html.haml b/app/views/projects/boards/components/_card.html.haml deleted file mode 100644 index 891c2c462515..000000000000 --- a/app/views/projects/boards/components/_card.html.haml +++ /dev/null @@ -1,10 +0,0 @@ -%li.card{ ":class" => '{ "user-can-drag": !disabled && issue.id, "is-disabled": disabled || !issue.id, "is-active": issueDetailVisible }', - ":index" => "index", - ":data-issue-id" => "issue.id", - "@mousedown" => "mouseDown", - "@mousemove" => "mouseMove", - "@mouseup" => "showIssue($event)" } - %issue-card-inner{ ":list" => "list", - ":issue" => "issue", - ":issue-link-base" => "issueLinkBase", - ":root-path" => "rootPath" } diff --git a/app/views/projects/boards/components/_sidebar.html.haml b/app/views/projects/boards/components/_sidebar.html.haml deleted file mode 100644 index 24d76da6f063..000000000000 --- a/app/views/projects/boards/components/_sidebar.html.haml +++ /dev/null @@ -1,26 +0,0 @@ -%board-sidebar{ "inline-template" => true, - ":current-user" => "#{current_user ? current_user.to_json(only: [:username, :id, :name], methods: [:avatar_url]) : {}}" } - %transition{ name: "boards-sidebar-slide" } - %aside.right-sidebar.right-sidebar-expanded.issue-boards-sidebar{ "v-show" => "showSidebar" } - .issuable-sidebar - .block.issuable-sidebar-header - %span.issuable-header-text.hide-collapsed.pull-left - %strong - {{ issue.title }} - %br/ - %span - = precede "#" do - {{ issue.id }} - %a.gutter-toggle.pull-right{ role: "button", - href: "#", - "@click.prevent" => "closeSidebar", - "aria-label" => "Toggle sidebar" } - = custom_icon("icon_close", size: 15) - .js-issuable-update - = render "projects/boards/components/sidebar/assignee" - = render "projects/boards/components/sidebar/milestone" - = render "projects/boards/components/sidebar/due_date" - = render "projects/boards/components/sidebar/labels" - = render "projects/boards/components/sidebar/notifications" - %remove-btn{ ":issue" => "issue", - ":list" => "list" } diff --git a/app/views/projects/boards/components/sidebar/_assignee.html.haml b/app/views/projects/boards/components/sidebar/_assignee.html.haml deleted file mode 100644 index e75ce305440c..000000000000 --- a/app/views/projects/boards/components/sidebar/_assignee.html.haml +++ /dev/null @@ -1,40 +0,0 @@ -.block.assignee - .title.hide-collapsed - Assignee - - if can?(current_user, :admin_issue, @project) - = icon("spinner spin", class: "block-loading") - = link_to "Edit", "#", class: "edit-link pull-right" - .value.hide-collapsed - %span.assign-yourself.no-value{ "v-if" => "!issue.assignee" } - No assignee - - if can?(current_user, :admin_issue, @project) - \- - %a.js-assign-yourself{ href: "#" } - assign yourself - %a.author_link.bold{ ":href" => "'#{root_url}' + issue.assignee.username", - "v-if" => "issue.assignee" } - %img.avatar.avatar-inline.s32{ ":src" => "issue.assignee.avatar", - width: "32", alt: "Avatar" } - %span.author - {{ issue.assignee.name }} - %span.username - = precede "@" do - {{ issue.assignee.username }} - - if can?(current_user, :admin_issue, @project) - .selectbox.hide-collapsed - %input{ type: "hidden", - name: "issue[assignee_id]", - id: "issue_assignee_id", - ":value" => "issue.assignee.id", - "v-if" => "issue.assignee" } - .dropdown - %button.dropdown-menu-toggle.js-user-search.js-author-search.js-issue-board-sidebar{ type: "button", data: { toggle: "dropdown", field_name: "issue[assignee_id]", first_user: (current_user.username if current_user), current_user: "true", project_id: @project.id, null_user: "true" }, - ":data-issuable-id" => "issue.id", - ":data-issue-update" => "'#{namespace_project_issues_path(@project.namespace, @project)}/' + issue.id + '.json'" } - Select assignee - = icon("chevron-down") - .dropdown-menu.dropdown-menu-user.dropdown-menu-selectable.dropdown-menu-author - = dropdown_title("Assign to") - = dropdown_filter("Search users") - = dropdown_content - = dropdown_loading -- GitLab From 5c2eeb9a681bd538fcafee2522abbc156959b0e0 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Tue, 7 Feb 2017 09:28:18 +0000 Subject: [PATCH 2/3] Updated for webpack --- .../javascripts/boards/boards_bundle.js.es6 | 8 +- .../boards/components/board.js.es6 | 223 +++++++------- .../components/board_blank_state.js.es6 | 140 +++++---- .../boards/components/board_card.js.es6 | 139 +++++---- .../boards/components/board_delete.js.es6 | 50 ++- .../boards/components/board_header.js.es6 | 112 ++++--- .../boards/components/board_list.js.es6 | 284 +++++++++--------- .../boards/components/board_new_issue.js.es6 | 176 ++++++----- .../boards/components/board_sidebar.js.es6 | 193 ++++++------ .../boards/components/issue_card_inner.js.es6 | 198 ++++++------ .../boards/components/modal/list.js.es6 | 4 +- .../boards/components/sidebar/assignee.js.es6 | 2 + .../components/sidebar/remove_issue.js.es6 | 92 +++--- 13 files changed, 793 insertions(+), 828 deletions(-) diff --git a/app/assets/javascripts/boards/boards_bundle.js.es6 b/app/assets/javascripts/boards/boards_bundle.js.es6 index 05cf70438e33..b0821438910c 100644 --- a/app/assets/javascripts/boards/boards_bundle.js.es6 +++ b/app/assets/javascripts/boards/boards_bundle.js.es6 @@ -12,8 +12,8 @@ requireAll(require.context('./stores', true, /^\.\/.*\.(js|es6)$/)); requireAll(require.context('./services', true, /^\.\/.*\.(js|es6)$/)); requireAll(require.context('./mixins', true, /^\.\/.*\.(js|es6)$/)); requireAll(require.context('./filters', true, /^\.\/.*\.(js|es6)$/)); -require('./components/board'); -require('./components/board_sidebar'); +const board = require('./components/board'); +const boardSidebar = require('./components/board_sidebar'); require('./components/new_list_dropdown'); require('./components/modal/index'); require('../vue_shared/vue_resource_interceptor'); @@ -34,8 +34,8 @@ $(() => { gl.IssueBoardsApp = new Vue({ el: $boardApp, components: { - 'board': gl.issueBoards.Board, - 'board-sidebar': gl.issueBoards.BoardSidebar, + board, + boardSidebar, 'board-add-issues-modal': gl.issueBoards.IssuesModal, }, data: { diff --git a/app/assets/javascripts/boards/components/board.js.es6 b/app/assets/javascripts/boards/components/board.js.es6 index 82ef7fa0f680..4e847500b34a 100644 --- a/app/assets/javascripts/boards/components/board.js.es6 +++ b/app/assets/javascripts/boards/components/board.js.es6 @@ -2,129 +2,124 @@ /* global Vue */ /* global Sortable */ -require('./board_blank_state'); -require('./board_delete'); -require('./board_list'); -require('./board_header'); +const boardBlankState = require('./board_blank_state'); +const boardList = require('./board_list'); +const boardHeader = require('./board_header'); +const Store = gl.issueBoards.BoardsStore; -(() => { - const Store = gl.issueBoards.BoardsStore; - - window.gl = window.gl || {}; - window.gl.issueBoards = window.gl.issueBoards || {}; - - gl.issueBoards.Board = Vue.extend({ - template: ` -
    -
    - - - - - - -
    +module.exports = Vue.extend({ + name: 'board', + template: ` +
    +
    + + + + + +
    - `, - components: { - 'board-list': gl.issueBoards.BoardList, - 'board-blank-state': gl.issueBoards.BoardBlankState, - 'board-header': gl.issueBoards.BoardHeader, - }, - props: { - list: Object, - disabled: Boolean, - issueLinkBase: String, - rootPath: String, - canCreateIssue: Boolean, - canAdminIssue: Boolean, - canAdminList: Boolean, - }, - data () { - return { - detailIssue: Store.detail, - filters: Store.state.filters, - }; - }, - watch: { - filters: { - handler () { - this.list.page = 1; - this.list.getIssues(true); - }, - deep: true +
    + `, + components: { + boardList, + boardBlankState, + boardHeader, + }, + props: { + list: Object, + disabled: Boolean, + issueLinkBase: String, + rootPath: String, + canCreateIssue: Boolean, + canAdminIssue: Boolean, + canAdminList: Boolean, + }, + data () { + return { + detailIssue: Store.detail, + filters: Store.state.filters, + }; + }, + watch: { + filters: { + handler () { + this.list.page = 1; + this.list.getIssues(true); }, - detailIssue: { - handler () { - if (!Object.keys(this.detailIssue.issue).length) return; + deep: true + }, + detailIssue: { + handler () { + if (!Object.keys(this.detailIssue.issue).length) return; - const issue = this.list.findIssue(this.detailIssue.issue.id); + const issue = this.list.findIssue(this.detailIssue.issue.id); - if (issue) { - const offsetLeft = this.$el.offsetLeft; - const boardsList = document.querySelectorAll('.boards-list')[0]; - const left = boardsList.scrollLeft - offsetLeft; - let right = (offsetLeft + this.$el.offsetWidth); + if (issue) { + const offsetLeft = this.$el.offsetLeft; + const boardsList = document.querySelectorAll('.boards-list')[0]; + const left = boardsList.scrollLeft - offsetLeft; + let right = (offsetLeft + this.$el.offsetWidth); - if (window.innerWidth > 768 && boardsList.classList.contains('is-compact')) { - // -290 here because width of boardsList is animating so therefore - // getting the width here is incorrect - // 290 is the width of the sidebar - right -= (boardsList.offsetWidth - 290); - } else { - right -= boardsList.offsetWidth; - } + if (window.innerWidth > 768 && boardsList.classList.contains('is-compact')) { + // -290 here because width of boardsList is animating so therefore + // getting the width here is incorrect + // 290 is the width of the sidebar + right -= (boardsList.offsetWidth - 290); + } else { + right -= boardsList.offsetWidth; + } - if (right - boardsList.scrollLeft > 0) { - $(boardsList).animate({ - scrollLeft: right - }, this.sortableOptions.animation); - } else if (left > 0) { - $(boardsList).animate({ - scrollLeft: offsetLeft - }, this.sortableOptions.animation); - } + if (right - boardsList.scrollLeft > 0) { + $(boardsList).animate({ + scrollLeft: right + }, this.sortableOptions.animation); + } else if (left > 0) { + $(boardsList).animate({ + scrollLeft: offsetLeft + }, this.sortableOptions.animation); } - }, - deep: true - } - }, - mounted () { - this.sortableOptions = gl.issueBoards.getBoardSortableDefaultOptions({ - disabled: this.disabled, - group: 'boards', - draggable: '.is-draggable', - handle: '.js-board-handle', - onEnd: (e) => { - gl.issueBoards.onEnd(); + } + }, + deep: true + } + }, + mounted () { + this.sortableOptions = gl.issueBoards.getBoardSortableDefaultOptions({ + disabled: this.disabled, + group: 'boards', + draggable: '.is-draggable', + handle: '.js-board-handle', + onEnd: (e) => { + gl.issueBoards.onEnd(); - if (e.newIndex !== undefined && e.oldIndex !== e.newIndex) { - const order = this.sortable.toArray(); - const list = Store.findList('id', parseInt(e.item.dataset.id, 10)); + if (e.newIndex !== undefined && e.oldIndex !== e.newIndex) { + const order = this.sortable.toArray(); + const list = Store.findList('id', parseInt(e.item.dataset.id, 10)); - this.$nextTick(() => { - Store.moveList(list, order); - }); - } + this.$nextTick(() => { + Store.moveList(list, order); + }); } - }); + } + }); - this.sortable = Sortable.create(this.$el.parentNode, this.sortableOptions); - }, - }); -})(); + this.sortable = Sortable.create(this.$el.parentNode, this.sortableOptions); + }, +}); diff --git a/app/assets/javascripts/boards/components/board_blank_state.js.es6 b/app/assets/javascripts/boards/components/board_blank_state.js.es6 index f3dce8b1a82c..ec2858afde6b 100644 --- a/app/assets/javascripts/boards/components/board_blank_state.js.es6 +++ b/app/assets/javascripts/boards/components/board_blank_state.js.es6 @@ -2,83 +2,79 @@ /* global Vue */ /* global ListLabel */ -(() => { - const Store = gl.issueBoards.BoardsStore; +const Store = gl.issueBoards.BoardsStore; - window.gl = window.gl || {}; - window.gl.issueBoards = window.gl.issueBoards || {}; +module.exports = Vue.extend({ + name: 'board-blank-state', + template: ` +
    +

    + Add the following default lists to your Issue Board with one click: +

    +
      +
    • + + + {{ label.title }} +
    • +
    +

    + Starting out with the default set of lists will get you right on the way to making the most of your board. +

    + + +
    + `, + data () { + return { + predefinedLabels: [ + new ListLabel({ title: 'To Do', color: '#F0AD4E' }), + new ListLabel({ title: 'Doing', color: '#5CB85C' }) + ] + }; + }, + methods: { + addDefaultLists () { + this.clearBlankState(); - gl.issueBoards.BoardBlankState = Vue.extend({ - template: ` -
    -

    - Add the following default lists to your Issue Board with one click: -

    -
      -
    • - - - {{ label.title }} -
    • -
    -

    - Starting out with the default set of lists will get you right on the way to making the most of your board. -

    - - -
    - `, - data () { - return { - predefinedLabels: [ - new ListLabel({ title: 'To Do', color: '#F0AD4E' }), - new ListLabel({ title: 'Doing', color: '#5CB85C' }) - ] - }; - }, - methods: { - addDefaultLists () { - this.clearBlankState(); - - this.predefinedLabels.forEach((label, i) => { - Store.addList({ + this.predefinedLabels.forEach((label, i) => { + Store.addList({ + title: label.title, + position: i, + list_type: 'label', + label: { title: label.title, - position: i, - list_type: 'label', - label: { - title: label.title, - color: label.color - } - }); + color: label.color + } }); + }); - Store.state.lists = _.sortBy(Store.state.lists, 'position'); + Store.state.lists = _.sortBy(Store.state.lists, 'position'); - // Save the labels - gl.boardService.generateDefaultLists() - .then((resp) => { - resp.json().forEach((listObj) => { - const list = Store.findList('title', listObj.title); + // Save the labels + gl.boardService.generateDefaultLists() + .then((resp) => { + resp.json().forEach((listObj) => { + const list = Store.findList('title', listObj.title); - list.id = listObj.id; - list.label.id = listObj.label.id; - list.getIssues(); - }); + list.id = listObj.id; + list.label.id = listObj.label.id; + list.getIssues(); }); - }, - clearBlankState: Store.removeBlankState.bind(Store) - } - }); -})(); + }); + }, + clearBlankState: Store.removeBlankState.bind(Store) + } +}); diff --git a/app/assets/javascripts/boards/components/board_card.js.es6 b/app/assets/javascripts/boards/components/board_card.js.es6 index da1df2fc0469..0fa00a5d0b35 100644 --- a/app/assets/javascripts/boards/components/board_card.js.es6 +++ b/app/assets/javascripts/boards/components/board_card.js.es6 @@ -1,86 +1,81 @@ /* eslint-disable comma-dangle, space-before-function-paren, dot-notation */ /* global Vue */ -require('./issue_card_inner'); +const issueCardInner = require('./issue_card_inner'); +const Store = gl.issueBoards.BoardsStore; -(() => { - const Store = gl.issueBoards.BoardsStore; - - window.gl = window.gl || {}; - window.gl.issueBoards = window.gl.issueBoards || {}; - - gl.issueBoards.BoardCard = Vue.extend({ - components: { - 'issue-card-inner': gl.issueBoards.IssueCardInner, +module.exports = Vue.extend({ + name: 'board-card', + components: { + issueCardInner, + }, + template: ` +
  • + + +
  • + `, + props: { + list: Object, + issue: Object, + issueLinkBase: String, + disabled: Boolean, + index: Number, + rootPath: String, + }, + data () { + return { + showDetail: false, + detailIssue: Store.detail + }; + }, + computed: { + issueDetailVisible () { + return this.detailIssue.issue && this.detailIssue.issue.id === this.issue.id; }, - template: ` -
  • - - -
  • - `, - props: { - list: Object, - issue: Object, - issueLinkBase: String, - disabled: Boolean, - index: Number, - rootPath: String, + userCanDrag() { + return !this.disabled && this.issue.id; }, - data () { - return { - showDetail: false, - detailIssue: Store.detail - }; + isDisabled() { + return this.disabled || !this.issue.id; }, - computed: { - issueDetailVisible () { - return this.detailIssue.issue && this.detailIssue.issue.id === this.issue.id; - }, - userCanDrag() { - return !this.disabled && this.issue.id; - }, - isDisabled() { - return this.disabled || !this.issue.id; - }, - relativeUrl() { - return gon.relative_url_root; - } + relativeUrl() { + return gon.relative_url_root; + } + }, + methods: { + mouseDown () { + this.showDetail = true; }, - methods: { - mouseDown () { - this.showDetail = true; - }, - mouseMove() { - this.showDetail = false; - }, - showIssue (e) { - const targetTagName = e.target.tagName.toLowerCase(); + mouseMove() { + this.showDetail = false; + }, + showIssue (e) { + const targetTagName = e.target.tagName.toLowerCase(); - if (targetTagName === 'a' || targetTagName === 'button') return; + if (targetTagName === 'a' || targetTagName === 'button') return; - if (this.showDetail) { - this.showDetail = false; + if (this.showDetail) { + this.showDetail = false; - if (Store.detail.issue && Store.detail.issue.id === this.issue.id) { - Store.detail.issue = {}; - } else { - Store.detail.issue = this.issue; - Store.detail.list = this.list; - } + if (Store.detail.issue && Store.detail.issue.id === this.issue.id) { + Store.detail.issue = {}; + } else { + Store.detail.issue = this.issue; + Store.detail.list = this.list; } } } - }); -})(); + } +}); diff --git a/app/assets/javascripts/boards/components/board_delete.js.es6 b/app/assets/javascripts/boards/components/board_delete.js.es6 index a42361dab125..3d9401d51f0d 100644 --- a/app/assets/javascripts/boards/components/board_delete.js.es6 +++ b/app/assets/javascripts/boards/components/board_delete.js.es6 @@ -1,33 +1,29 @@ /* eslint-disable comma-dangle, space-before-function-paren, no-alert */ /* global Vue */ -(() => { - window.gl = window.gl || {}; - window.gl.issueBoards = window.gl.issueBoards || {}; +module.exports = Vue.extend({ + name: 'board-delete', + template: ` + + `, + props: { + list: Object + }, + methods: { + deleteBoard () { + $(this.$el).tooltip('hide'); - gl.issueBoards.BoardDelete = Vue.extend({ - template: ` - - `, - props: { - list: Object - }, - methods: { - deleteBoard () { - $(this.$el).tooltip('hide'); - - if (confirm('Are you sure you want to delete this list?')) { - this.list.destroy(); - } + if (confirm('Are you sure you want to delete this list?')) { + this.list.destroy(); } } - }); -})(); + } +}); diff --git a/app/assets/javascripts/boards/components/board_header.js.es6 b/app/assets/javascripts/boards/components/board_header.js.es6 index 516e3cae1942..944c59133f1d 100644 --- a/app/assets/javascripts/boards/components/board_header.js.es6 +++ b/app/assets/javascripts/boards/components/board_header.js.es6 @@ -1,60 +1,58 @@ -(() => { - window.gl = window.gl || {}; - window.gl.issueBoards = window.gl.issueBoards || {}; +const boardDelete = require('./board_delete'); - gl.issueBoards.BoardHeader = Vue.extend({ - template: ` -
    -

    +module.exports = Vue.extend({ + name: 'board-header', + template: ` +
    +

    + + {{ list.title }} + +
    - {{ list.title }} + class="board-issue-count pull-left" + :class="{ 'has-btn': list.type !== 'done' && !disabled }"> + {{ list.issuesSize }} -
    - - {{ list.issuesSize }} - - -
    - - -

    -
    - `, - components: { - 'board-delete': gl.issueBoards.BoardDelete, - }, - props: [ - 'disabled', 'list', 'canAdminList', 'canAdminIssue' - ], - methods: { - showNewIssueForm() { - this.$parent.$refs['board-list'].showIssueForm = !this.$parent.$refs['board-list'].showIssueForm; - } - }, - }); -})(); + +

    + + + + + `, + components: { + boardDelete, + }, + props: [ + 'disabled', 'list', 'canAdminList', 'canAdminIssue' + ], + methods: { + showNewIssueForm() { + this.$parent.$refs['board-list'].showIssueForm = !this.$parent.$refs['board-list'].showIssueForm; + } + }, +}); diff --git a/app/assets/javascripts/boards/components/board_list.js.es6 b/app/assets/javascripts/boards/components/board_list.js.es6 index 1e90bff6ed6a..a4df4ad14922 100644 --- a/app/assets/javascripts/boards/components/board_list.js.es6 +++ b/app/assets/javascripts/boards/components/board_list.js.es6 @@ -2,161 +2,157 @@ /* global Vue */ /* global Sortable */ -require('./board_card'); -require('./board_new_issue'); +const boardCard = require('./board_card'); +const boardNewIssue = require('./board_new_issue'); +const Store = gl.issueBoards.BoardsStore; -(() => { - const Store = gl.issueBoards.BoardsStore; - - window.gl = window.gl || {}; - window.gl.issueBoards = window.gl.issueBoards || {}; - - gl.issueBoards.BoardList = Vue.extend({ - template: ` -
    -
    - -
    - - -
      - - -
    • - - - Showing all issues - - - Showing {{ list.issues.length }} of {{ list.issuesSize }} issues - -
    +module.exports = Vue.extend({ + name: 'board-list', + template: ` +
    +
    +
    - `, - components: { - 'board-card': gl.issueBoards.BoardCard, - 'board-new-issue': gl.issueBoards.BoardNewIssue + + +
      + + +
    • + + + Showing all issues + + + Showing {{ list.issues.length }} of {{ list.issuesSize }} issues + +
    +
    + `, + components: { + boardCard, + boardNewIssue, + }, + props: { + disabled: Boolean, + list: Object, + issues: Array, + loading: Boolean, + issueLinkBase: String, + rootPath: String, + canCreateIssue: Boolean, + }, + data () { + return { + scrollOffset: 250, + filters: Store.state.filters, + showCount: false, + showIssueForm: false + }; + }, + watch: { + filters: { + handler () { + this.list.loadingMore = false; + this.$refs.list.scrollTop = 0; + }, + deep: true }, - props: { - disabled: Boolean, - list: Object, - issues: Array, - loading: Boolean, - issueLinkBase: String, - rootPath: String, - canCreateIssue: Boolean, + issues () { + this.$nextTick(() => { + if (this.scrollHeight() <= this.listHeight() && this.list.issuesSize > this.list.issues.length) { + this.list.page += 1; + this.list.getIssues(false); + } + + if (this.scrollHeight() > this.listHeight()) { + this.showCount = true; + } else { + this.showCount = false; + } + }); + } + }, + computed: { + orderedIssues () { + return _.sortBy(this.issues, 'priority'); }, - data () { - return { - scrollOffset: 250, - filters: Store.state.filters, - showCount: false, - showIssueForm: false - }; + }, + methods: { + listHeight () { + return this.$refs.list.getBoundingClientRect().height; }, - watch: { - filters: { - handler () { - this.list.loadingMore = false; - this.$refs.list.scrollTop = 0; - }, - deep: true - }, - issues () { - this.$nextTick(() => { - if (this.scrollHeight() <= this.listHeight() && this.list.issuesSize > this.list.issues.length) { - this.list.page += 1; - this.list.getIssues(false); - } - - if (this.scrollHeight() > this.listHeight()) { - this.showCount = true; - } else { - this.showCount = false; - } - }); - } + scrollHeight () { + return this.$refs.list.scrollHeight; }, - computed: { - orderedIssues () { - return _.sortBy(this.issues, 'priority'); - }, + scrollTop () { + return this.$refs.list.scrollTop + this.listHeight(); }, - methods: { - listHeight () { - return this.$refs.list.getBoundingClientRect().height; - }, - scrollHeight () { - return this.$refs.list.scrollHeight; - }, - scrollTop () { - return this.$refs.list.scrollTop + this.listHeight(); - }, - loadNextPage () { - const getIssues = this.list.nextPage(); + loadNextPage () { + const getIssues = this.list.nextPage(); - if (getIssues) { - this.list.loadingMore = true; - getIssues.then(() => { - this.list.loadingMore = false; - }); - } - }, + if (getIssues) { + this.list.loadingMore = true; + getIssues.then(() => { + this.list.loadingMore = false; + }); + } }, - mounted () { - const options = gl.issueBoards.getBoardSortableDefaultOptions({ - scroll: document.querySelectorAll('.boards-list')[0], - group: 'issues', - sort: false, - disabled: this.disabled, - filter: '.board-list-count, .is-disabled', - onStart: (e) => { - const card = this.$refs.issue[e.oldIndex]; + }, + mounted () { + const options = gl.issueBoards.getBoardSortableDefaultOptions({ + scroll: document.querySelectorAll('.boards-list')[0], + group: 'issues', + sort: false, + disabled: this.disabled, + filter: '.board-list-count, .is-disabled', + onStart: (e) => { + const card = this.$refs.issue[e.oldIndex]; - card.showDetail = false; - Store.moving.list = card.list; - Store.moving.issue = Store.moving.list.findIssue(+e.item.dataset.issueId); + card.showDetail = false; + Store.moving.list = card.list; + Store.moving.issue = Store.moving.list.findIssue(+e.item.dataset.issueId); - gl.issueBoards.onStart(); - }, - onAdd: (e) => { - gl.issueBoards.BoardsStore.moveIssueToList(Store.moving.list, this.list, Store.moving.issue, e.newIndex); + gl.issueBoards.onStart(); + }, + onAdd: (e) => { + gl.issueBoards.BoardsStore.moveIssueToList(Store.moving.list, this.list, Store.moving.issue, e.newIndex); - this.$nextTick(() => { - e.item.remove(); - }); - }, - }); + this.$nextTick(() => { + e.item.remove(); + }); + }, + }); - this.sortable = Sortable.create(this.$refs.list, options); + this.sortable = Sortable.create(this.$refs.list, options); - // Scroll event on list to load more - this.$refs.list.onscroll = () => { - if ((this.scrollTop() > this.scrollHeight() - this.scrollOffset) && !this.list.loadingMore) { - this.loadNextPage(); - } - }; - } - }); -})(); + // Scroll event on list to load more + this.$refs.list.onscroll = () => { + if ((this.scrollTop() > this.scrollHeight() - this.scrollOffset) && !this.list.loadingMore) { + this.loadNextPage(); + } + }; + } +}); diff --git a/app/assets/javascripts/boards/components/board_new_issue.js.es6 b/app/assets/javascripts/boards/components/board_new_issue.js.es6 index 2e1ae64dc814..fded23da5a08 100644 --- a/app/assets/javascripts/boards/components/board_new_issue.js.es6 +++ b/app/assets/javascripts/boards/components/board_new_issue.js.es6 @@ -1,103 +1,99 @@ /* eslint-disable comma-dangle, no-unused-vars */ /* global Vue */ /* global ListIssue */ +const Store = gl.issueBoards.BoardsStore; -(() => { - const Store = gl.issueBoards.BoardsStore; - - window.gl = window.gl || {}; - - gl.issueBoards.BoardNewIssue = Vue.extend({ - template: ` -
    -
    -
    -
    - An error occured. Please try again. -
    +module.exports = Vue.extend({ + name: 'board-new-issue', + template: ` +
    + +
    +
    + An error occured. Please try again.
    - - -
    - - -
    - -
    - `, - props: { - list: Object, - }, - data() { - return { - title: '', - error: false - }; - }, - methods: { - submit(e) { - e.preventDefault(); - if (this.title.trim() === '') return; +
    + + +
    + + +
    + +
    + `, + props: { + list: Object, + }, + data() { + return { + title: '', + error: false + }; + }, + methods: { + submit(e) { + e.preventDefault(); + if (this.title.trim() === '') return; - this.error = false; + this.error = false; - const labels = this.list.label ? [this.list.label] : []; - const issue = new ListIssue({ - title: this.title, - labels, - subscribed: true - }); + const labels = this.list.label ? [this.list.label] : []; + const issue = new ListIssue({ + title: this.title, + labels, + subscribed: true + }); - this.list.newIssue(issue) - .then((data) => { - // Need this because our jQuery very kindly disables buttons on ALL form submissions - $(this.$refs.submitButton).enable(); + this.list.newIssue(issue) + .then((data) => { + // Need this because our jQuery very kindly disables buttons on ALL form submissions + $(this.$refs.submitButton).enable(); - Store.detail.issue = issue; - Store.detail.list = this.list; - }) - .catch(() => { - // Need this because our jQuery very kindly disables buttons on ALL form submissions - $(this.$refs.submitButton).enable(); + Store.detail.issue = issue; + Store.detail.list = this.list; + }) + .catch(() => { + // Need this because our jQuery very kindly disables buttons on ALL form submissions + $(this.$refs.submitButton).enable(); - // Remove the issue - this.list.removeIssue(issue); + // Remove the issue + this.list.removeIssue(issue); - // Show error message - this.error = true; - }); + // Show error message + this.error = true; + }); - this.cancel(); - }, - cancel() { - this.title = ''; - this.$parent.showIssueForm = false; - } - }, - mounted() { - this.$refs.input.focus(); + this.cancel(); }, - }); -})(); + cancel() { + this.title = ''; + this.$parent.showIssueForm = false; + } + }, + mounted() { + this.$refs.input.focus(); + }, +}); diff --git a/app/assets/javascripts/boards/components/board_sidebar.js.es6 b/app/assets/javascripts/boards/components/board_sidebar.js.es6 index 0d5cd2516831..c52ff454eb2a 100644 --- a/app/assets/javascripts/boards/components/board_sidebar.js.es6 +++ b/app/assets/javascripts/boards/components/board_sidebar.js.es6 @@ -5,108 +5,105 @@ /* global LabelsSelect */ /* global Sidebar */ -require('./sidebar/remove_issue'); +const removeBtn = require('./sidebar/remove_issue'); require('./sidebar/assignee'); +const Store = gl.issueBoards.BoardsStore; -(() => { - const Store = gl.issueBoards.BoardsStore; - - window.gl = window.gl || {}; - window.gl.issueBoards = window.gl.issueBoards || {}; - - gl.issueBoards.BoardSidebar = Vue.extend({ - template: ` - - + + `, + components: { + removeBtn, + 'boards-sidebar-assignee': gl.issueBoards.BoardsSidebarAssignee, + }, + props: [ + 'currentUser', 'closeIconHtml', 'canAdminIssue', 'issueLinkBase', 'projectId', + ], + data() { + return { + detail: Store.detail, + issue: {}, + list: {}, + }; + }, + computed: { + showSidebar () { + return Object.keys(this.issue).length; + } + }, + watch: { + detail: { + handler () { + if (this.issue.id !== this.detail.issue.id) { + $('.js-issue-board-sidebar', this.$el).each((i, el) => { + $(el).data('glDropdown').clearMenu(); }); } - } + + this.issue = this.detail.issue; + this.list = this.detail.list; + }, + deep: true }, - methods: { - closeSidebar () { - this.detail.issue = {}; + issue () { + if (this.showSidebar) { + this.$nextTick(() => { + $('.right-sidebar').getNiceScroll(0).doScrollTop(0, 0); + $('.right-sidebar').getNiceScroll().resize(); + }); } - }, - mounted () { - new IssuableContext(this.currentUser); - new MilestoneSelect(); - new gl.DueDateSelectors(); - new LabelsSelect(); - new Sidebar(); - gl.Subscription.bindAll('.subscription'); - }, - components: { - removeBtn: gl.issueBoards.RemoveIssueBtn, - }, - }); -})(); + } + }, + methods: { + closeSidebar () { + this.detail.issue = {}; + } + }, + mounted () { + new IssuableContext(this.currentUser); + new MilestoneSelect(); + new gl.DueDateSelectors(); + new LabelsSelect(); + new Sidebar(); + gl.Subscription.bindAll('.subscription'); + }, +}); diff --git a/app/assets/javascripts/boards/components/issue_card_inner.js.es6 b/app/assets/javascripts/boards/components/issue_card_inner.js.es6 index 22a8b971ff8d..2eeeed8edca8 100644 --- a/app/assets/javascripts/boards/components/issue_card_inner.js.es6 +++ b/app/assets/javascripts/boards/components/issue_card_inner.js.es6 @@ -1,111 +1,107 @@ /* global Vue */ -(() => { - const Store = gl.issueBoards.BoardsStore; +const Store = gl.issueBoards.BoardsStore; - window.gl = window.gl || {}; - window.gl.issueBoards = window.gl.issueBoards || {}; - - gl.issueBoards.IssueCardInner = Vue.extend({ - props: { - issue: { - type: Object, - required: true, - }, - issueLinkBase: { - type: String, - required: true, - }, - list: { - type: Object, - required: false, - }, - rootPath: { - type: String, - required: true, - }, +module.exports = Vue.extend({ + name: 'issue-card-inner', + props: { + issue: { + type: Object, + required: true, + }, + issueLinkBase: { + type: String, + required: true, + }, + list: { + type: Object, + required: false, }, - methods: { - showLabel(label) { - if (!this.list) return true; + rootPath: { + type: String, + required: true, + }, + }, + methods: { + showLabel(label) { + if (!this.list) return true; - return !this.list.label || label.id !== this.list.label.id; - }, - filterByLabel(label, e) { - let labelToggleText = label.title; - const labelIndex = Store.state.filters.label_name.indexOf(label.title); - $(e.currentTarget).tooltip('hide'); + return !this.list.label || label.id !== this.list.label.id; + }, + filterByLabel(label, e) { + let labelToggleText = label.title; + const labelIndex = Store.state.filters.label_name.indexOf(label.title); + $(e.currentTarget).tooltip('hide'); - if (labelIndex === -1) { - Store.state.filters.label_name.push(label.title); - $('.labels-filter').prepend(``); - } else { - Store.state.filters.label_name.splice(labelIndex, 1); - labelToggleText = Store.state.filters.label_name[0]; - $(`.labels-filter input[name="label_name[]"][value="${label.title}"]`).remove(); - } + if (labelIndex === -1) { + Store.state.filters.label_name.push(label.title); + $('.labels-filter').prepend(``); + } else { + Store.state.filters.label_name.splice(labelIndex, 1); + labelToggleText = Store.state.filters.label_name[0]; + $(`.labels-filter input[name="label_name[]"][value="${label.title}"]`).remove(); + } - const selectedLabels = Store.state.filters.label_name; - if (selectedLabels.length === 0) { - labelToggleText = 'Label'; - } else if (selectedLabels.length > 1) { - labelToggleText = `${selectedLabels[0]} + ${selectedLabels.length - 1} more`; - } + const selectedLabels = Store.state.filters.label_name; + if (selectedLabels.length === 0) { + labelToggleText = 'Label'; + } else if (selectedLabels.length > 1) { + labelToggleText = `${selectedLabels[0]} + ${selectedLabels.length - 1} more`; + } - $('.labels-filter .dropdown-toggle-text').text(labelToggleText); + $('.labels-filter .dropdown-toggle-text').text(labelToggleText); - Store.updateFiltersUrl(); - }, - labelStyle(label) { - return { - backgroundColor: label.color, - color: label.textColor, - }; - }, + Store.updateFiltersUrl(); + }, + labelStyle(label) { + return { + backgroundColor: label.color, + color: label.textColor, + }; }, - template: ` -
    -

    - - - {{ issue.title }} - -

    - + }, + template: ` +
    +

    + + + {{ issue.title }} + +

    + - `, - }); -})(); +
    + `, +}); diff --git a/app/assets/javascripts/boards/components/modal/list.js.es6 b/app/assets/javascripts/boards/components/modal/list.js.es6 index 3730c1ecaeb2..60ac25f371a1 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 bp */ +const issueCardInner = require('../issue_card_inner'); + (() => { const ModalStore = gl.issueBoards.ModalStore; @@ -108,7 +110,7 @@ window.removeEventListener('resize', this.setColumnCountWrapper); }, components: { - 'issue-card-inner': gl.issueBoards.IssueCardInner, + issueCardInner, }, template: `
    { window.gl = window.gl || {}; window.gl.issueBoards = window.gl.issueBoards || {}; diff --git a/app/assets/javascripts/boards/components/sidebar/remove_issue.js.es6 b/app/assets/javascripts/boards/components/sidebar/remove_issue.js.es6 index e74935e1cb0a..38b89b2b7da6 100644 --- a/app/assets/javascripts/boards/components/sidebar/remove_issue.js.es6 +++ b/app/assets/javascripts/boards/components/sidebar/remove_issue.js.es6 @@ -1,59 +1,55 @@ /* eslint-disable no-new */ /* global Vue */ /* global Flash */ -(() => { - const Store = gl.issueBoards.BoardsStore; +const Store = gl.issueBoards.BoardsStore; - window.gl = window.gl || {}; - window.gl.issueBoards = window.gl.issueBoards || {}; - - gl.issueBoards.RemoveIssueBtn = Vue.extend({ - props: { - issue: { - type: Object, - required: true, - }, - list: { - type: Object, - required: true, - }, +module.exports = Vue.extend({ + name: 'remove-issue', + props: { + issue: { + type: Object, + required: true, + }, + list: { + type: Object, + required: true, }, - methods: { - removeIssue() { - const issue = this.issue; - const lists = issue.getLists(); - const labelIds = lists.map(list => list.label.id); + }, + methods: { + removeIssue() { + const issue = this.issue; + const lists = issue.getLists(); + const labelIds = lists.map(list => list.label.id); - // Post the remove data - gl.boardService.bulkUpdate([issue.globalId], { - remove_label_ids: labelIds, - }).catch(() => { - new Flash('Failed to remove issue from board, please try again.', 'alert'); + // Post the remove data + gl.boardService.bulkUpdate([issue.globalId], { + remove_label_ids: labelIds, + }).catch(() => { + new Flash('Failed to remove issue from board, please try again.', 'alert'); - lists.forEach((list) => { - list.addIssue(issue); - }); - }); - - // Remove from the frontend store lists.forEach((list) => { - list.removeIssue(issue); + list.addIssue(issue); }); + }); + + // Remove from the frontend store + lists.forEach((list) => { + list.removeIssue(issue); + }); - Store.detail.issue = {}; - }, + Store.detail.issue = {}; }, - template: ` -
    - -
    - `, - }); -})(); + }, + template: ` +
    + +
    + `, +}); -- GitLab From 799c9738f729b773feb65360023434de85142428 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Tue, 7 Feb 2017 09:32:01 +0000 Subject: [PATCH 3/3] Eslint fixes --- app/assets/javascripts/boards/boards_bundle.js.es6 | 4 ++-- app/assets/javascripts/boards/components/board.js.es6 | 1 + app/assets/javascripts/boards/components/board_card.js.es6 | 1 + app/assets/javascripts/boards/components/board_header.js.es6 | 5 +++-- app/assets/javascripts/boards/components/board_list.js.es6 | 1 + .../javascripts/boards/components/board_sidebar.js.es6 | 1 + .../javascripts/boards/components/sidebar/assignee.js.es6 | 2 +- .../javascripts/vue_common_component/bs_dropdown_menu.js.es6 | 3 ++- 8 files changed, 12 insertions(+), 6 deletions(-) diff --git a/app/assets/javascripts/boards/boards_bundle.js.es6 b/app/assets/javascripts/boards/boards_bundle.js.es6 index b0821438910c..db53e3edbb7a 100644 --- a/app/assets/javascripts/boards/boards_bundle.js.es6 +++ b/app/assets/javascripts/boards/boards_bundle.js.es6 @@ -12,7 +12,7 @@ requireAll(require.context('./stores', true, /^\.\/.*\.(js|es6)$/)); requireAll(require.context('./services', true, /^\.\/.*\.(js|es6)$/)); requireAll(require.context('./mixins', true, /^\.\/.*\.(js|es6)$/)); requireAll(require.context('./filters', true, /^\.\/.*\.(js|es6)$/)); -const board = require('./components/board'); +const boardComponent = require('./components/board'); const boardSidebar = require('./components/board_sidebar'); require('./components/new_list_dropdown'); require('./components/modal/index'); @@ -34,7 +34,7 @@ $(() => { gl.IssueBoardsApp = new Vue({ el: $boardApp, components: { - board, + board: boardComponent, boardSidebar, 'board-add-issues-modal': gl.issueBoards.IssuesModal, }, diff --git a/app/assets/javascripts/boards/components/board.js.es6 b/app/assets/javascripts/boards/components/board.js.es6 index 4e847500b34a..8d65a6b952bd 100644 --- a/app/assets/javascripts/boards/components/board.js.es6 +++ b/app/assets/javascripts/boards/components/board.js.es6 @@ -5,6 +5,7 @@ const boardBlankState = require('./board_blank_state'); const boardList = require('./board_list'); const boardHeader = require('./board_header'); + const Store = gl.issueBoards.BoardsStore; module.exports = Vue.extend({ diff --git a/app/assets/javascripts/boards/components/board_card.js.es6 b/app/assets/javascripts/boards/components/board_card.js.es6 index 0fa00a5d0b35..ee14ed73196b 100644 --- a/app/assets/javascripts/boards/components/board_card.js.es6 +++ b/app/assets/javascripts/boards/components/board_card.js.es6 @@ -2,6 +2,7 @@ /* global Vue */ const issueCardInner = require('./issue_card_inner'); + const Store = gl.issueBoards.BoardsStore; module.exports = Vue.extend({ diff --git a/app/assets/javascripts/boards/components/board_header.js.es6 b/app/assets/javascripts/boards/components/board_header.js.es6 index 944c59133f1d..831259b8142c 100644 --- a/app/assets/javascripts/boards/components/board_header.js.es6 +++ b/app/assets/javascripts/boards/components/board_header.js.es6 @@ -1,3 +1,4 @@ +/* global Vue */ const boardDelete = require('./board_delete'); module.exports = Vue.extend({ @@ -48,11 +49,11 @@ module.exports = Vue.extend({ boardDelete, }, props: [ - 'disabled', 'list', 'canAdminList', 'canAdminIssue' + 'disabled', 'list', 'canAdminList', 'canAdminIssue', ], methods: { showNewIssueForm() { this.$parent.$refs['board-list'].showIssueForm = !this.$parent.$refs['board-list'].showIssueForm; - } + }, }, }); diff --git a/app/assets/javascripts/boards/components/board_list.js.es6 b/app/assets/javascripts/boards/components/board_list.js.es6 index a4df4ad14922..9353379fba35 100644 --- a/app/assets/javascripts/boards/components/board_list.js.es6 +++ b/app/assets/javascripts/boards/components/board_list.js.es6 @@ -4,6 +4,7 @@ const boardCard = require('./board_card'); const boardNewIssue = require('./board_new_issue'); + const Store = gl.issueBoards.BoardsStore; module.exports = Vue.extend({ diff --git a/app/assets/javascripts/boards/components/board_sidebar.js.es6 b/app/assets/javascripts/boards/components/board_sidebar.js.es6 index c52ff454eb2a..9c8fa46f79e8 100644 --- a/app/assets/javascripts/boards/components/board_sidebar.js.es6 +++ b/app/assets/javascripts/boards/components/board_sidebar.js.es6 @@ -7,6 +7,7 @@ const removeBtn = require('./sidebar/remove_issue'); require('./sidebar/assignee'); + const Store = gl.issueBoards.BoardsStore; module.exports = Vue.extend({ diff --git a/app/assets/javascripts/boards/components/sidebar/assignee.js.es6 b/app/assets/javascripts/boards/components/sidebar/assignee.js.es6 index 5272f30f71fd..e3b6cd9c2804 100644 --- a/app/assets/javascripts/boards/components/sidebar/assignee.js.es6 +++ b/app/assets/javascripts/boards/components/sidebar/assignee.js.es6 @@ -90,7 +90,7 @@ require('../../../vue_common_component/bs_dropdown_menu'); ], computed: { assigneeUrl() { - return `${gon.relative_url_root}/${this.issue.assignee.username}` + return `${gon.relative_url_root}/${this.issue.assignee.username}`; }, currentUsername() { return this.currentUser.username || false; diff --git a/app/assets/javascripts/vue_common_component/bs_dropdown_menu.js.es6 b/app/assets/javascripts/vue_common_component/bs_dropdown_menu.js.es6 index d6ba8862b859..a7475fba7bf1 100644 --- a/app/assets/javascripts/vue_common_component/bs_dropdown_menu.js.es6 +++ b/app/assets/javascripts/vue_common_component/bs_dropdown_menu.js.es6 @@ -1,3 +1,4 @@ +/* global Vue */ (() => { Vue.component('bs-dropdown-menu', { props: { @@ -69,5 +70,5 @@ return classNamesObject; }, }, - }) + }); })(); -- GitLab