All Boards: "Selected:" star/home actions + Home board badge (#2220).

Below the "Multi-Selection is on" button a "Selected:" row now offers two
actions on the multi-selected boards:
- star icon: stars every selected board (sets them as Starred).
- home icon: sets the first selected board as the Home board (opened after
  login) via the existing toggleDefaultBoard method + router redirect, which
  brings the previously hidden Home-board feature back into use.

The Home board also always shows FIRST in the Starred list (even when it is
not itself starred), badged with a home icon centred at the top of its tile.
This commit is contained in:
Lauri Ojansivu committed 2026-07-18 03:19:42 +03:00
1 parent 3736f8431a
commit d67d27f0d8
5 files changed
+108 -9

No files matched your search

+35
View File
@@ -289,6 +289,27 @@
gap: 4px;
}
/* "Selected:" actions row (star / home) below the Multi-Selection button. */
.boards-path-header .selected-actions {
display: flex;
align-items: center;
gap: 8px;
}
.boards-path-header .selected-label {
font-size: 13px;
color: #333;
}
.boards-path-header .selected-action {
cursor: pointer;
color: #333;
font-size: 16px;
line-height: 1;
padding: 2px 4px;
}
.boards-path-header .selected-action:hover {
color: #2980b9;
}
.boards-path-header .multiselection-hint {
background: #FFF3CD;
color: #856404;
@@ -555,6 +576,20 @@
word-wrap: break-word;
}
/* #2220: Home-board badge — a home icon centred at the top of the board tile. */
.board-list .board-home-badge {
position: absolute;
top: 2px;
left: 50%;
transform: translateX(-50%);
z-index: 3;
color: #fff;
font-size: 14px;
line-height: 1;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.45);
pointer-events: none;
}
.board-list .board-list-item > .js-open-board {
text-decoration: none;
color: inherit;
+13
View File
@@ -106,6 +106,14 @@ template(name="boardList")
span.emoji-icon
i.fa.fa-thumb-tack
| {{_ 'multi-selection-active'}}
//- "Selected:" actions on the multi-selected boards: star them,
or set one as the Home board (opened after login, #2220).
.selected-actions
span.selected-label {{_ 'selected-label'}}
a.selected-action.js-star-selected(title="{{_ 'set-selected-starred'}}")
i.fa.fa-star
a.selected-action.js-home-selected(title="{{_ 'set-selected-home'}}")
i.fa.fa-home
a.board-header-btn.js-open-boards-sort(title="{{_ 'sort-boards'}}" class="{{#unless isBoardsSort 'custom'}}emphasis{{/unless}}")
span.emoji-icon
i.fa.fa-sort-alpha-asc
@@ -191,6 +199,11 @@ template(name="boardList")
if BoardMultiSelection.isActive
.materialCheckBox.multi-selection-checkbox.js-toggle-board-multi-selection(
class="{{#if BoardMultiSelection.isSelected _id}}is-checked{{/if}}")
//- #2220: the Home board (opened after login) is badged with a
home icon at the top centre of its tile.
if isDefaultBoard
span.board-home-badge(title="{{_ 'home-board-badge'}}")
i.fa.fa-home
span.board-handle.nodragscroll(title="{{boardWorkspaceDragHint}}")
span.emoji-icon
i.fa.fa-arrows
+52 -9
View File
@@ -542,6 +542,21 @@ Template.boardList.helpers({
const boards = ReactiveCache.getBoards(query, {});
const currentUser = ReactiveCache.getCurrentUser();
// #2220: the Home board (opened after login) always appears FIRST in the
// Starred view, even when it has not been explicitly starred.
const withHomeFirst = (arr) => {
if (tpl.selectedMenu.get() !== 'starred') return arr;
if ((tpl.boardSearchVar.get() || '').trim()) return arr;
const homeId =
currentUser && typeof currentUser.getDefaultBoardId === 'function'
? currentUser.getDefaultBoardId()
: null;
if (!homeId) return arr;
const homeBoard = ReactiveCache.getBoard(homeId);
if (!homeBoard || homeBoard.archived) return arr;
return [homeBoard, ...arr.filter((b) => b && b._id !== homeId)];
};
// #5799: in a sorted (non-custom) mode the server already computed the
// current page (filtered by menu/search and sorted), so render exactly that
// ordered page of board icons. Custom (manual drag order) falls through to
@@ -552,9 +567,11 @@ Template.boardList.helpers({
: 'custom';
if (sortMode !== 'custom') {
const paged = tpl.pagedBoardsVar.get();
return (paged.ids || [])
.map((id) => ReactiveCache.getBoard(id))
.filter(Boolean);
return withHomeFirst(
(paged.ids || [])
.map((id) => ReactiveCache.getBoard(id))
.filter(Boolean),
);
}
let list = boards;
@@ -591,11 +608,11 @@ Template.boardList.helpers({
}
if (currentUser && typeof currentUser.sortBoardsForUser === 'function') {
return currentUser.sortBoardsForUser(list);
return withHomeFirst(currentUser.sortBoardsForUser(list));
}
return list
.slice()
.sort((a, b) => (a.title || '').localeCompare(b.title || ''));
return withHomeFirst(
list.slice().sort((a, b) => (a.title || '').localeCompare(b.title || '')),
);
},
// #5174 / #4825: the board tiles' per-list card-count line and member avatar
// row. Data comes from the one-shot getAllBoardsTileData method fetch in
@@ -629,6 +646,11 @@ Template.boardList.helpers({
const user = ReactiveCache.getCurrentUser();
return user && user.hasStarred(this._id);
},
// #2220: is this the user's Home board (the one opened after login)?
isDefaultBoard() {
const user = ReactiveCache.getCurrentUser();
return user && user.isDefaultBoard(this._id);
},
isAdministrable() {
const user = ReactiveCache.getCurrentUser();
return user && user.isBoardAdmin(this._id);
@@ -916,8 +938,29 @@ Template.boardList.events({
Meteor.call('toggleBoardStar', boardId);
}
},
// #2220 Home-board toggle is disabled: setting a default board from the All
// Boards tiles is intentionally removed (no js-set-default-board handler).
// "Selected:" star action: star every multi-selected board that isn't yet
// starred (so it becomes Starred, never toggled back off by this button).
'click .js-star-selected'(evt) {
evt.preventDefault();
evt.stopPropagation();
const user = ReactiveCache.getCurrentUser();
BoardMultiSelection.getSelectedBoardIds().forEach((id) => {
if (user && !user.hasStarred(id)) {
Meteor.call('toggleBoardStar', id);
}
});
},
// #2220 "Selected:" home action: set the first selected board as the Home
// board (opened after login). Clicking it again when it is already Home clears
// it (toggle), matching toggleDefaultBoard.
'click .js-home-selected'(evt) {
evt.preventDefault();
evt.stopPropagation();
const ids = BoardMultiSelection.getSelectedBoardIds();
if (ids.length) {
Meteor.call('toggleDefaultBoard', ids[0]);
}
},
// HTML5 DnD from boards to spaces
// #5850: drag a (template) board onto an Org/Team/Domain target to share it.
'dragover .js-share-target'(evt) {
+4
View File
@@ -109,6 +109,10 @@
"allboards.delete-workspace-confirm": "Are you sure you want to delete this workspace?",
"allboards.delete-workspace-confirm-check": "Confirm workspace deletion",
"multi-selection-active": "Click checkboxes to select boards",
"selected-label": "Selected:",
"set-selected-starred": "Star the selected boards",
"set-selected-home": "Set as Home board (opened after login)",
"home-board-badge": "Home board (opened after login)",
"activity-dueDate": "edited due date to %s of %s",
"activity-endDate": "edited end date to %s of %s",
"add-attachment": "Add Attachment",
+4
View File
@@ -109,6 +109,10 @@
"allboards.delete-workspace-confirm": "Haluatko varmasti poistaa tämän työtilan?",
"allboards.delete-workspace-confirm-check": "Varmista työtilan poisto",
"multi-selection-active": "Valitse taulut napsauttamalla valintaruutuja",
"selected-label": "Valitut:",
"set-selected-starred": "Merkitse valitut taulut tähdellä",
"set-selected-home": "Aseta kotitauluksi (avautuu kirjautumisen jälkeen)",
"home-board-badge": "Kotitaulu (avautuu kirjautumisen jälkeen)",
"activity-dueDate": "muokkasi eräpäiväksi %s / %s",
"activity-endDate": "muokkasi loppumispäiväksi %s / %s",
"add-attachment": "Lisää liite",