From d51e8d1d1dbf74cdd6bf51a6713c9712161d1aa9 Mon Sep 17 00:00:00 2001 From: Nadav Tasher Date: Sun, 29 Dec 2024 22:54:32 +0200 Subject: [PATCH 1/3] Move swimlane creation button to board header when using swimlane view mode --- client/components/boards/boardColors.css | 8 ---- client/components/boards/boardHeader.jade | 21 ++++++++ client/components/boards/boardHeader.js | 38 +++++++++++++++ .../components/swimlanes/swimlaneHeader.jade | 14 ------ client/components/swimlanes/swimlaneHeader.js | 48 +------------------ client/components/swimlanes/swimlanes.css | 5 -- 6 files changed, 60 insertions(+), 74 deletions(-) diff --git a/client/components/boards/boardColors.css b/client/components/boards/boardColors.css index cecf559f0..61335d2e8 100644 --- a/client/components/boards/boardColors.css +++ b/client/components/boards/boardColors.css @@ -2181,9 +2181,6 @@ THEME - Modern Dark padding: 6px; font-size: 16px; } -.board-color-moderndark .swimlane .swimlane-header-wrap .swimlane-header-plus-icon { - font-size: 16px; -} .board-color-moderndark .swimlane { background: #2a2a2a; line-height: 18px; @@ -3395,11 +3392,6 @@ THEME - Clean Light background-color: #2E2E39; } -.board-color-cleanlight .swimlane .swimlane-header-wrap .swimlane-header-plus-icon, -.board-color-cleandark .swimlane .swimlane-header-wrap .swimlane-header-plus-icon { - margin-left: 14px; -} - .board-color-cleanlight .swimlane .swimlane-header-wrap .list-composer, .board-color-cleandark .swimlane .swimlane-header-wrap .list-composer { display: flex; diff --git a/client/components/boards/boardHeader.jade b/client/components/boards/boardHeader.jade index 93da227b2..fce2913ed 100644 --- a/client/components/boards/boardHeader.jade +++ b/client/components/boards/boardHeader.jade @@ -16,6 +16,10 @@ template(name="boardHeaderBar") a.board-header-btn(class="{{#if currentUser.isBoardAdmin}}js-edit-board-title{{else}}is-disabled{{/if}}" title="{{_ 'edit'}}" value=title) i.fa.fa-pencil-square-o + if $eq boardView 'board-view-swimlanes' + a.board-header-btn.js-open-add-swimlane-menu(title="{{_ 'add-swimlane'}}") + i.fa.fa-plus + a.board-header-btn.js-star-board(class="{{#if isStarred}}is-active{{/if}}" title="{{#if isStarred}}{{_ 'click-to-unstar'}}{{else}}{{_ 'click-to-star'}}{{/if}} {{_ 'starred-boards-description'}}") i.fa(class="fa-star{{#unless isStarred}}-o{{/unless}}") @@ -59,6 +63,10 @@ template(name="boardHeaderBar") a.board-header-btn(class="{{#if currentUser.isBoardAdmin}}js-edit-board-title{{else}}is-disabled{{/if}}" title="{{_ 'edit'}}" value=title) i.fa.fa-pencil-square-o + if $eq boardView 'board-view-swimlanes' + a.board-header-btn.js-open-add-swimlane-menu(title="{{_ 'add-swimlane'}}") + i.fa.fa-plus + a.board-header-btn.js-star-board(class="{{#if isStarred}}is-active{{/if}}" title="{{#if isStarred}}{{_ 'click-to-unstar'}}{{else}}{{_ 'click-to-star'}}{{/if}} {{_ 'starred-boards-description'}}") i.fa(class="fa-star{{#unless isStarred}}-o{{/unless}}") @@ -295,3 +303,16 @@ template(name="cardsSortPopup") li a.js-sort-created-asc {{_ 'created-at-oldest-first'}} + +template(name="swimlaneAddPopup") + unless currentUser.isCommentOnly + form + input.swimlane-name-input.full-line(type="text" placeholder="{{_ 'add-swimlane'}}" + autocomplete="off" autofocus) + .edit-controls.clearfix + button.primary.confirm(type="submit") {{_ 'add'}} + unless currentBoard.isTemplatesBoard + unless currentBoard.isTemplateBoard + span.quiet + | {{_ 'or'}} + a.js-swimlane-template {{_ 'template'}} diff --git a/client/components/boards/boardHeader.js b/client/components/boards/boardHeader.js index 01859ead5..6ff723d73 100644 --- a/client/components/boards/boardHeader.js +++ b/client/components/boards/boardHeader.js @@ -2,6 +2,8 @@ import { ReactiveCache } from '/imports/reactiveCache'; import { TAPi18n } from '/imports/i18n'; import dragscroll from '@wekanteam/dragscroll'; +const { calculateIndexData } = Utils; + /* const DOWNCLS = 'fa-sort-down'; const UPCLS = 'fa-sort-up'; @@ -68,6 +70,7 @@ BlazeComponent.extendComponent({ events() { return [ { + 'click .js-open-add-swimlane-menu': Popup.open('swimlaneAdd'), 'click .js-edit-board-title': Popup.open('boardChangeTitle'), 'click .js-star-board'() { ReactiveCache.getCurrentUser().toggleBoardStar(Session.get('currentBoard')); @@ -128,6 +131,41 @@ BlazeComponent.extendComponent({ }, }).register('boardHeaderBar'); +BlazeComponent.extendComponent({ + events() { + return [ + { + submit(event) { + event.preventDefault(); + const currentBoard = Utils.getCurrentBoard(); + const titleInput = this.find('.swimlane-name-input'); + const title = titleInput.value.trim(); + const swimlaneType = currentBoard.isTemplatesBoard() + ? 'template-swimlane' + : 'swimlane'; + + if (title) { + Swimlanes.insert({ + title, + boardId: Session.get('currentBoard'), + sort: 0, + type: swimlaneType, + }); + + titleInput.value = ''; + titleInput.focus(); + } + // XXX ideally, we should move the popup to the newly + // created swimlane so a user can add more than one swimlane + // with a minimum of interactions + Popup.back(); + }, + 'click .js-swimlane-template': Popup.open('searchElement'), + }, + ]; + }, +}).register('swimlaneAddPopup'); + Template.boardHeaderBar.helpers({ boardView() { return Utils.boardView(); diff --git a/client/components/swimlanes/swimlaneHeader.jade b/client/components/swimlanes/swimlaneHeader.jade index d14686163..e5477ce40 100644 --- a/client/components/swimlanes/swimlaneHeader.jade +++ b/client/components/swimlanes/swimlaneHeader.jade @@ -24,7 +24,6 @@ template(name="swimlaneFixedHeader") | {{isTitleDefault title}} .swimlane-header-menu unless currentUser.isCommentOnly - a.fa.fa-plus.js-open-add-swimlane-menu.swimlane-header-plus-icon(title="{{_ 'add-swimlane'}}") a.fa.fa-navicon.js-open-swimlane-menu(title="{{_ 'swimlaneActionPopup-title'}}") //// TODO: Collapse Swimlane: make button working, etc. //unless collapsed @@ -75,19 +74,6 @@ template(name="swimlaneActionPopup") i.fa.fa-arrow-up | {{_ 'move-swimlane'}} -template(name="swimlaneAddPopup") - unless currentUser.isCommentOnly - form - input.swimlane-name-input.full-line(type="text" placeholder="{{_ 'add-swimlane'}}" - autocomplete="off" autofocus) - .edit-controls.clearfix - button.primary.confirm(type="submit") {{_ 'add'}} - unless currentBoard.isTemplatesBoard - unless currentBoard.isTemplateBoard - span.quiet - | {{_ 'or'}} - a.js-swimlane-template {{_ 'template'}} - template(name="setSwimlaneColorPopup") form.edit-label .palette-colors: each colors diff --git a/client/components/swimlanes/swimlaneHeader.js b/client/components/swimlanes/swimlaneHeader.js index 2b1547500..de2ef95eb 100644 --- a/client/components/swimlanes/swimlaneHeader.js +++ b/client/components/swimlanes/swimlaneHeader.js @@ -38,7 +38,6 @@ BlazeComponent.extendComponent({ this.collapsed(!this.collapsed()); }, 'click .js-open-swimlane-menu': Popup.open('swimlaneAction'), - 'click .js-open-add-swimlane-menu': Popup.open('swimlaneAdd'), submit: this.editTitle, }, ]; @@ -81,7 +80,7 @@ Template.editSwimlaneTitleForm.helpers({ // When that happens, try use translation "defaultdefault" that has same content of default, or return text "Default". // This can happen, if swimlane does not have name. // Yes, this is fixing the symptom (Swimlane title does not have title) - // instead of fixing the problem (Add Swimlane title when creating swimlane) + // instead of fixing the problem (Add Swimlane title when creating swimlane) // because there could be thousands of swimlanes, adding name Default to all of them // would be very slow. if (title.startsWith("key 'default") && title.endsWith('returned an object instead of string.')) { @@ -116,51 +115,6 @@ Template.swimlaneActionPopup.events({ }, }); -BlazeComponent.extendComponent({ - onCreated() { - this.currentSwimlane = this.currentData(); - }, - - events() { - return [ - { - submit(event) { - event.preventDefault(); - const currentBoard = Utils.getCurrentBoard(); - const nextSwimlane = currentBoard.nextSwimlane(this.currentSwimlane); - const titleInput = this.find('.swimlane-name-input'); - const title = titleInput.value.trim(); - const sortValue = calculateIndexData( - this.currentSwimlane, - nextSwimlane, - 1, - ); - const swimlaneType = currentBoard.isTemplatesBoard() - ? 'template-swimlane' - : 'swimlane'; - - if (title) { - Swimlanes.insert({ - title, - boardId: Session.get('currentBoard'), - sort: sortValue.base, - type: swimlaneType, - }); - - titleInput.value = ''; - titleInput.focus(); - } - // XXX ideally, we should move the popup to the newly - // created swimlane so a user can add more than one swimlane - // with a minimum of interactions - Popup.back(); - }, - 'click .js-swimlane-template': Popup.open('searchElement'), - }, - ]; - }, -}).register('swimlaneAddPopup'); - BlazeComponent.extendComponent({ onCreated() { this.currentSwimlane = this.currentData(); diff --git a/client/components/swimlanes/swimlanes.css b/client/components/swimlanes/swimlanes.css index 373de8ab3..5b4523456 100644 --- a/client/components/swimlanes/swimlanes.css +++ b/client/components/swimlanes/swimlanes.css @@ -73,11 +73,6 @@ display: none; } } -.swimlane .swimlane-header-wrap .swimlane-header-plus-icon { - margin-left: 5px; - padding-right: 20px; - font-size: 22px; -} .swimlane .swimlane-header-wrap .swimlane-header-menu-icon { padding-right: 20px; font-size: 22px; From fecae8d0a3f1ed82e9f19c2fea92c3ee72ad1b0d Mon Sep 17 00:00:00 2001 From: Nadav Tasher Date: Mon, 30 Dec 2024 00:17:56 +0200 Subject: [PATCH 2/3] Revert "Move swimlane creation button to board header when using swimlane view mode" This reverts commit d51e8d1d1dbf74cdd6bf51a6713c9712161d1aa9. --- client/components/boards/boardColors.css | 8 ++++ client/components/boards/boardHeader.jade | 21 -------- client/components/boards/boardHeader.js | 38 --------------- .../components/swimlanes/swimlaneHeader.jade | 14 ++++++ client/components/swimlanes/swimlaneHeader.js | 48 ++++++++++++++++++- client/components/swimlanes/swimlanes.css | 5 ++ 6 files changed, 74 insertions(+), 60 deletions(-) diff --git a/client/components/boards/boardColors.css b/client/components/boards/boardColors.css index 61335d2e8..cecf559f0 100644 --- a/client/components/boards/boardColors.css +++ b/client/components/boards/boardColors.css @@ -2181,6 +2181,9 @@ THEME - Modern Dark padding: 6px; font-size: 16px; } +.board-color-moderndark .swimlane .swimlane-header-wrap .swimlane-header-plus-icon { + font-size: 16px; +} .board-color-moderndark .swimlane { background: #2a2a2a; line-height: 18px; @@ -3392,6 +3395,11 @@ THEME - Clean Light background-color: #2E2E39; } +.board-color-cleanlight .swimlane .swimlane-header-wrap .swimlane-header-plus-icon, +.board-color-cleandark .swimlane .swimlane-header-wrap .swimlane-header-plus-icon { + margin-left: 14px; +} + .board-color-cleanlight .swimlane .swimlane-header-wrap .list-composer, .board-color-cleandark .swimlane .swimlane-header-wrap .list-composer { display: flex; diff --git a/client/components/boards/boardHeader.jade b/client/components/boards/boardHeader.jade index fce2913ed..93da227b2 100644 --- a/client/components/boards/boardHeader.jade +++ b/client/components/boards/boardHeader.jade @@ -16,10 +16,6 @@ template(name="boardHeaderBar") a.board-header-btn(class="{{#if currentUser.isBoardAdmin}}js-edit-board-title{{else}}is-disabled{{/if}}" title="{{_ 'edit'}}" value=title) i.fa.fa-pencil-square-o - if $eq boardView 'board-view-swimlanes' - a.board-header-btn.js-open-add-swimlane-menu(title="{{_ 'add-swimlane'}}") - i.fa.fa-plus - a.board-header-btn.js-star-board(class="{{#if isStarred}}is-active{{/if}}" title="{{#if isStarred}}{{_ 'click-to-unstar'}}{{else}}{{_ 'click-to-star'}}{{/if}} {{_ 'starred-boards-description'}}") i.fa(class="fa-star{{#unless isStarred}}-o{{/unless}}") @@ -63,10 +59,6 @@ template(name="boardHeaderBar") a.board-header-btn(class="{{#if currentUser.isBoardAdmin}}js-edit-board-title{{else}}is-disabled{{/if}}" title="{{_ 'edit'}}" value=title) i.fa.fa-pencil-square-o - if $eq boardView 'board-view-swimlanes' - a.board-header-btn.js-open-add-swimlane-menu(title="{{_ 'add-swimlane'}}") - i.fa.fa-plus - a.board-header-btn.js-star-board(class="{{#if isStarred}}is-active{{/if}}" title="{{#if isStarred}}{{_ 'click-to-unstar'}}{{else}}{{_ 'click-to-star'}}{{/if}} {{_ 'starred-boards-description'}}") i.fa(class="fa-star{{#unless isStarred}}-o{{/unless}}") @@ -303,16 +295,3 @@ template(name="cardsSortPopup") li a.js-sort-created-asc {{_ 'created-at-oldest-first'}} - -template(name="swimlaneAddPopup") - unless currentUser.isCommentOnly - form - input.swimlane-name-input.full-line(type="text" placeholder="{{_ 'add-swimlane'}}" - autocomplete="off" autofocus) - .edit-controls.clearfix - button.primary.confirm(type="submit") {{_ 'add'}} - unless currentBoard.isTemplatesBoard - unless currentBoard.isTemplateBoard - span.quiet - | {{_ 'or'}} - a.js-swimlane-template {{_ 'template'}} diff --git a/client/components/boards/boardHeader.js b/client/components/boards/boardHeader.js index 6ff723d73..01859ead5 100644 --- a/client/components/boards/boardHeader.js +++ b/client/components/boards/boardHeader.js @@ -2,8 +2,6 @@ import { ReactiveCache } from '/imports/reactiveCache'; import { TAPi18n } from '/imports/i18n'; import dragscroll from '@wekanteam/dragscroll'; -const { calculateIndexData } = Utils; - /* const DOWNCLS = 'fa-sort-down'; const UPCLS = 'fa-sort-up'; @@ -70,7 +68,6 @@ BlazeComponent.extendComponent({ events() { return [ { - 'click .js-open-add-swimlane-menu': Popup.open('swimlaneAdd'), 'click .js-edit-board-title': Popup.open('boardChangeTitle'), 'click .js-star-board'() { ReactiveCache.getCurrentUser().toggleBoardStar(Session.get('currentBoard')); @@ -131,41 +128,6 @@ BlazeComponent.extendComponent({ }, }).register('boardHeaderBar'); -BlazeComponent.extendComponent({ - events() { - return [ - { - submit(event) { - event.preventDefault(); - const currentBoard = Utils.getCurrentBoard(); - const titleInput = this.find('.swimlane-name-input'); - const title = titleInput.value.trim(); - const swimlaneType = currentBoard.isTemplatesBoard() - ? 'template-swimlane' - : 'swimlane'; - - if (title) { - Swimlanes.insert({ - title, - boardId: Session.get('currentBoard'), - sort: 0, - type: swimlaneType, - }); - - titleInput.value = ''; - titleInput.focus(); - } - // XXX ideally, we should move the popup to the newly - // created swimlane so a user can add more than one swimlane - // with a minimum of interactions - Popup.back(); - }, - 'click .js-swimlane-template': Popup.open('searchElement'), - }, - ]; - }, -}).register('swimlaneAddPopup'); - Template.boardHeaderBar.helpers({ boardView() { return Utils.boardView(); diff --git a/client/components/swimlanes/swimlaneHeader.jade b/client/components/swimlanes/swimlaneHeader.jade index e5477ce40..d14686163 100644 --- a/client/components/swimlanes/swimlaneHeader.jade +++ b/client/components/swimlanes/swimlaneHeader.jade @@ -24,6 +24,7 @@ template(name="swimlaneFixedHeader") | {{isTitleDefault title}} .swimlane-header-menu unless currentUser.isCommentOnly + a.fa.fa-plus.js-open-add-swimlane-menu.swimlane-header-plus-icon(title="{{_ 'add-swimlane'}}") a.fa.fa-navicon.js-open-swimlane-menu(title="{{_ 'swimlaneActionPopup-title'}}") //// TODO: Collapse Swimlane: make button working, etc. //unless collapsed @@ -74,6 +75,19 @@ template(name="swimlaneActionPopup") i.fa.fa-arrow-up | {{_ 'move-swimlane'}} +template(name="swimlaneAddPopup") + unless currentUser.isCommentOnly + form + input.swimlane-name-input.full-line(type="text" placeholder="{{_ 'add-swimlane'}}" + autocomplete="off" autofocus) + .edit-controls.clearfix + button.primary.confirm(type="submit") {{_ 'add'}} + unless currentBoard.isTemplatesBoard + unless currentBoard.isTemplateBoard + span.quiet + | {{_ 'or'}} + a.js-swimlane-template {{_ 'template'}} + template(name="setSwimlaneColorPopup") form.edit-label .palette-colors: each colors diff --git a/client/components/swimlanes/swimlaneHeader.js b/client/components/swimlanes/swimlaneHeader.js index de2ef95eb..2b1547500 100644 --- a/client/components/swimlanes/swimlaneHeader.js +++ b/client/components/swimlanes/swimlaneHeader.js @@ -38,6 +38,7 @@ BlazeComponent.extendComponent({ this.collapsed(!this.collapsed()); }, 'click .js-open-swimlane-menu': Popup.open('swimlaneAction'), + 'click .js-open-add-swimlane-menu': Popup.open('swimlaneAdd'), submit: this.editTitle, }, ]; @@ -80,7 +81,7 @@ Template.editSwimlaneTitleForm.helpers({ // When that happens, try use translation "defaultdefault" that has same content of default, or return text "Default". // This can happen, if swimlane does not have name. // Yes, this is fixing the symptom (Swimlane title does not have title) - // instead of fixing the problem (Add Swimlane title when creating swimlane) + // instead of fixing the problem (Add Swimlane title when creating swimlane) // because there could be thousands of swimlanes, adding name Default to all of them // would be very slow. if (title.startsWith("key 'default") && title.endsWith('returned an object instead of string.')) { @@ -115,6 +116,51 @@ Template.swimlaneActionPopup.events({ }, }); +BlazeComponent.extendComponent({ + onCreated() { + this.currentSwimlane = this.currentData(); + }, + + events() { + return [ + { + submit(event) { + event.preventDefault(); + const currentBoard = Utils.getCurrentBoard(); + const nextSwimlane = currentBoard.nextSwimlane(this.currentSwimlane); + const titleInput = this.find('.swimlane-name-input'); + const title = titleInput.value.trim(); + const sortValue = calculateIndexData( + this.currentSwimlane, + nextSwimlane, + 1, + ); + const swimlaneType = currentBoard.isTemplatesBoard() + ? 'template-swimlane' + : 'swimlane'; + + if (title) { + Swimlanes.insert({ + title, + boardId: Session.get('currentBoard'), + sort: sortValue.base, + type: swimlaneType, + }); + + titleInput.value = ''; + titleInput.focus(); + } + // XXX ideally, we should move the popup to the newly + // created swimlane so a user can add more than one swimlane + // with a minimum of interactions + Popup.back(); + }, + 'click .js-swimlane-template': Popup.open('searchElement'), + }, + ]; + }, +}).register('swimlaneAddPopup'); + BlazeComponent.extendComponent({ onCreated() { this.currentSwimlane = this.currentData(); diff --git a/client/components/swimlanes/swimlanes.css b/client/components/swimlanes/swimlanes.css index 5b4523456..373de8ab3 100644 --- a/client/components/swimlanes/swimlanes.css +++ b/client/components/swimlanes/swimlanes.css @@ -73,6 +73,11 @@ display: none; } } +.swimlane .swimlane-header-wrap .swimlane-header-plus-icon { + margin-left: 5px; + padding-right: 20px; + font-size: 22px; +} .swimlane .swimlane-header-wrap .swimlane-header-menu-icon { padding-right: 20px; font-size: 22px; From 96e11cb727ddfca48ae24db48c3122dbce01964a Mon Sep 17 00:00:00 2001 From: Nadav Tasher Date: Mon, 30 Dec 2024 01:25:25 +0200 Subject: [PATCH 3/3] Display new swimlane creation button when no swimlanes exist --- client/components/boards/boardBody.jade | 12 +++++++++--- client/components/boards/boardBody.js | 5 +++++ client/components/swimlanes/swimlaneHeader.js | 2 +- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/client/components/boards/boardBody.jade b/client/components/boards/boardBody.jade index 32cd274f2..89e99ae6d 100644 --- a/client/components/boards/boardBody.jade +++ b/client/components/boards/boardBody.jade @@ -17,7 +17,8 @@ template(name="boardBody") | {{_ 'tableVisibilityMode-allowPrivateOnly'}} else .board-wrapper(class=currentBoard.colorClass) - .board-canvas.js-swimlanes.dragscroll( + .board-canvas.js-swimlanes( + class="{{#if hasSwimlanes}}dragscroll{{/if}}" class="{{#if Sidebar.isOpen}}is-sibling-sidebar-open{{/if}}" class="{{#if MultiSelection.isActive}}is-multiselection-active{{/if}}" class="{{#if draggingActive.get}}is-dragging-active{{/if}}") @@ -27,8 +28,13 @@ template(name="boardBody") each currentBoard.swimlanes +swimlane(this) else if isViewSwimlanes - each currentBoard.swimlanes - +swimlane(this) + if hasSwimlanes + each currentBoard.swimlanes + +swimlane(this) + else + a.js-empty-board-add-swimlane(title="{{_ 'add-swimlane'}}") + h1.big-message.quiet + | {{_ 'add-swimlane'}} + else if isViewLists +listsGroup(currentBoard) else if isViewCalendar diff --git a/client/components/boards/boardBody.js b/client/components/boards/boardBody.js index 346bb181f..eb5690f43 100644 --- a/client/components/boards/boardBody.js +++ b/client/components/boards/boardBody.js @@ -248,6 +248,10 @@ BlazeComponent.extendComponent({ } }, + hasSwimlanes() { + return Utils.getCurrentBoard().swimlanes().length > 0; + }, + isViewLists() { const currentUser = ReactiveCache.getCurrentUser(); if (currentUser) { @@ -288,6 +292,7 @@ BlazeComponent.extendComponent({ this._isDragging = false; } }, + 'click .js-empty-board-add-swimlane': Popup.open('swimlaneAdd'), }, ]; }, diff --git a/client/components/swimlanes/swimlaneHeader.js b/client/components/swimlanes/swimlaneHeader.js index 2b1547500..17988f454 100644 --- a/client/components/swimlanes/swimlaneHeader.js +++ b/client/components/swimlanes/swimlaneHeader.js @@ -143,7 +143,7 @@ BlazeComponent.extendComponent({ Swimlanes.insert({ title, boardId: Session.get('currentBoard'), - sort: sortValue.base, + sort: sortValue.base || 0, type: swimlaneType, });