Most Unicode Icons back to Font Awesome 4.7 for better accessibility. Less always visible buttons, More at ☰ Men.

Thanks to xet7 !
This commit is contained in:
Lauri Ojansivu 2026-01-28 12:59:07 +02:00
parent 440f553de0
commit 7ad04f4535
84 changed files with 1828 additions and 1381 deletions

View file

@ -79,7 +79,7 @@ ejson@1.1.3
logging@1.3.3
wekan-fullcalendar
momentjs:moment@2.29.3
# wekan-fontawesome
wekan-fontawesome
useraccounts:flow-routing-extra
ostrio:flow-router-extra

View file

@ -141,6 +141,7 @@ wekan-accounts-cas@0.1.0
wekan-accounts-lockout@1.0.0
wekan-accounts-oidc@1.0.10
wekan-accounts-sandstorm@0.8.0
wekan-fontawesome@6.4.2
wekan-fullcalendar@3.10.5
wekan-ldap@0.0.2
wekan-markdown@1.0.9

View file

@ -25,7 +25,8 @@ template(name="comment")
= text
.edit-controls
button.primary(type="submit") {{_ 'edit'}}
a.js-close-inlined-form(title="{{_ 'close' }}") ❌
a.js-close-inlined-form(title="{{_ 'close' }}")
i.fa.fa-times-thin
else
.comment-text
+viewer

View file

@ -3,7 +3,7 @@ template(name="boardConversionProgress")
.board-conversion-modal
.board-conversion-header
h3
| ⚙️
i.fa.fa-cog
| {{_ 'converting-board'}}
p {{_ 'converting-board-description'}}
@ -14,14 +14,14 @@ template(name="boardConversionProgress")
.progress-text {{conversionProgress}}%
.conversion-status
| ⚙️
i.fa.fa-cog
| {{conversionStatus}}
.conversion-time(style="{{#unless conversionEstimatedTime}}display: none;{{/unless}}")
| ⏰
i.fa.fa-clock-o
| {{_ 'estimated-time-remaining'}}: {{conversionEstimatedTime}}
.board-conversion-footer
.conversion-info
|
i.fa.fa-info-circle
| {{_ 'conversion-info-text'}}

View file

@ -1,6 +1,7 @@
template(name="archivedBoards")
h2
span(title="{{_ 'archived-boards'}}") 📦
span(title="{{_ 'archived-boards'}}")
i.fa.fa-archive
| {{_ 'archived-boards'}}
ul.archived-lists
@ -8,10 +9,10 @@ template(name="archivedBoards")
li.archived-lists-item
div.board-header-btns
button.board-header-btn.js-delete-board
| 🗑️
i.fa.fa-trash
| {{_ 'delete-board'}}
button.board-header-btn.js-restore-board
| ↩️
i.fa.fa-undo
| {{_ 'restore-board'}}
= title
span {{ moment archivedAt 'LLL' }}

View file

