Collapse Lists.

Thanks to xet7 !
This commit is contained in:
Lauri Ojansivu 2024-04-26 07:33:06 +03:00
parent f22f470ba4
commit a601ba542a
9 changed files with 159 additions and 58 deletions

View file

@ -7,7 +7,7 @@
border-left: 1px solid #ccc; border-left: 1px solid #ccc;
padding: 0; padding: 0;
float: left; float: left;
min-width: 100px; /* TODO(mark-i-m): hardcoded? */ /* min-width: 100px; TODO(mark-i-m): hardcoded? */
/*max-width: 270px;*/ /*max-width: 270px;*/
/* Reverted incomplete change list width: */ /* Reverted incomplete change list width: */
/* https://github.com/wekan/wekan/issues/4558 */ /* https://github.com/wekan/wekan/issues/4558 */
@ -82,6 +82,16 @@
text-overflow: ellipsis; text-overflow: ellipsis;
word-wrap: break-word; word-wrap: break-word;
} }
.list-rotated {
width: 10px;
margin-top: 10px;
margin-left: 0;
margin-right: 0;
transform: rotate(90deg);
position: relative;
text-overflow: ellipsis;
white-space: nowrap;
}
.list-header .list-header-watch-icon { .list-header .list-header-watch-icon {
padding-left: 10px; padding-left: 10px;
color: #a6a6a6; color: #a6a6a6;
@ -99,6 +109,23 @@
color: #a6a6a6; color: #a6a6a6;
margin-right: 15px; margin-right: 15px;
} }
.list-header .list-header-collapse-right {
color: #a6a6a6;
}
.list-header .list-header-collapse-left {
color: #a6a6a6;
margin-right: 15px;
}
.list-header .list-header-uncollapse-left {
color: #a6a6a6;
}
.list-header .list-header-uncollapse-right {
color: #a6a6a6;
}
.list-header .list-header-collapse {
color: #a6a6a6;
margin-right: 15px;
}
.list-header .highlight { .list-header .highlight {
color: #ce1414; color: #ce1414;
} }

View file

@ -1,6 +1,7 @@
template(name='list') template(name='list')
.list.js-list(id="js-list-{{_id}}" .list.js-list(id="js-list-{{_id}}"
style="width:{{listWidth}}px;") style="{{#unless collapsed}}width:{{listWidth}}px;{{/unless}}"
class="{{#if collapsed}}list-collapsed{{/if}}")
+listHeader +listHeader
+listBody +listBody

View file