@ -339,9 +339,9 @@ BlazeComponent.extendComponent({
.js-add-card[tabindex] {
outline: none;
}
/* Hamburger menu */
.fa-bars, .icon-hamburger {
color: #222 !important;
/* Sidebar hamburger menu button in header */
.js-toggle-sidebar .fa-bars {
color: #fff !important;
}
/* Grey icons in card detail header */
.card-detail-header .fa, .card-detail-header .icon {

View file

@ -49,6 +49,12 @@ THEME - NEPHRITIS
border-bottom: 2px solid #27ae60;
border-right: 2px solid #27ae60;
}
.board-color-nephritis .checklist-progress-bar {
background-color: #d4f1dd !important;
}
.board-color-nephritis .checklist-progress-bar .checklist-progress {
background-color: #27ae60 !important;
}
.board-color-nephritis .is-multiselection-active .multi-selection-checkbox.is-checked + .minicard {
background: #e7faef;
}
@ -150,6 +156,12 @@ THEME - Pomegranate
border-bottom: 2px solid #c0392b;
border-right: 2px solid #c0392b;
}
.board-color-pomegranate .checklist-progress-bar {
background-color: #f5d5d2 !important;
}
.board-color-pomegranate .checklist-progress-bar .checklist-progress {
background-color: #c0392b !important;
}
.board-color-pomegranate .is-multiselection-active .multi-selection-checkbox.is-checked + .minicard {
background: #faeae9;
}
@ -251,6 +263,12 @@ THEME - Belize
border-bottom: 2px solid #2980b9;
border-right: 2px solid #2980b9;
}
.board-color-belize .checklist-progress-bar {
background-color: #d1e7f5 !important;
}
.board-color-belize .checklist-progress-bar .checklist-progress {
background-color: #2980b9 !important;
}
.board-color-belize .is-multiselection-active .multi-selection-checkbox.is-checked + .minicard {
background: #e8f3fa;
}
@ -352,6 +370,12 @@ THEME - Wisteria
border-bottom: 2px solid #8e44ad;
border-right: 2px solid #8e44ad;
}
.board-color-wisteria .checklist-progress-bar {
background-color: #e8d9f0 !important;
}
.board-color-wisteria .checklist-progress-bar .checklist-progress {
background-color: #8e44ad !important;
}
.board-color-wisteria .is-multiselection-active .multi-selection-checkbox.is-checked + .minicard {
background: #f4ecf7;
}
@ -453,6 +477,12 @@ THEME - Midnight
border-bottom: 2px solid #2c3e50;
border-right: 2px solid #2c3e50;
}
.board-color-midnight .checklist-progress-bar {
background-color: #d2dae2 !important;
}
.board-color-midnight .checklist-progress-bar .checklist-progress {
background-color: #2c3e50 !important;
}
.board-color-midnight .is-multiselection-active .multi-selection-checkbox.is-checked + .minicard {
background: #e6ecf1;
}
@ -554,6 +584,12 @@ THEME - Pumpkin
border-bottom: 2px solid #e67e22;
border-right: 2px solid #e67e22;
}
.board-color-pumpkin .checklist-progress-bar {
background-color: #f9e5d1 !important;
}
.board-color-pumpkin .checklist-progress-bar .checklist-progress {
background-color: #e67e22 !important;
}
.board-color-pumpkin .is-multiselection-active .multi-selection-checkbox.is-checked + .minicard {
background: #fdf2e9;
}
@ -655,6 +691,12 @@ THEME - Moderate Pink
border-bottom: 2px solid #cd5a91;
border-right: 2px solid #cd5a91;
}
.board-color-moderatepink .checklist-progress-bar {
background-color: #f4dde8 !important;
}
.board-color-moderatepink .checklist-progress-bar .checklist-progress {
background-color: #cd5a91 !important;
}
.board-color-moderatepink .is-multiselection-active .multi-selection-checkbox.is-checked + .minicard {
background: #faeef4;
}
@ -756,6 +798,12 @@ THEME - Strong Cyan
border-bottom: 2px solid #00aecc;
border-right: 2px solid #00aecc;
}
.board-color-strongcyan .checklist-progress-bar {
background-color: #ccf2f9 !important;
}
.board-color-strongcyan .checklist-progress-bar .checklist-progress {
background-color: #00aecc !important;
}
.board-color-strongcyan .is-multiselection-active .multi-selection-checkbox.is-checked + .minicard {
background: #e0fbff;
}
@ -857,6 +905,12 @@ THEME - Lime Green
border-bottom: 2px solid #4bbf6b;
border-right: 2px solid #4bbf6b;
}
.board-color-limegreen .checklist-progress-bar {
background-color: #daf4de !important;
}
.board-color-limegreen .checklist-progress-bar .checklist-progress {
background-color: #4bbf6b !important;
}
.board-color-limegreen .is-multiselection-active .multi-selection-checkbox.is-checked + .minicard {
background: #edf9f0;
}
@ -959,6 +1013,12 @@ THEME - Dark
border-bottom: 2px solid #2c3e51;
border-right: 2px solid #2c3e51;
}
.board-color-dark .checklist-progress-bar {
background-color: #d2dae2 !important;
}
.board-color-dark .checklist-progress-bar .checklist-progress {
background-color: #2c3e51 !important;
}
.board-color-dark .is-multiselection-active .multi-selection-checkbox.is-checked + .minicard {
background: #e6ecf1;
}
@ -1162,6 +1222,12 @@ THEME - Relax
border-bottom: 2px solid #27ae61;
border-right: 2px solid #27ae61;
}
.board-color-relax .checklist-progress-bar {
background-color: #d4f1dd !important;
}
.board-color-relax .checklist-progress-bar .checklist-progress {
background-color: #27ae61 !important;
}
.board-color-relax .is-multiselection-active .multi-selection-checkbox.is-checked + .minicard {
background: #e7faef;
}
@ -1292,6 +1358,12 @@ THEME - Corteza
border-bottom: 2px solid #568ba2;
border-right: 2px solid #568ba2;
}
.board-color-corteza .checklist-progress-bar {
background-color: #dce6ec !important;
}
.board-color-corteza .checklist-progress-bar .checklist-progress {
background-color: #568ba2 !important;
}
.board-color-corteza .is-multiselection-active .multi-selection-checkbox.is-checked + .minicard {
background: #eef3f6;
}
@ -1397,6 +1469,12 @@ THEME - Clear Blue
border-bottom: 2px solid #499bea;
border-right: 2px solid #499bea;
}
.board-color-clearblue .checklist-progress-bar {
background-color: #daeefb !important;
}
.board-color-clearblue .checklist-progress-bar .checklist-progress {
background-color: #499bea !important;
}
.board-color-clearblue .is-multiselection-active .multi-selection-checkbox.is-checked + .minicard {
background: #e0fbff;
}
@ -1660,6 +1738,12 @@ THEME - Natural
border-bottom: 2px solid #596557;
border-right: 2px solid #596557;
}
.board-color-natural .checklist-progress-bar {
background-color: #dee0dd !important;
}
.board-color-natural .checklist-progress-bar .checklist-progress {
background-color: #596557 !important;
}
.board-color-natural .is-multiselection-active .multi-selection-checkbox.is-checked + .minicard {
background: #eef0ee;
}
@ -1770,6 +1854,12 @@ THEME - Modern
border-bottom: 2px solid #2a80b8;
border-right: 2px solid #2a80b8;
}
.board-color-modern .checklist-progress-bar {
background-color: #d1e7f5 !important;
}
.board-color-modern .checklist-progress-bar .checklist-progress {
background-color: #2a80b8 !important;
}
.board-color-modern .is-multiselection-active .multi-selection-checkbox.is-checked + .minicard {
background: #e8f3fa;
}
@ -2062,6 +2152,12 @@ THEME - Modern Dark
border-bottom: 2px solid #2a2a2a;
border-right: 2px solid #2a2a2a;
}
.board-color-moderndark .checklist-progress-bar {
background-color: #d1d1d1 !important;
}
.board-color-moderndark .checklist-progress-bar .checklist-progress {
background-color: #2a2a2a !important;
}
.board-color-moderndark .is-multiselection-active .multi-selection-checkbox.is-checked + .minicard {
background: #eaeaea;
}
@ -2547,6 +2643,12 @@ THEME - Exodark
border-bottom: 2px solid #dbdbdb!important;/*Fix contrast of checkbox*/
border-right: 2px solid #dbdbdb!important;
}
.board-color-exodark .checklist-progress-bar {
background-color: #cccccc !important;
}
.board-color-exodark .checklist-progress-bar .checklist-progress {
background-color: #222 !important;
}
.board-color-exodark .is-multiselection-active .multi-selection-checkbox.is-checked + .minicard {
background: #e9e9e9;
}
@ -3140,6 +3242,12 @@ THEME - Clean Dark
margin-left: 3px;
margin-top: 3px;
}
.board-color-cleandark .checklist-progress-bar {
background-color: #6b6b78 !important;
}
.board-color-cleandark .checklist-progress-bar .checklist-progress {
background-color: #23232B !important;
}
.board-color-cleandark .allBoards {
white-space: nowrap;
@ -3892,6 +4000,13 @@ THEME - Clean Light
margin-left: 3px;
margin-top: 3px;
}
.board-color-cleanlight .checklist-progress-bar {
background-color: #f5f5f5 !important;
}
.board-color-cleanlight .checklist-progress-bar .checklist-progress {
background-color: #c0c0c0 !important;
color: #010101 !important;
}
.board-color-cleanlight .allBoards {
white-space: nowrap;

View file

@ -14,41 +14,39 @@ template(name="boardHeaderBar")
with currentBoard
if currentUser.isBoardAdmin
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
a.board-header-btn(
class="{{#if currentUser.isBoardAdmin}}js-change-visibility{{else}}is-disabled{{/if}}"
title="{{_ currentBoard.permission}}")
| {{#if currentBoard.isPublic}}🌐{{else}}🔒{{/if}}
i.fa(class="{{#if currentBoard.isPublic}}fa-globe{{else}}fa-lock{{/if}}")
span {{_ currentBoard.permission}}
a.board-header-btn.js-watch-board(
title="{{_ watchLevel }}")
if $eq watchLevel "watching"
| 👁️
i.fa.fa-eye
if $eq watchLevel "tracking"
| 🔔
i.fa.fa-bell
if $eq watchLevel "muted"
| 🔕
i.fa.fa-bell-slash
span {{_ watchLevel}}
a.board-header-btn.js-star-board(title="{{_ 'star-board'}}")
if isStarred
| ⭐
else
| ☆
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}}")
if showStarCounter
span.board-star-counter {{currentBoard.stars}}
a.board-header-btn(title="{{_ 'sort-cards'}}" class="{{#if isSortActive }}emphasis{{else}} js-sort-cards {{/if}}")
| {{sortCardsIcon}}
i.fa.fa-sort
span {{#if isSortActive }}{{_ 'sort-is-on'}}{{else}}{{_ 'sort-cards'}}{{/if}}
if isSortActive
a.board-header-btn-close.js-sort-reset(title="{{_ 'remove-sort'}}")
| ❌
i.fa.fa-times-thin
else
a.board-header-btn.js-log-in(
title="{{_ 'log-in'}}")
| 🚪
i.fa.fa-sign-in
span {{_ 'log-in'}}
.board-header-btns.center
@ -59,41 +57,40 @@ template(name="boardHeaderBar")
if currentUser
with currentBoard
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
a.board-header-btn(
class="{{#if currentUser.isBoardAdmin}}js-change-visibility{{else}}is-disabled{{/if}}"
title="{{_ currentBoard.permission}}")
| {{#if currentBoard.isPublic}}🌐{{else}}🔒{{/if}}
i.fa(class="{{#if currentBoard.isPublic}}fa-globe{{else}}fa-lock{{/if}}")
a.board-header-btn.js-watch-board(
title="{{_ watchLevel }}")
if $eq watchLevel "watching"
| 👁️
i.fa.fa-eye
if $eq watchLevel "tracking"
| 🔔
i.fa.fa-bell
if $eq watchLevel "muted"
| 🔕
a.board-header-btn.js-star-board(title="{{_ 'star-board'}}")
if isStarred
| ⭐
else
| ☆
i.fa.fa-bell-slash
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}}")
a.board-header-btn(title="{{_ 'sort-cards'}}" class="{{#if isSortActive }}emphasis{{else}} js-sort-cards {{/if}}")
| {{sortCardsIcon}}
i.fa.fa-sort
span {{#if isSortActive }}{{_ 'sort-is-on'}}{{else}}{{_ 'sort-cards'}}{{/if}}
if isSortActive
a.board-header-btn-close.js-sort-reset(title="{{_ 'remove-sort'}}")
| ❌
i.fa.fa-times-thin
else
a.board-header-btn.js-log-in(
title="{{_ 'log-in'}}")
| 🚪
i.fa.fa-sign-in
if isSandstorm
if currentUser
a.board-header-btn.js-open-archived-board
| 📦
i.fa.fa-archive
//if showSort
// a.board-header-btn.js-open-sort-view(title="{{_ 'sort-desc'}}")
@ -103,72 +100,68 @@ template(name="boardHeaderBar")
a.board-header-btn.js-open-filter-view(
title="{{#if Filter.isActive}}{{_ 'filter-on-desc'}}{{else}}{{_ 'filter'}}{{/if}}"
class="{{#if Filter.isActive}}js-filter-active{{/if}}")
| 🎛️
i.fa.fa-filter
span {{#if Filter.isActive}}{{_ 'filter-on-desc'}}{{else}}{{_ 'filter'}}{{/if}}
if Filter.isActive
a.board-header-btn-close.js-filter-reset(title="{{_ 'filter-clear'}}")
| ❌
i.fa.fa-times-thin
a.board-header-btn.js-open-search-view(title="{{_ 'search'}}")
| 🔍
i.fa.fa-search
span {{_ 'search'}}
unless currentBoard.isTemplatesBoard
a.board-header-btn.js-toggle-board-view(
title="{{_ 'board-view'}}")
| ▼
a.board-header-btn.js-toggle-board-view
i.fa.fa-caret-down
if $eq boardView 'board-view-swimlanes'
| 🏊
i.fa.fa-th-large
if $eq boardView 'board-view-lists'
| 📋
i.fa.fa-trello
if $eq boardView 'board-view-cal'
| 📅
i.fa.fa-calendar
if $eq boardView 'board-view-gantt'
| 📊
i.fa.fa-bar-chart
span
if $eq boardView 'board-view-swimlanes'
| {{_ 'board-view-swimlanes'}}
| {{_ 'swimlanes'}}
if $eq boardView 'board-view-lists'
| {{_ 'board-view-lists'}}
| {{_ 'lists'}}
if $eq boardView 'board-view-cal'
| {{_ 'board-view-cal'}}
| {{_ 'calendar'}}
if $eq boardView 'board-view-gantt'
| {{_ 'board-view-gantt'}}
| {{_ 'gantt'}}
if canModifyBoard
a.board-header-btn.js-multiselection-activate(
title="{{#if MultiSelection.isActive}}{{_ 'multi-selection-on'}}{{else}}{{_ 'multi-selection'}}{{/if}}"
class="{{#if MultiSelection.isActive}}js-multiselection-active{{/if}}")
if MultiSelection.isActive
| 🗂️
else
| 🗂️
class="{{#if MultiSelection.isActive}}emphasis{{/if}}")
i.fa.fa-check-square-o
span {{#if MultiSelection.isActive}}{{_ 'multi-selection-on'}}{{else}}{{_ 'multi-selection'}}{{/if}}
if MultiSelection.isActive
a.board-header-btn-close.js-multiselection-reset(title="{{_ 'multi-selection-off'}}")
| ❌
a.board-header-btn-close.js-multiselection-reset(title="{{_ 'filter-clear'}}")
i.fa.fa-times-thin
.separator
a.board-header-btn.js-toggle-sidebar(title="{{_ 'sidebar-open'}} {{_ 'or'}} {{_ 'sidebar-close'}}")
| ☰
i.fa.fa-bars
template(name="boardVisibilityList")
ul.pop-over-list
li
with "private"
a.js-select-visibility
| 🔒
i.fa.fa-lock
| {{_ 'private'}}
if visibilityCheck
| ✅
i.fa.fa-check
span.sub-name {{_ 'private-desc'}}
if notAllowPrivateVisibilityOnly
li
with "public"
a.js-select-visibility
| 🌐
i.fa.fa-globe
| {{_ 'public'}}
if visibilityCheck
| ✅
i.fa.fa-check
span.sub-name {{_ 'public-desc'}}
template(name="boardChangeVisibilityPopup")
@ -179,26 +172,26 @@ template(name="boardChangeWatchPopup")
li
with "watching"
a.js-select-watch
| 👁️
i.fa.fa-eye
| {{_ 'watching'}}
if watchCheck
| ✅
i.fa.fa-check
span.sub-name {{_ 'watching-info'}}
li
with "tracking"
a.js-select-watch
| 🔔
i.fa.fa-bell
| {{_ 'tracking'}}
if watchCheck
| ✅
i.fa.fa-check
span.sub-name {{_ 'tracking-info'}}
li
with "muted"
a.js-select-watch
| 🔕
i.fa.fa-bell-slash
| {{_ 'muted'}}
if watchCheck
| ✅
i.fa.fa-check
span.sub-name {{_ 'muted-info'}}
template(name="boardChangeViewPopup")
@ -206,31 +199,31 @@ template(name="boardChangeViewPopup")
li
with "board-view-swimlanes"
a.js-open-swimlanes-view
| 🏊
| {{_ 'board-view-swimlanes'}}
i.fa.fa-th-large
| {{_ 'swimlanes'}}
if $eq Utils.boardView "board-view-swimlanes"
| ✅
i.fa.fa-check
li
with "board-view-lists"
a.js-open-lists-view
| 📋
i.fa.fa-trello
| {{_ 'board-view-lists'}}
if $eq Utils.boardView "board-view-lists"
| ✅
i.fa.fa-check
li
with "board-view-cal"
a.js-open-cal-view
| 📅
i.fa.fa-calendar
| {{_ 'board-view-cal'}}
if $eq Utils.boardView "board-view-cal"
| ✅
i.fa.fa-check
li
with "board-view-gantt"
a.js-open-gantt-view
| 📊
i.fa.fa-bar-chart
| {{_ 'board-view-gantt'}}
if $eq Utils.boardView "board-view-gantt"
| ✅
i.fa.fa-check
template(name="createBoard")
form
@ -242,11 +235,11 @@ template(name="createBoard")
else
p.quiet
if $eq visibility.get 'public'
span 🌐
span.fa.fa-globe.colorful
= " "
| {{{_ 'board-public-info'}}}
else
span 🔒
span.fa.fa-lock.colorful
= " "
| {{{_ 'board-private-info'}}}
a.js-change-visibility {{_ 'change'}}.
@ -271,11 +264,11 @@ template(name="createBoardPopup")
else
p.quiet
if $eq visibility.get 'public'
span 🌐
span.fa.fa-globe.colorful
= " "
| {{{_ 'board-public-info'}}}
else
span 🔒
span.fa.fa-lock.colorful
= " "
| {{{_ 'board-private-info'}}}
a.js-change-visibility {{_ 'change'}}.
@ -301,11 +294,11 @@ template(name="createTemplateContainerPopup")
else
p.quiet
if $eq visibility.get 'public'
span 🌐
span.fa.fa-globe.colorful
= " "
| {{{_ 'board-public-info'}}}
else
span 🔒
span.fa.fa-lock.colorful
= " "
| {{{_ 'board-private-info'}}}
a.js-change-visibility {{_ 'change'}}.
@ -332,8 +325,7 @@ template(name="createTemplateContainerPopup")
// | {{#if $eq Direction "fa-arrow-up"}}⬆️{{else}}⬇️{{/if}}
// | {{_ value.label }}{{_ value.shortLabel}}
// if $eq sortby value.name
// | ✅
// i.fa.fa-check
template(name="boardChangeTitlePopup")
form
label
@ -353,21 +345,21 @@ template(name="cardsSortPopup")
ul.pop-over-list
li
a.js-sort-due
| 📅
i.fa.fa-calendar
| {{_ 'due-date'}}
hr
li
a.js-sort-title
| 🔤
i.fa.fa-sort-alpha-asc
| {{_ 'title-alphabetically'}}
hr
li
a.js-sort-created-desc
| ⬇️
i.fa.fa-arrow-down
| {{_ 'created-at-newest-first'}}
hr
li
a.js-sort-created-asc
| ⬆️
i.fa.fa-arrow-up
| {{_ 'created-at-oldest-first'}}

View file

@ -436,10 +436,17 @@
background-color: #999; /* Darker background for better text contrast */
border-radius: 3px;
padding: 36px 8px 32px 8px;
color: #fff; /* White text */
}
.board-list .js-add-board .label i {
color: #fff; /* White icon */
}
.board-list .js-add-board .label:hover {
background-color: #808080; /* Even darker on hover */
}
.board-list .js-add-board .label:hover i {
color: #fff; /* Keep icon white on hover */
}
.board-list .is-star-active,
.board-list .is-not-star-active {
top: 0;

View file

@ -9,24 +9,28 @@ template(name="boardList")
li(class="menu-item {{#if isSelectedMenu 'starred'}}active{{/if}}")
a.js-select-menu(data-type="starred")
span.menu-label
span.emoji-icon ⭐
span.emoji-icon
i.fa.fa-star
| {{_ 'allboards.starred'}}
span.menu-count {{menuItemCount 'starred'}}
li(class="menu-item {{#if isSelectedMenu 'templates'}}active{{/if}}")
a.js-select-menu(data-type="templates")
span.menu-label
span.emoji-icon 📋
span.emoji-icon
i.fa.fa-clipboard
| {{_ 'allboards.templates'}}
span.menu-count {{menuItemCount 'templates'}}
li(class="menu-item {{#if isSelectedMenu 'remaining'}}active{{/if}}")
a.js-select-menu(data-type="remaining")
span.menu-label
span.emoji-icon 📂
span.emoji-icon
i.fa.fa-folder
| {{_ 'allboards.remaining'}}
span.menu-count {{menuItemCount 'remaining'}}
.workspaces-header
span
span.emoji-icon 🗂️
span.emoji-icon
i.fa.fa-folder-open
| {{_ 'allboards.workspaces'}}
a.js-add-workspace(title="{{_ 'allboards.add-workspace'}}") +
// Workspaces tree
@ -51,11 +55,13 @@ template(name="boardList")
li.AllBoardBtns
div.AllBoardButtonsContainer
if userHasOrgsOrTeams
span.emoji-icon 🔍
span.emoji-icon
i.fa.fa-search
input#filterBtn(type="button" value="{{_ 'filter'}}")
button#resetBtn.filter-reset-btn
span.reset-icon
span.emoji-icon ❌
span.emoji-icon
i.fa.fa-times-thin
span {{_ 'filter-clear'}}
// Right boards grid
@ -66,34 +72,41 @@ template(name="boardList")
span.path-text {{currentMenuPath.text}}
if BoardMultiSelection.isActive
span.multiselection-hint
span.emoji-icon 📌
span.emoji-icon
i.fa.fa-thumb-tack
| {{_ 'multi-selection-active'}}
.path-right
if canModifyBoards
if hasBoardsSelected
button.js-archive-selected-boards.board-header-btn
span.emoji-icon 📦
span.emoji-icon
i.fa.fa-archive
span {{_ 'archive-board'}}
button.js-duplicate-selected-boards.board-header-btn
span.emoji-icon 📋
span.emoji-icon
i.fa.fa-clipboard
span {{_ 'duplicate-board'}}
a.board-header-btn.js-multiselection-activate(
title="{{#if BoardMultiSelection.isActive}}{{_ 'multi-selection-on'}}{{else}}{{_ 'multi-selection'}}{{/if}}"
class="{{#if BoardMultiSelection.isActive}}emphasis{{/if}}")
span.emoji-icon ☑️
span.emoji-icon
i.fa.fa-check-square-o
if BoardMultiSelection.isActive
a.board-header-btn-close.js-multiselection-reset(title="{{_ 'filter-clear'}}")
span.emoji-icon ✖
span.emoji-icon
i.fa.fa-times
ul.board-list.clearfix.js-boards(class="{{#if isMiniScreen}}mobile-view{{/if}} {{#if BoardMultiSelection.isActive}}is-multiselection-active{{/if}}")
li.js-add-board
if isSelectedMenu 'templates'
a.board-list-item.label(title="{{_ 'add-template-container'}}")
span.emoji-icon
| {{_ 'add-template-container'}}
span.emoji-icon
i.fa.fa-plus
|  {{_ 'add-template-container'}}
else
a.board-list-item.label(title="{{_ 'add-board'}}")
span.emoji-icon
| {{_ 'add-board'}}
span.emoji-icon
i.fa.fa-plus
|  {{_ 'add-board'}}
each boards
li.js-board(class="{{_id}} {{#if isStarred}}starred{{/if}} {{colorClass}} {{#if BoardMultiSelection.isSelected _id}}is-checked{{/if}}", draggable="true")
if isInvited
@ -118,7 +131,8 @@ template(name="boardList")
.materialCheckBox.multi-selection-checkbox.js-toggle-board-multi-selection(
class="{{#if BoardMultiSelection.isSelected _id}}is-checked{{/if}}")
span.board-handle(title="{{_ 'drag-board'}}")
span.emoji-icon ↕️
span.emoji-icon
i.fa.fa-arrows
a.js-open-board(href="{{pathFor 'board' id=_id slug=slug}}")
span.details
@ -132,19 +146,21 @@ template(name="boardList")
span.js-has-spenttime-cards(
class="{{#if hasOvertimeCards}}has-overtime-card-active{{else}}no-overtime-card-active{{/if}}"
title="{{#if hasOvertimeCards}}{{_ 'has-overtime-cards'}}{{else}}{{_ 'has-spenttime-cards'}}{{/if}}")
span.emoji-icon ⏱️
span.emoji-icon
i.fa.fa-clock-o
span.js-star-board(
class="{{#if isStarred}}is-star-active{{else}}is-not-star-active{{/if}}"
title="{{_ 'star-board-title'}}")
span.emoji-icon
| {{#if isStarred}}⭐{{else}}☆{{/if}}
i.fa(class="fa-star{{#unless isStarred}}-o{{/unless}}")
else
.board-list-item
if BoardMultiSelection.isActive
.materialCheckBox.multi-selection-checkbox.js-toggle-board-multi-selection(
class="{{#if BoardMultiSelection.isSelected _id}}is-checked{{/if}}")
span.board-handle(title="{{_ 'drag-board'}}")
span.emoji-icon ↕️
span.emoji-icon
i.fa.fa-arrows
a.js-open-board(href="{{pathFor 'board' id=_id slug=slug}}")
span.details
@ -170,12 +186,13 @@ template(name="boardList")
span.js-has-spenttime-cards(
class="{{#if hasOvertimeCards}}has-overtime-card-active{{else}}no-overtime-card-active{{/if}}"
title="{{#if hasOvertimeCards}}{{_ 'has-overtime-cards'}}{{else}}{{_ 'has-spenttime-cards'}}{{/if}}")
span.emoji-icon ⏱️
span.emoji-icon
i.fa.fa-clock-o
a.js-star-board(
class="{{#if isStarred}}is-star-active{{else}}is-not-star-active{{/if}}"
title="{{_ 'star-board-title'}}")
span.emoji-icon
| {{#if isStarred}}⭐{{else}}☆{{/if}}
i.fa(class="fa-star{{#unless isStarred}}-o{{/unless}}")
template(name="boardListHeaderBar")
h1 {{_ title }}
@ -195,7 +212,8 @@ template(name="workspaceTree")
li.workspace-node(class="{{#if $eq id selectedWorkspaceId}}active{{/if}}" data-workspace-id="{{id}}" draggable="true")
.workspace-node-content
span.workspace-drag-handle
span.emoji-icon ↕️
span.emoji-icon
i.fa.fa-arrows
a.js-select-workspace(data-id="{{id}}")
span.workspace-icon
@ -203,10 +221,12 @@ template(name="workspaceTree")
+viewer
= icon
else
span.emoji-icon 📁
span.emoji-icon
i.fa.fa-folder
span.workspace-name= name
a.js-edit-workspace(data-id="{{id}}" title="{{_ 'allboards.edit-workspace'}}")
span.emoji-icon ✏️
span.emoji-icon
i.fa.fa-pencil-square-o
span.workspace-count {{workspaceCount id}}
a.js-add-subworkspace(data-id="{{id}}" title="{{_ 'allboards.add-subworkspace'}}") +
if children

View file

@ -197,48 +197,66 @@ BlazeComponent.extendComponent({
return ret;
},
currentMenuPath() {
const selectedMenuVar = this.selectedMenu;
if (!selectedMenuVar) {
return { icon: '🗂️', text: TAPi18n.__('allboards.workspaces') };
}
const sel = selectedMenuVar.get();
const currentUser = ReactiveCache.getCurrentUser();
// Helper to find space by id in tree
const findSpaceById = (nodes, targetId, path = []) => {
for (const node of nodes) {
if (node.id === targetId) {
return [...path, node];
}
if (node.children && node.children.length > 0) {
const result = findSpaceById(node.children, targetId, [
...path,
node,
]);
if (result) return result;
}
try {
const selectedMenuVar = this.selectedMenu;
if (!selectedMenuVar || typeof selectedMenuVar.get !== 'function') {
return { icon: '🗂️', text: 'Workspaces' };
}
return null;
};
const sel = selectedMenuVar.get();
const currentUser = ReactiveCache.getCurrentUser();
if (sel === 'starred') {
return { icon: '⭐', text: TAPi18n.__('allboards.starred') };
} else if (sel === 'templates') {
return { icon: '📋', text: TAPi18n.__('allboards.templates') };
} else if (sel === 'remaining') {
return { icon: '📂', text: TAPi18n.__('allboards.remaining') };
} else {
// sel is a workspaceId, build path
const tree = this.workspacesTreeVar.get();
const spacePath = findSpaceById(tree, sel);
if (spacePath && spacePath.length > 0) {
const pathText = spacePath.map((s) => s.name).join(' / ');
return {
icon: '🗂️',
text: `${TAPi18n.__('allboards.workspaces') || 'Workspaces'} / ${pathText}`,
};
// Helper function to safely get translation or fallback
const safeTranslate = (key, fallback) => {
try {
return TAPi18n.__(key) || fallback;
} catch (e) {
return fallback;
}
};
// Helper to find space by id in tree
const findSpaceById = (nodes, targetId, path = []) => {
if (!nodes || !Array.isArray(nodes)) return null;
for (const node of nodes) {
if (node.id === targetId) {
return [...path, node];
}
if (node.children && node.children.length > 0) {
const result = findSpaceById(node.children, targetId, [
...path,
node,
]);
if (result) return result;
}
}
return null;
};
if (sel === 'starred') {
return { icon: '⭐', text: safeTranslate('allboards.starred', 'Starred') };
} else if (sel === 'templates') {
return { icon: '📋', text: safeTranslate('allboards.templates', 'Templates') };
} else if (sel === 'remaining') {
return { icon: '📂', text: safeTranslate('allboards.remaining', 'Remaining') };
} else {
// sel is a workspaceId, build path
if (!this.workspacesTreeVar || typeof this.workspacesTreeVar.get !== 'function') {
return { icon: '🗂️', text: safeTranslate('allboards.workspaces', 'Workspaces') };
}
const tree = this.workspacesTreeVar.get();
const spacePath = findSpaceById(tree, sel);
if (spacePath && spacePath.length > 0) {
const pathText = spacePath.map((s) => s.name).join(' / ');
return {
icon: '🗂️',
text: `${safeTranslate('allboards.workspaces', 'Workspaces')} / ${pathText}`,
};
}
return { icon: '🗂️', text: safeTranslate('allboards.workspaces', 'Workspaces') };
}
return { icon: '🗂️', text: TAPi18n.__('allboards.workspaces') };
} catch (error) {
console.error('Error in currentMenuPath:', error);
return { icon: '🗂️', text: 'Workspaces' };
}
},
boards() {

View file

@ -3,6 +3,7 @@ template(name="miniboard")
class="minicard-{{colorClass}}")
.minicard-title
.handle
span.drag-handle(title="{{_ 'dragBoard'}}") ↕️
span.drag-handle(title="{{_ 'dragBoard'}}")
i.fa.fa-arrows
+viewer
= title

View file

@ -55,6 +55,12 @@
flex-direction: row;
align-items: center;
}
.attachment-actions a {
margin-left: 16px;
}
.attachment-actions a:first-child {
margin-left: 0;
}
.add-attachment {
display: flex;
align-items: center;
@ -106,6 +112,9 @@
color: white;
cursor: pointer;
font-size: 4em;
position: absolute;
right: 50px;
top: 16px;
}
/* Upload progress indicators for drag-and-drop uploads */
@ -241,10 +250,6 @@
.js-card-details.is-dragging-over {
border: 2px dashed #007bff !important;
background: rgba(0, 123, 255, 0.05) !important;
}
top: 0;
right: 8px;
position: absolute;
}
.attachment-arrow {
font-size: 4em;
@ -253,6 +258,20 @@
align-self: center;
margin: 0 20px;
}
#prev-attachment {
font-size: 4em;
color: white;
cursor: pointer;
align-self: center;
margin-left: 70px;
}
#next-attachment {
font-size: 4em;
color: white;
cursor: pointer;
align-self: center;
margin-right: 70px;
}
#viewer-content {
display: flex;
justify-content: center;
@ -266,6 +285,13 @@
max-width: 100%;
max-height: 100%;
}
#video-viewer {
max-width: 100%;
max-height: 100%;
}
#audio-viewer {
max-width: 100%;
}
#pdf-viewer {
width: 40vw;
height: 100%;
@ -300,9 +326,19 @@
}
#prev-attachment {
left: 0;
position: absolute;
bottom: 2.2em;
font-size: 1.6em;
padding: 16px;
margin-left: 0;
}
#next-attachment {
right: 0;
position: absolute;
bottom: 2.2em;
font-size: 1.6em;
padding: 16px;
margin-right: 0;
}
#pdf-viewer {
width: 100%;

View file

@ -34,10 +34,11 @@ template(name="attachmentViewer")
#viewer-overlay.hidden
#viewer-top-bar
span#attachment-name
a#viewer-close ❌
a#viewer-close
i.fa.fa-times-thin
#viewer-container
| ◀️
i.fa.fa-caret-left#prev-attachment
#viewer-content
img#image-viewer.hidden
video#video-viewer.hidden(controls="true")
@ -45,7 +46,7 @@ template(name="attachmentViewer")
object#pdf-viewer.hidden(type="application/pdf")
span.pdf-preview-error {{_ 'preview-pdf-not-supported' }}
object#txt-viewer.hidden(type="text/plain")
| ▶️
i.fa.fa-caret-right#next-attachment
template(name="attachmentGallery")
@ -53,7 +54,7 @@ template(name="attachmentGallery")
if canModifyCard
a.attachment-item.add-attachment.js-add-attachment
|
i.fa.fa-plus
each attachments
@ -87,22 +88,21 @@ template(name="attachmentGallery")
span.file-size ({{fileSize size}})
.attachment-actions
a.js-download(href="{{link}}?download=true", download="{{name}}", title="{{_ 'download'}}")
| ⬇️
i.fa.fa-arrow-down
if currentUser.isBoardMember
unless currentUser.isCommentOnly
unless currentUser.isWorker
a.js-rename(title="{{_ 'rename'}}")
| ✏️
i.fa.fa-pencil-square-o
a.js-confirm-delete(title="{{_ 'delete'}}")
| 🗑️
i.fa.fa-trash
a.js-open-attachment-menu(data-attachment-link="{{link}}", title="{{_ 'attachmentActionsPopup-title'}}")
| ☰
i.fa.fa-bars
// Migration spinner overlay
if isAttachmentMigrating _id
.attachment-migration-overlay
.migration-spinner
| ⚙️
i.fa.fa-cog.fa-spin
.migration-text {{_ 'migrating-attachment'}}
template(name="attachmentActionsPopup")
@ -110,16 +110,12 @@ template(name="attachmentActionsPopup")
li
if isImage
a(class="{{#if isCover}}js-remove-cover{{else}}js-add-cover{{/if}}")
| 📖
| 🖼️
if isCover
| {{_ 'remove-cover'}}
else
| {{_ 'add-cover'}}
i.fa.fa-picture-o
| {{#if isCover}}{{_ 'remove-cover'}}{{else}}{{_ 'add-cover'}}{{/if}}
if currentUser.isBoardAdmin
if isImage
a(class="{{#if isBackgroundImage}}js-remove-background-image{{else}}js-add-background-image{{/if}}")
| 🖼️
i.fa.fa-picture-o
if isBackgroundImage
| {{_ 'remove-background-image'}}
else
@ -127,19 +123,19 @@ template(name="attachmentActionsPopup")
if $neq versions.original.storage "fs"
a.js-move-storage-fs
| ▶️
i.fa.fa-arrow-right
| {{_ 'attachment-move-storage-fs'}}
if $neq versions.original.storage "gridfs"
if versions.original.storage
a.js-move-storage-gridfs
| ▶️
i.fa.fa-arrow-right
| {{_ 'attachment-move-storage-gridfs'}}
if $neq versions.original.storage "s3"
if versions.original.storage
a.js-move-storage-s3
| ▶️
i.fa.fa-arrow-right
| {{_ 'attachment-move-storage-s3'}}
template(name="attachmentRenamePopup")

View file

@ -6,10 +6,10 @@ template(name="cardCustomFieldsPopup")
span.full-name
= name
if hasCustomField
| ✅
i.fa.fa-check
hr
a.quiet-button.full.js-settings
| ⚙️
i.fa.fa-cog
span {{_ 'settings'}}
template(name="cardCustomField")
@ -55,9 +55,11 @@ template(name="cardCustomField-number")
template(name="cardCustomField-checkbox")
.js-checklist-item.checklist-item(class="{{#if data.value }}is-checked{{/if}}")
if canModifyCard
span.check-box-unicode {{#if data.value }}✅{{else}}⬜{{/if}}
span.check-box-unicode
i.fa(class="{{#if data.value}}fa-check-square{{else}}fa-square-o{{/if}}")
else
span.check-box-unicode {{#if data.value }}✅{{else}}⬜{{/if}}
span.check-box-unicode
i.fa(class="{{#if data.value}}fa-check-square{{else}}fa-square-o{{/if}}")
template(name="cardCustomField-currency")
if canModifyCard

View file

@ -95,58 +95,61 @@ template(name="minicardCustomFieldDate")
| {{showWeek}}
template(name="editCardReceivedDatePopup")
form.edit-card-received-date
.datepicker
// Date input field (existing)
// Insert calendar selector right after date input
.calendar-selector
label(for="calendar-received") 🗓️
input#calendar-received.js-calendar-date(type="date")
// Time input field (if present)
.clear-date
a.js-clear-date {{_ 'clear'}}
.datepicker-actions
button.primary.wide.left(type="submit") {{_ 'save'}}
button.js-delete-date.negate.wide.right {{_ 'delete'}}
.datepicker-container
form.edit-date
.fields
.left
label(for="date") {{_ 'date'}}
input.js-date-field#date(type="date" name="date" value=showDate autofocus)
.right
label(for="time") {{_ 'time'}}
input.js-time-field#time(type="time" name="time" value=showTime)
if error.get
.warning {{_ error.get}}
button.primary.wide.left.js-submit-date(type="submit") {{_ 'save'}}
button.js-delete-date.negate.wide.right.js-delete-date {{_ 'delete'}}
template(name="editCardStartDatePopup")
form.edit-card-start-date
.datepicker
// Date input field (existing)
.calendar-selector
label(for="calendar-start") 🗓️
input#calendar-start.js-calendar-date(type="date")
// Time input field (if present)
.clear-date
a.js-clear-date {{_ 'clear'}}
.datepicker-actions
button.primary.wide.left(type="submit") {{_ 'save'}}
button.js-delete-date.negate.wide.right {{_ 'delete'}}
.datepicker-container
form.edit-date
.fields
.left
label(for="date") {{_ 'date'}}
input.js-date-field#date(type="date" name="date" value=showDate autofocus)
.right
label(for="time") {{_ 'time'}}
input.js-time-field#time(type="time" name="time" value=showTime)
if error.get
.warning {{_ error.get}}
button.primary.wide.left.js-submit-date(type="submit") {{_ 'save'}}
button.js-delete-date.negate.wide.right.js-delete-date {{_ 'delete'}}
template(name="editCardDueDatePopup")
form.edit-card-due-date
.datepicker
// Date input field (existing)
.calendar-selector
label(for="calendar-due") 🗓️
input#calendar-due.js-calendar-date(type="date")
// Time input field (if present)
.clear-date
a.js-clear-date {{_ 'clear'}}
.datepicker-actions
button.primary.wide.left(type="submit") {{_ 'save'}}
button.js-delete-date.negate.wide.right {{_ 'delete'}}
.datepicker-container
form.edit-date
.fields
.left
label(for="date") {{_ 'date'}}
input.js-date-field#date(type="date" name="date" value=showDate autofocus)
.right
label(for="time") {{_ 'time'}}
input.js-time-field#time(type="time" name="time" value=showTime)
if error.get
.warning {{_ error.get}}
button.primary.wide.left.js-submit-date(type="submit") {{_ 'save'}}
button.js-delete-date.negate.wide.right.js-delete-date {{_ 'delete'}}
template(name="editCardEndDatePopup")
form.edit-card-end-date
.datepicker
// Date input field (existing)
.calendar-selector
label(for="calendar-end") 🗓️
input#calendar-end.js-calendar-date(type="date")
// Time input field (if present)
.clear-date
a.js-clear-date {{_ 'clear'}}
.datepicker-actions
button.primary.wide.left(type="submit") {{_ 'save'}}
button.js-delete-date.negate.wide.right {{_ 'delete'}}
.datepicker-container
form.edit-date
.fields
.left
label(for="date") {{_ 'date'}}
input.js-date-field#date(type="date" name="date" value=showDate autofocus)
.right
label(for="time") {{_ 'time'}}
input.js-time-field#time(type="time" name="time" value=showTime)
if error.get
.warning {{_ error.get}}
button.primary.wide.left.js-submit-date(type="submit") {{_ 'save'}}
button.js-delete-date.negate.wide.right.js-delete-date {{_ 'delete'}}

View file

@ -47,22 +47,6 @@ import {
this.data().getStart() && this.date.set(new Date(this.data().getStart()));
}
onRendered() {
super.onRendered();
// DatePicker base class handles initialization with native HTML inputs
const self = this;
this.$('.js-calendar-date').on('change', function(evt) {
const currentUser = ReactiveCache.getCurrentUser && ReactiveCache.getCurrentUser();
const dateFormat = currentUser ? currentUser.getDateFormat() : 'YYYY-MM-DD';
const value = evt.target.value;
if (value) {
// Format date according to user preference
const formatted = formatDateByUserPreference(new Date(value), dateFormat, true);
self._storeDate(new Date(value));
}
});
}
_storeDate(date) {
this.card.setStart(formatDateTime(date));
}
@ -79,11 +63,6 @@ import {
this.data().getDue() && this.date.set(new Date(this.data().getDue()));
}
onRendered() {
super.onRendered();
// DatePicker base class handles initialization with native HTML inputs
}
_storeDate(date) {
this.card.setDue(formatDateTime(date));
}
@ -100,11 +79,6 @@ import {
this.data().getEnd() && this.date.set(new Date(this.data().getEnd()));
}
onRendered() {
super.onRendered();
// DatePicker base class handles initialization with native HTML inputs
}
_storeDate(date) {
this.card.setEnd(formatDateTime(date));
}

View file

@ -192,6 +192,8 @@ body.desktop-mode .card-details.card-details-collapsed {
position: sticky;
top: 0px;
z-index: 500;
display: flow-root;
min-height: 40px;
}
.card-details .card-details-header .card-number {
color: #b3b3b3;
@ -209,6 +211,8 @@ body.desktop-mode .card-details.card-details-collapsed {
cursor: pointer;
user-select: none;
color: #000;
vertical-align: middle;
line-height: 1.2;
}
/* Drag handle */
@ -220,6 +224,8 @@ body.desktop-mode .card-details.card-details-collapsed {
user-select: none;
display: inline-block;
float: right;
vertical-align: middle;
line-height: 1.2;
}
.card-details .card-details-header .close-card-details,
@ -241,6 +247,8 @@ body.desktop-mode .card-details.card-details-collapsed {
margin-right: -8px;
cursor: pointer;
user-select: none;
vertical-align: middle;
line-height: 1.2;
}
.card-details .card-details-header .close-card-details-mobile-web,
.card-details .card-details-header .card-mobile-desktop-toggle {
@ -263,6 +271,8 @@ body.desktop-mode .card-details.card-details-collapsed {
.card-details .card-details-header .card-details-menu {
font-size: 17px;
padding: 10px;
vertical-align: middle;
line-height: 1.2;
}
.card-details .card-details-header .card-details-menu-mobile-web {
font-size: 17px;
@ -309,6 +319,9 @@ body.desktop-mode .card-details.card-details-collapsed {
font-size: 1.33em;
margin: 7px 0 0;
padding: 0;
display: inline-block;
vertical-align: middle;
line-height: 1.3;
}
.card-details .card-details-header .linked-card-location {
font-style: italic;

View file

@ -14,55 +14,53 @@ template(name="cardDetails")
unless isPopup
span.card-collapse-toggle.js-card-collapse-toggle(title="{{_ 'collapse-card'}}")
if cardCollapsed
| ▶
i.fa.fa-caret-right
else
| 🔽
i.fa.fa-caret-down
a.close-card-details.js-close-card-details(title="{{_ 'close-card'}}")
| ❌
i.fa.fa-times-thin
if cardMaximized
a.minimize-card-details.js-minimize-card-details(title="{{_ 'minimize-card'}}")
| 🔽
a.fa.fa-window-minimize.minimize-card-details.js-minimize-card-details(title="{{_ 'minimize-card'}}")
else
a.maximize-card-details.js-maximize-card-details(title="{{_ 'maximize-card'}}")
| 🔼
a.fa.fa-window-maximize.maximize-card-details.js-maximize-card-details(title="{{_ 'maximize-card'}}")
a.card-details-menu.js-open-card-details-menu(title="{{_ 'cardDetailsActionsPopup-title'}}")
| ☰
i.fa.fa-bars
a.card-copy-button.js-copy-link(
id="cardURL_copy"
title="{{_ 'copy-card-link-to-clipboard'}}"
href="{{ originRelativeUrl }}"
)
span.emoji-icon 🔗
span.emoji-icon
i.fa.fa-link
if canModifyCard
span.card-drag-handle.js-card-drag-handle(title="Drag card")
| ↕️
i.fa.fa-arrows
span.copied-tooltip {{_ 'copied'}}
else
a.close-card-details.js-close-card-details(title="{{_ 'close-card'}}")
| ❌
i.fa.fa-times-thin
a.card-zoom-out.js-card-zoom-out(title="{{_ 'zoom-out'}}")
| 🔍➖
i.fa.fa-search-minus
a.card-zoom-in.js-card-zoom-in(title="{{_ 'zoom-in'}}")
| 🔍➕
i.fa.fa-search-plus
a.card-mobile-desktop-toggle.js-card-mobile-desktop-toggle(title="{{_ 'mobile-desktop-toggle'}}")
if mobileMode
| 🖥️
i.fa.fa-desktop
else
| 📱
i.fa.fa-mobile
if cardMaximized
a.minimize-card-details.js-minimize-card-details(title="{{_ 'minimize-card'}}")
| 🔽
a.fa.fa-window-minimize.minimize-card-details.js-minimize-card-details(title="{{_ 'minimize-card'}}")
else
a.maximize-card-details.js-maximize-card-details(title="{{_ 'maximize-card'}}")
| 🔼
a.fa.fa-window-maximize.maximize-card-details.js-maximize-card-details(title="{{_ 'maximize-card'}}")
a.card-details-menu-mobile-web.js-open-card-details-menu(title="{{_ 'cardDetailsActionsPopup-title'}}")
| ☰
i.fa.fa-bars
a.card-copy-mobile-button.js-copy-link(
id="cardURL_copy"
title="{{_ 'copy-card-link-to-clipboard'}}"
href="{{ originRelativeUrl }}"
)
span.emoji-icon 🔗
span.emoji-icon
i.fa.fa-link
span.copied-tooltip {{_ 'copied'}}
h2.card-details-title.js-card-title(
class="{{#if canModifyCard}}js-open-inlined-form is-editable{{else}}js-card-title-drag-handle{{/if}}")
@ -73,7 +71,7 @@ template(name="cardDetails")
= getTitle
if isWatching
i.card-details-watch
| 👁️
i.fa.fa-eye
.card-details-path
each parentList
|   >  
@ -95,7 +93,7 @@ template(name="cardDetails")
if hasActiveUploads
.card-details-upload-progress
.upload-progress-header
| 📤
i.fa.fa-upload
span {{_ 'uploading-files'}} ({{uploadCount}})
each uploads
.upload-progress-item(class="{{#if $eq status 'error'}}upload-error{{/if}}")
@ -104,11 +102,11 @@ template(name="cardDetails")
.upload-progress-fill(style="width: {{progress}}%")
if $eq status 'error'
.upload-progress-error
| ⚠️
i.fa.fa-exclamation-triangle
span {{_ 'upload-failed'}}
else if $eq status 'completed'
.upload-progress-success
| ✅
i.fa.fa-check
span {{_ 'upload-completed'}}
.card-details-left
@ -117,7 +115,7 @@ template(name="cardDetails")
if currentBoard.allowsLabels
.card-details-item.card-details-item-labels
h3.card-details-item-title
| 🏷️
i.fa.fa-tags
| {{_ 'labels'}}
a(class="{{#if canModifyCard}}js-add-labels{{else}}is-disabled{{/if}}" title="{{_ 'card-labels-title'}}")
each labels
@ -127,14 +125,14 @@ template(name="cardDetails")
if canModifyCard
unless currentUser.isWorker
a.card-label.add-label.js-add-labels(title="{{_ 'card-labels-title'}}")
|
i.fa.fa-plus
if currentBoard.hasAnyAllowsDate
hr
.card-details-item.card-details-item-date-format
h3.card-details-item-title
| 📅
i.fa.fa-calendar
| {{_ 'date-format'}}
.card-details-item-content
select.js-date-format-selector
@ -145,7 +143,7 @@ template(name="cardDetails")
if currentBoard.allowsReceivedDate
.card-details-item.card-details-item-received
h3.card-details-item-title
| 📥
i.fa.fa-sign-out
| {{_ 'card-received'}}
if getReceived
+cardReceivedDate
@ -153,12 +151,12 @@ template(name="cardDetails")
if canModifyCard
unless currentUser.isWorker
a.card-label.add-label.js-received-date
|
i.fa.fa-plus
if currentBoard.allowsStartDate
.card-details-item.card-details-item-start
h3.card-details-item-title
| 🚀
i.fa.fa-hourglass-start
| {{_ 'card-start'}}
if getStart
+cardStartDate
@ -166,12 +164,12 @@ template(name="cardDetails")
if canModifyCard
unless currentUser.isWorker
a.card-label.add-label.js-start-date
|
i.fa.fa-plus
if currentBoard.allowsDueDate
.card-details-item.card-details-item-due
h3.card-details-item-title
| ⏰
i.fa.fa-clock-o
| {{_ 'card-due'}}
if getDue
+cardDueDate
@ -179,12 +177,12 @@ template(name="cardDetails")
if canModifyCard
unless currentUser.isWorker
a.card-label.add-label.js-due-date
|
i.fa.fa-plus
if currentBoard.allowsEndDate
.card-details-item.card-details-item-end
h3.card-details-item-title
| 🏁
i.fa.fa-hourglass-end
| {{_ 'card-end'}}
if getEnd
+cardEndDate
@ -192,7 +190,7 @@ template(name="cardDetails")
if canModifyCard
unless currentUser.isWorker
a.card-label.add-label.js-end-date
|
i.fa.fa-plus
if currentBoard.hasAnyAllowsUser
hr
@ -200,7 +198,7 @@ template(name="cardDetails")
if currentBoard.allowsCreator
.card-details-item.card-details-item-creator
h3.card-details-item-title
| 👤
i.fa.fa-user
| {{_ 'creator'}}
+userAvatar(userId=userId noRemove=true)
@ -210,7 +208,7 @@ template(name="cardDetails")
if currentBoard.allowsMembers
.card-details-item.card-details-item-members
h3.card-details-item-title
| 👥
i.fa.fa-users
| {{_ 'members'}}
each userId in getMembers
+userAvatar(userId=userId cardId=_id)
@ -218,30 +216,30 @@ template(name="cardDetails")
if canModifyCard
unless currentUser.isWorker
a.member.add-member.card-details-item-add-button.js-add-members(title="{{_ 'card-members-title'}}")
|
i.fa.fa-plus
//if assigneeSelected
if currentBoard.allowsAssignee
.card-details-item.card-details-item-assignees
h3.card-details-item-title
| 👤
i.fa.fa-user
| {{_ 'assignee'}}
each userId in getAssignees
+userAvatar(userId=userId cardId=_id assignee=true)
| {{! XXX Hack to hide syntaxic coloration /// }}
if canModifyCard
a.assignee.add-assignee.card-details-item-add-button.js-add-assignees(title="{{_ 'assignee'}}")
|
i.fa.fa-plus
if currentUser.isWorker
unless assigneeSelected
a.assignee.add-assignee.card-details-item-add-button.js-add-assignees(title="{{_ 'assignee'}}")
|
i.fa.fa-plus
//.card-details-items
if currentBoard.allowsRequestedBy
.card-details-item.card-details-item-name
h3.card-details-item-title
| 🛒
i.fa.fa-shopping-cart
| {{_ 'requested-by'}}
if canModifyCard
unless currentUser.isWorker
@ -261,7 +259,7 @@ template(name="cardDetails")
if currentBoard.allowsAssignedBy
.card-details-item.card-details-item-name
h3.card-details-item-title
| ✍️
i.fa.fa-user-plus
| {{_ 'assigned-by'}}
if canModifyCard
unless currentUser.isWorker
@ -284,7 +282,7 @@ template(name="cardDetails")
if currentBoard.allowsCardSortingByNumber
.card-details-item.card-details-sort-order
h3.card-details-item-title
| 🔢
i.fa.fa-sort-numeric-asc
| {{_ 'sort'}}
if canModifyCard
+inlinedForm(classNames="js-card-details-sort")
@ -297,7 +295,7 @@ template(name="cardDetails")
if currentBoard.allowsShowLists
.card-details-item.card-details-show-lists
h3.card-details-item-title
| 📋
i.fa.fa-list
| {{_ 'list'}}
select.js-select-card-details-lists(disabled="{{#unless canModifyCard}}disabled{{/unless}}")
each currentBoard.lists
@ -323,7 +321,7 @@ template(name="cardDetails")
hr
.card-details-item.card-details-item-customfield
h3.card-details-item-title
| 📋
i.fa.fa-list
= definition.name
+cardCustomField
@ -341,7 +339,7 @@ template(name="cardDetails")
.vote-title
div.flex
h3
| 👍
i.fa.fa-thumbs-up
| {{_ 'vote-question'}}
if getVoteEnd
+voteEndDate
@ -359,7 +357,7 @@ template(name="cardDetails")
if showVotingButtons
button.card-details-green.js-vote.js-vote-positive(class="{{#if voteState}}voted{{/if}}")
if voteState
| 👍
i.fa.fa-thumbs-up
| {{_ 'vote-for-it'}}
button.card-details-red.js-vote.js-vote-negative(class="{{#if $eq voteState false}}voted{{/if}}")
if $eq voteState false
@ -371,7 +369,7 @@ template(name="cardDetails")
.poker-title
div.flex
h3
| 👍
i.fa.fa-thumbs-up
| {{_ 'poker-question'}}
if getPokerEnd
+pokerEndDate
@ -386,52 +384,52 @@ template(name="cardDetails")
.poker-card
span.inner.js-poker.js-poker-vote-one(class="{{#if $eq pokerState 'one'}}poker-voted{{/if}}") {{_ 'poker-one'}}
if $eq pokerState "one"
| ✅
i.fa.fa-check
.poker-deck
.poker-card
span.inner.js-poker.js-poker-vote-two(class="{{#if $eq pokerState 'two'}}poker-voted{{/if}}") {{_ 'poker-two'}}
if $eq pokerState "two"
| ✅
i.fa.fa-check
.poker-deck
.poker-card
span.inner.js-poker.js-poker-vote-three(class="{{#if $eq pokerState 'three'}}poker-voted{{/if}}") {{_ 'poker-three'}}
if $eq pokerState "three"
| ✅
i.fa.fa-check
.poker-deck
.poker-card
span.inner.js-poker.js-poker-vote-five(class="{{#if $eq pokerState 'five'}}poker-voted{{/if}}") {{_ 'poker-five'}}
if $eq pokerState "five"
| ✅
i.fa.fa-check
.poker-deck
.poker-card
span.inner.js-poker.js-poker-vote-eight(class="{{#if $eq pokerState 'eight'}}poker-voted{{/if}}") {{_ 'poker-eight'}}
if $eq pokerState "eight"
| ✅
i.fa.fa-check
.poker-deck
.poker-card
span.inner.js-poker.js-poker-vote-thirteen(class="{{#if $eq pokerState 'thirteen'}}poker-voted{{/if}}") {{_ 'poker-thirteen'}}
if $eq pokerState "thirteen"
| ✅
i.fa.fa-check
.poker-deck
.poker-card
span.inner.js-poker.js-poker-vote-twenty(class="{{#if $eq pokerState 'twenty'}}poker-voted{{/if}}") {{_ 'poker-twenty'}}
if $eq pokerState "twenty"
| ✅
i.fa.fa-check
.poker-deck
.poker-card
span.inner.js-poker.js-poker-vote-forty(class="{{#if $eq pokerState 'forty'}}poker-voted{{/if}}") {{_ 'poker-forty'}}
if $eq pokerState "forty"
| ✅
i.fa.fa-check
.poker-deck
.poker-card
span.inner.js-poker.js-poker-vote-one-hundred(class="{{#if $eq pokerState 'oneHundred'}}poker-voted{{/if}}") {{_ 'poker-oneHundred'}}
if $eq pokerState "oneHundred"
| ✅
i.fa.fa-check
.poker-deck
.poker-card
span.inner.js-poker.js-poker-vote-unsure(class="{{#if $eq pokerState 'unsure'}}poker-voted{{/if}}") {{_ 'poker-unsure'}}
if $eq pokerState "unsure"
| ✅
i.fa.fa-check
if currentUser.isBoardAdmin
button.card-details-blue.js-poker-finish(class="{{#if $eq voteState false}}poker-voted{{/if}}") {{_ 'poker-finish'}}
@ -561,7 +559,7 @@ template(name="cardDetails")
button.card-details-red.js-poker-replay(class="{{#if $eq voteState false}}voted{{/if}}") {{_ 'poker-replay'}}
div.estimation-add
button.js-poker-estimation
|
i.fa.fa-plus
| {{_ 'set-estimation'}}
input(type=text,autofocus value=getPokerEstimation,id="pokerEstimation")
@ -571,7 +569,7 @@ template(name="cardDetails")
if currentBoard.allowsDescriptionTitle
hr
h3.card-details-item-title
| 📝
i.fa.fa-file-text-o
| {{_ 'description'}}
if currentBoard.allowsDescriptionText
+inlinedCardDescription(classNames="card-description js-card-description")
@ -582,7 +580,7 @@ template(name="cardDetails")
else
if currentBoard.allowsDescriptionText
a.js-open-inlined-form(title="{{_ 'edit'}}" value=title)
| ✏️
i.fa.fa-pencil-square-o
a.js-open-inlined-form(title="{{_ 'edit'}}" value=title)
if getDescription
+viewer
@ -612,7 +610,7 @@ template(name="cardDetails")
if currentBoard.allowsAttachments
hr
h3.card-details-item-title
| 📎
i.fa.fa-paperclip
| {{_ 'attachments'}}
if Meteor.settings.public.attachmentsUploadMaxSize
| {{_ 'max-upload-filesize'}} {{Meteor.settings.public.attachmentsUploadMaxSize}}
@ -628,7 +626,7 @@ template(name="cardDetails")
unless currentUser.isNoComments
.comment-title
h3.card-details-item-title
| 💬
i.fa.fa-comment-o
| {{_ 'comments'}}
if currentBoard.allowsComments
@ -645,7 +643,7 @@ template(name="cardDetails")
if currentUser.isBoardAdmin
.activity-title
h3.card-details-item-title
| 📜
i.fa.fa-history
| {{ _ 'activities'}}
if currentUser.isBoardMember
.material-toggle-switch(title="{{_ 'show-activities'}}")
@ -696,10 +694,10 @@ template(name="cardDetailsActionsPopup")
li
a.js-toggle-watch-card
if isWatching
| 👁️
i.fa.fa-eye
| {{_ 'unwatch'}}
else
| 👁️
i.fa.fa-eye
| {{_ 'watch'}}
hr
if canModifyCard
@ -710,16 +708,16 @@ template(name="cardDetailsActionsPopup")
//li: a.js-attachments {{_ 'card-edit-attachments'}}
li
a.js-start-voting
| 👍
i.fa.fa-thumbs-up
| {{_ 'card-edit-voting'}}
li
a.js-start-planning-poker
| 👍
i.fa.fa-thumbs-up
| {{_ 'card-edit-planning-poker'}}
if currentUser.isBoardAdmin
li
a.js-custom-fields
| 📋
i.fa.fa-list
| {{_ 'card-edit-custom-fields'}}
//li: a.js-received-date {{_ 'editCardReceivedDatePopup-title'}}
//li: a.js-start-date {{_ 'editCardStartDatePopup-title'}}
@ -727,19 +725,19 @@ template(name="cardDetailsActionsPopup")
//li: a.js-end-date {{_ 'editCardEndDatePopup-title'}}
li
a.js-spent-time
| 🕐
i.fa.fa-clock-o
| {{_ 'editCardSpentTimePopup-title'}}
li
a.js-set-card-color
| 🎨
i.fa.fa-paint-brush
| {{_ 'setCardColorPopup-title'}}
li
a.js-toggle-show-list-on-minicard
if showListOnMinicard
| 👁️
i.fa.fa-eye
| {{_ 'hide-list-on-minicard'}}
else
| 👁️
i.fa.fa-eye
| {{_ 'show-list-on-minicard'}}
if canModifyCard
hr
@ -750,7 +748,7 @@ template(name="cardDetailsActionsPopup")
ul.pop-over-list
li
a.js-export-card
| 📤
i.fa.fa-upload
| {{_ 'export-card'}}
unless canModifyCard
unless currentUser.isReadOnly
@ -759,95 +757,93 @@ template(name="cardDetailsActionsPopup")
ul.pop-over-list
li
a.js-move-card-to-top
| ⬆️
i.fa.fa-arrow-up
| {{_ 'moveCardToTop-title'}}
li
a.js-move-card-to-bottom
| ⬇️
i.fa.fa-arrow-down
| {{_ 'moveCardToBottom-title'}}
hr
ul.pop-over-list
if currentUser.isBoardAdmin
li
a.js-move-card
| ➡️
i.fa.fa-arrow-right
| {{_ 'moveCardPopup-title'}}
unless currentUser.isWorker
li
a.js-copy-card
| 📋
i.fa.fa-clipboard
| {{_ 'copyCardPopup-title'}}
unless currentUser.isWorker
ul.pop-over-list
li
a.js-copy-checklist-cards
| 📋
| 📋
i.fa.fa-copy
| {{_ 'copyManyCardsPopup-title'}}
unless archived
hr
ul.pop-over-list
li
a.js-archive
| ➡️
| 📦
i.fa.fa-archive
| {{_ 'archive-card'}}
hr
ul.pop-over-list
li
a.js-more
span.emoji-icon 🔗
span.emoji-icon
i.fa.fa-link
| {{_ 'cardMorePopup-title'}}
if canModifyCard
hr
ul.pop-over-list
li
a.js-move-card-to-top
| ⬆️
i.fa.fa-arrow-up
| {{_ 'moveCardToTop-title'}}
li
a.js-move-card-to-bottom
| ⬇️
i.fa.fa-arrow-down
| {{_ 'moveCardToBottom-title'}}
hr
ul.pop-over-list
if currentUser.isBoardAdmin
li
a.js-move-card
| ➡️
i.fa.fa-arrow-right
| {{_ 'moveCardPopup-title'}}
unless currentUser.isWorker
li
a.js-copy-card
| 📋
i.fa.fa-clipboard
| {{_ 'copyCardPopup-title'}}
unless currentUser.isWorker
ul.pop-over-list
li
a.js-copy-checklist-cards
| 📋
| 📋
i.fa.fa-copy
| {{_ 'copyManyCardsPopup-title'}}
unless archived
hr
ul.pop-over-list
li
a.js-archive
| ➡️
| 📦
i.fa.fa-archive
| {{_ 'archive-card'}}
hr
ul.pop-over-list
li
a.js-more
span.emoji-icon 🔗
span.emoji-icon
i.fa.fa-link
| {{_ 'cardMorePopup-title'}}
template(name="exportCardPopup")
ul.pop-over-list
li
a(href="{{exportUrlCardPDF}}",, download="{{exportFilenameCardPDF}}")
| 📤
i.fa.fa-upload
| {{_ 'export-card-pdf'}}
template(name="moveCardPopup")
@ -915,8 +911,7 @@ template(name="cardMembersPopup")
if userData.username
| (#{userData.username})
if isCardMember
| ✅
i.fa.fa-check
template(name="cardAssigneesPopup")
input.card-assignees-filter(type="text" placeholder="{{_ 'search'}}")
unless currentUser.isWorker
@ -930,8 +925,7 @@ template(name="cardAssigneesPopup")
if userData.username
| (#{userData.username})
if isCardAssignee
| ✅
if currentUser.isWorker
i.fa.fa-check if currentUser.isWorker
ul.pop-over-list.js-card-assignee-list
li.item(class="{{#if currentUser.isCardAssignee}}active{{/if}}")
a.name.js-select-assignee(href="#")
@ -941,8 +935,7 @@ template(name="cardAssigneesPopup")
if currentUser.username
| (#{currentUser.username})
if currentUser.isCardAssignee
| ✅
i.fa.fa-check
template(name="cardAssigneePopup")
.board-assignee-menu
.mini-profile-info
@ -965,7 +958,7 @@ template(name="cardMorePopup")
span.clearfix
span {{_ 'link-card'}}
= ' '
| {{#if board.isPublic}}🌐{{else}}🔒{{/if}}
i.fa(class="{{#if currentBoard.isPublic}}fa-globe{{else}}fa-lock{{/if}}")
input.inline-input(type="text" id="cardURL" readonly value="{{ originRelativeUrl }}" autofocus="autofocus")
button.js-copy-card-link-to-clipboard(class="btn" id="clipboard") {{_ 'copy-card-link-to-clipboard'}}
.copied-tooltip {{_ 'copied'}}
@ -1003,13 +996,14 @@ template(name="cardMorePopup")
template(name="setCardColorPopup")
form.edit-label
.palette-colors: each colors
unless $eq color 'white'
span.card-label.palette-color.js-palette-color(class="card-details-{{color}}")
if(isSelected color)
| ✅
button.primary.confirm.js-submit {{_ 'save'}}
button.js-remove-color.negate.wide.right {{_ 'unset-color'}}
.palette-colors
each colors
unless $eq color 'white'
span.card-label.palette-color.js-palette-color(class="card-details-{{color}}")
if(isSelected color)
i.fa.fa-check
button.primary.confirm.js-submit {{_ 'save'}}
button.js-remove-color.negate.wide.right {{_ 'unset-color'}}
template(name="cardDeletePopup")
p {{_ "card-delete-pop"}}
@ -1041,12 +1035,12 @@ template(name="cardStartVotingPopup")
.materialCheckBox#vote-public(name="vote-public" class="{{#if votePublic}}is-checked{{/if}}")
span {{_ 'vote-public'}}
.check-div.flex
| ⏰
i.fa.fa-clock-o
a.js-end-date
span
| {{_ 'card-end'}}
unless getVoteEnd
|
i.fa.fa-plus
if getVoteEnd
+voteEndDate
@ -1087,12 +1081,12 @@ template(name="cardStartPlanningPokerPopup")
.materialCheckBox#poker-allow-non-members(name="poker-allow-non-members" class="{{#if pokerAllowNonBoardMembers}}is-checked{{/if}}")
span {{_ 'allowNonBoardMembers'}}
.check-div.flex
| ⏰
i.fa.fa-clock-o
a.js-end-date
span
| {{_ 'card-end'}}
unless getPokerEnd
|
i.fa.fa-plus
if getPokerEnd
+pokerEndDate

View file

@ -37,23 +37,16 @@ textarea.js-edit-checklist-item {
.checklist-progress-bar-container .checklist-progress-bar {
width: 80%;
height: 10px;
background-color: #d6ebff !important;
background-color: #e0e0e0;
border-radius: 16px;
}
.checklist-progress-bar-container .checklist-progress-bar .checklist-progress {
color: #fff !important;
background-color: #3cb500 !important;
color: #fff;
background-color: #666;
padding: 0.01em 16px;
border-radius: 16px;
height: 100%;
}
/* Grey progress bar when grey icons setting is enabled */
body.grey-icons-enabled .checklist-progress-bar-container .checklist-progress-bar {
background-color: #d9d9d9;
}
body.grey-icons-enabled .checklist-progress-bar-container .checklist-progress-bar .checklist-progress {
background-color: #7a7a7a !important;
}
.checklist-title {
padding: 10px;
}
@ -76,14 +69,10 @@ body.grey-icons-enabled .checklist-progress-bar-container .checklist-progress-ba
.checklist-title .checklist-stat.is-finished {
color: #3cb500;
}
.checklist-title span.checklist-handle {
.checklist-title span.fa.checklist-handle {
padding-right: 20px;
padding-top: 3px;
float: left;
display: inline-block;
width: 1.2em;
text-align: center;
color: #999;
}
#card-details-overlay {
top: 0;
@ -114,25 +103,6 @@ body.grey-icons-enabled .checklist-progress-bar-container .checklist-progress-ba
height: auto;
overflow: hidden;
}
/* iPhone mobile: larger checklist titles and more spacing between items */
body.mobile-mode.iphone-device .checklist-title .title {
font-size: 1.3em !important;
font-weight: bold;
}
body.mobile-mode.iphone-device .checklist-item {
margin-top: 12px !important;
margin-bottom: 8px !important;
padding: 8px 4px !important;
min-height: 44px; /* iOS recommended touch target size */
}
body.mobile-mode.iphone-device .checklist-item span.checklistitem-handle {
font-size: 1.5em !important;
padding-right: 15px !important;
width: 1.5em !important;
}
.checklist-item.is-checked.invisible {
opacity: 0;
height: 0;
@ -162,27 +132,6 @@ body.mobile-mode.iphone-device .checklist-item span.checklistitem-handle {
border-bottom: 2px solid #3cb500;
border-right: 2px solid #3cb500;
}
/* Unicode checkbox icons styling */
.checklist-item .check-box-unicode,
.cardCustomField-checkbox .check-box-unicode {
font-size: 1.3em;
margin-right: 8px;
cursor: pointer;
display: inline-block;
vertical-align: middle;
line-height: 1;
}
/* Grey checkmarks when grey icons setting is enabled */
body.grey-icons-enabled .checklist-item .check-box.is-checked {
border-bottom: 2px solid #7a7a7a;
border-right: 2px solid #7a7a7a;
}
body.grey-icons-enabled .checklist-item .check-box-unicode,
body.grey-icons-enabled .cardCustomField-checkbox .check-box-unicode {
filter: grayscale(100%);
-webkit-filter: grayscale(100%);
opacity: 0.85;
}
.checklist-item .item-title {
flex: 1;
}
@ -197,14 +146,9 @@ body.grey-icons-enabled .cardCustomField-checkbox .check-box-unicode {
word-wrap: break-word;
max-width: 420px;
}
.checklist-item span.checklistitem-handle {
.checklist-item span.fa.checklistitem-handle {
padding-top: 2px;
padding-right: 10px;
display: inline-block;
width: 1.2em;
text-align: center;
color: #999;
cursor: pointer;
}
.js-delete-checklist-item,
.js-convert-checklist-item-to-card {

View file

@ -1,25 +1,34 @@
template(name="checklists")
.checklists-title
h3.card-details-item-title
| ✅
i.fa.fa-check
| {{_ 'checklists'}}
if canModifyCard
+inlinedForm(autoclose=false classNames="js-add-checklist" cardId = cardId position="top")
+addChecklistItemForm
else
a.add-checklist-top.js-open-inlined-form(title="{{_ 'add-checklist'}}")
|
i.fa.fa-plus
if currentUser.isBoardMember
.material-toggle-switch(title="{{_ 'hide-finished-checklist'}}")
//span.toggle-switch-title
if card.hideFinishedChecklistIfItemsAreHidden
input.toggle-switch(type="checkbox" id="toggleHideFinishedChecklist" checked="checked")
else
input.toggle-switch(type="checkbox" id="toggleHideFinishedChecklist")
label.toggle-label(for="toggleHideFinishedChecklist")
.card-checklist-items
each checklist in checklists
+checklistDetail(checklist = checklist card = card)
if checklist.showChecklist card.hideFinishedChecklistIfItemsAreHidden
+checklistDetail(checklist = checklist card = card)
if canModifyCard
+inlinedForm(autoclose=false classNames="js-add-checklist" cardId = cardId)
+addChecklistItemForm(checklist=checklist showNewlineBecomesNewChecklistItem=false)
else
a.add-checklist.js-open-inlined-form(title="{{_ 'add-checklist'}}")
|
i.fa.fa-plus
template(name="checklistDetail")
.js-checklist.checklist.nodragscroll
@ -29,12 +38,12 @@ template(name="checklistDetail")
.checklist-title
span
if canModifyCard
a.checklist-details-menu.js-open-checklist-details-menu(title="{{_ 'checklistActionsPopup-title'}}")
a.fa.fa-navicon.checklist-details-menu.js-open-checklist-details-menu(title="{{_ 'checklistActionsPopup-title'}}")
if canModifyCard
h4.title.js-open-inlined-form.is-editable
if isTouchScreenOrShowDesktopDragHandles
span.checklist-handle(title="{{_ 'dragChecklist'}}") ↕️
span.fa.checklist-handle(class="fa-arrows" title="{{_ 'dragChecklist'}}")
+viewer
= checklist.title
else
@ -53,18 +62,13 @@ template(name="checklistDeletePopup")
p {{_ 'confirm-checklist-delete-popup'}}
button.js-confirm.negate.full(type="submit") {{_ 'delete'}}
template(name="checklistItemDeletePopup")
p {{_ 'confirm-checklist-delete-popup'}}
button.js-confirm.negate.full(type="submit") {{_ 'delete'}}
template(name="addChecklistItemForm")
a(title="{{_ 'copy-text-to-clipboard'}}")
a.fa.fa-copy(title="{{_ 'copy-text-to-clipboard'}}")
span.copied-tooltip {{_ 'copied'}}
textarea.js-add-checklist-item(rows='1' autofocus)
.edit-controls.clearfix
button.primary.confirm.js-submit-add-checklist-item-form(type="submit") {{_ 'save'}}
a.js-close-inlined-form(title="{{_ 'close-add-checklist-item'}}")
| ❌
a.fa.fa-times-thin.js-close-inlined-form(title="{{_ 'close-add-checklist-item'}}")
if showNewlineBecomesNewChecklistItem
.material-toggle-switch(title="{{_ 'newlineBecomesNewChecklistItem'}}")
input.toggle-switch(type="checkbox" id="toggleNewlineBecomesNewChecklistItem")
@ -77,7 +81,7 @@ template(name="addChecklistItemForm")
| {{_ 'originOrder'}}
template(name="editChecklistItemForm")
a(title="{{_ 'copy-text-to-clipboard'}}")
a.fa.fa-copy(title="{{_ 'copy-text-to-clipboard'}}")
span.copied-tooltip {{_ 'copied'}}
textarea.js-edit-checklist-item(rows='1' autofocus dir="auto")
if $eq type 'item'
@ -86,17 +90,13 @@ template(name="editChecklistItemForm")
= checklist.title
.edit-controls.clearfix
button.primary.confirm.js-submit-edit-checklist-item-form(type="submit") {{_ 'save'}}
a.js-close-inlined-form(title="{{_ 'close-edit-checklist-item'}}")
| ❌
a.fa.fa-times-thin.js-close-inlined-form(title="{{_ 'close-edit-checklist-item'}}")
span(title=createdAt) {{ moment createdAt }}
if canModifyCard
if $eq type 'item'
a.js-delete-checklist-item {{_ "delete"}}...
a.js-convert-checklist-item-to-card
| 📋
| {{_ 'convertChecklistItemToCardPopup-title'}}
else
a.js-delete-checklist {{_ "delete"}}...
a.js-delete-checklist-item {{_ "delete"}}...
a.js-convert-checklist-item-to-card
i.fa.fa-copy
| {{_ 'convertChecklistItemToCardPopup-title'}}
template(name="checklistItems")
if checklist.items.length
@ -105,7 +105,7 @@ template(name="checklistItems")
+addChecklistItemForm(checklist=checklist showNewlineBecomesNewChecklistItem=true position="top")
else
a.add-checklist-item.js-open-inlined-form(title="{{_ 'add-checklist-item'}}")
|
i.fa.fa-plus
.checklist-items.js-checklist-items
each item in checklist.items
+inlinedForm(classNames="js-edit-checklist-item" item = item checklist = checklist)
@ -117,20 +117,21 @@ template(name="checklistItems")
+addChecklistItemForm(checklist=checklist showNewlineBecomesNewChecklistItem=true)
else
a.add-checklist-item.js-open-inlined-form(title="{{_ 'add-checklist-item'}}")
|
i.fa.fa-plus
template(name='checklistItemDetail')
.js-checklist-item.checklist-item(class="{{#if item.isFinished }}is-checked{{#if checklist.hideCheckedChecklistItems}} invisible{{/if}}{{/if}}{{#if checklist.hideAllChecklistItems}} is-checked invisible{{/if}}"
role="checkbox" aria-checked="{{#if item.isFinished }}true{{else}}false{{/if}}" tabindex="0")
if canModifyCard
span.check-box-unicode {{#if item.isFinished }}✅{{else}}⬜{{/if}}
.check-box-container
.check-box.materialCheckBox(class="{{#if item.isFinished }}is-checked{{/if}}")
if isTouchScreenOrShowDesktopDragHandles
span.checklistitem-handle(title="{{_ 'dragChecklistItem'}}") ↕️
span.fa.checklistitem-handle(class="fa-arrows" title="{{_ 'dragChecklistItem'}}")
.item-title.js-open-inlined-form.is-editable(class="{{#if item.isFinished }}is-checked{{/if}}")
+viewer
= item.title
else
span.check-box-unicode {{#if item.isFinished }}✅{{else}}⬜{{/if}}
.materialCheckBox(class="{{#if item.isFinished }}is-checked{{/if}}")
.item-title(class="{{#if item.isFinished }}is-checked{{/if}}")
+viewer
= item.title
@ -139,16 +140,16 @@ template(name="checklistActionsPopup")
ul.pop-over-list
li
a.js-delete-checklist.delete-checklist
| 🗑️
i.fa.fa-trash
| {{_ "delete"}} ...
a.js-move-checklist.move-checklist
| ➡️
i.fa.fa-arrow-right
| {{_ "moveChecklist"}} ...
a.js-copy-checklist.copy-checklist
| 📋
i.fa.fa-copy
| {{_ "copyChecklist"}} ...
a.js-hide-checked-checklist-items
| 🙈
i.fa.fa-eye-slash
| {{_ "hideCheckedChecklistItems"}} ...
.material-toggle-switch(title="{{_ 'hide-checked-items'}}")
if checklist.hideCheckedChecklistItems
@ -157,7 +158,7 @@ template(name="checklistActionsPopup")
input.toggle-switch(type="checkbox" id="toggleHideCheckedChecklistItems_{{checklist._id}}")
label.toggle-label(for="toggleHideCheckedChecklistItems_{{checklist._id}}")
a.js-hide-all-checklist-items
| 🚫
i.fa.fa-ban
| {{_ "hideAllChecklistItems"}} ...
.material-toggle-switch(title="{{_ 'hideAllChecklistItems'}}")
if checklist.hideAllChecklistItems
@ -165,62 +166,34 @@ template(name="checklistActionsPopup")
else
input.toggle-switch(type="checkbox" id="toggleHideAllChecklistItems_{{checklist._id}}")
label.toggle-label(for="toggleHideAllChecklistItems_{{checklist._id}}")
a.js-toggle-show-checklist-at-minicard
| 📋
| {{_ "showChecklistAtMinicard"}} ...
.material-toggle-switch(title="{{_ 'showChecklistAtMinicard'}}")
if checklist.showChecklistAtMinicard
input.toggle-switch(type="checkbox" id="toggleShowChecklistAtMinicard_{{checklist._id}}" checked="checked")
else
input.toggle-switch(type="checkbox" id="toggleShowChecklistAtMinicard_{{checklist._id}}")
label.toggle-label(for="toggleShowChecklistAtMinicard_{{checklist._id}}")
template(name="copyChecklistPopup")
unless currentUser.isWorker
label {{_ 'boards'}}:
select.js-select-boards(autofocus)
each boards
option(value="{{_id}}" selected="{{#if isDialogOptionBoardId _id}}selected{{/if}}") {{add @index 1}}. {{title}}
label {{_ 'swimlanes'}}:
select.js-select-swimlanes
each swimlanes
option(value="{{_id}}" selected="{{#if isDialogOptionSwimlaneId _id}}selected{{/if}}") {{add @index 1}}. {{isTitleDefault title}}
label {{_ 'lists'}}:
select.js-select-lists
each lists
option(value="{{_id}}" selected="{{#if isDialogOptionListId _id}}selected{{/if}}") {{add @index 1}}. {{title}}
label {{_ 'card'}}:
select.js-select-cards
each cards
option(value="{{_id}}" selected="{{#if isDialogOptionCardId _id}}selected{{/if}}") {{add @index 1}}. {{title}}
.edit-controls.clearfix
button.primary.confirm.js-done {{_ 'done'}}
+copyAndMoveChecklist
template(name="moveChecklistPopup")
+copyAndMoveChecklist
template(name="copyAndMoveChecklist")
unless currentUser.isWorker
label {{_ 'boards'}}:
select.js-select-boards(autofocus)
each boards
option(value="{{_id}}" selected="{{#if isDialogOptionBoardId _id}}selected{{/if}}") {{add @index 1}}. {{title}}
option(value="{{_id}}" selected="{{#if isDialogOptionBoardId _id}}selected{{/if}}") {{title}}
label {{_ 'swimlanes'}}:
select.js-select-swimlanes
each swimlanes
option(value="{{_id}}" selected="{{#if isDialogOptionSwimlaneId _id}}selected{{/if}}") {{add @index 1}}. {{isTitleDefault title}}
option(value="{{_id}}" selected="{{#if isDialogOptionSwimlaneId _id}}selected{{/if}}") {{title}}
label {{_ 'lists'}}:
select.js-select-lists
each lists
option(value="{{_id}}" selected="{{#if isDialogOptionListId _id}}selected{{/if}}") {{add @index 1}}. {{title}}
option(value="{{_id}}" selected="{{#if isDialogOptionListId _id}}selected{{/if}}") {{title}}
label {{_ 'card'}}:
label {{_ 'cards'}}:
select.js-select-cards
each cards
option(value="{{_id}}" selected="{{#if isDialogOptionCardId _id}}selected{{/if}}") {{add @index 1}}. {{title}}
option(value="{{_id}}" selected="{{#if isDialogOptionCardId _id}}selected{{/if}}") {{title}}
.edit-controls.clearfix
button.primary.confirm.js-done {{_ 'done'}}

View file

@ -65,7 +65,7 @@ BlazeComponent.extendComponent({
$(self.itemsDom).sortable('option', 'disabled', !userIsMember());
if (Utils.isTouchScreenOrShowDesktopDragHandles()) {
$(self.itemsDom).sortable({
handle: 'span.checklistitem-handle',
handle: 'span.fa.checklistitem-handle',
});
}
}
@ -157,21 +157,29 @@ BlazeComponent.extendComponent({
textarea.focus();
},
async editChecklist(event) {
deleteItem() {
const checklist = this.currentData().checklist;
const item = this.currentData().item;
if (checklist && item && item._id) {
ChecklistItems.remove(item._id);
}
},
editChecklist(event) {
event.preventDefault();
const textarea = this.find('textarea.js-edit-checklist-item');
const title = textarea.value.trim();
const checklist = this.currentData().checklist;
await checklist.setTitle(title);
checklist.setTitle(title);
},
async editChecklistItem(event) {
editChecklistItem(event) {
event.preventDefault();
const textarea = this.find('textarea.js-edit-checklist-item');
const title = textarea.value.trim();
const item = this.currentData().item;
await item.setTitle(title);
item.setTitle(title);
},
pressKey(event) {
@ -208,28 +216,14 @@ BlazeComponent.extendComponent({
'submit .js-add-checklist-item': this.addChecklistItem,
'submit .js-edit-checklist-item': this.editChecklistItem,
'click .js-convert-checklist-item-to-card': Popup.open('convertChecklistItemToCard'),
'click .js-delete-checklist-item'(event) {
const item = this.currentData().item;
const confirmFunc = Popup.afterConfirm('checklistItemDelete', function () {
if (item && item._id) {
ChecklistItems.remove(item._id);
}
});
confirmFunc.call(this, event);
},
'click .js-delete-checklist'(event) {
const checklist = this.currentData().checklist;
const confirmFunc = Popup.afterConfirm('checklistDelete', function () {
Popup.back(2);
if (checklist && checklist._id) {
Checklists.remove(checklist._id);
}
});
confirmFunc.call(this, event);
},
'click .js-delete-checklist-item': this.deleteItem,
'focus .js-add-checklist-item': this.focusChecklistItem,
// add and delete checklist / checklist-item
'click .js-open-inlined-form': this.closeAllInlinedForms,
'click #toggleHideFinishedChecklist'(event) {
event.preventDefault();
this.data().card.toggleHideFinishedChecklist();
},
keydown: this.pressKey,
},
];
@ -281,8 +275,8 @@ BlazeComponent.extendComponent({
Template.checklists.helpers({
checklists() {
const card = ReactiveCache.getCard(this.cardId);
if (!card || typeof card.checklists !== 'function') return [];
return card.checklists();
const ret = card.checklists();
return ret;
},
});
@ -309,32 +303,23 @@ BlazeComponent.extendComponent({
events() {
return [
{
'click .js-delete-checklist'(event) {
const checklist = this.data().checklist;
const confirmFunc = Popup.afterConfirm('checklistDelete', function () {
Popup.back(2);
if (checklist && checklist._id) {
Checklists.remove(checklist._id);
}
});
confirmFunc.call(this, event);
},
'click .js-delete-checklist': Popup.afterConfirm('checklistDelete', function () {
Popup.back(2);
const checklist = this.checklist;
if (checklist && checklist._id) {
Checklists.remove(checklist._id);
}
}),
'click .js-move-checklist': Popup.open('moveChecklist'),
'click .js-copy-checklist': Popup.open('copyChecklist'),
async 'click .js-hide-checked-checklist-items'(event) {
'click .js-hide-checked-checklist-items'(event) {
event.preventDefault();
await this.data().checklist.toggleHideCheckedChecklistItems();
this.data().checklist.toggleHideCheckedChecklistItems();
Popup.back();
},
async 'click .js-hide-all-checklist-items'(event) {
'click .js-hide-all-checklist-items'(event) {
event.preventDefault();
await this.data().checklist.toggleHideAllChecklistItems();
Popup.back();
},
async 'click .js-toggle-show-checklist-at-minicard'(event) {
event.preventDefault();
const checklist = this.data().checklist;
await checklist.toggleShowChecklistAtMinicard();
this.data().checklist.toggleHideAllChecklistItems();
Popup.back();
},
}
@ -365,17 +350,16 @@ Template.checklistItemDetail.helpers({
});
BlazeComponent.extendComponent({
async toggleItem() {
toggleItem() {
const checklist = this.currentData().checklist;
const item = this.currentData().item;
if (checklist && item && item._id) {
await item.toggleItem();
item.toggleItem();
}
},
events() {
return [
{
'click .js-checklist-item .check-box-unicode': this.toggleItem,
'click .js-checklist-item .check-box-container': this.toggleItem,
},
];
@ -390,12 +374,7 @@ BlazeComponent.extendComponent({
}
setDone(cardId, options) {
ReactiveCache.getCurrentUser().setMoveChecklistDialogOption(this.currentBoardId, options);
const checklist = this.data().checklist;
Meteor.call('moveChecklist', checklist._id, cardId, (error) => {
if (error) {
console.error('Error moving checklist:', error);
}
});
this.data().checklist.move(cardId);
}
}).register('moveChecklistPopup');

View file

@ -6,7 +6,7 @@ template(name="formLabel")
.palette-colors: each labels
span.card-label.palette-color.js-palette-color(class="card-label-{{color}}")
if(isSelected color)
| ✅
i.fa.fa-check
template(name="createLabelPopup")
form.create-label
@ -28,14 +28,13 @@ template(name="cardLabelsPopup")
ul.edit-labels-pop-over
each board.labels
li.js-card-label-item
a.card-label-edit-button.js-edit-label
| ✏️
a.card-label-edit-button.fa.fa-pencil.js-edit-label
if isTouchScreenOrShowDesktopDragHandles
span.label-handle(title="{{_ 'dragLabel'}}") ↕️
span.fa.label-handle(class="fa-arrows" title="{{_ 'dragLabel'}}")
span.card-label.card-label-selectable.js-select-label.card-label-wrapper(class="card-label-{{color}}"
class="{{# if isLabelSelected ../_id }}active{{/if}}")
+viewer
= name
if(isLabelSelected ../_id)
| ✅
i.card-label-selectable-icon.fa.fa-check
a.quiet-button.full.js-add-label {{_ 'label-create'}}

View file

@ -125,19 +125,8 @@ Template.createLabelPopup.events({
.$('#labelName')
.val()
.trim();
// Find the selected color by looking for the palette color that contains the checkmark
let selectedColor = null;
templateInstance.$('.js-palette-color').each(function() {
if ($(this).text().includes('✅')) {
selectedColor = Blaze.getData(this).color;
return false; // break out of loop
}
});
if (selectedColor) {
board.addLabel(name, selectedColor);
}
const color = Blaze.getData(templateInstance.find('.fa-check')).color;
board.addLabel(name, color);
Popup.back();
},
});
@ -155,19 +144,8 @@ Template.editLabelPopup.events({
.$('#labelName')
.val()
.trim();
// Find the selected color by looking for the palette color that contains the checkmark
let selectedColor = null;
templateInstance.$('.js-palette-color').each(function() {
if ($(this).text().includes('✅')) {
selectedColor = Blaze.getData(this).color;
return false; // break out of loop
}
});
if (selectedColor) {
board.editLabel(this._id, name, selectedColor);
}
const color = Blaze.getData(templateInstance.find('.fa-check')).color;
board.editLabel(this._id, name, color);
Popup.back();
},
});

View file

@ -49,7 +49,7 @@
top: 0.7vh;
font-size: clamp(14px, 3vw, 18px);
padding: 0;
z-index: 10;
z-index: 1;
}
.minicard-details-menu {
float: right;
@ -99,6 +99,7 @@
}
.minicard .minicard-labels {
float: none;
margin-right: 6vw;
}
.minicard .minicard-labels .minicard-label {
width: clamp(12px, 1.5vw, 16px);
@ -113,6 +114,7 @@
}
.minicard .minicard-custom-fields {
display: block;
margin-right: 6vw;
}
.minicard .minicard-custom-field {
display: flex;
@ -138,7 +140,7 @@
right: 3vw;
top: 0.7vh;
display: none;
z-index: 10;
z-index: 1;
}
@media only screen {
.minicard .handle {
@ -152,6 +154,9 @@
width: 1.4em;
text-align: center;
}
.minicard .minicard-title {
margin-right: 6vw;
}
.minicard .minicard-title .card-number {
color: #b3b3b3;
display: inline-block;
@ -170,6 +175,10 @@
display: flex;
flex-direction: row;
flex-wrap: wrap;
position: relative;
z-index: 5;
margin-right: 6vw;
clear: both;
}
.minicard .date {
margin-right: 0.4vw;

View file

@ -6,9 +6,10 @@ template(name="minicard")
if canMoveCard
if isTouchScreenOrShowDesktopDragHandles
.handle
| ↕️
i.fa.fa-arrows
if canModifyCard
a.minicard-details-menu-with-handle.js-open-minicard-details-menu(title="{{_ 'cardDetailsActionsPopup-title'}}") ☰
a.minicard-details-menu-with-handle.js-open-minicard-details-menu(title="{{_ 'cardDetailsActionsPopup-title'}}")
i.fa.fa-bars
.dates
if getReceived
.date
@ -32,7 +33,7 @@ template(name="minicard")
if hasActiveUploads
.minicard-upload-progress
.upload-progress-header
| 📤
i.fa.fa-upload
span {{_ 'uploading-files'}} ({{uploadCount}})
each uploads
.upload-progress-item(class="{{#if $eq status 'error'}}upload-error{{/if}}")
@ -41,12 +42,11 @@ template(name="minicard")
.upload-progress-fill(style="width: {{progress}}%")
if $eq status 'error'
.upload-progress-error
| ⚠️
i.fa.fa-warning
span {{_ 'upload-failed'}}
else if $eq status 'completed'
.upload-progress-success
| ✅
span {{_ 'upload-completed'}}
i.fa.fa-check span {{_ 'upload-completed'}}
.minicard-title
if $eq 'prefix-with-full-path' currentBoard.presentParentTask
@ -57,12 +57,15 @@ template(name="minicard")
| {{ parentCardName }}
if isLinkedBoard
a.js-linked-link
span.linked-icon | 📁
span.linked-icon
i.fa.fa-folder
else if isLinkedCard
a.js-linked-link
span.linked-icon | 🃏
span.linked-icon
i.fa.fa-id-card
if getArchived
span.linked-icon.linked-archived | 📦
span.linked-icon.linked-archived
i.fa.fa-archive
+viewer
if currentBoard.allowsCardNumber
span.card-number
@ -143,7 +146,8 @@ template(name="minicard")
if canModifyCard
if comments.length
.badge(title="{{_ 'card-comments-title' comments.length }}")
span.badge-icon.badge-comment.badge-text 💬
span.badge-icon.badge-comment.badge-text
i.fa.fa-comment-o
= ' '
= comments.length
//span.badge-comment.badge-text
@ -151,32 +155,39 @@ template(name="minicard")
if getDescription
unless currentBoard.allowsDescriptionTextOnMinicard
.badge.badge-state-image-only(title=getDescription)
span.badge-icon 📝
span.badge-icon
i.fa.fa-file-text-o
if getVoteQuestion
.badge.badge-state-image-only(title=getVoteQuestion)
span.badge-icon(class="{{#if voteState}}text-green{{/if}}") 👍
span.badge-icon(class="{{#if voteState}}text-green{{/if}}")
i.fa.fa-thumbs-up
span.badge-text {{ voteCountPositive }}
span.badge-icon(class="{{#if $eq voteState false}}text-red{{/if}}") 👎
span.badge-icon(class="{{#if $eq voteState false}}text-red{{/if}}")
i.fa.fa-thumbs-down
span.badge-text {{ voteCountNegative }}
if getPokerQuestion
.badge.badge-state-image-only(title=getPokerQuestion)
span.badge-icon(class="{{#if pokerState}}text-green{{/if}}") ✅
span.badge-icon(class="{{#if pokerState}}text-green{{/if}}")
i.fa.fa-check-square
if expiredPoker
span.badge-text {{ getPokerEstimation }}
if attachments.length
if currentBoard.allowsBadgeAttachmentOnMinicard
.badge
span.badge-icon 📎
span.badge-icon
i.fa.fa-paperclip
span.badge-text= attachments.length
if allSubtasks.count
.badge
span.badge-icon 🌐
span.badge-icon
i.fa.fa-globe
span.badge-text.check-list-text {{subtasksFinishedCount}}/{{allSubtasksCount}}
//{{subtasksFinishedCount}}/{{subtasksCount}} does not work because when a subtaks is archived, the count goes down
if currentBoard.allowsCardSortingByNumber
if currentBoard.allowsCardSortingByNumberOnMinicard
.badge
span.badge-icon 🔢
span.badge-icon
i.fa.fa-sort-numeric-asc
span.badge-text.check-list-sort {{ sort }}
if shouldShowChecklistAtMinicard
each shouldShowChecklistAtMinicard
@ -188,7 +199,7 @@ template(name="minicard")
| {{ getDescription }}
if shouldShowListOnMinicard
.minicard-list-name
| 📋
i.fa.fa-list
| {{ listName }}
if $eq 'subtext-with-full-path' currentBoard.presentParentTask
.parent-subtext
@ -207,7 +218,8 @@ template(name="minicardChecklist")
.checklist-header
.checklist-title= checklist.title
if canModifyCard
a.checklist-menu.js-open-checklist-menu(title="{{_ 'checklistActionsPopup-title'}}") ☰
a.checklist-menu.js-open-checklist-menu(title="{{_ 'checklistActionsPopup-title'}}")
i.fa.fa-bars
each visibleItems
+checklistItemDetail(item = . checklist = checklist card = card)

View file

@ -13,7 +13,7 @@ template(name="resultCard")
.broken-cards-null
| {{_ 'no-name'}}
if getBoard.archived
| 📦
i.fa.fa-archive
li.result-card-context.result-card-context-separator
= ' '
| {{_ 'context-separator'}}
@ -27,7 +27,7 @@ template(name="resultCard")
.broken-cards-null
| {{_ 'no-name'}}
if getSwimlane.archived
| 📦
i.fa.fa-archive
li.result-card-context.result-card-context-separator
= ' '
| {{_ 'context-separator'}}
@ -41,4 +41,4 @@ template(name="resultCard")
.broken-cards-null
| {{_ 'no-name'}}
if getList.archived
| 📦
i.fa.fa-archive

View file

@ -1,6 +1,6 @@
template(name="subtasks")
h3.card-details-item-title
| 🌐
i.fa.fa-globe
| {{_ 'subtasks'}}
if currentUser.isBoardAdmin
if toggleDeleteDialog.get
@ -16,7 +16,7 @@ template(name="subtasks")
+addSubtaskItemForm
else
a.js-open-inlined-form(title="{{_ 'add-subtask'}}")
|
i.fa.fa-plus
template(name="subtaskDetail")
.js-subtasks.subtask
@ -68,18 +68,20 @@ template(name="subtasksItems")
+addSubtaskItemForm
else
a.add-subtask-item.js-open-inlined-form
|
i.fa.fa-plus
| {{_ 'add-subtask-item'}}...
template(name='subtaskItemDetail')
.js-subtasks-item.subtasks-item
if canModifyCard
span.check-box-unicode {{#if item.isFinished }}✅{{else}}⬜{{/if}}
span.check-box-unicode
i.fa(class="{{#if item.isFinished}}fa-check-square{{else}}fa-square-o{{/if}}")
.item-title.js-open-inlined-form.is-editable(class="{{#if item.isFinished }}is-checked{{/if}}")
+viewer
= item.title
else
span.check-box-unicode {{#if item.isFinished }}✅{{else}}⬜{{/if}}
span.check-box-unicode
i.fa(class="{{#if item.isFinished}}fa-check-square{{else}}fa-square-o{{/if}}")
.item-title(class="{{#if item.isFinished }}is-checked{{/if}}")
+viewer
= item.title
@ -92,10 +94,10 @@ template(name="subtaskActionsPopup")
ul.pop-over-list
li
a.js-view-subtask(title="{{ subtask.title }}")
| 👁️
i.fa.fa-eye
| {{_ "view-it"}}
if currentUser.isBoardAdmin
a.js-delete-subtask.delete-subtask
| 🗑️
i.fa.fa-trash
| {{_ "delete"}} ...

View file

@ -130,8 +130,8 @@ textarea.editor {
}
input[type="submit"],
button {
background: #cfcfcf;
background: linear-gradient(#cfcfcf, #c2c2c2);
background: #000;
background: linear-gradient(#000, #000);
border: none;
cursor: pointer;
display: inline-block;
@ -139,6 +139,7 @@ button {
line-height: 1.3;
padding: 1vh 2.5vw;
text-align: center;
color: #fff;
}
input[type="submit"] .wide,
button .wide {
@ -149,14 +150,16 @@ input[type="submit"]:hover,
button:hover,
input[type="submit"]:focus,
button:focus {
background: #c2c2c2;
background: linear-gradient(#c2c2c2, #b5b5b5);
background: #222;
background: linear-gradient(#222, #222);
color: #fff;
}
input[type="submit"]:active,
button:active {
background: #b5b5b5;
background: linear-gradient(#b5b5b5, #a8a8a8);
box-shadow: inset 0 3px 6px rgba(0,0,0,0.1);
background: #111;
background: linear-gradient(#111, #111);
box-shadow: inset 0 3px 6px rgba(0,0,0,0.3);
color: #fff;
}
input[type="submit"]:active:hover,
button:active:hover,
@ -183,6 +186,12 @@ input[type="submit"].primary:active,
button.primary:active {
background: #01628c;
}
input[type="submit"].negate,
button.negate {
background: #eb5a46;
box-shadow: 0 1px 0 #4d4d4d;
color: #fff;
}
input[type="submit"].negate:hover,
button.negate:hover,
input[type="submit"].negate:focus,
@ -217,10 +226,10 @@ input[type="submit"]:disabled:active,
input[type="button"].disabled:active,
button.disabled:active,
.button.disabled:active {
background: #cfcfcf;
background: #555;
cursor: default;
box-shadow: none;
color: #a8a8a8;
color: #999;
}
fieldset {
border: 1px solid #bfbfbf;
@ -400,12 +409,12 @@ body.grey-icons-enabled .materialCheckBox.is-checked {
.button-link.setting.disabled.primary,
.button-link.setting.disabled.primary:hover,
.button-link.setting.disabled.primary:active {
background: #cfcfcf;
border-color: #c2c2c2;
border-bottom-color: #b5b5b5;
background: #555;
border-color: #444;
border-bottom-color: #333;
cursor: default;
box-shadow: none;
color: #a8a8a8;
color: #999;
}
.button-link.setting .label {
color: #222;

View file

@ -1,7 +1,7 @@
template(name="importHeaderBar")
h1
a.back-btn(href="{{pathFor 'home'}}")
| ⬅️
i.fa-arrow-left
| {{_ title}}
template(name="import")
@ -36,7 +36,7 @@ template(name="importMapMembers")
+userAvatar(userId=wekanId)
else
a.member.add-member
|
i.fa.fa-plus
//-
Due to the way the flewbox layout is working, we need to set some
invisible items so that the last row items have a consistent width.

View file

@ -161,29 +161,35 @@ body.list-resizing-active * {
/* Use original display for consistent button positioning */
display: block !important;
position: relative !important;
/* Prevent vertical expansion but allow normal height */
overflow: hidden !important;
/* Allow overflow for text wrapping and forms */
overflow: visible !important;
}
/* Clearfix for floated buttons */
.list-header::after {
content: "";
display: table;
clear: both;
}
/* Ensure title text doesn't cause height changes for all lists */
.list-header .list-header-name {
/* Prevent text wrapping to maintain consistent height */
white-space: nowrap !important;
/* Truncate text with ellipsis if too long */
text-overflow: ellipsis !important;
/* Allow text wrapping to flow below buttons */
white-space: normal !important;
/* Ensure proper line height */
line-height: 1.2 !important;
/* Ensure it doesn't overflow */
overflow: hidden !important;
/* Add margin to prevent overlap with buttons */
margin-right: 120px !important;
/* Ensure it doesn't overflow horizontally */
overflow-wrap: break-word !important;
word-wrap: break-word !important;
/* Full width since buttons are now absolutely positioned above */
width: 100% !important;
}
/* Position elements from right to left: hamburger, add card, drag handle */
/* Position elements at top aligned with collapse button */
.list-header .js-open-list-menu {
position: absolute !important;
top: 2.5vh !important;
right: 1.5vw !important;
top: 5px !important;
right: 10px !important;
z-index: 15 !important;
display: inline-block !important;
padding: 4px !important;
@ -191,8 +197,8 @@ body.list-resizing-active * {
.list-header .list-header-plus-top {
position: absolute !important;
top: 2.5vh !important;
right: 3.25vw !important;
top: 5px !important;
right: 10px !important;
z-index: 15 !important;
display: inline-block !important;
padding: 4px !important;
@ -200,8 +206,8 @@ body.list-resizing-active * {
.list-header .list-header-handle-desktop {
position: absolute !important;
top: 2.5vh !important;
right: 6.5vw !important;
top: 5px !important;
right: 40px !important;
z-index: 15 !important;
display: inline-block !important;
cursor: move !important;
@ -245,42 +251,61 @@ body.list-resizing-active * {
}
.list.list-collapsed {
flex: none;
min-width: 60px;
max-width: 80px;
width: 60px;
min-width: 30px;
max-width: 30px;
width: 30px;
min-height: 60vh;
height: 60vh;
overflow: visible;
position: relative;
}
.list.list-collapsed .list-header {
padding: 1vh 1.5vw 0.5vh;
min-height: 2.5vh !important;
height: auto !important;
padding: 5px 0;
min-height: 100% !important;
height: 100% !important;
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start;
position: relative;
overflow: visible !important;
width: 100%;
max-width: 60px;
margin: 0 auto;
width: 30px;
max-width: 30px;
margin: 0;
}
.list.list-collapsed .list-header .js-collapse {
margin: 0 auto 0 auto;
position: relative !important;
left: -10px !important;
margin: 5px auto;
z-index: 10;
padding: 8px 12px;
font-size: 12px;
padding: 5px;
font-size: 16px;
white-space: nowrap;
display: block;
width: fit-content;
width: auto;
left: auto !important;
top: auto !important;
}
.list.list-collapsed .list-header .list-header-handle {
position: absolute !important;
top: 30px !important;
right: 1.5vw !important;
z-index: 15 !important;
position: static !important;
margin: 5px auto;
z-index: 10;
padding: 5px;
display: block;
width: auto;
top: auto !important;
right: auto !important;
}
.list.list-collapsed .list-header .list-header-handle-desktop {
position: static !important;
margin: 5px auto;
z-index: 10;
padding: 5px;
display: block;
width: auto;
top: auto !important;
right: auto !important;
}
.list.list-collapsed .list-header .list-rotated {
width: auto !important;
@ -288,30 +313,43 @@ body.list-resizing-active * {
margin: 20px 0 0 0 !important;
position: relative !important;
overflow: visible !important;
transform: rotate(90deg);
transform-origin: center center;
flex: 1;
display: flex;
align-items: center;
justify-content: center;
}
.list.list-collapsed .list-header .list-rotated h2.list-header-name {
text-align: left;
text-align: center;
overflow: visible;
white-space: nowrap;
display: block !important;
font-size: 12px;
line-height: 1.2;
color: #333;
background-color: rgba(255, 255, 255, 0.95);
border: 1px solid #ddd;
padding: 0;
border-radius: 4px;
padding: 4px 8px;
margin: 0;
width: 100vh;
height: 30px;
position: absolute;
left: 40px;
top: 50%;
transform: translateY(calc(-50% + 20px)) rotate(0deg);
width: auto;
height: auto;
position: static;
left: auto;
top: auto;
transform: none;
z-index: 10;
visibility: visible !important;
opacity: 1 !important;
pointer-events: none;
pointer-events: auto;
}
.list.list-composer,
.list-composer {
display: none;
}
/* Show list-composer when inside an active inlined form */
form.inlined-form .list-composer {
display: block;
}
.list.list-composer .open-list-composer,
@ -348,16 +386,17 @@ body.list-resizing-active * {
display: none;
}
.list-header .list-header-name {
display: inline;
display: block;
font-size: clamp(14px, 3vw, 18px);
line-height: 1.2;
margin: 0;
font-weight: bold;
min-height: 1.2vh;
min-width: 4vw;
overflow: hidden;
text-overflow: ellipsis;
overflow-wrap: break-word;
word-wrap: break-word;
vertical-align: top;
width: 100%;
}
/* Sum badge shown before list title */
.list-header .list-sum-badge {
@ -398,6 +437,8 @@ body.list-resizing-active * {
.list-header .list-header-plus-top {
color: #a6a6a6;
margin-right: 15px;
vertical-align: middle;
line-height: 1.2;
}
.list-header .list-header-collapse-right {
color: #a6a6a6;
@ -406,41 +447,38 @@ body.list-resizing-active * {
color: #a6a6a6;
margin-right: 15px;
}
/* List header collapse button styling */
.list-header .list-header-collapse-container {
display: flex;
flex-direction: row;
align-items: flex-start;
gap: 10px;
flex: 1;
min-width: 0;
}
/* List header collapse button styling - positioned at top left */
.list-header .js-collapse {
position: absolute !important;
top: 5px !important;
left: 10px !important;
color: #a6a6a6;
display: inline-block;
vertical-align: middle;
vertical-align: top;
padding: 5px 8px;
border: none;
border-radius: 0;
background-color: transparent;
cursor: pointer;
font-size: 18px;
line-height: 1;
line-height: 1.2;
min-width: 30px;
text-align: center;
flex-shrink: 0;
text-decoration: none;
margin: 0;
z-index: 15;
}
.list-header .js-collapse:hover {
background-color: transparent;
color: #333;
}
.list-header .list-header-collapse-container > div {
flex: 1;
min-width: 0;
/* Title text container - full width below buttons */
.list-header > div {
padding-top: 25px;
width: 100%;
display: block;
clear: both;
}
.list.list-collapsed .list-header .js-collapse {
display: inline-block !important;
@ -448,132 +486,155 @@ body.list-resizing-active * {
opacity: 1 !important;
}
/* Hide menu button in collapsed state */
.list.list-collapsed .list-header .js-open-list-menu,
.list.list-collapsed .list-header .list-header-menu {
display: none !important;
}
/* Responsive adjustments for collapsed lists */
@media (min-width: 768px) {
.list.list-collapsed {
min-width: 60px;
max-width: 80px;
width: 60px;
min-width: 30px;
max-width: 30px;
width: 30px;
min-height: 60vh;
height: 60vh;
}
.list.list-collapsed .list-header {
max-width: 60px;
margin: 0 auto;
min-height: 2.5vh !important;
height: auto !important;
width: 30px;
max-width: 30px;
margin: 0;
min-height: 100% !important;
height: 100% !important;
}
.list.list-collapsed .list-header .list-rotated {
width: auto !important;
height: auto !important;
margin: 20px 0 0 0 !important;
position: relative !important;
transform: rotate(90deg);
flex: 1;
}
.list.list-collapsed .list-header .list-rotated h2.list-header-name {
width: 100vh;
width: auto;
font-size: 12px;
height: 30px;
height: auto;
line-height: 1.2;
padding: 0;
padding: 4px 8px;
margin: 0;
overflow: visible;
position: absolute;
left: 40px;
top: 50%;
transform: translateY(calc(-50% + 120px)) rotate(0deg);
position: static;
left: auto;
top: auto;
transform: none;
text-align: center;
visibility: visible !important;
opacity: 1 !important;
display: block !important;
background-color: rgba(255, 255, 255, 0.95);
border: 1px solid #ddd;
background-color: transparent;
border: none;
color: #333;
z-index: 10;
}
.list.list-collapsed .list-header .js-collapse {
margin: 0 auto 20px auto;
margin: 5px auto;
}
}
@media (min-width: 1024px) {
.list.list-collapsed {
min-width: 30px;
max-width: 30px;
width: 30px;
min-height: 60vh;
height: 60vh;
}
.list.list-collapsed .list-header {
min-height: 2.5vh !important;
height: auto !important;
width: 30px;
max-width: 30px;
min-height: 100% !important;
height: 100% !important;
}
.list.list-collapsed .list-header .list-rotated {
width: auto !important;
height: auto !important;
margin: 20px 0 0 0 !important;
position: relative !important;
transform: rotate(90deg);
flex: 1;
}
.list.list-collapsed .list-header .list-rotated h2.list-header-name {
width: 100vh;
width: auto;
font-size: 12px;
height: 30px;
height: auto;
line-height: 1.2;
padding: 0;
padding: 4px 8px;
margin: 0;
overflow: visible;
position: absolute;
left: 40px;
top: 50%;
transform: translateY(calc(-50% + 120px)) rotate(0deg);
position: static;
left: auto;
top: auto;
transform: none;
text-align: center;
visibility: visible !important;
opacity: 1 !important;
display: block !important;
background-color: rgba(255, 255, 255, 0.95);
border: 1px solid #ddd;
background-color: transparent;
border: none;
color: #333;
z-index: 10;
}
.list.list-collapsed .list-header .js-collapse {
margin: 0 auto 20px auto;
margin: 5px auto;
}
}
@media (min-width: 1200px) {
.list.list-collapsed {
min-width: 30px;
max-width: 30px;
width: 30px;
min-height: 60vh;
height: 60vh;
}
.list.list-collapsed .list-header {
min-height: 2.5vh !important;
height: auto !important;
width: 30px;
max-width: 30px;
min-height: 100% !important;
height: 100% !important;
}
.list.list-collapsed .list-header .list-rotated {
width: auto !important;
height: auto !important;
margin: 20px 0 0 0 !important;
position: relative !important;
transform: rotate(90deg);
flex: 1;
}
.list.list-collapsed .list-header .list-rotated h2.list-header-name {
width: 100vh;
width: auto;
font-size: 12px;
height: 30px;
height: auto;
line-height: 1.2;
padding: 0;
padding: 4px 8px;
margin: 0;
overflow: visible;
position: absolute;
left: 40px;
top: 50%;
transform: translateY(calc(-50% + 40px)) rotate(0deg);
text-align: left;
position: static;
left: auto;
top: auto;
transform: none;
text-align: center;
visibility: visible !important;
opacity: 1 !important;
display: block !important;
background-color: rgba(255, 255, 255, 0.95);
border: 1px solid #ddd;
background-color: transparent;
border: none;
color: #333;
z-index: 10;
}
.list.list-collapsed .list-header .js-collapse {
margin: 0 auto 20px auto;
margin: 5px auto;
}
}
.list-header .list-header-collapse {
@ -596,6 +657,8 @@ body.list-resizing-active * {
}
.js-open-list-menu {
font-size: 18px;
vertical-align: middle;
line-height: 1.2;
}
.list-body {
flex: 1 1 auto;
@ -1078,9 +1141,9 @@ body.list-resizing-active * {
white-space: normal !important;
overflow: visible !important;
text-overflow: clip !important;
display: inline-block !important;
/* Reserve space for right-side controls (menu, handle, count) */
max-width: calc(100% - 120px) !important;
display: block !important;
/* Full width since buttons are absolutely positioned */
width: 100% !important;
/* Break long words to avoid overflow */
word-break: break-word !important;
}
@ -1173,3 +1236,48 @@ body.list-resizing-active * {
.list-header-indigo {
border-bottom: 6px solid #4b0082;
}
.list.list-collapsed .collapsed-list-drag-area {
width: 100%;
height: 60px;
display: flex;
align-items: center;
justify-content: center;
cursor: grab;
user-select: none;
}
.list.list-collapsed .collapsed-list-drag-area:active {
cursor: grabbing;
}
.list.list-collapsed .list-header-name-collapsed {
writing-mode: vertical-rl;
text-align: center;
font-size: 12px;
color: #333;
margin: 0;
padding: 0;
width: 100%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.list.list-collapsed .list-header .js-collapse {
position: relative !important;
left: -10px !important;
color: #333;
background: transparent;
border: none;
border-radius: 0;
width: auto;
height: auto;
min-width: 0;
min-height: 0;
display: block !important;
align-items: initial;
justify-content: initial;
font-size: 16px !important;
box-shadow: none;
margin: 5px auto;
z-index: 10;
}

View file

@ -276,20 +276,21 @@ BlazeComponent.extendComponent({
return;
}
// Only enable resize for non-collapsed, non-auto-width lists
const isAutoWidth = this.autoWidth();
const isCollapsed = Utils.getListCollapseState(list);
if (isCollapsed || isAutoWidth) {
$resizeHandle.hide();
return;
}
// Reactively show/hide resize handle based on collapse and auto-width state
this.autorun(() => {
const isAutoWidth = this.autoWidth();
const isCollapsed = Utils.getListCollapseState(list);
if (isCollapsed || isAutoWidth) {
$resizeHandle.hide();
} else {
$resizeHandle.show();
}
});
let isResizing = false;
let startX = 0;
let startWidth = 0;
let minWidth = 100; // Minimum width as defined in the existing code
let maxWidth = this.listConstraint() || 1000; // Use constraint as max width
let listConstraint = this.listConstraint(); // Store constraint value for use in event handlers
const component = this; // Store reference to component for use in event handlers
@ -318,7 +319,7 @@ BlazeComponent.extendComponent({
const currentX = e.pageX || e.originalEvent.touches[0].pageX;
const deltaX = currentX - startX;
const newWidth = Math.max(minWidth, Math.min(maxWidth, startWidth + deltaX));
const newWidth = Math.max(minWidth, startWidth + deltaX);
// Apply the new width immediately for real-time feedback
$list[0].style.setProperty('--list-width', `${newWidth}px`);
@ -343,7 +344,7 @@ BlazeComponent.extendComponent({
// Calculate final width
const currentX = e.pageX || e.originalEvent.touches[0].pageX;
const deltaX = currentX - startX;
const finalWidth = Math.max(minWidth, Math.min(maxWidth, startWidth + deltaX));
const finalWidth = Math.max(minWidth, startWidth + deltaX);
// Ensure the final width is applied
$list[0].style.setProperty('--list-width', `${finalWidth}px`);
@ -466,3 +467,16 @@ Template.miniList.events({
Session.set('currentList', listId);
},
});
// Enable drag-reorder for collapsed lists from .js-collapsed-list-drag area
this.$('.js-collapsed-list-drag').draggable({
axis: 'x',
helper: 'clone',
revert: 'invalid',
start(evt, ui) {
boardComponent.setIsDragging(true);
},
stop(evt, ui) {
boardComponent.setIsDragging(false);
}
});

View file

@ -2,9 +2,8 @@ template(name="listBody")
unless collapsed
.list-body(class="{{#unless isVerticalScrollbars}}no-scrollbars{{/unless}}")
.minicards.clearfix.js-minicards(class="{{#if reachedWipLimit}}js-list-full{{/if}}")
if cards.length
+inlinedForm(autoclose=false position="top")
+addCardForm(listId=_id position="top")
+inlinedForm(autoclose=false position="top")
+addCardForm(listId=_id position="top")
ul.sidebar-list
each customFieldsSum
li
@ -26,13 +25,8 @@ template(name="listBody")
+minicard(this)
if (showSpinner (idOrNull ../../_id))
+spinnerList
if canSeeAddCard
+inlinedForm(autoclose=false position="bottom")
+addCardForm(listId=_id position="bottom")
else
a.open-minicard-composer.js-card-composer.js-open-inlined-form(title="{{_ 'add-card-to-bottom-of-list'}}")
|
+inlinedForm(autoclose=false position="bottom")
+addCardForm(listId=_id position="bottom")
template(name="spinnerList")
.sk-spinner.sk-spinner-list(
@ -54,7 +48,8 @@ template(name="addCardForm")
.add-controls.clearfix
button.primary.confirm(type="submit") {{_ 'add'}}
a.js-close-inlined-form | ❌
a.js-close-inlined-form
i.fa.fa-times-thin
.add-controls.clearfix
unless currentBoard.isTemplatesBoard
unless currentBoard.isTemplateBoard

View file

@ -8,7 +8,7 @@ template(name="listHeader")
if isMiniScreen
if currentList
a.list-header-left-icon.js-unselect-list
| ◀️
i.fa.fa-caret-left
else
if collapsed
if showCardsCountForList cards.length
@ -30,22 +30,21 @@ template(name="listHeader")
|  
span.list-sum-badge(title="{{_ 'sum-of-number-fields'}}") ∑ {{numberFieldsSum}}
else
div.list-header-collapse-container
a.list-collapse-indicator.js-collapse(title="{{_ 'collapse'}}")
if collapsed
| ▶
else
| 🔽
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})
a.list-collapse-indicator.js-collapse(title="{{_ 'collapse'}}")
if collapsed
i.fa.fa-caret-right
else
i.fa.fa-caret-down
div(class="{{#if collapsed}}list-rotated{{/if}}")
h2.list-header-name(
title="{{ moment modifiedAt 'LLL' }}"
class="{{#unless collapsed}}{{#if currentUser.isBoardMember}}{{#unless currentUser.isCommentOnly}}{{#unless currentUser.isWorker}}js-open-inlined-form is-editable{{/unless}}{{/unless}}{{/if}}{{/unless}}")
+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}}
@ -55,22 +54,29 @@ template(name="listHeader")
if isMiniScreen
if currentList
if isWatching
i.list-header-watch-icon | 👁️
i.list-header-watch-icon i.fa.fa-eye
div.list-header-menu
unless currentUser.isCommentOnly
unless currentUser.isReadOnly
unless currentUser.isReadAssignedOnly
if canSeeAddCard
a.js-add-card.list-header-plus-top(title="{{_ 'add-card-to-top-of-list'}}")
a.js-open-list-menu(title="{{_ 'listActionPopup-title'}}") ☰
a.js-open-list-menu(title="{{_ 'listActionPopup-title'}}")
i.fa.fa-bars
else
a.list-header-menu-icon.js-select-list ▶️
a.list-header-menu-icon.js-select-list
i.fa.fa-caret-right
unless currentUser.isWorker
if isTouchScreenOrShowDesktopDragHandles
a.list-header-handle.handle.js-list-handle ↕️
a.list-header-handle.handle.js-list-handle
i.fa.fa-arrows
else if currentUser.isBoardMember
if isWatching
i.list-header-watch-icon | 👁️
i.list-header-watch-icon i.fa.fa-eye
unless currentUser.isCommentOnly
unless currentUser.isReadOnly
unless currentUser.isReadAssignedOnly
if isTouchScreenOrShowDesktopDragHandles
a.list-header-handle-desktop.handle.js-list-handle(title="{{_ 'drag-list'}}")
i.fa.fa-arrows
unless collapsed
div.list-header-menu
unless currentUser.isCommentOnly
@ -78,11 +84,8 @@ template(name="listHeader")
unless currentUser.isReadAssignedOnly
//if isBoardAdmin
// a.fa.js-list-star.list-header-plus-top(class="fa-star{{#unless starred}}-o{{/unless}}")
if isTouchScreenOrShowDesktopDragHandles
a.list-header-handle-desktop.handle.js-list-handle(title="{{_ 'drag-list'}}") ↕️
if canSeeAddCard
a.js-add-card.list-header-plus-top(title="{{_ 'add-card-to-top-of-list'}}")
a.js-open-list-menu(title="{{_ 'listActionPopup-title'}}") ☰
a.js-open-list-menu(title="{{_ 'listActionPopup-title'}}")
i.fa.fa-bars
template(name="editListTitleForm")
.list-composer
@ -90,31 +93,42 @@ template(name="editListTitleForm")
.edit-controls.clearfix
button.primary.confirm(type="submit") {{_ 'save'}}
a.js-close-inlined-form
| ❌
i.fa.fa-times-thin
template(name="listActionPopup")
unless currentUser.isReadOnly
unless currentUser.isReadAssignedOnly
ul.pop-over-list
li
a.js-add-card.list-header-plus-top
i.fa.fa-plus
i.fa.fa-arrow-up
| {{_ 'add-card-to-top-of-list'}}
li
a.js-add-card.list-header-plus-bottom
|
| ⬇️
i.fa.fa-plus
i.fa.fa-arrow-down
| {{_ 'add-card-to-bottom-of-list'}}
hr
ul.pop-over-list
li
a.js-add-list
i.fa.fa-plus
| {{_ 'add-list'}}
hr
ul.pop-over-list
li
a.js-set-list-width
| ↔️
i.fa.fa-arrows-h
| {{_ 'set-list-width'}}
ul.pop-over-list
li
a.js-toggle-watch-list
if isWatching
| 👁️
i.fa.fa-eye
| {{_ 'unwatch'}}
else
| 🙈
i.fa.fa-eye-slash
| {{_ 'watch'}}
unless currentUser.isCommentOnly
unless currentUser.isReadOnly
@ -123,33 +137,33 @@ template(name="listActionPopup")
ul.pop-over-list
li
a.js-set-color-list
| 🎨
i.fa.fa-paint-brush
| {{_ 'set-color-list'}}
ul.pop-over-list
if cards.length
li
a.js-select-cards
| ☑️
i.fa.fa-select-square
| {{_ 'list-select-cards'}}
if currentUser.isBoardAdmin
ul.pop-over-list
li
a.js-set-wip-limit
| 🚫
i.fa.fa-ban
| {{#if isWipLimitEnabled }}{{_ 'edit-wip-limit'}}{{else}}{{_ 'setWipLimitPopup-title'}}{{/if}}
unless currentUser.isWorker
hr
ul.pop-over-list
li
a.js-close-list
| ➡️
| 📦
i.fa.fa-arrow-right
i.fa.fa-archive
| {{_ 'archive-list'}}
hr
ul.pop-over-list
li
a.js-more
| 🔗
i.fa.fa-link
| {{_ 'listMorePopup-title'}}
template(name="boardLists")
@ -166,7 +180,7 @@ template(name="listMorePopup")
span.clearfix
span {{_ 'link-list'}}
= ' '
| {{#if board.isPublic}}🌐{{else}}🔒{{/if}}
i.fa(class="{{#if currentBoard.isPublic}}fa-globe{{else}}fa-lock{{/if}}")
input.inline-input(type="text" readonly value="{{ rootUrl }}")
| {{_ 'added'}}
span.date(title=list.createdAt) {{ moment createdAt 'LLL' }}
@ -186,7 +200,7 @@ template(name="setWipLimitPopup")
ul.pop-over-list
li: a.js-enable-wip-limit {{_ 'enable-wip-limit'}}
if isWipLimitEnabled
| ✅
i.fa.fa-check
if isWipLimitEnabled
p
input.wip-limit-value(type="number" value="{{ wipLimitValue }}" min="1" max="99")
@ -228,6 +242,29 @@ template(name="setListColorPopup")
// note: we use the swimlane palette to have more than just the border
span.card-label.palette-color.js-palette-color(class="card-details-{{color}}")
if(isSelected color)
| ✅
i.fa.fa-check
button.primary.confirm.js-submit {{_ 'save'}}
button.js-remove-color.negate.wide.right {{_ 'unset-color'}}
template(name="addListPopup")
form.js-add-list-form
input.list-name-input.full-line(type="text" placeholder="{{_ 'add-list'}}" autocomplete="off" autofocus)
if currentSwimlaneData
if swimlaneLists.length
label {{_ 'add-after-list'}}
select.list-position-input.full-line
each swimlaneLists
option(value="{{_id}}" selected="{{$eq _id currentListIdValue}}") {{increment @index}} {{title}}
else
if currentBoard.lists.length
label {{_ 'add-after-list'}}
select.list-position-input.full-line
each currentBoard.lists
option(value="{{_id}}" selected="{{$eq _id currentListIdValue}}") {{increment @index}} {{title}}
.edit-controls.clearfix
button.primary.confirm.js-submit-add-list(type="submit") {{_ 'save'}}
unless currentBoard.isTemplatesBoard
unless currentBoard.isTemplateBoard
span.quiet
| {{_ 'or'}}
a.js-list-template {{_ 'template'}}

View file

@ -123,15 +123,6 @@ BlazeComponent.extendComponent({
this.collapsed(!this.collapsed());
},
'click .js-open-list-menu': Popup.open('listAction'),
'click .js-add-card.list-header-plus-top'(event) {
const listDom = $(event.target).parents(
`#js-list-${this.currentData()._id}`,
)[0];
const listComponent = BlazeComponent.getComponentForElement(listDom);
listComponent.openForm({
position: 'top',
});
},
'click .js-unselect-list'() {
Session.set('currentList', null);
},
@ -204,14 +195,27 @@ Template.listActionPopup.helpers({
Template.listActionPopup.events({
'click .js-list-subscribe'() {},
'click .js-add-card.list-header-plus-top'(event) {
const listDom = $(`#js-list-${this._id}`)[0];
const listComponent = BlazeComponent.getComponentForElement(listDom);
if (listComponent) {
listComponent.openForm({
position: 'top',
});
}
Popup.back();
},
'click .js-add-card.list-header-plus-bottom'(event) {
const listDom = $(`#js-list-${this._id}`)[0];
const listComponent = BlazeComponent.getComponentForElement(listDom);
listComponent.openForm({
position: 'bottom',
});
if (listComponent) {
listComponent.openForm({
position: 'bottom',
});
}
Popup.back();
},
'click .js-add-list': Popup.open('addList'),
'click .js-set-list-width': Popup.open('setListWidth'),
'click .js-set-color-list': Popup.open('setListColor'),
'click .js-select-cards'() {
@ -440,3 +444,105 @@ BlazeComponent.extendComponent({
];
},
}).register('setListWidthPopup');
BlazeComponent.extendComponent({
onCreated() {
this.currentBoard = Utils.getCurrentBoard();
this.currentSwimlaneId = new ReactiveVar(null);
this.currentListId = new ReactiveVar(null);
// Get the swimlane context from opener
const openerData = Popup.getOpenerComponent()?.data();
// If opened from swimlane menu, openerData is the swimlane
if (openerData?.type === 'swimlane' || openerData?.type === 'template-swimlane') {
this.currentSwimlane = openerData;
this.currentSwimlaneId.set(openerData._id);
} else if (openerData?._id) {
// If opened from list menu, get swimlane from the list
const list = ReactiveCache.getList({ _id: openerData._id });
this.currentSwimlane = list?.swimlaneId ? ReactiveCache.getSwimlane({ _id: list.swimlaneId }) : null;
this.currentSwimlaneId.set(this.currentSwimlane?._id || null);
this.currentListId.set(openerData._id);
}
},
currentSwimlaneData() {
const swimlaneId = this.currentSwimlaneId.get();
return swimlaneId ? ReactiveCache.getSwimlane({ _id: swimlaneId }) : null;
},
currentListIdValue() {
return this.currentListId.get();
},
swimlaneLists() {
const swimlaneId = this.currentSwimlaneId.get();
if (swimlaneId) {
return ReactiveCache.getLists({ swimlaneId, archived: false }).sort((a, b) => a.sort - b.sort);
}
return this.currentBoard.lists;
},
events() {
return [
{
'submit .js-add-list-form'(evt) {
evt.preventDefault();
const titleInput = this.find('.list-name-input');
const title = titleInput?.value.trim();
if (!title) return;
let sortIndex = 0;
const boardId = Utils.getCurrentBoardId();
const swimlaneId = this.currentSwimlane?._id;
const positionInput = this.find('.list-position-input');
if (positionInput && positionInput.value) {
const positionId = positionInput.value.trim();
const selectedList = ReactiveCache.getList({ boardId, _id: positionId, archived: false });
if (selectedList) {
sortIndex = selectedList.sort + 1;
} else {
// No specific position, add at end of swimlane
if (swimlaneId) {
const swimlaneLists = ReactiveCache.getLists({ swimlaneId, archived: false });
const lastSwimlaneList = swimlaneLists.sort((a, b) => b.sort - a.sort)[0];
sortIndex = Utils.calculateIndexData(lastSwimlaneList, null).base;
} else {
const lastList = this.currentBoard.getLastList();
sortIndex = Utils.calculateIndexData(lastList, null).base;
}
}
} else {
// No position input, add at end of swimlane
if (swimlaneId) {
const swimlaneLists = ReactiveCache.getLists({ swimlaneId, archived: false });
const lastSwimlaneList = swimlaneLists.sort((a, b) => b.sort - a.sort)[0];
sortIndex = Utils.calculateIndexData(lastSwimlaneList, null).base;
} else {
const lastList = this.currentBoard.getLastList();
sortIndex = Utils.calculateIndexData(lastList, null).base;
}
}
Lists.insert({
title,
boardId: Session.get('currentBoard'),
sort: sortIndex,
type: 'list',
swimlaneId: swimlaneId,
});
Popup.back();
},
'click .js-list-template': Popup.open('searchElement'),
},
];
},
}).register('addListPopup');

View file

@ -3,6 +3,7 @@ template(name="minilist")
class="minicard-{{colorClass}}")
.minicard-title
.handle
span.drag-handle(title="{{_ 'dragList'}}") ↕️
span.drag-handle(title="{{_ 'dragList'}}")
i.fa.fa-arrows
+viewer
= title

View file

@ -1,23 +1,23 @@
template(name="dueCardsHeaderBar")
if currentUser
h1
| 📅
i.fa.fa-calendar
| {{_ 'dueCards-title'}}
.board-header-btns.left
a.board-header-btn.js-due-cards-view-change(title="{{_ 'dueCardsViewChange-title'}}")
| ▼
i.fa.fa-caret-down
if $eq dueCardsView 'me'
| 👤
i.fa.fa-user
| {{_ 'dueCardsViewChange-choice-me'}}
if $eq dueCardsView 'all'
| 👥
i.fa.fa-users
| {{_ 'dueCardsViewChange-choice-all'}}
template(name="dueCardsModalTitle")
if currentUser
h2
| ⌨️
i.fa.fa-keyboard-o
| {{_ 'dueCards-title'}}
template(name="dueCards")
@ -49,18 +49,17 @@ template(name="dueCardsViewChangePopup")
li
with "dueCardsViewChange-choice-me"
a.js-due-cards-view-me
| 👤
i.fa.fa-user
| {{_ 'dueCardsViewChange-choice-me'}}
if $eq Utils.dueCardsView "me"
| ✅
hr
i.fa.fa-check hr
li
with "dueCardsViewChange-choice-all"
a.js-due-cards-view-all
| 👥
i.fa.fa-users
| {{_ 'dueCardsViewChange-choice-all'}}
span.sub-name
+viewer
| {{_ 'dueCardsViewChange-choice-all-description' }}
if $eq Utils.dueCardsView "all"
| ✅
i.fa.fa-check

View file

@ -1,8 +1,6 @@
template(name="editor")
a(title="{{_ 'convert-to-markdown'}}")
| 📝
a(title="{{_ 'copy-text-to-clipboard'}}")
| 📋
a.fa.fa-brands.fa-markdown(title="{{_ 'convert-to-markdown'}}")
a.fa.fa-copy(title="{{_ 'copy-text-to-clipboard'}}")
span.copied-tooltip {{_ 'copied'}}
textarea.editor(
dir="auto"

View file

@ -1,13 +1,13 @@
template(name="globalSearchHeaderBar")
if currentUser
h1
| 🔍
i.fa.fa-search
| {{_ 'globalSearch-title'}}
template(name="globalSearchModalTitle")
if currentUser
h2
| ⌨️
i.fa.fa-keyboard-o
| {{_ 'globalSearch-title'}}
template(name="resultsPaged")

View file

@ -9,7 +9,7 @@ template(name="header")
// Home icon - always at left side of logo
span.home-icon.allBoards
a(href="{{pathFor 'home'}}")
| 🏠
i.fa.fa-home
| {{_ 'all-boards'}}
// Logo - visible; on mobile constrained by CSS
@ -32,11 +32,11 @@ template(name="header")
// Drag handles toggle - between zoom and mobile mode toggle
a.board-header-btn.js-toggle-desktop-drag-handles(title="{{_ 'show-desktop-drag-handles'}}")
| ↕️
i.fa.fa-arrows
if isShowDesktopDragHandles
| ✅
i.fa.fa-check
unless isShowDesktopDragHandles
| 🚫
i.fa.fa-ban
if isMiniScreen
ul.header-quick-access-list
@ -64,8 +64,9 @@ template(name="header")
a(href="{{pathFor 'board' id=_id slug=slug}}")
+viewer
= title
else
li.current.empty {{_ 'quick-access-description'}}
//else
// li.current.empty
// {{_ 'quick-access-description'}}
#header-new-board-icon
// Next line is used only for spacing at header,
// there is no visible clickable icon.
@ -77,8 +78,10 @@ template(name="header")
.mobile-mode-toggle
a.board-header-btn.js-mobile-mode-toggle(title="{{_ 'mobile-desktop-toggle'}}" class="{{#if mobileMode}}mobile-active{{else}}desktop-active{{/if}}")
i.mobile-icon(class="{{#if mobileMode}}active{{/if}}") 📱
i.desktop-icon(class="{{#unless mobileMode}}active{{/unless}}") 🖥️
i.mobile-icon(class="{{#if mobileMode}}active{{/if}}")
i.fa.fa-mobile
i.desktop-icon(class="{{#unless mobileMode}}active{{/unless}}")
i.fa.fa-desktop
// Notifications
+notifications
@ -86,7 +89,7 @@ template(name="header")
if currentSetting.customHelpLinkUrl
#header-help
a(href="{{currentSetting.customHelpLinkUrl}}", title="{{_ 'help'}}", target="_blank", rel="noopener noreferrer")
| ❓
i.fa.fa-question-circle
+headerUserBar
@ -105,17 +108,17 @@ template(name="header")
if hasAnnouncement
.announcement
p
| 📢
i.fa.fa-bullhorn
+viewer
| #{announcement}
a
.js-close-announcement
| ❌
i.fa.fa-times-thin
template(name="offlineWarning")
.offline-warning
p
| ⚠️
i.fa.fa-warning
| {{_ 'app-is-offline'}}
a.app-try-reconnect {{_ 'app-try-reconnect'}}

View file

@ -6,7 +6,7 @@ template(name="shortcutsHeaderBar")
template(name="shortcutsModalTitle")
h2
| ⌨️
i.fa.fa-keyboard-o
| {{_ 'keyboard-shortcuts'}}
template(name="keyboardShortcuts")

View file

@ -69,9 +69,15 @@ template(name="userFormsLayout")
select.select-lang.js-userform-set-language#userform-set-language-select(aria-label="{{_ 'changeLanguagePopup-title'}}")
each languages
if isCurrentLanguage
option(value="{{tag}}" selected="selected") {{name}}
if rtl
option(value="{{tag}}" selected="selected") {{name}} (RTL)
else
option(value="{{tag}}" selected="selected") {{name}}
else
option(value="{{tag}}") {{name}}
if rtl
option(value="{{tag}}") {{name}} (RTL)
else
option(value="{{tag}}") {{name}}
template(name="defaultLayout")
+header
@ -86,13 +92,13 @@ template(name="defaultLayout")
if (Modal.isWide)
.modal-content-wide.modal-container
a.modal-close-btn.js-close-modal
| ❌
i.fa.fa-times-thin
+Template.dynamic(template=Modal.getHeaderName)
+Template.dynamic(template=Modal.getTemplateName)
else
.modal-content.modal-container
a.modal-close-btn.js-close-modal
| ❌
i.fa.fa-times-thin
+Template.dynamic(template=Modal.getHeaderName)
+Template.dynamic(template=Modal.getTemplateName)
@ -103,8 +109,7 @@ template(name="message")
.big-message.quiet(class=color)
h1 {{_ label}}
unless currentUser
with(pathFor route='atSignIn')
p {{{_ 'page-maybe-private' this}}}
p {{{_ 'page-maybe-private' '/sign-in'}}}
template(name="loader")
h1.loadingText {{_ 'loading'}}

View file

@ -85,6 +85,70 @@ Template.userFormsLayout.onRendered(() => {
validator,
);
EscapeActions.executeAll();
// Set up MutationObserver for OIDC button instead of deprecated DOMSubtreeModified
const oidcButton = document.getElementById('at-oidc');
if (oidcButton) {
const observer = new MutationObserver((mutations) => {
if (alreadyCheck <= 2) {
let currSetting = ReactiveCache.getCurrentSetting();
let oidcBtnElt = $('#at-oidc');
if (
currSetting &&
currSetting !== undefined &&
currSetting.oidcBtnText !== undefined &&
oidcBtnElt != null &&
oidcBtnElt != undefined
) {
let htmlvalue = "<i class='fa fa-oidc'></i>" + currSetting.oidcBtnText;
if (alreadyCheck == 1) {
alreadyCheck++;
oidcBtnElt.html('');
} else {
alreadyCheck++;
oidcBtnElt.html(htmlvalue);
}
}
} else {
alreadyCheck = 1;
}
});
observer.observe(oidcButton, { childList: true, subtree: true });
}
// Set up MutationObserver for .at-form instead of deprecated DOMSubtreeModified
const atForm = document.querySelector('.at-form');
if (atForm) {
const formObserver = new MutationObserver((mutations) => {
if (alreadyCheck <= 2 && !isCheckDone) {
if (document.getElementById('at-oidc') != null) {
let currSetting = ReactiveCache.getCurrentSetting();
let oidcBtnElt = $('#at-oidc');
if (
currSetting &&
currSetting !== undefined &&
currSetting.oidcBtnText !== undefined &&
oidcBtnElt != null &&
oidcBtnElt != undefined
) {
let htmlvalue =
"<i class='fa fa-oidc'></i>" + currSetting.oidcBtnText;
if (alreadyCheck == 1) {
alreadyCheck++;
oidcBtnElt.html('');
} else {
alreadyCheck++;
isCheckDone = true;
oidcBtnElt.html(htmlvalue);
}
}
}
} else {
alreadyCheck = 1;
}
});
formObserver.observe(atForm, { childList: true, subtree: true });
}
// Add autocomplete attribute to login input for WCAG compliance
const loginInput = document.querySelector(
@ -152,7 +216,7 @@ Template.userFormsLayout.helpers({
languages() {
return TAPi18n.getSupportedLanguages()
.map(({ tag, name }) => ({ tag: tag, name }))
.map(({ tag, name, rtl }) => ({ tag, name, rtl }))
.sort((a, b) => {
if (a.name === b.name) {
return 0;
@ -183,61 +247,6 @@ Template.userFormsLayout.events({
}
isCheckDone = false;
},
'click #at-signUp'(event, templateInstance) {
isCheckDone = false;
},
'DOMSubtreeModified #at-oidc'(event) {
if (alreadyCheck <= 2) {
let currSetting = ReactiveCache.getCurrentSetting();
let oidcBtnElt = $('#at-oidc');
if (
currSetting &&
currSetting !== undefined &&
currSetting.oidcBtnText !== undefined &&
oidcBtnElt != null &&
oidcBtnElt != undefined
) {
let htmlvalue = "<i class='fa fa-oidc'></i>" + currSetting.oidcBtnText;
if (alreadyCheck == 1) {
alreadyCheck++;
oidcBtnElt.html('');
} else {
alreadyCheck++;
oidcBtnElt.html(htmlvalue);
}
}
} else {
alreadyCheck = 1;
}
},
'DOMSubtreeModified .at-form'(event) {
if (alreadyCheck <= 2 && !isCheckDone) {
if (document.getElementById('at-oidc') != null) {
let currSetting = ReactiveCache.getCurrentSetting();
let oidcBtnElt = $('#at-oidc');
if (
currSetting &&
currSetting !== undefined &&
currSetting.oidcBtnText !== undefined &&
oidcBtnElt != null &&
oidcBtnElt != undefined
) {
let htmlvalue =
"<i class='fa fa-oidc'></i>" + currSetting.oidcBtnText;
if (alreadyCheck == 1) {
alreadyCheck++;
oidcBtnElt.html('');
} else {
alreadyCheck++;
isCheckDone = true;
oidcBtnElt.html(htmlvalue);
}
}
}
} else {
alreadyCheck = 1;
}
},
});
Template.defaultLayout.events({

View file

@ -3,23 +3,23 @@ template(name="myCardsHeaderBar")
h1
//a.back-btn(href="{{pathFor 'home'}}")
// i.fa.fa-chevron-left
| 📋
i.fa.fa-list
| {{_ 'my-cards'}}
.board-header-btns.left
a.board-header-btn.js-my-cards-view-change(title="{{_ 'myCardsViewChange-title'}}")
| ▼
i.fa.fa-caret-down
if $eq myCardsView 'boards'
| 📋
i.fa.fa-list
| {{_ 'myCardsViewChange-choice-boards'}}
if $eq myCardsView 'table'
| 📊
i.fa.fa-bar-chart
| {{_ 'myCardsViewChange-choice-table'}}
template(name="myCardsModalTitle")
if currentUser
h2
| ⌨️
i.fa.fa-keyboard-o
| {{_ 'my-cards'}}
template(name="myCards")
@ -102,15 +102,15 @@ template(name="myCardsViewChangePopup")
li
with "myCardsViewChange-choice-boards"
a.js-my-cards-view-boards
| 📋
i.fa.fa-list
| {{_ 'myCardsViewChange-choice-boards'}}
if $eq Utils.myCardsView "boards"
| ✅
i.fa.fa-check
hr
li
with "myCardsViewChange-choice-table"
a.js-my-cards-view-table
| 📊
i.fa.fa-bar-chart
| {{_ 'myCardsViewChange-choice-table'}}
if $eq Utils.myCardsView "table"
| ✅
i.fa.fa-check

View file

@ -478,6 +478,7 @@
/* flex-wrap:wrap;*/
gap:5px;
align-items: center;
color: #000 !important;
}
.pop-over-list li > a > .member{
align-self: flex-start;

View file

@ -6,10 +6,10 @@
style="left:{{offset.left}}px; top:{{offset.top}}px;{{#if offset.maxHeight}} max-height:{{offset.maxHeight}}px;{{/if}}")
.header
a.back-btn.js-back-view(class="{{#unless hasPopupParent}}is-hidden{{/unless}}")
| ◀️
i.fa.fa-caret-left
span.header-title= title
a.close-btn.js-close-pop-over
| ❌
i.fa.fa-times-thin
.content-wrapper
//-
We display the all stack of popup content next to each other and move

View file

@ -25,7 +25,7 @@
height: 1.2em;
font-size: clamp(14px, 2vw, 17px);
display: block;
color: #bbb;
color: #000;
}
#notifications-drawer .notification .read-status .activity-type.hidden {
display: none;

View file

@ -1,6 +1,6 @@
template(name='notifications')
#notifications.board-header-btns.right
a.notifications-drawer-toggle(class="{{#if $gt unreadNotifications 0}}alert{{/if}}" title="{{_ 'notifications'}}")
| 🔔
i.fa.fa-bell
if $.Session.get 'showNotificationsDrawer'
+notificationsDrawer(unreadNotifications=unreadNotifications)

View file

@ -1,42 +1,54 @@
template(name='notificationsDrawer')
section#notifications-drawer(class="{{#if $.Session.get 'showReadNotifications'}}show-read{{/if}}")
.header
a.notification-menu-toggle ☰
a.notification-menu-toggle
i.fa.fa-bars
.notification-menu(class="{{#if $.Session.get 'showNotificationMenu'}}is-open{{/if}}")
.menu-section
a.menu-item(class="{{#unless $.Session.get 'showReadNotifications'}}selected{{/unless}}")
span.check-icon {{#unless $.Session.get 'showReadNotifications'}}✓{{/unless}}
span.menu-icon 📭
span.check-icon
if $not $.Session.get 'showReadNotifications'
i.fa.fa-check
span.menu-icon
i.fa.fa-envelope-open
span {{_ 'filter-by-unread'}}
a.menu-item(class="{{#if $.Session.get 'showReadNotifications'}}selected{{/if}}")
span.check-icon {{#if $.Session.get 'showReadNotifications'}}✓{{/if}}
span.menu-icon 📋
span.check-icon
if $.Session.get 'showReadNotifications'
i.fa.fa-check
span.menu-icon
i.fa.fa-copy
span {{_ 'view-all'}}
.menu-divider
.menu-section
if($gt unreadNotifications 0)
a.menu-item.mark-all-read
span.check-icon
span.menu-icon ✅
span.menu-icon
i.fa.fa-check
span {{_ 'mark-all-as-read'}}
if ($and ($.Session.get 'showReadNotifications') ($gt readNotifications 0))
a.menu-item.mark-all-unread
span.check-icon
span.menu-icon 📬
span.menu-icon
i.fa.fa-envelope-open
span {{_ 'mark-all-as-unread'}}
if ($and ($.Session.get 'showReadNotifications') ($gt readNotifications 0))
a.menu-item.delete-read
span.check-icon
span.menu-icon 🗑️
span.menu-icon
i.fa.fa-trash
span {{_ 'remove-all-read'}}
a.menu-item.delete-all
span.check-icon
span.menu-icon 🗑️
span.menu-icon
i.fa.fa-trash
span {{_ 'delete-all-notifications'}}
h5 {{_ 'notifications'}}
if($gt unreadNotifications 0)
|(#{unreadNotifications})
a.close ❌
a.close
i.fa.fa-times-thin
ul.notifications
each notifications
+notification(activityData=activityObj index=dbIndex read=read)

View file

@ -10,7 +10,7 @@ template(name="boardActions")
div.trigger-text
| {{_'r-its-list'}}
div.trigger-button.js-add-gen-move-action.js-goto-rules
|
i.fa.fa-plus
div.trigger-item
div.trigger-content
@ -39,7 +39,7 @@ template(name="boardActions")
div.trigger-dropdown
input(id="swimlaneName",type=text,placeholder="{{_'r-name'}}")
div.trigger-button.js-add-spec-move-action.js-goto-rules
|
i.fa.fa-plus
div.trigger-item
div.trigger-content
@ -50,7 +50,7 @@ template(name="boardActions")
div.trigger-text
| {{_'r-card'}}
div.trigger-button.js-add-arch-action.js-goto-rules
|
i.fa.fa-plus
div.trigger-item
div.trigger-content
@ -59,7 +59,7 @@ template(name="boardActions")
div.trigger-dropdown
input(id="swimlane-name",type=text,placeholder="{{_'r-name'}}")
div.trigger-button.js-add-swimlane-action.js-goto-rules
|
i.fa.fa-plus
div.trigger-item
div.trigger-content
@ -76,7 +76,7 @@ template(name="boardActions")
div.trigger-dropdown
input(id="swimlane-name2",type=text,placeholder="{{_'r-name'}}")
div.trigger-button.js-create-card-action.js-goto-rules
|
i.fa.fa-plus
div.trigger-item
div.trigger-content
@ -101,7 +101,7 @@ template(name="boardActions")
div.trigger-dropdown
input(id="swimlaneName-link",type=text,placeholder="{{_'r-name'}}")
div.trigger-button.js-link-card-action.js-goto-rules
|
i.fa.fa-plus

View file

@ -16,7 +16,7 @@ template(name="cardActions")
div.trigger-text
| {{_'r-to-current-datetime'}}
div.trigger-button.js-set-date-action.js-goto-rules
|
i.fa.fa-plus
div.trigger-item
div.trigger-content
@ -30,7 +30,7 @@ template(name="cardActions")
option(value="endAt") {{_'r-df-end-at'}}
option(value="receivedAt") {{_'r-df-received-at'}}
div.trigger-button.js-remove-datevalue-action.js-goto-rules
|
i.fa.fa-plus
div.trigger-item
div.trigger-content
@ -46,7 +46,7 @@ template(name="cardActions")
option(value="#{_id}")
= name
div.trigger-button.js-add-label-action.js-goto-rules
|
i.fa.fa-plus
div.trigger-item
div.trigger-content
@ -59,14 +59,14 @@ template(name="cardActions")
div.trigger-dropdown
input(id="member-name",type=text,placeholder="{{_'r-name'}}")
div.trigger-button.js-add-member-action.js-goto-rules
|
i.fa.fa-plus
div.trigger-item
div.trigger-content
div.trigger-text
| {{_'r-remove-all'}}
div.trigger-button.js-add-removeall-action.js-goto-rules
|
i.fa.fa-plus
div.trigger-item
div.trigger-content
@ -77,12 +77,11 @@ template(name="cardActions")
class="card-details-{{cardColorButton}}")
| {{_ cardColorButtonText }}
div.trigger-button.js-set-color-action.js-goto-rules
|
i.fa.fa-plus
template(name="setCardActionsColorPopup")
form.edit-label
.palette-colors: each colors
span.card-label.palette-color.js-palette-color(class="card-details-{{color}}")
if(isSelected color)
| ✅
button.primary.confirm.js-submit {{_ 'save'}}
i.fa.fa-check button.primary.confirm.js-submit {{_ 'save'}}

View file

@ -10,7 +10,7 @@ template(name="checklistActions")
div.trigger-dropdown
input(id="checklist-name",type=text,placeholder="{{_'r-name'}}")
div.trigger-button.js-add-checklist-action.js-goto-rules
|
i.fa.fa-plus
div.trigger-item
div.trigger-content
@ -23,7 +23,7 @@ template(name="checklistActions")
div.trigger-dropdown
input(id="checklist-name2",type=text,placeholder="{{_'r-name'}}")
div.trigger-button.js-add-checkall-action.js-goto-rules
|
i.fa.fa-plus
div.trigger-item
@ -41,7 +41,7 @@ template(name="checklistActions")
div.trigger-dropdown
input(id="checklist-name3",type=text,placeholder="{{_'r-name'}}")
div.trigger-button.js-add-check-item-action.js-goto-rules
|
i.fa.fa-plus
div.trigger-item
div.trigger-content
@ -54,17 +54,10 @@ template(name="checklistActions")
div.trigger-dropdown
input(id="checklist-items",type=text,placeholder="{{_'r-items-list'}}")
div.trigger-button.js-add-checklist-items-action.js-goto-rules
|
i.fa.fa-plus
div.trigger-item
div.trigger-content
div.trigger-text
| {{_'r-checklist-note'}}

View file

@ -8,4 +8,4 @@ template(name="mailActions")
input(id="email-subject",type=text,placeholder="{{_'r-subject'}}")
textarea(id="email-msg")
div.trigger-button.trigger-button-email.js-mail-action.js-goto-rules
|
i.fa.fa-plus

View file

@ -1,7 +1,7 @@
template(name="ruleDetails")
.rules
h2
| ✨
i.fa.fa-magic
| {{_ 'r-rule-details' }}
.triggers-content
.triggers-body
@ -20,5 +20,5 @@ template(name="ruleDetails")
= action
div.rules-back
button.js-goback
| ◀️
i.fa.fa-arrow-left
| {{_ 'back'}}

View file

@ -1,18 +1,17 @@
template(name="rulesActions")
h2
| ✨
i.fa.fa-magic
| {{_ 'r-rule' }} "{{ruleNameStr}}" - {{_ 'r-add-action'}}
.triggers-content
.triggers-body
.triggers-side-menu
ul
li.active.js-set-board-actions
| 📊
i.fa.fa-bar-chart
li.js-set-card-actions
| 📝
i.fa.fa-file-text-o
li.js-set-checklist-actions
| ✅
li.js-set-mail-actions
i.fa.fa-check li.js-set-mail-actions
| @
.triggers-main-body
if $eq currentActions.get 'board'
@ -25,5 +24,5 @@ template(name="rulesActions")
+mailActions(ruleName=data.ruleName triggerVar=data.triggerVar)
div.rules-back
button.js-goback
| ◀️
i.fa.fa-arrow-left
| {{_ 'back'}}

View file

@ -1,7 +1,7 @@
template(name="rulesList")
.rules
h2
| ✨
i.fa.fa-magic
| {{_ 'r-board-rules' }}
ul.rules-list
@ -11,27 +11,27 @@ template(name="rulesList")
= title
div.rules-btns-group
button.js-goto-details
| 👁️
i.fa.fa-eye
| {{_ 'r-view-rule'}}
if currentUser.isAdmin
button.js-delete-rule
| 🗑️
i.fa.fa-trash
| {{_ 'r-delete-rule'}}
else if currentUser.isBoardAdmin
button.js-delete-rule
| 🗑️
i.fa.fa-trash
| {{_ 'r-delete-rule'}}
else
li.no-items-message {{_ 'r-no-rules' }}
if currentUser.isAdmin
div.rules-add
button.js-goto-trigger
|
i.fa.fa-plus
| {{_ 'r-add-rule'}}
input(type=text,placeholder="{{_ 'r-new-rule-name' }}",id="ruleTitle")
else if currentUser.isBoardAdmin
div.rules-add
button.js-goto-trigger
|
i.fa.fa-plus
| {{_ 'r-add-rule'}}
input(type=text,placeholder="{{_ 'r-new-rule-name' }}",id="ruleTitle")

View file

@ -1,18 +1,17 @@
template(name="rulesTriggers")
h2
| ✨
i.fa.fa-magic
| {{_ 'r-rule' }} "{{ruleNameStr}}" - {{_ 'r-add-trigger'}}
.triggers-content
.triggers-body
.triggers-side-menu
ul
li.active.js-set-board-triggers
| 📊
i.fa.fa-bar-chart
li.js-set-card-triggers
| 📝
i.fa.fa-file-text-o
li.js-set-checklist-triggers
| ✅
.triggers-main-body
i.fa.fa-check .triggers-main-body
if showBoardTrigger.get
+boardTriggers
else if showCardTrigger.get
@ -21,5 +20,5 @@ template(name="rulesTriggers")
+checklistTriggers
div.rules-back
button.js-goback
| ◀️
i.fa.fa-arrow-left
| {{_ 'back'}}

View file

@ -4,7 +4,7 @@ template(name="boardTriggers")
div.trigger-text
| {{_'r-when-a-card'}}
div.trigger-inline-button.js-open-card-title-popup
| 🔍
i.fa.fa-search
div.trigger-text
| {{_'r-is'}}
div.trigger-text
@ -18,39 +18,39 @@ template(name="boardTriggers")
div.trigger-dropdown
input(id="create-swimlane-name",type=text,placeholder="{{_'r-swimlane-name'}}")
div.trigger-button.trigger-button-person.js-show-user-field
| 👤
i.fa.fa-user
div.user-details.hide-element
div.trigger-text
| {{_'r-by'}}
div.trigger-dropdown
input(class="user-name",type=text,placeholder="{{_'username'}}")
div.trigger-button.js-add-create-trigger.js-goto-action
|
i.fa.fa-plus
div.trigger-item#trigger-three
div.trigger-content
div.trigger-text
| {{_'r-when-a-card'}}
div.trigger-inline-button.js-open-card-title-popup
| 🔍
i.fa.fa-search
div.trigger-text
| {{_'r-is-moved'}}
div.trigger-button.trigger-button-person.js-show-user-field
| 👤
i.fa.fa-user
div.user-details.hide-element
div.trigger-text
| {{_'r-by'}}
div.trigger-dropdown
input(class="user-name",type=text,placeholder="{{_'username'}}")
div.trigger-button.js-add-gen-moved-trigger.js-goto-action
|
i.fa.fa-plus
div.trigger-item#trigger-four
div.trigger-content
div.trigger-text
| {{_'r-when-a-card'}}
div.trigger-inline-button.js-open-card-title-popup
| 🔍
i.fa.fa-search
div.trigger-text
| {{_'r-is'}}
div.trigger-dropdown
@ -66,21 +66,21 @@ template(name="boardTriggers")
div.trigger-dropdown
input(id="create-swimlane-name-2",type=text,placeholder="{{_'r-swimlane-name'}}")
div.trigger-button.trigger-button-person.js-show-user-field
| 👤
i.fa.fa-user
div.user-details.hide-element
div.trigger-text
| {{_'r-by'}}
div.trigger-dropdown
input(class="user-name",type=text,placeholder="{{_'username'}}")
div.trigger-button.js-add-moved-trigger.js-goto-action
|
i.fa.fa-plus
div.trigger-item#trigger-five
div.trigger-content
div.trigger-text
| {{_'r-when-a-card'}}
div.trigger-inline-button.js-open-card-title-popup
| 🔍
i.fa.fa-search
div.trigger-text
| {{_'r-is'}}
div.trigger-dropdown
@ -88,14 +88,14 @@ template(name="boardTriggers")
option(value="archived") {{_'r-archived'}}
option(value="unarchived") {{_'r-unarchived'}}
div.trigger-button.trigger-button-person.js-show-user-field
| 👤
i.fa.fa-user
div.user-details.hide-element
div.trigger-text
| {{_'r-by'}}
div.trigger-dropdown
input(class="user-name",type=text,placeholder="{{_'username'}}")
div.trigger-button.js-add-arch-trigger.js-goto-action
|
i.fa.fa-plus
div.trigger-item
div.trigger-content

View file

@ -10,14 +10,14 @@ template(name="cardTriggers")
div.trigger-text
| {{_'r-a-card'}}
div.trigger-button.trigger-button-person.js-show-user-field
| 👤
i.fa.fa-user
div.user-details.hide-element
div.trigger-text
| {{_'r-by'}}
div.trigger-dropdown
input(class="user-name",type=text,placeholder="{{_'username'}}")
div.trigger-button.js-add-gen-label-trigger.js-goto-action
|
i.fa.fa-plus
div.trigger-item
div.trigger-content
@ -37,14 +37,14 @@ template(name="cardTriggers")
div.trigger-text
| {{_'r-a-card'}}
div.trigger-button.trigger-button-person.js-show-user-field
| 👤
i.fa.fa-user
div.user-details.hide-element
div.trigger-text
| {{_'r-by'}}
div.trigger-dropdown
input(class="user-name",type=text,placeholder="{{_'username'}}")
div.trigger-button.js-add-spec-label-trigger.js-goto-action
|
i.fa.fa-plus
div.trigger-item
div.trigger-content
@ -57,14 +57,14 @@ template(name="cardTriggers")
div.trigger-text
| {{_'r-a-card'}}
div.trigger-button.trigger-button-person.js-show-user-field
| 👤
i.fa.fa-user
div.user-details.hide-element
div.trigger-text
| {{_'r-by'}}
div.trigger-dropdown
input(class="user-name",type=text,placeholder="{{_'username'}}")
div.trigger-button.js-add-gen-member-trigger.js-goto-action
|
i.fa.fa-plus
div.trigger-item
@ -82,14 +82,14 @@ template(name="cardTriggers")
div.trigger-text
| {{_'r-a-card'}}
div.trigger-button.trigger-button-person.js-show-user-field
| 👤
i.fa.fa-user
div.user-details.hide-element
div.trigger-text
| {{_'r-by'}}
div.trigger-dropdown
input(class="user-name",type=text,placeholder="{{_'username'}}")
div.trigger-button.js-add-spec-member-trigger.js-goto-action
|
i.fa.fa-plus
div.trigger-item
div.trigger-content
@ -104,11 +104,11 @@ template(name="cardTriggers")
div.trigger-text
| {{_'r-a-card'}}
div.trigger-button.trigger-button-person.js-show-user-field
| 👤
i.fa.fa-user
div.user-details.hide-element
div.trigger-text
| {{_'r-by'}}
div.trigger-dropdown
input(class="user-name",type=text,placeholder="{{_'username'}}")
div.trigger-button.js-add-attachment-trigger.js-goto-action
|
i.fa.fa-plus

View file

@ -10,14 +10,14 @@ template(name="checklistTriggers")
div.trigger-text
| {{_'r-a-card'}}
div.trigger-button.trigger-button-person.js-show-user-field
| 👤
i.fa.fa-user
div.user-details.hide-element
div.trigger-text
| {{_'r-by'}}
div.trigger-dropdown
input(class="user-name",type=text,placeholder="{{_'username'}}")
div.trigger-button.js-add-gen-check-trigger.js-goto-action
|
i.fa.fa-plus
div.trigger-item
@ -35,14 +35,14 @@ template(name="checklistTriggers")
div.trigger-text
| {{_'r-a-card'}}
div.trigger-button.trigger-button-person.js-show-user-field
| 👤
i.fa.fa-user
div.user-details.hide-element
div.trigger-text
| {{_'r-by'}}
div.trigger-dropdown
input(class="user-name",type=text,placeholder="{{_'username'}}")
div.trigger-button.js-add-spec-check-trigger.js-goto-action
|
i.fa.fa-plus
div.trigger-item
div.trigger-content
@ -53,14 +53,14 @@ template(name="checklistTriggers")
option(value="completed") {{_'r-completed'}}
option(value="uncompleted") {{_'r-made-incomplete'}}
div.trigger-button.trigger-button-person.js-show-user-field
| 👤
i.fa.fa-user
div.user-details.hide-element
div.trigger-text
| {{_'r-by'}}
div.trigger-dropdown
input(class="user-name",type=text,placeholder="{{_'username'}}")
div.trigger-button.js-add-gen-comp-trigger.js-goto-action
|
i.fa.fa-plus
div.trigger-item
div.trigger-content
@ -75,14 +75,14 @@ template(name="checklistTriggers")
option(value="completed") {{_'r-completed'}}
option(value="uncompleted") {{_'r-made-incomplete'}}
div.trigger-button.trigger-button-person.js-show-user-field
| 👤
i.fa.fa-user
div.user-details.hide-element
div.trigger-text
| {{_'r-by'}}
div.trigger-dropdown
input(class="user-name",type=text,placeholder="{{_'username'}}")
div.trigger-button.js-add-spec-comp-trigger.js-goto-action
|
i.fa.fa-plus
div.trigger-item
div.trigger-content
@ -93,14 +93,14 @@ template(name="checklistTriggers")
option(value="checked") {{_'r-checked'}}
option(value="unchecked") {{_'r-unchecked'}}
div.trigger-button.trigger-button-person.js-show-user-field
| 👤
i.fa.fa-user
div.user-details.hide-element
div.trigger-text
| {{_'r-by'}}
div.trigger-dropdown
input(class="user-name",type=text,placeholder="{{_'username'}}")
div.trigger-button.js-add-gen-check-item-trigger.js-goto-action
|
i.fa.fa-plus
div.trigger-item
div.trigger-content
@ -115,11 +115,11 @@ template(name="checklistTriggers")
option(value="checked") {{_'r-checked'}}
option(value="unchecked") {{_'r-unchecked'}}
div.trigger-button.trigger-button-person.js-show-user-field
| 👤
i.fa.fa-user
div.user-details.hide-element
div.trigger-text
| {{_'r-by'}}
div.trigger-dropdown
input(class="user-name",type=text,placeholder="{{_'username'}}")
div.trigger-button.js-add-spec-check-item-trigger.js-goto-action
|
i.fa.fa-plus

View file

@ -8,7 +8,7 @@ template(name="attachments")
ul
li
a.js-move-attachments(data-id="move-attachments")
| ➡️
i.fa.fa-arrow-right
| {{_ 'attachment-move'}}
.main-body
@ -80,17 +80,17 @@ template(name="moveAttachment")
td
if $neq version.storageName "fs"
button.js-move-storage-fs
| ➡️
i.fa.fa-arrow-right
| {{_ 'attachment-move-storage-fs'}}
if $neq version.storageName "gridfs"
if version.storageName
button.js-move-storage-gridfs
| ➡️
i.fa.fa-arrow-right
| {{_ 'attachment-move-storage-gridfs'}}
if $neq version.storageName "s3"
if version.storageName
button.js-move-storage-s3
| ➡️
i.fa.fa-arrow-right
| {{_ 'attachment-move-storage-s3'}}

View file

@ -82,13 +82,13 @@ template(name="cronMigrations")
| {{_ 'database-migrations'}}
.migration-controls
button.btn.btn-primary.js-start-all-migrations
| ▶️
i.fa.fa-play
| {{_ 'start-all-migrations'}}
button.btn.btn-warning.js-pause-all-migrations
| ⏸️
i.fa.fa-pause
| {{_ 'pause-all-migrations'}}
button.btn.btn-danger.js-stop-all-migrations
| ⏹️
i.fa.fa-stop
| {{_ 'stop-all-migrations'}}
.migration-progress
@ -99,11 +99,11 @@ template(name="cronMigrations")
.progress-label {{_ 'overall-progress'}}
.current-step
| ⚙️
i.fa.fa-cog
| {{migrationCurrentStep}}
.migration-status
|
i.fa.fa-info-circle
| {{migrationStatus}}
.migration-steps
@ -114,11 +114,11 @@ template(name="cronMigrations")
.step-header
.step-icon
if completed
| ✅
i.fa.fa-check
else if isCurrentStep
| ⚙️
i.fa.fa-cog
else
| ⭕
i.fa.fa-circle-o
.step-info
.step-name {{name}}
.step-description {{description}}
@ -137,17 +137,17 @@ template(name="cronBoardOperations")
.cron-board-operations
.board-operations-header
h2
| 📋
i.fa.fa-list
| {{_ 'board-operations'}}
.board-operations-controls
button.btn.btn-success.js-refresh-board-operations
| 🔄
i.fa.fa-recycle
| {{_ 'refresh'}}
button.btn.btn-primary.js-start-test-operation
| ▶️
i.fa.fa-play
| {{_ 'start-test-operation'}}
button.btn.btn-info.js-force-board-scan
| 🔍
i.fa.fa-search
| {{_ 'force-board-scan'}}
.board-operations-stats
@ -195,7 +195,7 @@ template(name="cronBoardOperations")
.board-operations-search
.search-box
input.form-control.js-search-board-operations(type="text" placeholder="{{_ 'search-boards-or-operations'}}")
| 🔍.search-icon
i.fa.fa-search.search-icon
.board-operations-list
.operations-header
@ -234,36 +234,36 @@ template(name="cronBoardOperations")
.btn-group
if isRunning
button.btn.btn-sm.btn-warning.js-pause-operation(data-operation="{{id}}")
| ⏸️
i.fa.fa-pause
else
button.btn.btn-sm.btn-success.js-resume-operation(data-operation="{{id}}")
| ▶️
i.fa.fa-play
button.btn.btn-sm.btn-danger.js-stop-operation(data-operation="{{id}}")
| ⏹️
i.fa.fa-stop
button.btn.btn-sm.btn-info.js-view-details(data-operation="{{id}}")
|
i.fa.fa-info-circle
.pagination
if pagination.hasPrev
button.btn.btn-sm.btn-default.js-prev-page
| ◀️
i.fa.fa-caret-left
| {{_ 'previous'}}
.page-info
| {{_ 'page'}} {{pagination.page}} {{_ 'of'}} {{pagination.totalPages}}
if pagination.hasNext
button.btn.btn-sm.btn-default.js-next-page
| {{_ 'next'}}
| ▶️
i.fa.fa-caret-right
template(name="cronJobs")
.cron-jobs
.jobs-header
h2
| ⏰
i.fa.fa-clock-o
| {{_ 'cron-jobs'}}
.jobs-controls
button.btn.btn-success.js-refresh-jobs
| 🔄
i.fa.fa-refresh
| {{_ 'refresh'}}
.jobs-list
@ -289,20 +289,20 @@ template(name="cronJobs")
.btn-group
if isRunning
button.btn.btn-sm.btn-warning.js-pause-job(data-job="{{name}}")
| ⏸️
i.fa.fa-pause
else
button.btn.btn-sm.btn-success.js-start-job(data-job="{{name}}")
| ▶️
i.fa.fa-caret-right
button.btn.btn-sm.btn-danger.js-stop-job(data-job="{{name}}")
| ⏹️
i.fa.fa-stop
button.btn.btn-sm.btn-danger.js-remove-job(data-job="{{name}}")
| 🗑️
i.fa.fa-trash
template(name="cronAddJob")
.cron-add-job
.add-job-header
h2
|
i.fa.fa-plus
| {{_ 'add-cron-job'}}
.add-job-form
@ -333,8 +333,8 @@ template(name="cronAddJob")
.form-actions
button.btn.btn-primary(type="submit")
|
i.fa.fa-plus
| {{_ 'add-job'}}
button.btn.btn-default.js-cancel-add-job
| ❌
i.fa.fa-times-thin
| {{_ 'cancel'}}

View file

@ -5,14 +5,14 @@ template(name='information')
else
.content-title
span
|
i.fa.fa-info-circle
| {{_ 'info'}}
.content-body
.side-menu
ul
li.active
a.js-setting-menu(data-id="information-display")
|
i.fa.fa-info-circle
| {{_ 'info'}}
.main-body
+statistics

View file

@ -4,9 +4,10 @@ template(name="migrationProgress")
.migration-progress-modal
.migration-progress-header
h3.migration-progress-title
| 🔄 {{_ 'migration-progress-title'}}
i.fa.fa-recycle
| {{_ 'migration-progress-title'}}
.migration-progress-close.js-close-migration-progress
| ❌
i.fa.fa-times-thin
.migration-progress-content
.migration-progress-overall

View file

@ -9,34 +9,34 @@ template(name="people")
+spinner
else if orgSetting.get
span
| 🌐
i.fa.fa-globe
unless isMiniScreen
| {{_ 'organizations'}}
input#searchOrgInput(placeholder="{{_ 'search'}}")
button#searchOrgButton
| 🔍
i.fa.fa-search
| {{_ 'search'}}
.ext-box-right
span {{#unless isMiniScreen}}{{_ 'org-number'}}{{/unless}} #{orgNumber}
else if teamSetting.get
span
| 👥
i.fa.fa-users
unless isMiniScreen
| {{_ 'teams'}}
input#searchTeamInput(placeholder="{{_ 'search'}}")
button#searchTeamButton
| 🔍
i.fa.fa-search
| {{_ 'search'}}
.ext-box-right
span {{#unless isMiniScreen}}{{_ 'team-number'}}{{/unless}} #{teamNumber}
else if peopleSetting.get
span
| 👤
i.fa.fa-user
unless isMiniScreen
| {{_ 'people'}}
input#searchInput(placeholder="{{_ 'search'}}")
button#searchButton
| 🔍
i.fa.fa-search
| {{_ 'search'}}
.divLockedUsersFilter
.flex-container
@ -48,17 +48,19 @@ template(name="people")
option(value="inactive") {{_ 'admin-people-filter-inactive'}}
option(value="admin") Admin
button#unlockAllUsers.unlock-all-btn
span.emoji-icon 🔓
span.emoji-icon
i.fa.fa-unlock
| {{_ 'accounts-lockout-unlock-all'}}
.ext-box-right
span {{#unless isMiniScreen}}{{_ 'people-number'}}{{/unless}} #{peopleNumber}
.divAddOrRemoveTeam#divAddOrRemoveTeam
button#addOrRemoveTeam
| ✏️
i.fa.fa-pencil-square-o
| {{_ 'add'}} / {{_ 'delete'}} {{_ 'teams'}}
else if lockedUsersSetting.get
span
span.emoji-icon.text-red 🔒
span.emoji-icon.text-red
i.fa.fa-lock
unless isMiniScreen
| {{_ 'accounts-lockout-locked-users'}}
@ -67,19 +69,20 @@ template(name="people")
ul
li.active
a.js-org-menu(data-id="org-setting")
| 🌐
i.fa.fa-globe
| {{_ 'organizations'}}
li
a.js-team-menu(data-id="team-setting")
| 👥
i.fa.fa-users
| {{_ 'teams'}}
li
a.js-people-menu(data-id="people-setting")
| 👤
i.fa.fa-user
| {{_ 'people'}}
li
a.js-locked-users-menu(data-id="locked-users-setting")
span.emoji-icon.text-red 🔒
span.emoji-icon.text-red
i.fa.fa-lock
| {{_ 'accounts-lockout-locked-users'}}
.main-body
if loading.get
@ -155,17 +158,17 @@ template(name="selectAllUser")
template(name="newOrgRow")
a.new-org
|
i.fa.fa-plus
| {{_ 'new'}}
template(name="newTeamRow")
a.new-team
|
i.fa.fa-plus
| {{_ 'new'}}
template(name="newUserRow")
a.new-user
|
i.fa.fa-plus
| {{_ 'new'}}
template(name="orgRow")
@ -197,7 +200,7 @@ template(name="orgRow")
| {{_ 'no'}}
td
a.edit-org
| ✏️
i.fa.fa-pencil-square-o
| {{_ 'edit'}}
a.more-settings-org
| ⋯
@ -231,7 +234,7 @@ template(name="teamRow")
| {{_ 'no'}}
td
a.edit-team
| ✏️
i.fa.fa-pencil-square-o
| {{_ 'edit'}}
a.more-settings-team
| ⋯
@ -240,7 +243,7 @@ template(name="peopleRow")
tr
td
a.edit-user
| ✏️
i.fa.fa-pencil-square-o
| {{_ 'edit'}}
a.more-settings-user
| ⋯
@ -268,14 +271,18 @@ template(name="peopleRow")
| {{_ 'no'}}
td.account-active-status
if userData.loginDisabled
span.text-red.js-toggle-active-status(data-user-id=userData._id, data-is-active="false", title="{{_ 'admin-people-user-inactive'}}") 🚫
span.text-red.js-toggle-active-status(data-user-id=userData._id, data-is-active="false", title="{{_ 'admin-people-user-inactive'}}")
i.fa.fa-ban
else
span.text-green.js-toggle-active-status(data-user-id=userData._id, data-is-active="true", title="{{_ 'admin-people-user-active'}}") ✅
span.text-green.js-toggle-active-status(data-user-id=userData._id, data-is-active="true", title="{{_ 'admin-people-user-active'}}")
i.fa.fa-check
td.account-status
if isUserLocked
span.text-red.js-toggle-lock-status.emoji-icon(data-user-id=userData._id, data-is-locked="true", title="{{_ 'accounts-lockout-click-to-unlock'}}") 🔒
span.text-red.js-toggle-lock-status.emoji-icon(data-user-id=userData._id, data-is-locked="true", title="{{_ 'accounts-lockout-click-to-unlock'}}")
i.fa.fa-lock
else
span.text-green.js-toggle-lock-status.emoji-icon(data-user-id=userData._id, data-is-locked="false", title="{{_ 'accounts-lockout-user-unlocked'}}") 🔓
span.text-green.js-toggle-lock-status.emoji-icon(data-user-id=userData._id, data-is-locked="false", title="{{_ 'accounts-lockout-user-unlocked'}}")
i.fa.fa-unlock
if userData.loginDisabled
td <s>{{ moment userData.createdAt 'LLL' }}</s>
else
@ -395,8 +402,10 @@ template(name="editUserPopup")
option(value="{{value}}") {{_ value}}
label
| {{_ 'organizations'}}
span#addUserOrg
span#removeUserOrg
span#addUserOrg
i.fa.fa-plus
span#removeUserOrg
i.fa.fa-minus
select.js-orgs#jsOrgs
option(value="-1") {{_ 'organizations'}} :
each value in orgsDatas
@ -405,8 +414,10 @@ template(name="editUserPopup")
input#jsUserOrgIdsInPut.js-userOrgIds.hide(type="hidden" value=user.orgIdsUserBelongs)
label
| {{_ 'teams'}}
span#addUserTeam
span#removeUserTeam
span#addUserTeam
i.fa.fa-plus
span#removeUserTeam
i.fa.fa-minus
select.js-teams#jsTeams
option(value="-1") {{_ 'teams'}} :
each value in teamsDatas
@ -538,8 +549,10 @@ template(name="newUserPopup")
option(value="{{value}}") {{_ value}}
label
| {{_ 'organizations'}}
span#addUserOrgNewUser
span#removeUserOrgNewUser
span#addUserOrgNewUser
i.fa.fa-plus
span#removeUserOrgNewUser
i.fa.fa-minus
select.js-orgsNewUser#jsOrgsNewUser
option(value="-1") {{_ 'organizations'}} :
each value in orgsDatas
@ -548,8 +561,10 @@ template(name="newUserPopup")
input#jsUserOrgIdsInPutNewUser.js-userOrgIdsNewUser.hide(type="text" value=user.orgIdsUserBelongs)
label
| {{_ 'teams'}}
span#addUserTeamNewUser
span#removeUserTeamNewUser
span#addUserTeamNewUser
i.fa.fa-plus
span#removeUserTeamNewUser
i.fa.fa-minus
select.js-teamsNewUser#jsTeamsNewUser
option(value="-1") {{_ 'teams'}} :
each value in teamsDatas
@ -583,7 +598,7 @@ template(name="settingsOrgPopup")
// to impersonate organization?
// li
// a.impersonate-org
// | 👤
// i.fa.fa-user
// | {{_ 'impersonate-org'}}
//
//
@ -606,7 +621,7 @@ template(name="settingsUserPopup")
ul.pop-over-list
li
a.impersonate-user
| 👤
i.fa.fa-user
| {{_ 'impersonate-user'}}
br
hr

View file

@ -6,87 +6,107 @@ template(name="setting")
.content-title.ext-box
if isGeneralSetting
span
span.emoji-icon 🔑
span.emoji-icon
i.fa.fa-key
| {{_ 'registration'}}
else if isEmailSetting
span
span.emoji-icon ✉️
span.emoji-icon
i.fa.fa-envelope
| {{_ 'email'}}
else if isAccountSetting
span
span.emoji-icon 👥
span.emoji-icon
i.fa.fa-users
| {{_ 'accounts'}}
else if isTableVisibilityModeSetting
span
span.emoji-icon 👁️
span.emoji-icon
i.fa.fa-eye
| {{_ 'tableVisibilityMode'}}
else if isAnnouncementSetting
span
span.emoji-icon 📢
span.emoji-icon
i.fa.fa-bullhorn
| {{_ 'admin-announcement'}}
else if isAccessibilitySetting
span
span.emoji-icon ♿
span.emoji-icon
i.fa.fa-universal-access
| {{_ 'accessibility'}}
else if isLayoutSetting
span
span.emoji-icon 🔗
span.emoji-icon
i.fa.fa-link
| {{_ 'layout'}}
else if isWebhookSetting
span
span.emoji-icon 🌐
span.emoji-icon
i.fa.fa-globe
| {{_ 'global-webhook'}}
else if isAttachmentSettings
span
span.emoji-iconpan.emoji-icon 📎
span.emoji-icon
i.fa.fa-paperclip
| {{_ 'attachments'}}
else if isCronSettings
span
span.emoji-icon ⏰
span.emoji-icon
i.fa.fa-clock
| {{_ 'cron'}}
.content-body
.side-menu
ul
li(class="{{#if isGeneralSetting}}active{{/if}}")
a.js-setting-menu(data-id="registration-setting")
span.emoji-icon 🔑
span.emoji-icon
i.fa.fa-key
| {{_ 'registration'}}
unless isSandstorm
li(class="{{#if isEmailSetting}}active{{/if}}")
a.js-setting-menu(data-id="email-setting")
span.emoji-icon ✉️
span.emoji-icon
i.fa.fa-envelope
| {{_ 'email'}}
li(class="{{#if isAccountSetting}}active{{/if}}")
a.js-setting-menu(data-id="account-setting")
span.emoji-icon 👥
span.emoji-icon
i.fa.fa-users
| {{_ 'accounts'}}
li(class="{{#if isTableVisibilityModeSetting}}active{{/if}}")
a.js-setting-menu(data-id="tableVisibilityMode-setting")
span.emoji-icon 👁️
span.emoji-icon
i.fa.fa-eye
| {{_ 'tableVisibilityMode'}}
li(class="{{#if isAnnouncementSetting}}active{{/if}}")
a.js-setting-menu(data-id="announcement-setting")
span.emoji-icon 📢
span.emoji-icon
i.fa.fa-bullhorn
| {{_ 'admin-announcement'}}
li(class="{{#if isAccessibilitySetting}}active{{/if}}")
a.js-setting-menu(data-id="accessibility-setting")
span.emoji-icon ♿
span.emoji-icon
i.fa.fa-universal-access
| {{_ 'accessibility'}}
li(class="{{#if isLayoutSetting}}active{{/if}}")
a.js-setting-menu(data-id="layout-setting")
span.emoji-icon 🔗
span.emoji-icon
i.fa.fa-link
| {{_ 'layout'}}
li(class="{{#if isWebhookSetting}}active{{/if}}")
a.js-setting-menu(data-id="webhook-setting")
span.emoji-icon 🌐
span.emoji-icon
i.fa.fa-globe
| {{_ 'global-webhook'}}
li(class="{{#if isAttachmentSettings}}active{{/if}}")
a.js-setting-menu(data-id="attachment-settings")
span.emoji-icon 📎
span.emoji-icon
i.fa.fa-paperclip
| {{_ 'attachments'}}
li(class="{{#if isCronSettings}}active{{/if}}")
a.js-setting-menu(data-id="cron-settings")
span.emoji-icon ⏰
span.emoji-icon
i.fa.fa-clock
| {{_ 'cron'}}
.main-body
if isLoading

View file

@ -5,31 +5,38 @@ template(name="settingHeaderBar")
.setting-header-btns.left
if currentUser
a.setting-header-btn.settings(class=isSettingsActive href="{{pathFor 'setting'}}")
span.emoji-icon ⚙️
span.emoji-icon
i.fa.fa-cog
span {{_ 'settings'}}
a.setting-header-btn.people(class=isPeopleActive href="{{pathFor 'people'}}")
span.emoji-icon 👥
span.emoji-icon
i.fa.fa-users
span {{_ 'people'}}
a.setting-header-btn.informations(class=isAdminReportsActive href="{{pathFor 'admin-reports'}}")
span.emoji-icon 📋
span.emoji-icon
i.fa.fa-file-text-o
span {{_ 'reports'}}
a.setting-header-btn.informations(class=isAttachmentsActive href="{{pathFor 'attachments'}}")
span.emoji-icon 📎
span.emoji-icon
i.fa.fa-paperclip
span {{_ 'attachments'}}
a.setting-header-btn.informations(class=isTranslationActive href="{{pathFor 'translation'}}")
span.emoji-icon 🔤
span.emoji-icon
i.fa.fa-globe
span {{_ 'translation'}}
a.setting-header-btn.informations(class=isInformationActive href="{{pathFor 'information'}}")
span.emoji-icon
span.emoji-icon
i.fa.fa-info-circle
span {{_ 'info'}}
else
a.setting-header-btn.js-log-in(
title="{{_ 'log-in'}}")
span.emoji-icon 🚪
span.emoji-icon
i.fa.fa-sign-in
span {{_ 'log-in'}}

View file

@ -9,12 +9,12 @@ template(name="translation")
+spinner
else if translationSetting.get
span
| 🔤
i.fa.fa-globe
unless isMiniScreen
| {{_ 'translation'}}
input#searchTranslationInput(placeholder="{{_ 'search'}}")
button#searchTranslationButton
| 🔍
i.fa.fa-search
| {{_ 'search'}}
.ext-box-right
span {{#unless isMiniScreen}}{{_ 'translation-number'}}{{/unless}} #{translationNumber}
@ -24,7 +24,7 @@ template(name="translation")
ul
li.active
a.js-translation-menu(data-id="translation-setting")
| 🔤
i.fa.fa-globe
| {{_ 'translation'}}
.main-body
if loading.get
@ -47,7 +47,7 @@ template(name="translationGeneral")
template(name="newTranslationRow")
a.new-translation
|
i.fa.fa-plus
| {{_ 'new'}}
template(name="translationRow")
@ -57,7 +57,7 @@ template(name="translationRow")
td {{translationData.translationText}}
td
a.edit-translation
| ✏️
i.fa.fa-pencil-square-o
| {{_ 'edit'}}
a.more-settings-translation
| ⋯

View file

@ -7,14 +7,14 @@ template(name="sidebar")
.sidebar-actions
.sidebar-shortcuts
a.sidebar-btn.js-shortcuts(title="{{_ 'keyboard-shortcuts' }}")
| ⌨️
i.fa.fa-keyboard-o
span {{_ 'keyboard-shortcuts' }}
a.sidebar-btn.js-keyboard-shortcuts-toggle(
title="{{#if isKeyboardShortcuts}}{{_ 'keyboard-shortcuts-enabled'}}{{else}}{{_ 'keyboard-shortcuts-disabled'}}{{/if}}")
| {{#if isKeyboardShortcuts}}✅{{else}}🚫{{/if}}
i.fa(class="{{#if isKeyboardShortcuts}}fa-check{{else}}fa-ban{{/if}}")
if isAccessibilityEnabled
a.sidebar-accessibility
| ♿
i.fa.fa-universal-access
span {{_ 'accessibility'}}
a.sidebar-xmark.js-close-sidebar &#10005;
.sidebar-content.js-board-sidebar-content
@ -22,7 +22,7 @@ template(name="sidebar")
// i.fa.fa-navicon
unless isDefaultView
h2
a.js-back-home ⬅️
a.fa.fa-arrow-left.js-back-home
= getViewTitle
if isOpen
+Template.dynamic(template=getViewTemplate)
@ -34,25 +34,25 @@ template(name='homeSidebar')
hr
ul#cards.label-text-hidden
a.flex.js-toggle-minicard-label-text(title="{{_ 'hide-minicard-label-text'}}")
span {{#if hiddenMinicardLabelText}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if hiddenMinicardLabelText}}fa-check{{else}}fa-square-o{{/if}}")
span {{_ 'hide-minicard-label-text'}}
if currentUser
ul#cards.vertical-scrollbars-toggle
a.flex.js-vertical-scrollbars-toggle(title="{{_ 'enable-vertical-scrollbars'}}")
span {{#if isVerticalScrollbars}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if isVerticalScrollbars}}fa-check{{else}}fa-square-o{{/if}}")
span {{_ 'enable-vertical-scrollbars'}}
ul#cards.show-week-of-year-toggle
a.flex.js-show-week-of-year-toggle(title="{{_ 'show-week-of-year'}}")
span {{#if isShowWeekOfYear}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if isShowWeekOfYear}}fa-check{{else}}fa-square-o{{/if}}")
span {{_ 'show-week-of-year'}}
hr
if currentUser.isBoardAdmin
h3.activity-title
| 💬
i.fa.fa-comment-o
| {{_ 'activities'}}
a.flex.js-toggle-show-activities(title="{{_ 'show-activities'}}")
span {{#if showActivities}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if showActivities}}fa-check{{else}}fa-square-o{{/if}}")
span {{_ 'show-activities'}}
+activities(mode="board")
@ -61,11 +61,11 @@ template(name="membersWidget")
unless currentUser.isWorker
h3
a.board-header-btn.js-open-board-menu(title="{{_ 'boardMenuPopup-title'}}")
| ⚙️
i.fa.fa-cog
| {{_ 'boardMenuPopup-title'}}
hr
h3
| 👥
i.fa.fa-users
| {{_ 'members'}}
+basicTabs(tabs=tabs)
+tabContent(slug="people")
@ -77,15 +77,15 @@ template(name="membersWidget")
if isSandstorm
if currentUser.isBoardMember
a.member.add-member.sandstorm-powerbox-request-identity(title="{{_ 'add-members'}}")
|
i.fa.fa-plus
else if currentUser.isBoardAdmin
a.member.add-member.js-manage-board-members(title="{{_ 'add-members'}}")
|
i.fa.fa-plus
.clearfix
if isInvited
hr
p
| ⚠️
i.fa.fa-exclamation-triangle
| {{_ 'just-invited'}}
button.js-member-invite-accept.primary {{_ 'accept'}}
button.js-member-invite-decline {{_ 'decline'}}
@ -121,7 +121,7 @@ template(name="boardOrgGeneral")
th
if currentUser.isBoardAdmin
a.member.orgOrTeamMember.add-member.js-manage-board-addOrg(title="{{_ 'add-members'}}")
|
i.fa.fa-plus
.divaddfaplusminus
| {{_ 'add'}}
each org in currentBoard.activeOrgs
@ -142,7 +142,7 @@ template(name="boardTeamGeneral")
th
if currentUser.isBoardAdmin
a.member.orgOrTeamMember.add-member.js-manage-board-addTeam(title="{{_ 'add-members'}}")
|
i.fa.fa-plus
.divaddfaplusminus
| {{_ 'add'}}
each currentBoard.activeTeams
@ -155,7 +155,7 @@ template(name="boardChangeColorPopup")
span.background-box(class="board-color-{{this}}")
span {{this}}
if isSelected
span.checkmark-no-grey ✅
i.fa.fa-check
template(name="boardChangeBackgroundImagePopup")
form
@ -179,16 +179,16 @@ template(name="boardInfoOnMyBoardsPopup")
unless currentSetting.hideCardCounterList
div.check-div
a.flex.js-field-has-cardcounterlist(class="{{#if allowsCardCounterList}}is-checked{{/if}}")
span {{#if allowsCardCounterList}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if allowsCardCounterList}}fa-check{{else}}fa-square-o{{/if}}")
span
| 🚪
i.fa.fa-sign-in
| {{_ 'show-card-counter-per-list'}}
unless currentSetting.hideBoardMemberList
div.check-div
a.flex.js-field-has-boardmemberlist(class="{{#if allowsBoardMemberList}}is-checked{{/if}}")
span {{#if allowsBoardMemberList}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if allowsBoardMemberList}}fa-check{{else}}fa-square-o{{/if}}")
span
| ⏳
i.fa.fa-hourglass
| {{_ 'show-board_members-avatar'}}
template(name="boardCardSettingsPopup")
@ -203,169 +203,170 @@ template(name="boardCardSettingsPopup")
.card-settings-row
.card-settings-column
a.flex.js-field-has-receiveddate(title="{{_ 'card-received'}}" class="{{#if allowsReceivedDate}}is-checked{{/if}}")
span {{#if allowsReceivedDate}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if allowsReceivedDate}}fa-check{{else}}fa-square-o{{/if}}")
.card-settings-column
a.flex.js-field-has-receiveddate(title="{{_ 'card-received'}}" class="{{#if allowsReceivedDate}}is-checked{{/if}}")
span {{#if allowsReceivedDate}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if allowsReceivedDate}}fa-check{{else}}fa-square-o{{/if}}")
.card-settings-column
span
| 🚪
i.fa.fa-sign-in
| {{_ 'card-received'}}
.card-settings-row
.card-settings-column
a.flex.js-field-has-startdate(title="{{_ 'card-start'}}" class="{{#if allowsStartDate}}is-checked{{/if}}")
span {{#if allowsStartDate}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if allowsStartDate}}fa-check{{else}}fa-square-o{{/if}}")
.card-settings-column
a.flex.js-field-has-startdate(title="{{_ 'card-start'}}" class="{{#if allowsStartDate}}is-checked{{/if}}")
span {{#if allowsStartDate}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if allowsStartDate}}fa-check{{else}}fa-square-o{{/if}}")
.card-settings-column
span
| ⏳
i.fa.fa-hourglass
| {{_ 'card-start'}}
.card-settings-row
.card-settings-column
a.flex.js-field-has-duedate(title="{{_ 'card-due'}}" class="{{#if allowsDueDate}}is-checked{{/if}}")
span {{#if allowsDueDate}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if allowsDueDate}}fa-check{{else}}fa-square-o{{/if}}")
.card-settings-column
a.flex.js-field-has-duedate(title="{{_ 'card-due'}}" class="{{#if allowsDueDate}}is-checked{{/if}}")
span {{#if allowsDueDate}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if allowsDueDate}}fa-check{{else}}fa-square-o{{/if}}")
.card-settings-column
span
| 🚪
i.fa.fa-sign-in
| {{_ 'card-due'}}
.card-settings-row
.card-settings-column
a.flex.js-field-has-enddate(title="{{_ 'card-end'}}" class="{{#if allowsEndDate}}is-checked{{/if}}")
span {{#if allowsEndDate}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if allowsEndDate}}fa-check{{else}}fa-square-o{{/if}}")
.card-settings-column
a.flex.js-field-has-enddate(title="{{_ 'card-end'}}" class="{{#if allowsEndDate}}is-checked{{/if}}")
span {{#if allowsEndDate}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if allowsEndDate}}fa-check{{else}}fa-square-o{{/if}}")
.card-settings-column
span
| ⏰
i.fa.fa-clock-o
| {{_ 'card-end'}}
.card-settings-row
.card-settings-column
a.flex.js-field-has-members(title="{{_ 'members'}}" class="{{#if allowsMembers}}is-checked{{/if}}")
span {{#if allowsMembers}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if allowsMembers}}fa-check{{else}}fa-square-o{{/if}}")
.card-settings-column
a.flex.js-field-has-members(title="{{_ 'members'}}" class="{{#if allowsMembers}}is-checked{{/if}}")
span {{#if allowsMembers}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if allowsMembers}}fa-check{{else}}fa-square-o{{/if}}")
.card-settings-column
span
| 👥
i.fa.fa-users
| {{_ 'members'}}
.card-settings-row
.card-settings-column
a.flex.js-field-has-creator(title="{{_ 'creator'}}" class="{{#if allowsCreator}}is-checked{{/if}}")
span {{#if allowsCreator}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if allowsCreator}}fa-check{{else}}fa-square-o{{/if}}")
.card-settings-column
span
.card-settings-column
span
| 👤
i.fa.fa-user
| {{_ 'creator'}}
.card-settings-row
.card-settings-column
span
.card-settings-column
a.flex.js-field-has-creator-on-minicard(title="{{_ 'creator-on-minicard'}}" class="{{#if allowsCreatorOnMinicard}}is-checked{{/if}}")
span {{#if allowsCreatorOnMinicard}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if allowsCreatorOnMinicard}}fa-check{{else}}fa-square-o{{/if}}")
.card-settings-column
span
| 👤
i.fa.fa-user
| {{_ 'creator-on-minicard'}}
.card-settings-row
.card-settings-column
a.flex.js-field-has-assignee(title="{{_ 'assignee'}}" class="{{#if allowsAssignee}}is-checked{{/if}}")
span {{#if allowsAssignee}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if allowsAssignee}}fa-check{{else}}fa-square-o{{/if}}")
.card-settings-column
a.flex.js-field-has-assignee(title="{{_ 'assignee'}}" class="{{#if allowsAssignee}}is-checked{{/if}}")
span {{#if allowsAssignee}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if allowsAssignee}}fa-check{{else}}fa-square-o{{/if}}")
.card-settings-column
span
| 👤
i.fa.fa-user
| {{_ 'assignee'}}
.card-settings-row
.card-settings-column
a.flex.js-field-has-assigned-by(title="{{_ 'assigned-by'}}" class="{{#if allowsAssignedBy}}is-checked{{/if}}")
span {{#if allowsAssignedBy}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if allowsAssignedBy}}fa-check{{else}}fa-square-o{{/if}}")
.card-settings-column
a.flex.js-field-has-assigned-by(title="{{_ 'assigned-by'}}" class="{{#if allowsAssignedBy}}is-checked{{/if}}")
span {{#if allowsAssignedBy}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if allowsAssignedBy}}fa-check{{else}}fa-square-o{{/if}}")
.card-settings-column
span
| 🛒
i.fa.fa-shopping-cart
| {{_ 'assigned-by'}}
.card-settings-row
.card-settings-column
a.flex.js-field-has-requested-by(title="{{_ 'requested-by'}}" class="{{#if allowsRequestedBy}}is-checked{{/if}}")
span {{#if allowsRequestedBy}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if allowsRequestedBy}}fa-check{{else}}fa-square-o{{/if}}")
.card-settings-column
a.flex.js-field-has-requested-by(title="{{_ 'requested-by'}}" class="{{#if allowsRequestedBy}}is-checked{{/if}}")
span {{#if allowsRequestedBy}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if allowsRequestedBy}}fa-check{{else}}fa-square-o{{/if}}")
.card-settings-column
span
| 👤➕
i.fa.fa-user
|
| {{_ 'requested-by'}}
.card-settings-row
.card-settings-column
a.flex.js-field-has-card-sorting-by-number(title="{{_ 'card-sorting-by-number'}}" class="{{#if allowsCardSortingByNumber}}is-checked{{/if}}")
span {{#if allowsCardSortingByNumber}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if allowsCardSortingByNumber}}fa-check{{else}}fa-square-o{{/if}}")
.card-settings-column
span
.card-settings-column
span
| 🔢
i.fa.fa-sort-numeric-asc
| {{_ 'card-sorting-by-number'}}
.card-settings-row
.card-settings-column
span
.card-settings-column
a.flex.js-field-has-card-sorting-by-number-on-minicard(title="{{_ 'card-sorting-by-number-on-minicard'}}" class="{{#if allowsCardSortingByNumberOnMinicard}}is-checked{{/if}}")
span {{#if allowsCardSortingByNumberOnMinicard}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if allowsCardSortingByNumberOnMinicard}}fa-check{{else}}fa-square-o{{/if}}")
.card-settings-column
span
| 🔢
i.fa.fa-sort-numeric-asc
| {{_ 'card-sorting-by-number-on-minicard'}}
.card-settings-row
.card-settings-column
a.flex.js-field-has-card-show-lists(title="{{_ 'card-show-lists'}}" class="{{#if allowsShowLists}}is-checked{{/if}}")
span {{#if allowsShowLists}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if allowsShowLists}}fa-check{{else}}fa-square-o{{/if}}")
.card-settings-column
span
.card-settings-column
span
| 📋
i.fa.fa-list
| {{_ 'card-show-lists'}}
.card-settings-row
.card-settings-column
a.flex.js-field-has-labels(title="{{_ 'labels'}}" class="{{#if allowsLabels}}is-checked{{/if}}")
span {{#if allowsLabels}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if allowsLabels}}fa-check{{else}}fa-square-o{{/if}}")
.card-settings-column
a.flex.js-field-has-labels(title="{{_ 'labels'}}" class="{{#if allowsLabels}}is-checked{{/if}}")
span {{#if allowsLabels}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if allowsLabels}}fa-check{{else}}fa-square-o{{/if}}")
.card-settings-column
span
| 🏷️
i.fa.fa-tag
| {{_ 'labels'}}
.card-settings-row
.card-settings-column
span
.card-settings-column
a.flex.js-field-has-card-show-lists-on-minicard(title="{{_ 'card-show-lists-on-minicard'}}" class="{{#if allowsShowListsOnMinicard}}is-checked{{/if}}")
span {{#if allowsShowListsOnMinicard}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if allowsShowListsOnMinicard}}fa-check{{else}}fa-square-o{{/if}}")
.card-settings-column
span
| 📋
i.fa.fa-list
| {{_ 'card-show-lists-on-minicard'}}
.card-settings-row
.card-settings-column
a.flex.js-field-has-card-number(title="{{_ 'card'}} {{_ 'number'}}" class="{{#if allowsCardNumber}}is-checked{{/if}}")
span {{#if allowsCardNumber}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if allowsCardNumber}}fa-check{{else}}fa-square-o{{/if}}")
.card-settings-column
a.flex.js-field-has-card-number(title="{{_ 'card'}} {{_ 'number'}}" class="{{#if allowsCardNumber}}is-checked{{/if}}")
span {{#if allowsCardNumber}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if allowsCardNumber}}fa-check{{else}}fa-square-o{{/if}}")
.card-settings-column
span
| #️⃣
@ -374,25 +375,25 @@ template(name="boardCardSettingsPopup")
.card-settings-row
.card-settings-column
a.flex.js-field-has-description-title(title="{{_ 'description'}} {{_ 'title'}}" class="{{#if allowsDescriptionTitle}}is-checked{{/if}}")
span {{#if allowsDescriptionTitle}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if allowsDescriptionTitle}}fa-check{{else}}fa-square-o{{/if}}")
.card-settings-column
a.flex.js-field-has-description-title(title="{{_ 'description'}} {{_ 'title'}}" class="{{#if allowsDescriptionTitle}}is-checked{{/if}}")
span {{#if allowsDescriptionTitle}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if allowsDescriptionTitle}}fa-check{{else}}fa-square-o{{/if}}")
.card-settings-column
span
| 📝
i.fa.fa-file-text-o
| {{_ 'description'}}
| {{_ 'title'}}
.card-settings-row
.card-settings-column
a.flex.js-field-has-description-text(title="{{_ 'description'}} {{_ 'custom-field-text'}}" class="{{#if allowsDescriptionText}}is-checked{{/if}}")
span {{#if allowsDescriptionText}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if allowsDescriptionText}}fa-check{{else}}fa-square-o{{/if}}")
.card-settings-column
a.flex.js-field-has-description-text(title="{{_ 'description'}} {{_ 'custom-field-text'}}" class="{{#if allowsDescriptionText}}is-checked{{/if}}")
span {{#if allowsDescriptionText}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if allowsDescriptionText}}fa-check{{else}}fa-square-o{{/if}}")
.card-settings-column
span
| 📝
i.fa.fa-file-text-o
| {{_ 'description'}}
| {{_ 'custom-field-text'}}
.card-settings-row
@ -400,64 +401,63 @@ template(name="boardCardSettingsPopup")
span
.card-settings-column
a.flex.js-field-has-description-text-on-minicard(title="{{_ 'description-on-minicard'}}" class="{{#if allowsDescriptionTextOnMinicard}}is-checked{{/if}}")
span {{#if allowsDescriptionTextOnMinicard}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if allowsDescriptionTextOnMinicard}}fa-check{{else}}fa-square-o{{/if}}")
.card-settings-column
span
| 📝
i.fa.fa-file-text-o
| {{_ 'description-on-minicard'}}
.card-settings-row
.card-settings-column
a.flex.js-field-has-checklists(title="{{_ 'checklists'}}" class="{{#if allowsChecklists}}is-checked{{/if}}")
span {{#if allowsChecklists}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if allowsChecklists}}fa-check{{else}}fa-square-o{{/if}}")
.card-settings-column
a.flex.js-field-has-checklists(title="{{_ 'checklists'}}" class="{{#if allowsChecklists}}is-checked{{/if}}")
span {{#if allowsChecklists}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if allowsChecklists}}fa-check{{else}}fa-square-o{{/if}}")
.card-settings-column
span
| ✅
i.fa.fa-check
| {{_ 'checklists'}}
.card-settings-row
.card-settings-column
a.flex.js-field-has-subtasks(title="{{_ 'subtasks'}}" class="{{#if allowsSubtasks}}is-checked{{/if}}")
span {{#if allowsSubtasks}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if allowsSubtasks}}fa-check{{else}}fa-square-o{{/if}}")
.card-settings-column
a.flex.js-field-has-subtasks(title="{{_ 'subtasks'}}" class="{{#if allowsSubtasks}}is-checked{{/if}}")
span {{#if allowsSubtasks}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if allowsSubtasks}}fa-check{{else}}fa-square-o{{/if}}")
.card-settings-column
span
| 🌐
i.fa.fa-globe
| {{_ 'subtasks'}}
.card-settings-row
.card-settings-column
a.flex.js-field-has-attachments(title="{{_ 'attachments'}}" class="{{#if allowsAttachments}}is-checked{{/if}}")
span {{#if allowsAttachments}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if allowsAttachments}}fa-check{{else}}fa-square-o{{/if}}")
.card-settings-column
a.flex.js-field-has-attachments(title="{{_ 'attachments'}}" class="{{#if allowsAttachments}}is-checked{{/if}}")
span {{#if allowsAttachments}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if allowsAttachments}}fa-check{{else}}fa-square-o{{/if}}")
.card-settings-column
span
| 📎
i.fa.fa-paperclip
| {{_ 'attachments'}}
.card-settings-row
.card-settings-column
span
.card-settings-column
a.flex.js-field-has-badge-attachment-on-minicard(title="{{_ 'badge-attachment-on-minicard'}}" class="{{#if allowsBadgeAttachmentOnMinicard}}is-checked{{/if}}")
span {{#if allowsBadgeAttachmentOnMinicard}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if allowsBadgeAttachmentOnMinicard}}fa-check{{else}}fa-square-o{{/if}}")
.card-settings-column
span
| 📎
i.fa.fa-paperclip
| {{_ 'badge-attachment-on-minicard'}}
.card-settings-row
.card-settings-column
span
.card-settings-column
a.flex.js-field-has-cover-attachment-on-minicard(title="{{_ 'cover-attachment-on-minicard'}}" class="{{#if allowsCoverAttachmentOnMinicard}}is-checked{{/if}}")
span {{#if allowsCoverAttachmentOnMinicard}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if allowsCoverAttachmentOnMinicard}}fa-check{{else}}fa-square-o{{/if}}")
.card-settings-column
span
| 📖
| 🖼️
i.fa.fa-picture-o
| {{_ 'cover-attachment-on-minicard'}}
//div.check-div
// a.flex.js-field-has-comments(class="{{#if allowsComments}}is-checked{{/if}}")
@ -476,26 +476,26 @@ template(name="boardSubtaskSettingsPopup")
form.board-subtask-settings
h3 {{_ 'show-parent-in-minicard'}}
a#prefix-with-full-path.flex.js-field-show-parent-in-minicard(title="{{_ 'prefix-with-full-path'}}" class="{{#if $eq presentParentTask 'prefix-with-full-path'}}is-checked{{/if}}")
span {{#if $eq presentParentTask 'prefix-with-full-path'}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if $eq presentParentTask 'prefix-with-full-path'}}fa-check{{else}}fa-square-o{{/if}}")
span {{_ 'prefix-with-full-path'}}
a#prefix-with-parent.flex.js-field-show-parent-in-minicard(title="{{_ 'prefix-with-parent'}}" class="{{#if $eq presentParentTask 'prefix-with-parent'}}is-checked{{/if}}")
span {{#if $eq presentParentTask 'prefix-with-parent'}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if $eq presentParentTask 'prefix-with-parent'}}fa-check{{else}}fa-square-o{{/if}}")
span {{_ 'prefix-with-parent'}}
a#subtext-with-full-path.flex.js-field-show-parent-in-minicard(title="{{_ 'subtext-with-full-path'}}" class="{{#if $eq presentParentTask 'subtext-with-full-path'}}is-checked{{/if}}")
span {{#if $eq presentParentTask 'subtext-with-full-path'}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if $eq presentParentTask 'subtext-with-full-path'}}fa-check{{else}}fa-square-o{{/if}}")
span {{_ 'subtext-with-full-path'}}
a#subtext-with-parent.flex.js-field-show-parent-in-minicard(title="{{_ 'subtext-with-parent'}}" class="{{#if $eq presentParentTask 'subtext-with-parent'}}is-checked{{/if}}")
span {{#if $eq presentParentTask 'subtext-with-parent'}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if $eq presentParentTask 'subtext-with-parent'}}fa-check{{else}}fa-square-o{{/if}}")
span {{_ 'subtext-with-parent'}}
a#no-parent.flex.js-field-show-parent-in-minicard(title="{{_ 'no-parent'}}" class="{{#if $eq presentParentTask 'no-parent'}}is-checked{{/if}}")
span {{#if $eq presentParentTask 'no-parent'}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if $eq presentParentTask 'no-parent'}}fa-check{{else}}fa-square-o{{/if}}")
span {{_ 'no-parent'}}
div
hr
div.check-div
a.flex.js-field-has-subtasks(title="{{_ 'show-subtasks-field'}}" class="{{#if allowsSubtasks}}is-checked{{/if}}")
span {{#if allowsSubtasks}}✅{{else}}⬜{{/if}}
i.fa(class="{{#if allowsSubtasks}}fa-check{{else}}fa-square-o{{/if}}")
span {{_ 'show-subtasks-field'}}
label
@ -534,20 +534,20 @@ template(name="chooseBoardSource")
template(name="archiveBoardPopup")
p {{_ 'close-board-pop'}}
button.js-confirm.negate.full(type="submit")
| 📦
i.fa.fa-archive
| {{_ 'archive'}}
template(name="deleteDuplicateListsPopup")
p {{_ 'delete-duplicate-lists-confirm'}}
button.js-confirm.negate.full(type="submit")
| 🗑️
i.fa.fa-trash
| {{_ 'delete'}}
template(name="outgoingWebhooksPopup")
each integrations
form.integration-form
a.flex
span {{#unless enabled}}✅{{else}}⬜{{/unless}}
i.fa(class="{{#unless enabled}}fa-check{{else}}fa-square-o{{/unless}}")
span {{_ 'disable-webhook'}}
input.js-outgoing-webhooks-title(placeholder="{{_ 'webhook-title'}}" type="text" name="title" value=title)
input.js-outgoing-webhooks-url(type="text" name="url" value=url)
@ -575,26 +575,25 @@ template(name="boardMenuPopup")
if currentUser.isBoardAdmin
li
a.js-open-rules-view(title="{{_ 'rules'}}")
span.emoji-icon
| ✨
i.fa.fa-magic
| {{_ 'rules'}}
if currentUser.isBoardAdmin
li
a.js-custom-fields
| 📝
i.fa.fa-file-text-o
| {{_ 'custom-fields'}}
li
a.js-open-archives
| 📦
i.fa.fa-archive
| {{_ 'archived-items'}}
if currentUser.isBoardAdmin
li
a.js-change-board-color
| 🎨
i.fa.fa-paint-brush
| {{_ 'board-change-color'}}
li
a.js-change-background-image
| 🖼️
i.fa.fa-picture-o
| {{_ 'board-change-background-image'}}
//Bug Board icons random dance https://github.com/wekan/wekan/issues/4214
//if currentUser.isBoardAdmin
@ -609,20 +608,20 @@ template(name="boardMenuPopup")
if withApi
li
a.js-export-board
| 📤
i.fa.fa-upload
| {{_ 'export-board'}}
if currentUser.isBoardAdmin
li
a.js-outgoing-webhooks
| 🌐
i.fa.fa-globe
| {{_ 'outgoing-webhooks'}}
li
a.js-card-settings
| 🃏
i.fa.fa-id-card
| {{_ 'card-settings'}}
li
a.js-subtask-settings
| 🌐
i.fa.fa-globe
| {{_ 'subtask-settings'}}
unless currentBoard.isTemplatesBoard
if currentUser.isBoardAdmin
@ -634,41 +633,40 @@ template(name="boardMenuPopup")
// | {{_ 'delete-duplicate-lists'}}
li
a.js-archive-board
span.emoji-icon
| ➡️📦
i.fa.fa-archive
| {{_ 'archive-board'}}
template(name="exportBoard")
ul.pop-over-list
li
a.download-json-link(href="{{exportUrl}}", download="{{exportJsonFilename}}")
| 📤
i.fa.fa-upload
| {{_ 'export-board-json'}}
li
a(href="{{exportUrlExcel}}", download="{{exportFilenameExcel}}")
| 📤
i.fa.fa-upload
| {{_ 'export-board-excel'}}
li
a(href="{{exportCsvUrl}}", download="{{exportCsvFilename}}")
| 📤
i.fa.fa-upload
| {{_ 'export-board-csv'}} ,
li
a(href="{{exportScsvUrl}}", download="{{exportCsvFilename}}")
| 📤
i.fa.fa-upload
| {{_ 'export-board-csv'}} ;
li
a(href="{{exportTsvUrl}}", download="{{exportTsvFilename}}")
| 📤
i.fa.fa-upload
| {{_ 'export-board-tsv'}}
li
a.html-export-board
| 📦
i.fa.fa-archive
| {{_ 'export-board-html'}}
template(name="labelsWidget")
.board-widget.board-widget-labels
h3
| 🏷️
i.fa.fa-tag
| {{_ 'labels'}}
.board-widget-content
each currentBoard.labels
@ -679,7 +677,7 @@ template(name="labelsWidget")
= name
if currentUser.isBoardAdmin
a.card-label.add-label.js-add-label(title="{{_ 'label-create'}}")
|
i.fa.fa-plus
template(name="memberPopup")
.board-member-menu
@ -691,7 +689,7 @@ template(name="memberPopup")
p.quiet @#{user.username}
if isInvited
p
| ⚠️
i.fa.fa-exclamation-triangle
| {{_ 'not-accepted-yet'}}
ul.pop-over-list
@ -789,55 +787,55 @@ template(name="changePermissionsPopup")
a(class="{{#if isLastAdmin}}disabled{{else}}js-set-admin{{/if}}")
| {{_ 'admin'}}
if isAdmin
| ✅
i.fa.fa-check
span.sub-name {{_ 'admin-desc'}}
li
a(class="{{#if isLastAdmin}}disabled{{else}}js-set-normal{{/if}}")
| {{_ 'normal'}}
if isNormal
| ✅
i.fa.fa-check
span.sub-name {{_ 'normal-desc'}}
li
a(class="{{#if isLastAdmin}}disabled{{else}}js-set-normal-assigned-only{{/if}}")
| {{_ 'normal-assigned-only'}}
if isNormalAssignedOnly
| ✅
i.fa.fa-check
span.sub-name {{_ 'normal-assigned-only-desc'}}
li
a(class="{{#if isLastAdmin}}disabled{{else}}js-set-no-comments{{/if}}")
| {{_ 'no-comments'}}
if isNoComments
| ✅
i.fa.fa-check
span.sub-name {{_ 'no-comments-desc'}}
li
a(class="{{#if isLastAdmin}}disabled{{else}}js-set-comment-only{{/if}}")
| {{_ 'comment-only'}}
if isCommentOnly
| ✅
i.fa.fa-check
span.sub-name {{_ 'comment-only-desc'}}
li
a(class="{{#if isLastAdmin}}disabled{{else}}js-set-comment-assigned-only{{/if}}")
| {{_ 'comment-assigned-only'}}
if isCommentAssignedOnly
| ✅
i.fa.fa-check
span.sub-name {{_ 'comment-assigned-only-desc'}}
li
a(class="{{#if isLastAdmin}}disabled{{else}}js-set-worker{{/if}}")
| {{_ 'worker'}}
if isWorker
| ✅
i.fa.fa-check
span.sub-name {{_ 'worker-desc'}}
li
a(class="{{#if isLastAdmin}}disabled{{else}}js-set-read-only{{/if}}")
| {{_ 'read-only'}}
if isReadOnly
| ✅
i.fa.fa-check
span.sub-name {{_ 'read-only-desc'}}
li
a(class="{{#if isLastAdmin}}disabled{{else}}js-set-read-assigned-only{{/if}}")
| {{_ 'read-assigned-only'}}
if isReadAssignedOnly
| ✅
i.fa.fa-check
span.sub-name {{_ 'read-assigned-only-desc'}}
if isLastAdmin
hr

View file

@ -14,7 +14,7 @@ template(name="customFieldsSidebar")
if currentUser.isBoardMember
hr
a.sidebar-btn.js-open-create-custom-field
|
i.fa.fa-plus
span {{_ 'createCustomField'}}
template(name="createCustomFieldPopup")

View file

@ -5,19 +5,19 @@
template(name="filterSidebar")
h3
| 📋
i.fa.fa-list
| {{_ 'list-filter-label'}}
ul.sidebar-list
form.js-list-filter
input(type="text")
hr
h3
| 📋
i.fa.fa-list
| {{_ 'filter-card-title-label'}}
input.js-field-card-filter(type="text")
hr
h3
| 🏷️
i.fa.fa-tag
| {{_ 'filter-labels-label'}}
ul.sidebar-list
li(class="{{#if Filter.labelIds.isSelected undefined}}active{{/if}}")
@ -25,7 +25,7 @@ template(name="filterSidebar")
span.sidebar-list-item-description
| {{_ 'filter-no-label'}}
if Filter.labelIds.isSelected undefined
| ✅
i.fa.fa-check
each currentBoard.labels
li
a.name.js-toggle-label-filter
@ -36,10 +36,10 @@ template(name="filterSidebar")
else
span.quiet {{_ "label-default" (_ (concat "color-" color))}}
if Filter.labelIds.isSelected _id
| ✅
i.fa.fa-check
hr
h3
| 👥
i.fa.fa-users
| {{_ 'filter-member-label'}}
ul.sidebar-list
li(class="{{#if Filter.members.isSelected undefined}}active{{/if}}")
@ -47,7 +47,7 @@ template(name="filterSidebar")
span.sidebar-list-item-description
| {{_ 'filter-no-member'}}
if Filter.members.isSelected undefined
| ✅
i.fa.fa-check
each currentBoard.activeMembers
with getUser userId
li(class="{{#if Filter.members.isSelected _id}}active{{/if}}")
@ -57,10 +57,9 @@ template(name="filterSidebar")
= profile.fullname
| (<span class="username">{{ username }}</span>)
if Filter.members.isSelected _id
| ✅
hr
i.fa.fa-check hr
h3
| 👤
i.fa.fa-user
| {{_ 'filter-assignee-label'}}
ul.sidebar-list
li(class="{{#if Filter.assignees.isSelected undefined}}active{{/if}}")
@ -68,7 +67,7 @@ template(name="filterSidebar")
span.sidebar-list-item-description
| {{_ 'filter-no-assignee'}}
if Filter.assignees.isSelected undefined
| ✅
i.fa.fa-check
each currentBoard.activeMembers
with getUser userId
li(class="{{#if Filter.assignees.isSelected _id}}active{{/if}}")
@ -78,11 +77,10 @@ template(name="filterSidebar")
= profile.fullname
| (<span class="username">{{ username }}</span>)
if Filter.assignees.isSelected _id
| ✅
i.fa.fa-check
hr
h3
| 📅
i.fa.fa-calendar
| {{_ 'filter-dates-label' }}
ul.sidebar-list
li(class="{{#if Filter.dueAt.isSelected 'noDate'}}active{{/if}}")
@ -90,40 +88,40 @@ template(name="filterSidebar")
span.sidebar-list-item-description
| {{_ 'filter-no-due-date' }}
if Filter.dueAt.isSelected 'noDate'
| ✅
i.fa.fa-check
li(class="{{#if Filter.dueAt.isSelected 'past'}}active{{/if}}")
a.name.js-toggle-overdue-filter
span.sidebar-list-item-description
| {{_ 'filter-overdue' }}
if Filter.dueAt.isSelected 'past'
| ✅
i.fa.fa-check
li(class="{{#if Filter.dueAt.isSelected 'today'}}active{{/if}}")
a.name.js-toggle-due-today-filter
span.sidebar-list-item-description
| {{_ 'filter-due-today' }}
if Filter.dueAt.isSelected 'today'
| ✅
i.fa.fa-check
li(class="{{#if Filter.dueAt.isSelected 'tomorrow'}}active{{/if}}")
a.name.js-toggle-due-tomorrow-filter
span.sidebar-list-item-description
| {{_ 'filter-due-tomorrow' }}
if Filter.dueAt.isSelected 'tomorrow'
| ✅
i.fa.fa-check
li(class="{{#if Filter.dueAt.isSelected 'thisweek'}}active{{/if}}")
a.name.js-toggle-due-this-week-filter
span.sidebar-list-item-description
| {{_ 'filter-due-this-week' }}
if Filter.dueAt.isSelected 'thisweek'
| ✅
i.fa.fa-check
li(class="{{#if Filter.dueAt.isSelected 'nextweek'}}active{{/if}}")
a.name.js-toggle-due-next-week-filter
span.sidebar-list-item-description
| {{_ 'filter-due-next-week' }}
if Filter.dueAt.isSelected 'nextweek'
| ✅
i.fa.fa-check
hr
h3
| 📋
i.fa.fa-list
| {{_ 'filter-custom-fields-label'}}
ul.sidebar-list
li(class="{{#if Filter.customFields.isSelected undefined}}active{{/if}}")
@ -131,14 +129,14 @@ template(name="filterSidebar")
span.sidebar-list-item-description
| {{_ 'filter-no-custom-fields'}}
if Filter.customFields.isSelected undefined
| ✅
i.fa.fa-check
each currentBoard.customFields
li(class="{{#if Filter.customFields.isSelected _id}}active{{/if}}")
a.name.js-toggle-custom-fields-filter
span.sidebar-list-item-description
| {{ name }}
if Filter.customFields.isSelected _id
| ✅
i.fa.fa-check
hr
h3
| {{_ 'other-filters-label'}}
@ -148,14 +146,14 @@ template(name="filterSidebar")
span.sidebar-list-item-description
| {{_ 'filter-show-archive'}}
if Filter.archive.isSelected _id
| ✅
i.fa.fa-check
ul.sidebar-list
li(class="{{#if Filter.hideEmpty.isSelected _id}}active{{/if}}")
a.name.js-toggle-hideEmpty-filter
span.sidebar-list-item-description
| {{_ 'filter-hide-empty'}}
if Filter.hideEmpty.isSelected _id
| ✅
i.fa.fa-check
hr
h3 {{_ 'advanced-filter-label'}}
input.js-field-advanced-filter(type="text")
@ -163,15 +161,15 @@ template(name="filterSidebar")
if Filter.isActive
hr
a.sidebar-btn.js-clear-all
| 🔍
i.fa.fa-search
span {{_ 'filter-clear'}}
a.sidebar-btn.js-filter-to-selection
| ☑️
i.fa.fa-check
span {{_ 'filter-to-selection'}}
template(name="multiselectionSidebar")
h3
| 🏷️
i.fa.fa-tag
| {{_ 'multi-selection-label'}}
ul.sidebar-list
each currentBoard.labels
@ -184,12 +182,12 @@ template(name="multiselectionSidebar")
else
span.quiet {{_ "label-default" (_ (concat "color-" color))}}
if allSelectedElementHave 'label' _id
| ✅
i.fa.fa-check
else if someSelectedElementHave 'label' _id
| ⋯
hr
h3
| 👥
i.fa.fa-users
| {{_ 'multi-selection-member'}}
ul.sidebar-list
each currentBoard.activeMembers
@ -201,22 +199,22 @@ template(name="multiselectionSidebar")
= profile.fullname
| (<span class="username">{{ username }}</span>)
if allSelectedElementHave 'member' _id
| ✅
i.fa.fa-check
else if someSelectedElementHave 'member' _id
| ⋯
if currentUser.isBoardAdmin
hr
a.sidebar-btn.js-selection-color
| 🎨
i.fa.fa-paint-brush
span {{_ 'selection-color'}}
a.sidebar-btn.js-copy-selection
| 📋
i.fa.fa-clipboard
span {{_ 'copy-selection'}}
a.sidebar-btn.js-move-selection
| 📤
i.fa.fa-upload
span {{_ 'move-selection'}}
a.sidebar-btn.js-archive-selection
| 📦
i.fa.fa-archive
span {{_ 'archive-selection'}}
template(name="disambiguateMultiLabelPopup")
@ -300,6 +298,6 @@ template(name="setSelectionColorPopup")
unless $eq color 'white'
span.card-label.palette-color.js-palette-color(class="card-details-{{color}}")
if(isSelected color)
| ✅
i.fa.fa-check
button.primary.confirm.js-submit {{_ 'save'}}
button.js-remove-color.negate.wide.right {{_ 'unset-color'}}

View file

@ -3,6 +3,6 @@ template(name="miniswimlane")
class="minicard-{{colorClass}}")
.minicard-title
.handle
| ↕️
i.fa.fa-arrows
+viewer
= title

View file

@ -30,20 +30,18 @@ template(name="swimlaneFixedHeader")
unless currentUser.isWorker
a.swimlane-collapse-indicator.js-collapse-swimlane.swimlane-header-collapse(title="{{_ 'collapse'}}")
if collapseSwimlane
| ▶
i.fa.fa-caret-right
else
| 🔽
a.js-open-add-swimlane-menu.swimlane-header-plus-icon(title="{{_ 'add-swimlane'}}")
|
i.fa.fa-caret-down
a.js-open-swimlane-menu(title="{{_ 'swimlaneActionPopup-title'}}")
i.fa.fa-bars
if isTouchScreenOrShowDesktopDragHandles
unless isTouchScreen
a.swimlane-header-handle.handle.js-swimlane-header-handle
| ↕️
i.fa.fa-arrows
if isTouchScreen
a.swimlane-header-miniscreen-handle.handle.js-swimlane-header-handle
| ↕️
a.js-open-swimlane-menu(title="{{_ 'swimlaneActionPopup-title'}}")
| ☰
i.fa.fa-arrows
template(name="editSwimlaneTitleForm")
.list-composer
@ -51,36 +49,45 @@ template(name="editSwimlaneTitleForm")
.edit-controls.clearfix
button.primary.confirm(type="submit") {{_ 'save'}}
a.js-close-inlined-form
| ❌
i.fa.fa-times-thin
template(name="swimlaneActionPopup")
if currentUser
unless currentUser.isCommentOnly
unless currentUser.isReadOnly
unless currentUser.isReadAssignedOnly
ul.pop-over-list
li: a.js-add-swimlane
i.fa.fa-plus
span {{_ 'add-swimlane'}}
hr
ul.pop-over-list
li: a.js-add-list-from-swimlane
i.fa.fa-plus
span {{_ 'add-list'}}
hr
ul.pop-over-list
if currentUser.isBoardAdmin
li: a.js-set-swimlane-color
| 🎨
i.fa.fa-paint-brush
| {{_ 'select-color'}}
li: a.js-set-swimlane-height
| ↕️
i.fa.fa-arrows
| {{_ 'set-swimlane-height'}}
if currentUser.isBoardAdmin
unless this.isTemplateContainer
hr
ul.pop-over-list
li: a.js-close-swimlane
| ▶️
| 📦
i.fa.fa-archive
| {{_ 'archive-swimlane'}}
ul.pop-over-list
li: a.js-copy-swimlane
| 📋
i.fa.fa-clipboard
| {{_ 'copy-swimlane'}}
ul.pop-over-list
li: a.js-move-swimlane
| ⬆️
i.fa.fa-arrow-up
| {{_ 'move-swimlane'}}
template(name="swimlaneAddPopup")
@ -107,8 +114,7 @@ template(name="setSwimlaneColorPopup")
each colors
span.card-label.palette-color.js-palette-color(class="card-details-{{color}}")
if(isSelected color)
| ✅
// Buttons aligned left too
i.fa.fa-check // Buttons aligned left too
.flush-left
button.primary.confirm.js-submit(style="margin-left:0") {{_ 'save'}}
button.js-remove-color.negate.wide.right(style="margin-left:8px") {{_ 'unset-color'}}

View file

@ -39,7 +39,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,
},
];
@ -104,6 +103,8 @@ Template.editSwimlaneTitleForm.helpers({
});
Template.swimlaneActionPopup.events({
'click .js-add-swimlane': Popup.open('swimlaneAdd'),
'click .js-add-list-from-swimlane': Popup.open('addList'),
'click .js-set-swimlane-color': Popup.open('setSwimlaneColor'),
'click .js-set-swimlane-height': Popup.open('setSwimlaneHeight'),
async 'click .js-close-swimlane'(event) {

View file

@ -10,6 +10,9 @@
max-height: 100%;
position: relative;
}
.swimlane.js-lists.js-swimlane {
min-height: 150px;
}
.swimlane-header-menu .swimlane-header-collapse-down {
font-size: 50%;
color: #a6a6a6;
@ -73,6 +76,10 @@
position: relative;
z-index: 10;
pointer-events: auto;
display: flex;
align-items: center;
justify-content: center;
line-height: 1.2;
}
.swimlane .swimlane-header-wrap .swimlane-header-menu {
position: absolute;
@ -89,7 +96,10 @@
top: calc(50% + 6px);
padding: 5px;
display: inline-block;
margin-left: 74px;
margin-left: 30px;
color: #a6a6a6;
vertical-align: middle;
line-height: 1.2;
}
@media print {
.swimlane .swimlane-header-wrap .swimlane-header-menu {
@ -100,6 +110,7 @@
top: calc(50% + 6px);
padding: 5px;
font-size: 22px;
color: #a6a6a6;
}
.swimlane .swimlane-header-wrap .swimlane-header-menu-icon {
top: calc(50% + 6px);
@ -107,29 +118,29 @@
font-size: 22px;
}
.swimlane .swimlane-header-wrap .swimlane-header-handle {
position: absolute;
position: relative;
top: calc(50% + 2px);
right: 60px;
padding: 2px;
padding: 2px 5px;
font-size: clamp(16px, 3vw, 20px);
transform: translateY(-50%);
display: flex;
align-items: center;
justify-content: center;
display: inline-block;
vertical-align: middle;
margin-left: 30px;
cursor: move;
z-index: 15;
pointer-events: auto;
color: #a6a6a6;
line-height: 1.2;
}
.swimlane .swimlane-header-wrap .swimlane-header-miniscreen-handle {
position: absolute;
padding: 2px;
position: relative;
padding: 2px 5px;
top: calc(50% + 2px);
transform: translateY(-50%);
right: 60px;
font-size: 24px;
display: inline-block;
vertical-align: middle;
margin-left: 30px;
cursor: move;
z-index: 15;
pointer-events: auto;
color: #a6a6a6;
}
/* Swimlane collapse button styling - matches list collapse button */
@ -137,14 +148,13 @@
color: #a6a6a6;
display: inline-block;
vertical-align: middle;
padding: 5px 8px;
padding: 5px;
border: none;
border-radius: 0;
background-color: transparent;
cursor: pointer;
font-size: 18px;
line-height: 1;
min-width: 30px;
line-height: 1.2;
text-align: center;
text-decoration: none;
margin: 0;
@ -155,6 +165,19 @@
color: #333;
}
.swimlane .swimlane-header-wrap .swimlane-header-menu .js-open-swimlane-menu:hover {
color: #333;
}
.swimlane .swimlane-header-wrap .swimlane-header-plus-icon:hover {
color: #333;
}
.swimlane .swimlane-header-wrap .swimlane-header-handle:hover,
.swimlane .swimlane-header-wrap .swimlane-header-miniscreen-handle:hover {
color: #333;
}
#js-swimlane-height-edit .swimlane-height-error {
display: none;
}

View file

@ -9,15 +9,9 @@ template(name="swimlane")
if currentListIsInThisSwimlane _id
+list(currentList)
unless currentList
if currentUser.isBoardMember
unless currentUser.isCommentOnly
+addListForm
each lists
+miniList(this)
else
if currentUser.isBoardMember
unless currentUser.isCommentOnly
+addListForm
each lists
if visible this
+list(this)
@ -30,15 +24,9 @@ template(name="listsGroup")
if currentList
+list(currentList)
else
if currentUser.isBoardMember
unless currentUser.isCommentOnly
+addListForm
each lists
+miniList(this)
else
if currentUser.isBoardMember
unless currentUser.isCommentOnly
+addListForm
each lists
if visible this
+list(this)
@ -63,7 +51,7 @@ template(name="addListForm")
.edit-controls.clearfix
button.primary.confirm(type="submit") {{_ 'save'}}
.js-close-inlined-form
| ❌
i.fa.fa-times-thin
unless currentBoard.isTemplatesBoard
unless currentBoard.isTemplateBoard
span.quiet
@ -71,7 +59,7 @@ template(name="addListForm")
a.js-list-template {{_ 'template'}}
else
a.open-list-composer.js-open-inlined-form(title="{{_ 'add-list'}}")
|
i.fa.fa-plus
template(name="moveSwimlanePopup")
if currentUser

View file

@ -3,11 +3,9 @@ template(name='passwordInput')
label(for='at-field-{{_id}}') {{displayName}}
.password-input-container
input.password-field(type="{{type}}" placeholder="{{displayName}}" autocomplete="{{autocomplete}}" required="{{required}}")
button.password-toggle-btn(type="button" aria-label="Toggle password visibility" title="Toggle password visibility")
.eye-container
span.eye-text 👁️
svg.eye-slash(width="20" height="20" viewBox="0 0 20 20" class="eye-slash-line")
line(x1="6" y1="14" x2="32" y2="-14" stroke="#000" stroke-width="2" stroke-linecap="round")
button.password-toggle-btn(type="button" tabindex="-1" aria-label="Toggle password visibility" title="Toggle password visibility")
i.fa.fa-eye.eye-icon
i.fa.fa-eye-slash.eye-slash-icon
if errs
.at-error
each errs

View file

@ -15,10 +15,14 @@ Template.passwordInput.onRendered(function() {
// Ensure the input starts as password type for password fields
input.type = 'password';
// Initially hide the slash line since password starts hidden
const slashLine = template.find('.eye-slash-line');
if (slashLine) {
slashLine.style.display = 'none';
// Initially show eye icon (password is hidden) and hide eye-slash icon
const eyeIcon = template.find('.eye-icon');
const eyeSlashIcon = template.find('.eye-slash-icon');
if (eyeIcon) {
eyeIcon.style.display = 'inline-block';
}
if (eyeSlashIcon) {
eyeSlashIcon.style.display = 'none';
}
}
});
@ -27,19 +31,26 @@ Template.passwordInput.events({
'click .password-toggle-btn'(event, template) {
event.preventDefault();
const input = template.find('input.password-field');
const slashLine = template.find('.eye-slash-line');
const eyeIcon = template.find('.eye-icon');
const eyeSlashIcon = template.find('.eye-slash-icon');
if (input.type === 'password') {
input.type = 'text';
// Show the slash line when password is visible
if (slashLine) {
slashLine.style.display = 'block';
// Show eye-slash icon when password is visible
if (eyeIcon) {
eyeIcon.style.display = 'none';
}
if (eyeSlashIcon) {
eyeSlashIcon.style.display = 'inline-block';
}
} else {
input.type = 'password';
// Hide the slash line when password is hidden
if (slashLine) {
slashLine.style.display = 'none';
// Show eye icon when password is hidden
if (eyeIcon) {
eyeIcon.style.display = 'inline-block';
}
if (eyeSlashIcon) {
eyeSlashIcon.style.display = 'none';
}
}
},

View file

@ -16,7 +16,7 @@ template(name="userAvatar")
if showEdit
if $eq currentUser._id userData._id
a.edit-avatar.js-change-avatar
| ✏️
i.fa.fa-pencil-square-o
template(name="userAvatarInitials")
svg.avatar.avatar-initials(viewBox="0 0 {{viewPortWidth}} 15")
@ -92,8 +92,7 @@ template(name="changeAvatarPopup")
.member
img.avatar.avatar-image(src="{{link}}")
if isSelected
| ✅
p.sub-name
i.fa.fa-check p.sub-name
a.js-delete-avatar {{_ 'delete'}}
| -
= name
@ -102,8 +101,7 @@ template(name="changeAvatarPopup")
+userAvatarInitials(userId=currentUser._id)
| {{_ 'initials' }}
if noAvatarUrl
| ✅
p.sub-name {{_ 'default-avatar'}}
i.fa.fa-check p.sub-name {{_ 'default-avatar'}}
input.hide.js-upload-avatar-input(accept="image/*;capture=camera" type="file")
if Meteor.settings.public.avatarsUploadMaxSize
| {{_ 'max-avatar-filesize'}} {{Meteor.settings.public.avatarsUploadMaxSize}}
@ -113,7 +111,7 @@ template(name="changeAvatarPopup")
br
| {{_ 'invalid-file'}}
button.full.js-upload-avatar
| 📤
i.fa.fa-upload
| {{_ 'upload-avatar' }}
template(name="deleteAvatarPopup")

View file

@ -37,14 +37,14 @@
.password-toggle-btn {
position: absolute;
right: 5px; /* Adjusted for larger button */
top: calc(50% - 6px); /* Moved up by 6px total */
top: calc(50% - 26px); /* Moved up by 20px + 6px = 26px total */
transform: translateY(-50%);
background: #f8f8f8 !important;
border: 1px solid #ddd !important;
border-radius: 3px !important;
color: #000 !important; /* Black color for the icon */
cursor: pointer;
padding: 8px 12px; /* 2x bigger padding */
padding: 8px 6px 8px 12px; /* 2x bigger padding, 6px less on right */
font-size: 16px; /* 2x bigger font size */
width: auto !important;
height: auto !important;
@ -56,6 +56,10 @@
min-width: 40px; /* 2x bigger minimum width */
min-height: 32px; /* 2x bigger minimum height */
}
/* Adjust position for login and register pages */
.auth-layout .password-toggle-btn {
top: calc(50% - 11px); /* Move 15px down for login/register */
}
.password-toggle-btn .eye-text {
color: #000 !important;
font-size: 16px !important;

View file

@ -15,95 +15,95 @@ template(name="memberMenuPopup")
with currentUser
li
a.js-toggle-grey-icons(href="#")
| 🎨
i.fa.fa-paint-brush
| {{_ 'grey-icons'}}
if currentUser.profile
if currentUser.profile.GreyIcons
span(key="grey-icons-checkmark") ✅
i.fa.fa-check
li
a.js-my-cards(href="{{pathFor 'my-cards'}}")
| 📋
i.fa.fa-list
| {{_ 'my-cards'}}
li
a.js-due-cards(href="{{pathFor 'due-cards'}}")
| 📅
i.fa.fa-calendar
| {{_ 'dueCards-title'}}
li
a.js-global-search(href="{{pathFor 'global-search'}}")
| 🔍
i.fa.fa-search
| {{_ 'globalSearch-title'}}
li
a(href="{{pathFor 'home'}}")
| 🏠
i.fa.fa-home
| {{_ 'all-boards'}}
li
a(href="{{pathFor 'public'}}")
| 🌐
i.fa.fa-globe
| {{_ 'public'}}
li
a.board-header-btn.js-open-archived-board
| 📦
i.fa.fa-archive
span {{_ 'archives'}}
li
a.js-notifications-drawer-toggle
| 🔔
i.fa.fa-bell
| {{_ 'notifications'}}
if currentSetting.customHelpLinkUrl
li
a(href="{{currentSetting.customHelpLinkUrl}}", title="{{_ 'help'}}", target="_blank", rel="noopener noreferrer")
| ❓
i.fa.fa-question-circle
| {{_ 'help'}}
unless currentUser.isWorker
ul.pop-over-list
li
a(href="{{pathFor 'board' id=templatesBoardId slug=templatesBoardSlug}}")
| 📋
i.fa.fa-list
| {{_ 'templates'}}
if currentUser.isAdmin
li
a.js-go-setting(href="{{pathFor 'setting'}}")
| 🔒
i.fa.fa-lock
| {{_ 'admin-panel'}}
hr
if isSameDomainNameSettingValue
li
a.js-invite-people
| ✉️
i.fa.fa-envelope
| {{_ 'invite-people'}}
if isNotOAuth2AuthenticationMethod
li
a.js-edit-profile
| 👤
i.fa.fa-user
| {{_ 'edit-profile'}}
li
a.js-change-settings
| ⚙️
i.fa.fa-cog
| {{_ 'change-settings'}}
li
a.js-change-avatar
| 🖼️
i.fa.fa-picture-o
| {{_ 'edit-avatar'}}
unless isSandstorm
if isNotOAuth2AuthenticationMethod
li
a.js-change-password
| 🔑
i.fa.fa-key
| {{_ 'changePasswordPopup-title'}}
li
a.js-change-language
| 🏁
i.fa.fa-flag
| {{_ 'changeLanguagePopup-title'}}
if isSupportPageEnabled
li
a(href="{{pathFor 'support'}}")
| ❓
i.fa.fa-question-circle
| {{_ 'support'}}
unless isSandstorm
hr
ul.pop-over-list
li
a.js-logout
| 🚪
i.fa.fa-sign-out
| {{_ 'log-out'}}
template(name="invitePeoplePopup")
@ -177,25 +177,25 @@ template(name="changeLanguagePopup")
a.js-set-language
span.emoji-icon {{languageFlag}}
| {{name}}
if rtl
| (RTL)
if isCurrentLanguage
| ✅
i.fa.fa-check
template(name="changeSettingsPopup")
ul.pop-over-list
li
a.js-toggle-desktop-drag-handles
| ↕️
i.fa.fa-arrows
| {{_ 'show-desktop-drag-handles'}}
if isShowDesktopDragHandles
| ✅
unless currentUser.isWorker
i.fa.fa-check unless currentUser.isWorker
li
label.bold.clear
| 🔢
i.fa.fa-sort-numeric-asc
| {{_ 'show-cards-minimum-count'}}
input#show-cards-count-at.inline-input.left(type="number" value="#{showCardsCountAt}" min="-1")
label.bold.clear
| 📅
i.fa.fa-calendar
| {{_ 'start-day-of-week'}}
select#start-day-of-week.inline-input.left
each day in weekDays startDayOfWeek

View file

@ -295,7 +295,7 @@ Template.changePasswordPopup.onRendered(function() {
Template.changeLanguagePopup.helpers({
languages() {
return TAPi18n.getSupportedLanguages()
.map(({ tag, name }) => ({ tag: tag, name }))
.map(({ tag, name, rtl }) => ({ tag, name, rtl }))
.sort((a, b) => {
if (a.name === b.name) {
return 0;

View file

@ -82,3 +82,5 @@ Blaze.registerHelper('canModifyBoard', () =>
);
Blaze.registerHelper('add', (a, b) => a + b);
Blaze.registerHelper('increment', (n) => (n || 0) + 1);

View file

@ -24,6 +24,26 @@ InlinedForm = BlazeComponent.extendComponent({
this.isOpen = new ReactiveVar(false);
},
onRendered() {
// Autofocus when form becomes open
this.autorun(() => {
if (this.isOpen.get()) {
Tracker.afterFlush(() => {
const input = this.find('textarea,input[type=text]');
if (input && typeof input.focus === 'function') {
setTimeout(() => {
input.focus();
// Select content if it exists (useful for editing)
if (input.value && input.select) {
input.select();
}
}, 50);
}
});
}
});
},
onDestroyed() {
currentlyOpenedForm.set(null);
},