@ -1,37 +1,38 @@
template(name="listBody") template(name="listBody")
.list-body unless collapsed
.minicards.clearfix.js-minicards(class="{{#if reachedWipLimit}}js-list-full{{/if}}") .list-body
if cards.length .minicards.clearfix.js-minicards(class="{{#if reachedWipLimit}}js-list-full{{/if}}")
+inlinedForm(autoclose=false position="top") if cards.length
+addCardForm(listId=_id position="top") +inlinedForm(autoclose=false position="top")
ul.sidebar-list +addCardForm(listId=_id position="top")
each customFieldsSum ul.sidebar-list
li each customFieldsSum
+viewer li
= name
if $eq customFieldsSum.type "number"
+viewer +viewer
= value = name
if $eq customFieldsSum.type "currency" if $eq customFieldsSum.type "number"
+viewer +viewer
= formattedCurrencyCustomFieldValue(value) = value
each (cardsWithLimit (idOrNull ../../_id)) if $eq customFieldsSum.type "currency"
a.minicard-wrapper.js-minicard(href=originRelativeUrl +viewer
class="{{#if cardIsSelected}}is-selected{{/if}}" = formattedCurrencyCustomFieldValue(value)
class="{{#if MultiSelection.isSelected _id}}is-checked{{/if}}") each (cardsWithLimit (idOrNull ../../_id))
if MultiSelection.isActive a.minicard-wrapper.js-minicard(href=originRelativeUrl
.materialCheckBox.multi-selection-checkbox.js-toggle-multi-selection( class="{{#if cardIsSelected}}is-selected{{/if}}"
class="{{#if MultiSelection.isSelected _id}}is-checked{{/if}}") class="{{#if MultiSelection.isSelected _id}}is-checked{{/if}}")
+minicard(this) if MultiSelection.isActive
if (showSpinner (idOrNull ../../_id)) .materialCheckBox.multi-selection-checkbox.js-toggle-multi-selection(
+spinnerList class="{{#if MultiSelection.isSelected _id}}is-checked{{/if}}")
+minicard(this)
if (showSpinner (idOrNull ../../_id))
+spinnerList
if canSeeAddCard if canSeeAddCard
+inlinedForm(autoclose=false position="bottom") +inlinedForm(autoclose=false position="bottom")
+addCardForm(listId=_id position="bottom") +addCardForm(listId=_id position="bottom")
else else
a.open-minicard-composer.js-card-composer.js-open-inlined-form(title="{{_ 'add-card-to-bottom-of-list'}}") a.open-minicard-composer.js-card-composer.js-open-inlined-form(title="{{_ 'add-card-to-bottom-of-list'}}")
i.fa.fa-plus i.fa.fa-plus
template(name="spinnerList") template(name="spinnerList")
.sk-spinner.sk-spinner-list( .sk-spinner.sk-spinner-list(

View file

@ -5,22 +5,43 @@ template(name="listHeader")
+inlinedForm +inlinedForm
+editListTitleForm +editListTitleForm
else else
unless isMiniScreen
if collapsed
a.js-collapse(title="{{_ 'uncollapse'}}")
i.fa.fa-arrow-left.list-header-uncollapse-left
i.fa.fa-arrow-right.list-header-uncollapse-right
if isMiniScreen if isMiniScreen
if currentList if currentList
a.list-header-left-icon.fa.fa-angle-left.js-unselect-list a.list-header-left-icon.fa.fa-angle-left.js-unselect-list
h2.list-header-name( unless isMiniScreen
title="{{ moment modifiedAt 'LLL' }}" if collapsed
class="{{#if currentUser.isBoardMember}}{{#unless currentUser.isCommentOnly}}{{#unless currentUser.isWorker}}js-open-inlined-form is-editable{{/unless}}{{/unless}}{{/if}}") if showCardsCountForList cards.length
+viewer br
= title span.cardCount {{cardsCount}}
if wipLimit.enabled if isMiniScreen
| ( h2.list-header-name(
span(class="{{#if exceededWipLimit}}highlight{{/if}}") {{cards.length}} title="{{ moment modifiedAt 'LLL' }}"
|/#{wipLimit.value}) class="{{#if currentUser.isBoardMember}}{{#unless currentUser.isCommentOnly}}{{#unless currentUser.isWorker}}js-open-inlined-form is-editable{{/unless}}{{/unless}}{{/if}}")
+viewer
if showCardsCountForList cards.length = title
span.cardCount {{cardsCount}} {{cardsCountForListIsOne cards.length}} if wipLimit.enabled
| (
span(class="{{#if exceededWipLimit}}highlight{{/if}}") {{cards.length}}
|/#{wipLimit.value})
unless isMiniScreen
div(class="{{#if collapsed}}list-rotated{{/if}}")
h2.list-header-name(
title="{{ moment modifiedAt 'LLL' }}"
class="{{#if currentUser.isBoardMember}}{{#unless currentUser.isCommentOnly}}{{#unless currentUser.isWorker}}js-open-inlined-form is-editable{{/unless}}{{/unless}}{{/if}}")
+viewer
= title
if wipLimit.enabled
| (
span(class="{{#if exceededWipLimit}}highlight{{/if}}") {{cards.length}}
|/#{wipLimit.value})
unless collapsed
if showCardsCountForList cards.length
span.cardCount {{cardsCount}} {{cardsCountForListIsOne cards.length}}
if isMiniScreen if isMiniScreen
if currentList if currentList
if isWatching if isWatching
@ -36,16 +57,20 @@ template(name="listHeader")
else if currentUser.isBoardMember else if currentUser.isBoardMember
if isWatching if isWatching
i.list-header-watch-icon.fa.fa-eye i.list-header-watch-icon.fa.fa-eye
div.list-header-menu unless collapsed
unless currentUser.isCommentOnly div.list-header-menu
//if isBoardAdmin unless currentUser.isCommentOnly
// a.fa.js-list-star.list-header-plus-top(class="fa-star{{#unless starred}}-o{{/unless}}") //if isBoardAdmin
if canSeeAddCard // a.fa.js-list-star.list-header-plus-top(class="fa-star{{#unless starred}}-o{{/unless}}")
a.js-add-card.fa.fa-plus.list-header-plus-top(title="{{_ 'add-card-to-top-of-list'}}") if canSeeAddCard
a.fa.fa-navicon.js-open-list-menu(title="{{_ 'listActionPopup-title'}}") a.js-add-card.fa.fa-plus.list-header-plus-top(title="{{_ 'add-card-to-top-of-list'}}")
if currentUser.isBoardAdmin a.js-collapse(title="{{_ 'collapse'}}")
if isTouchScreenOrShowDesktopDragHandles i.fa.fa-arrow-right.list-header-collapse-right
a.list-header-handle.handle.fa.fa-arrows.js-list-handle i.fa.fa-arrow-left.list-header-collapse-left
a.fa.fa-navicon.js-open-list-menu(title="{{_ 'listActionPopup-title'}}")
if currentUser.isBoardAdmin
if isTouchScreenOrShowDesktopDragHandles
a.list-header-handle.handle.fa.fa-arrows.js-list-handle
template(name="editListTitleForm") template(name="editListTitleForm")
.list-composer .list-composer

View file

@ -31,6 +31,17 @@ BlazeComponent.extendComponent({
return !status; return !status;
} }
}, },
collapsed(check = undefined) {
const list = Template.currentData();
const status = list.isCollapsed();
if (check === undefined) {
// just check
return status;
} else {
list.collapse(!status);
return !status;
}
},
editTitle(event) { editTitle(event) {
event.preventDefault(); event.preventDefault();
const newTitle = this.childComponents('inlinedForm')[0] const newTitle = this.childComponents('inlinedForm')[0]
@ -104,6 +115,10 @@ BlazeComponent.extendComponent({
event.preventDefault(); event.preventDefault();
this.starred(!this.starred()); this.starred(!this.starred());
}, },
'click .js-collapse'(event) {
event.preventDefault();
this.collapsed(!this.collapsed());
},
'click .js-open-list-menu': Popup.open('listAction'), 'click .js-open-list-menu': Popup.open('listAction'),
'click .js-add-card.list-header-plus-top'(event) { 'click .js-add-card.list-header-plus-top'(event) {
const listDom = $(event.target).parents( const listDom = $(event.target).parents(

View file

@ -1246,5 +1246,7 @@
"show-checklist-at-minicard": "Show checklist at minicard", "show-checklist-at-minicard": "Show checklist at minicard",
"show-subtasks-field": "Show subtasks field", "show-subtasks-field": "Show subtasks field",
"convert-to-markdown": "Convert to markdown", "convert-to-markdown": "Convert to markdown",
"import-board-zip": "Add .zip file that has board JSON files, and board name subdirectories with attachments" "import-board-zip": "Add .zip file that has board JSON files, and board name subdirectories with attachments",
"collapse": "Collapse",
"uncollapse": "Uncollapse"
} }

View file

@ -156,6 +156,13 @@ Lists.attachSchema(
type: String, type: String,
defaultValue: 'list', defaultValue: 'list',
}, },
collapsed: {
/**
* is the list collapsed
*/
type: Boolean,
defaultValue: false,
},
}), }),
); );
@ -286,6 +293,10 @@ Lists.helpers({
return this.starred === true; return this.starred === true;
}, },
isCollapsed() {
return this.collapsed === true;
},
absoluteUrl() { absoluteUrl() {
const card = ReactiveCache.getCard({ listId: this._id }); const card = ReactiveCache.getCard({ listId: this._id });
return card && card.absoluteUrl(); return card && card.absoluteUrl();
@ -306,6 +317,9 @@ Lists.mutations({
star(enable = true) { star(enable = true) {
return { $set: { starred: !!enable } }; return { $set: { starred: !!enable } };
}, },
collapse(enable = true) {
return { $set: { collapsed: !!enable } };
},
archive() { archive() {
if (this.isTemplateList()) { if (this.isTemplateList()) {

View file

@ -107,6 +107,13 @@ Swimlanes.attachSchema(
type: String, type: String,
defaultValue: 'swimlane', defaultValue: 'swimlane',
}, },
collapsed: {
/**
* is the swimlane collapsed
*/
type: Boolean,
defaultValue: false,
},
}), }),
); );
@ -232,6 +239,10 @@ Swimlanes.helpers({
return ret; return ret;
}, },
isCollapsed() {
return this.collapsed === true;
},
board() { board() {
return ReactiveCache.getBoard(this.boardId); return ReactiveCache.getBoard(this.boardId);
}, },
@ -274,6 +285,10 @@ Swimlanes.mutations({
return { $set: { title } }; return { $set: { title } };
}, },
collapse(enable = true) {
return { $set: { collapsed: !!enable } };
},
archive() { archive() {
if (this.isTemplateSwimlane()) { if (this.isTemplateSwimlane()) {
this.myLists().forEach(list => { this.myLists().forEach(list => {

View file

@ -61,6 +61,7 @@ Meteor.publishRelations('boards', function() {
title: 1, title: 1,
boardId: 1, boardId: 1,
archived: 1, archived: 1,
collapsed: 1,
sort: 1 sort: 1
} }
}, },
@ -221,7 +222,7 @@ Meteor.publishRelations('board', function(boardId, isArchived) {
), ),
function(boardId, board) { function(boardId, board) {
this.cursor(ReactiveCache.getLists({ boardId, archived: isArchived }, {}, true)); this.cursor(ReactiveCache.getLists({ boardId, archived: isArchived }, {}, true));
this.cursor(ReactiveCache.getSwimlanes({ boardId, archived: isArchived }, {}, true)); this.cursor(ReactiveCache.getSwimlanes({ boardId, collapsed: 1, archived: isArchived }, {}, true));
this.cursor(ReactiveCache.getIntegrations({ boardId }, {}, true)); this.cursor(ReactiveCache.getIntegrations({ boardId }, {}, true));
this.cursor(ReactiveCache.getCardCommentReactions({ boardId }, {}, true)); this.cursor(ReactiveCache.getCardCommentReactions({ boardId }, {}, true));
this.cursor( this.cursor(