diff --git a/client/components/activities/activities.css b/client/components/activities/activities.css index 08c9eea08..f1e461cfa 100644 --- a/client/components/activities/activities.css +++ b/client/components/activities/activities.css @@ -1,16 +1,22 @@ .activity-title { - margin: 0 0.7vw 1vh; display: flex; + gap: 0.5lh; justify-content: space-between; } +.reactions-popup { + display: flex; + gap: 1ch; + flex-wrap: wrap; + margin: 0.5lh 0.5ch; + max-width: 80vw; +} .reactions-popup .add-comment-reaction { display: inline-block; cursor: pointer; border-radius: 0.7vw; - font-size: clamp(18px, 4vw, 22px); text-align: center; line-height: 1.3; - width: 5vw; + font-size: 1.2em; } .reactions-popup .add-comment-reaction:hover { background-color: #b0c4de; @@ -18,20 +24,20 @@ .activities { clear: both; } +.activity { + display: flex; +} .activities .activity { margin: 0.1vh 0; padding: 0.8vh 0; display: flex; -} -.activities .activity .member { - width: 4vw; - height: 4vw; + font-size: 0.8em; } .activities .activity .activity-member { font-weight: 700; } .activities .activity .activity-desc { - word-wrap: break-word; + overflow-wrap: break-word; overflow: hidden; flex: 1; align-self: center; diff --git a/client/components/activities/activities.js b/client/components/activities/activities.js index 5a0a81315..4f829d7b1 100644 --- a/client/components/activities/activities.js +++ b/client/components/activities/activities.js @@ -275,7 +275,7 @@ Template.commentReactions.events({ cardComment.toggleReaction(codepoint); } }, - 'click .open-comment-reaction-popup': Popup.open('addReaction'), + 'click .open-comment-reaction-popup': Popup.open('addReaction', {showHeader: false}) }) Template.addReactionPopup.events({ @@ -306,6 +306,11 @@ Template.addReactionPopup.helpers({ '😊', '🤔', '😔']; + }, + hasUserReacted(codepoint) { + const commentId = Template.instance().data.commentId; + const cardComment = ReactiveCache.getCardComment(commentId); + return cardComment.hasUserReacted(codepoint); } }) diff --git a/client/components/activities/comments.css b/client/components/activities/comments.css index de0189de7..de7512e03 100644 --- a/client/components/activities/comments.css +++ b/client/components/activities/comments.css @@ -1,12 +1,12 @@ .new-comment { position: relative; - margin: 0 0 20px 38px; + display: flex; + align-items: center; + justify-content: stretch; + gap: 1ch; } .new-comment .member { opacity: 0.7; - position: absolute; - top: 1px; - left: -38px; } .new-comment.is-open .member { opacity: 1; @@ -14,34 +14,44 @@ .new-comment.is-open .helper { display: inline-block; } -.new-comment.is-open textarea { - min-height: 100px; - color: #4d4d4d; - cursor: auto; - overflow: hidden; - word-wrap: break-word; + +.new-comment, .comment { + .is-open textarea { + min-height: 100px; + color: #4d4d4d; + cursor: auto; + overflow-wrap: break-word; + } + textarea { + grid-area: editor; + background-color: #fff; + border: 0; + box-shadow: 0 1px 2px rgba(0,0,0,0.23); + min-height: 3lh; + &:hover, &.is-open { + cursor: auto; + background-color: #fff; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.33); + border: 0; + cursor: pointer; + } + } } + .new-comment .too-long { margin-top: 8px; } -.new-comment textarea { - background-color: #fff; - border: 0; - box-shadow: 0 1px 2px rgba(0,0,0,0.23); - height: 36px; - margin: 4px 4px 6px 0; - padding: 9px 11px; - width: 100%; -} -.new-comment textarea:hover, -.new-comment textarea:is-open { - background-color: #fff; - box-shadow: 0 1px 3px rgba(0,0,0,0.33); - border: 0; - cursor: pointer; -} -.new-comment textarea:is-open { - cursor: auto; + +.js-new-comment-form, .js-edit-comment { + display: grid !important; + grid-template-areas: + "editor editor editor editor" + "main-controls main-controls link-controls editor-controls"; + grid-auto-columns: 1fr; + grid-auto-rows: min-content; + align-items: center; + flex: 1; + gap: 0.3lh; } .comment-item { background-color: #fff; @@ -65,31 +75,30 @@ } .comments { clear: both; + display: flex; + flex-direction: column; + gap: 1lh; + padding-top: 1lh; } .comments .comment { - margin: 0.5px 0; - padding: 6px 0; display: flex; + gap: 1ch; } -.comments .comment .member { - width: 32px; - height: 32px; -} + .comments .comment .comment-member { font-weight: 700; } .comments .comment .comment-desc { - word-wrap: break-word; - overflow: hidden; + overflow-wrap: break-word; flex: 1; align-self: center; margin: 0; - margin-left: 3px; - overflow: hidden; - word-break: break-word; + display: flex; + flex-direction: column; + gap: 0.3lh; } .comments .comment .comment-desc .comment-text { - display: block; + display: flex; border-radius: 3px; background: #fff; text-decoration: none; @@ -101,6 +110,7 @@ display: flex; margin-top: 5px; gap: 5px; + align-items: center; } .comments .comment .comment-desc .reactions .open-comment-reaction-popup { display: flex; @@ -110,7 +120,6 @@ } .comments .comment .comment-desc .reactions .open-comment-reaction-popup span { display: inline-block; - font-size: clamp(14px, 2vw, 18px); font-weight: 500; line-height: 1; margin-left: 4px; @@ -128,10 +137,14 @@ .comments .comment .comment-desc .reactions .reaction:hover { background-color: #b0c4de; } -.comments .comment .comment-desc .reactions .reaction .reaction-count { - font-size: 12px; -} .comments .comment .comment-desc .comment-meta { font-size: 0.8em; color: #999; + display: grid; + grid-auto-flow: column; + grid-auto-columns: max-content; + gap: 1ch; + align-items: center; + /* #FIXME maybe put date outside of comment body ?*/ + margin-inline-start: -10vw; } diff --git a/client/components/activities/comments.jade b/client/components/activities/comments.jade index 1860eb4f4..5f317a261 100644 --- a/client/components/activities/comments.jade +++ b/client/components/activities/comments.jade @@ -64,5 +64,5 @@ template(name="commentReactions") template(name="addReactionPopup") .reactions-popup each codepoint in codepoints - span.add-comment-reaction(data-codepoint="#{codepoint}") !{codepoint} - + unless (hasUserReacted codepoint) + span.add-comment-reaction(data-codepoint="#{codepoint}") !{codepoint} diff --git a/client/components/boardConversionProgress.css b/client/components/boardConversionProgress.css index fd186908f..de79d13a4 100644 --- a/client/components/boardConversionProgress.css +++ b/client/components/boardConversionProgress.css @@ -18,7 +18,7 @@ .board-conversion-modal { background: white; - border-radius: 8px; + border-radius: 0.8ch; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3); max-width: 500px; width: 90%; @@ -47,7 +47,7 @@ .board-conversion-header h3 { margin: 0 0 8px 0; color: #333; - font-size: 20px; + font-weight: 500; } @@ -59,7 +59,7 @@ .board-conversion-header p { margin: 0; color: #666; - font-size: 14px; + } .board-conversion-content { @@ -74,7 +74,7 @@ width: 100%; height: 8px; background-color: #e0e0e0; - border-radius: 4px; + border-radius: 0.4ch; overflow: hidden; margin-bottom: 8px; } @@ -82,7 +82,7 @@ .progress-fill { height: 100%; background: linear-gradient(90deg, #2196F3, #21CBF3); - border-radius: 4px; + border-radius: 0.4ch; transition: width 0.3s ease; position: relative; } @@ -116,14 +116,14 @@ text-align: center; font-weight: 600; color: #2196F3; - font-size: 16px; + } .conversion-status { text-align: center; margin-bottom: 16px; color: #333; - font-size: 16px; + } .conversion-status i { @@ -134,10 +134,10 @@ .conversion-time { text-align: center; color: #666; - font-size: 14px; + background-color: #f5f5f5; padding: 8px 12px; - border-radius: 4px; + border-radius: 0.4ch; margin-bottom: 16px; } @@ -155,7 +155,7 @@ .conversion-info { text-align: center; color: #666; - font-size: 13px; + line-height: 1.4; } @@ -170,15 +170,15 @@ width: 95%; margin: 20px; } - + .board-conversion-header, .board-conversion-content, .board-conversion-footer { padding-left: 16px; padding-right: 16px; } - + .board-conversion-header h3 { - font-size: 18px; + } } diff --git a/client/components/boards/boardArchive.jade b/client/components/boards/boardArchive.jade index 839f183e1..761736e81 100644 --- a/client/components/boards/boardArchive.jade +++ b/client/components/boards/boardArchive.jade @@ -1,7 +1,7 @@ template(name="archivedBoards") h2 span(title="{{_ 'archived-boards'}}") - i.fa.fa-archive + i.fa.fa-archive | {{_ 'archived-boards'}} ul.archived-lists diff --git a/client/components/boards/boardBody.css b/client/components/boards/boardBody.css index b23d7f4d8..1bbb3d595 100644 --- a/client/components/boards/boardBody.css +++ b/client/components/boards/boardBody.css @@ -1,43 +1,25 @@ +.swim-flex { + display: flex; + flex: 1; + flex-direction: column; + align-items: stretch; + padding-bottom: 40vw; +} + .board-wrapper { - position: absolute; - left: 0; - right: 0; - top: 0; - bottom: 0; - overflow-x: hidden; - overflow-y: hidden; - width: 100%; - min-width: 100%; + display: flex; + flex: 1; + overflow: auto; } -/* When zoom is 50% or lower, ensure full width like content */ -.board-wrapper[style*="transform: scale(0.5)"] { - width: 100% !important; - max-width: 100% !important; - margin: 0 !important; -} - -.board-wrapper[style*="transform: scale(0.4)"] { - width: 100% !important; - max-width: 100% !important; - margin: 0 !important; -} - -.board-wrapper[style*="transform: scale(0.3)"] { - width: 100% !important; - max-width: 100% !important; - margin: 0 !important; -} .board-wrapper .board-canvas { - position: absolute; - left: 0; - right: 0; - top: 0; - bottom: 0; transition: margin 0.1s; overflow-y: auto; - width: 100%; - min-width: 100%; + overflow-x: hidden; + display: flex; + /* don't stretch vertically if not needed (e.g collapsed) */ + align-self: start; + flex: 1; } /* Ensure horizontal scrollbar is visible for high zoom levels */ @@ -97,172 +79,12 @@ position: relative; } -#content[style*="overflow-x: auto"]::-webkit-scrollbar { - height: 12px; - width: 12px; + +/* Force vertical scrollbar to always be visible */ +#content[style*="overflow-y: auto"] { + overflow-y: scroll !important; } - /* Force vertical scrollbar to always be visible */ - #content[style*="overflow-y: auto"] { - overflow-y: scroll !important; - } - - /* Mobile - make all text 2x bigger inside #content by default (icons stay same size) */ - @media screen and (max-width: 800px), - screen and (max-device-width: 800px), - screen and (-webkit-min-device-pixel-ratio: 2) and (max-width: 800px), - screen and (max-width: 800px) and (orientation: portrait), - screen and (max-width: 800px) and (orientation: landscape) { - #content { - font-size: 2em !important; /* 2x bigger base font size for content area */ - } - - /* Make all text elements 2x bigger */ - #content h1, #content h2, #content h3, #content h4, #content h5, #content h6, - #content p, #content span, #content div, #content a, #content button, - #content .minicard, #content .list-header-name, #content .board-header-btn, - #content .card-title, #content .card-details, #content .card-description, - #content .swimlane-header, #content .list-title, #content .card-text, - #content .member, #content .member-name, #content .member-initials, - #content .checklist-item, #content .checklist-title, #content .comment, - #content .activity, #content .activity-text, #content .activity-time, - #content .board-title, #content .board-description, #content .list-name, - #content .card-text, #content .card-title, #content .card-description, - #content .swimlane-title, #content .swimlane-description, - #content .board-header-title, #content .board-header-description, - #content .card-detail-title, #content .card-detail-description, - #content .list-header-title, #content .list-header-description, - #content .swimlane-header-title, #content .swimlane-header-description, - #content .minicard-title, #content .minicard-description, - #content .card-comment, #content .card-comment-text, - #content .checklist-item-text, #content .checklist-item-title, - #content .activity-item, #content .activity-item-text, - #content .board-member, #content .board-member-name, - #content .team-member, #content .team-member-name, - #content .org-member, #content .org-member-name, - #content .template-member, #content .template-member-name, - #content .user-name, #content .user-email, #content .user-role, - #content .setting-title, #content .setting-description, - #content .popup-title, #content .popup-description, - #content .modal-title, #content .modal-description, - #content .notification-title, #content .notification-text, - #content .announcement-title, #content .announcement-text, - #content .offline-warning-title, #content .offline-warning-text, - #content .error-title, #content .error-text, - #content .success-title, #content .success-text, - #content .info-title, #content .info-text, - #content .warning-title, #content .warning-text { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - /* Keep icons the same size (don't scale them) */ - #content .fa, #content .icon, #content i { - font-size: 1em !important; /* Keep original icon size */ - } - - /* Reset specific icon sizes to prevent double scaling */ - #content .fa-home, #content .fa-bars, #content .fa-search, - #content .fa-bell, #content .fa-user, #content .fa-cog, - #content .fa-plus, #content .fa-minus, #content .fa-edit, - #content .fa-trash, #content .fa-save, #content .fa-cancel, - #content .fa-arrow-left, #content .fa-arrow-right, - #content .fa-arrow-up, #content .fa-arrow-down, - #content .fa-check, #content .fa-times, #content .fa-close, - #content .fa-star, #content .fa-heart, #content .fa-thumbs-up, - #content .fa-thumbs-down, #content .fa-comment, #content .fa-reply, - #content .fa-share, #content .fa-download, #content .fa-upload, - #content .fa-copy, #content .fa-paste, #content .fa-cut, - #content .fa-undo, #content .fa-redo, #content .fa-refresh, - #content .fa-sync, #content .fa-spinner, #content .fa-loading, - #content .fa-info, #content .fa-question, #content .fa-exclamation, - #content .fa-warning, #content .fa-error, #content .fa-success, - #content .fa-check-circle, #content .fa-times-circle, - #content .fa-exclamation-circle, #content .fa-question-circle, - #content .fa-info-circle, #content .fa-warning-circle, - #content .fa-error-circle, #content .fa-success-circle { - font-size: 1em !important; /* Keep original icon size */ - } - } - - /* Fallback for iPhone devices using JavaScript detection */ - .iphone-device #content { - font-size: 2em !important; /* 2x bigger base font size for content area */ - } - - .iphone-device #content h1, .iphone-device #content h2, .iphone-device #content h3, .iphone-device #content h4, .iphone-device #content h5, .iphone-device #content h6, - .iphone-device #content p, .iphone-device #content span, .iphone-device #content div, .iphone-device #content a, .iphone-device #content button, - .iphone-device #content .minicard, .iphone-device #content .list-header-name, .iphone-device #content .board-header-btn, - .iphone-device #content .card-title, .iphone-device #content .card-details, .iphone-device #content .card-description, - .iphone-device #content .swimlane-header, .iphone-device #content .list-title, .iphone-device #content .card-text, - .iphone-device #content .member, .iphone-device #content .member-name, .iphone-device #content .member-initials, - .iphone-device #content .checklist-item, .iphone-device #content .checklist-title, .iphone-device #content .comment, - .iphone-device #content .activity, .iphone-device #content .activity-text, .iphone-device #content .activity-time, - .iphone-device #content .board-title, .iphone-device #content .board-description, .iphone-device #content .list-name, - .iphone-device #content .card-text, .iphone-device #content .card-title, .iphone-device #content .card-description, - .iphone-device #content .swimlane-title, .iphone-device #content .swimlane-description, - .iphone-device #content .board-header-title, .iphone-device #content .board-header-description, - .iphone-device #content .card-detail-title, .iphone-device #content .card-detail-description, - .iphone-device #content .list-header-title, .iphone-device #content .list-header-description, - .iphone-device #content .swimlane-header-title, .iphone-device #content .swimlane-header-description, - .iphone-device #content .minicard-title, .iphone-device #content .minicard-description, - .iphone-device #content .card-comment, .iphone-device #content .card-comment-text, - .iphone-device #content .checklist-item-text, .iphone-device #content .checklist-item-title, - .iphone-device #content .activity-item, .iphone-device #content .activity-item-text, - .iphone-device #content .board-member, .iphone-device #content .board-member-name, - .iphone-device #content .team-member, .iphone-device #content .team-member-name, - .iphone-device #content .org-member, .iphone-device #content .org-member-name, - .iphone-device #content .template-member, .iphone-device #content .template-member-name, - .iphone-device #content .user-name, .iphone-device #content .user-email, .iphone-device #content .user-role, - .iphone-device #content .setting-title, .iphone-device #content .setting-description, - .iphone-device #content .popup-title, .iphone-device #content .popup-description, - .iphone-device #content .modal-title, .iphone-device #content .modal-description, - .iphone-device #content .notification-title, .iphone-device #content .notification-text, - .iphone-device #content .announcement-title, .iphone-device #content .announcement-text, - .iphone-device #content .offline-warning-title, .iphone-device #content .offline-warning-text, - .iphone-device #content .error-title, .iphone-device #content .error-text, - .iphone-device #content .success-title, .iphone-device #content .success-text, - .iphone-device #content .info-title, .iphone-device #content .info-text, - .iphone-device #content .warning-title, .iphone-device #content .warning-text { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - /* Keep icons the same size for iPhone devices */ - .iphone-device #content .fa, .iphone-device #content .icon, .iphone-device #content i { - font-size: 1em !important; /* Keep original icon size */ - } - -/* Mobile iPhone: scale card details text and icons to 2x */ -body.mobile-mode.iphone-device .card-details { - font-size: 2em !important; -} -body.mobile-mode.iphone-device .card-details .fa, -body.mobile-mode.iphone-device .card-details .icon, -body.mobile-mode.iphone-device .card-details i, -body.mobile-mode.iphone-device .card-details .emoji-icon, -body.mobile-mode.iphone-device .card-details a, -body.mobile-mode.iphone-device .card-details p, -body.mobile-mode.iphone-device .card-details span, -body.mobile-mode.iphone-device .card-details div, -body.mobile-mode.iphone-device .card-details button, -body.mobile-mode.iphone-device .card-details input, -body.mobile-mode.iphone-device .card-details select, -body.mobile-mode.iphone-device .card-details textarea { - font-size: inherit !important; -} -/* Section titles slightly larger than content but not as big as card title */ -body.mobile-mode.iphone-device .card-details .card-details-item-title { - font-size: 1.1em !important; - font-weight: bold; -} - -/* Ensure scrollbars are positioned correctly */ -#content[style*="overflow-x: auto"]::-webkit-scrollbar:vertical { - width: 12px; -} - -#content[style*="overflow-x: auto"]::-webkit-scrollbar:horizontal { - height: 12px; -} /* Force both scrollbars to always be visible for high zoom levels */ #content[style*="overflow-x: auto"][style*="overflow-y: auto"] { @@ -274,36 +96,6 @@ body.mobile-mode.iphone-device .card-details .card-details-item-title { #content[style*="overflow-y: auto"] { scrollbar-gutter: stable; } -.board-wrapper .board-canvas .board-overlay { - position: fixed; - left: 0; - right: 0; - top: 0; - bottom: 0; - top: -100px; - right: -400px; - background: #000; - opacity: 0.33; - animation: fadeIn 0.2s; - z-index: 16; -} - -/* Fix for mobile Safari: ensure overlay stays behind card details */ -@media screen and (max-width: 800px) { - .board-wrapper .board-canvas .board-overlay { - z-index: 17 !important; - } - - /* In desktop mode on small screens, still keep overlay behind card */ - body.desktop-mode .board-wrapper .board-canvas .board-overlay { - z-index: 17 !important; - } -} - -/* In mobile mode, lower the overlay z-index to stay behind card details */ -body.mobile-mode .board-wrapper .board-canvas .board-overlay { - z-index: 17 !important; -} /* iPhone in desktop mode: remove overlay to avoid blocking card */ body.desktop-mode.iphone-device .board-wrapper .board-canvas .board-overlay { @@ -320,73 +112,14 @@ body.desktop-mode .board-wrapper .board-canvas .board-overlay { .board-wrapper .board-canvas.is-dragging-active .minicard-wrapper.is-checked { display: none; } -/* Mobile view styles - applied when isMiniScreen is true (iPhone, etc.) */ -.board-wrapper.mobile-view { - width: 100vw !important; - max-width: 100vw !important; - min-width: 100vw !important; - left: 0 !important; - right: 0 !important; - overflow-x: hidden !important; - overflow-y: auto !important; -} - -.board-wrapper.mobile-view .board-canvas { - width: 100vw !important; - max-width: 100vw !important; - min-width: 100vw !important; - left: 0 !important; - right: 0 !important; - overflow-x: hidden !important; - overflow-y: auto !important; -} - -.board-wrapper.mobile-view .board-canvas.mobile-view .swimlane { - border-bottom: 1px solid #ccc; - display: block !important; - flex-direction: column; - margin: 0; - padding: 0; - overflow-x: hidden !important; - overflow-y: auto; - width: 100vw !important; - max-width: 100vw !important; - min-width: 100vw !important; -} @media screen and (max-width: 800px), screen and (max-device-width: 932px) and (-webkit-min-device-pixel-ratio: 3) { - .board-wrapper { - width: 100vw !important; - max-width: 100vw !important; - min-width: 100vw !important; - left: 0 !important; - right: 0 !important; - overflow-x: hidden !important; - overflow-y: auto !important; - } - .board-wrapper .board-canvas { - width: 100vw !important; - max-width: 100vw !important; - min-width: 100vw !important; - left: 0 !important; - right: 0 !important; - overflow-x: hidden !important; - overflow-y: auto !important; - } - - .board-wrapper .board-canvas .swimlane { - border-bottom: 1px solid #ccc; - display: block !important; - flex-direction: column; - margin: 0; - padding: 0; - overflow-x: hidden !important; - overflow-y: auto; - width: 100vw !important; - max-width: 100vw !important; - min-width: 100vw !important; +.board-wrapper .board-canvas .swimlane { + /* this effectively prevents board + to shrink */ + min-width: 100vw; } } .calendar-event-green { @@ -545,7 +278,6 @@ body.desktop-mode .board-wrapper .board-canvas .board-overlay { justify-content: center; align-items: center; margin: 0; - font-size: 18px; } .modal-footer { display: flex; @@ -558,10 +290,6 @@ body.desktop-mode .board-wrapper .board-canvas .board-overlay { display: flex; justify-content: center; align-items: center; - position: absolute; - top: 5px; - right: 5px; - font-size: 25px; cursor: pointer; } diff --git a/client/components/boards/boardBody.jade b/client/components/boards/boardBody.jade index 4af638f08..f965a55a3 100644 --- a/client/components/boards/boardBody.jade +++ b/client/components/boards/boardBody.jade @@ -1,13 +1,9 @@ template(name="board") - if isConverting.get +boardConversionProgress else if isBoardReady.get if currentBoard - if onlyShowCurrentCard - +cardDetails(currentCard) - else - +boardBody + +boardBody else //-- XXX We need a better error message in case the board has been archived +message(label="board-not-found") @@ -17,32 +13,32 @@ template(name="board") template(name="boardBody") if notDisplayThisBoard - | {{_ 'tableVisibilityMode-allowPrivateOnly'}} + | {{_ 'tableVisibilityMode-allowPrivateOnly'}} else - // Debug information (remove in production) + //- Debug information (remove in production) if debugBoardState + //- Debug information (remove in production) .debug-info(style="position: fixed; top: 0; left: 0; background: rgba(0,0,0,0.8); color: white; padding: 10px; z-index: 9999; font-size: 12px;") | {{_ 'board'}}: {{currentBoard.title}} | {{_ 'view'}}: {{boardView}} | {{_ 'has-swimlanes'}}: {{hasSwimlanes}} | {{_ 'swimlanes'}}: {{currentBoard.swimlanes.length}} .board-wrapper(class=currentBoard.colorClass class="{{#if isMiniScreen}}mobile-view{{/if}}") .board-canvas.js-swimlanes( class="{{#if hasSwimlanes}}dragscroll{{/if}}" - class="{{#if Sidebar.isOpen}}is-sibling-sidebar-open{{/if}}" class="{{#if MultiSelection.isActive}}is-multiselection-active{{/if}}" class="{{#if draggingActive.get}}is-dragging-active{{/if}}" class="{{#unless isVerticalScrollbars}}no-scrollbars{{/unless}}" class="{{#if isMiniScreen}}mobile-view{{/if}}") - if showOverlay.get - .board-overlay if currentBoard.isTemplatesBoard - each currentBoard.swimlanes - +swimlane(this) - else if isViewSwimlanes - if hasSwimlanes + .swim-flex each currentBoard.swimlanes +swimlane(this) - else - // Fallback: If no swimlanes exist, show lists instead of empty message - +listsGroup(currentBoard) + else if isViewSwimlanes + .swim-flex + if hasSwimlanes + each currentBoard.swimlanes + +swimlane(this) + else + // Fallback: If no swimlanes exist, show lists instead of empty message + +listsGroup(currentBoard) else if isViewLists +listsGroup(currentBoard) else if isViewCalendar @@ -56,10 +52,6 @@ template(name="boardBody") +swimlane(this) else +listsGroup(currentBoard) - //- Render multiple open cards in desktop mode - unless isMiniScreen - each openCards - +cardDetails(this cardIndex=@index) +sidebar template(name="calendarView") diff --git a/client/components/boards/boardBody.js b/client/components/boards/boardBody.js index a5d6b9760..c5144f5f5 100644 --- a/client/components/boards/boardBody.js +++ b/client/components/boards/boardBody.js @@ -27,16 +27,16 @@ BlazeComponent.extendComponent({ this.autorun(() => { const currentBoardId = Session.get('currentBoard'); if (!currentBoardId) return; - + const handle = subManager.subscribe('board', currentBoardId, false); - + // Use a separate autorun for subscription ready state to avoid reactive loops this.subscriptionReadyAutorun = Tracker.autorun(() => { if (handle.ready()) { if (!this._boardProcessed || this._lastProcessedBoardId !== currentBoardId) { this._boardProcessed = true; this._lastProcessedBoardId = currentBoardId; - + // Ensure default swimlane exists (only once per board) this.ensureDefaultSwimlane(currentBoardId); // Check if board needs conversion @@ -67,7 +67,7 @@ BlazeComponent.extendComponent({ if (!board) return; const swimlanes = board.swimlanes(); - + if (swimlanes.length === 0) { // Check if any swimlane exists in the database to avoid race conditions const existingSwimlanes = ReactiveCache.getSwimlanes({ boardId }); @@ -105,7 +105,6 @@ BlazeComponent.extendComponent({ this.isBoardReady.set(true); // Show board even if conversion check failed } }, - onlyShowCurrentCard() { const isMiniScreen = Utils.isMiniScreen(); const currentCardId = Utils.getCurrentCardId(true); @@ -114,7 +113,7 @@ BlazeComponent.extendComponent({ openCards() { // In desktop mode, return array of all open cards - const isMobile = Utils.getMobileMode(); + const isMobile = Utils.isMiniScreen(); if (!isMobile) { const openCardIds = Session.get('openCards') || []; return openCardIds.map(id => ReactiveCache.getCard(id)).filter(card => card); @@ -123,7 +122,7 @@ BlazeComponent.extendComponent({ }, goHome() { - FlowRouter.go('home'); + FlowRouter.go('home') }, isConverting() { @@ -195,7 +194,7 @@ BlazeComponent.extendComponent({ } }, onRendered() { - // Initialize user settings (zoom and mobile mode) + // Initialize user settings (mobile mode) Utils.initializeUserSettings(); // Detect iPhone devices and add class for better CSS targeting @@ -221,9 +220,9 @@ BlazeComponent.extendComponent({ const popupObserver = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { mutation.addedNodes.forEach(function(node) { - if (node.nodeType === 1 && + if (node.nodeType === 1 && (node.classList.contains('popup') || node.classList.contains('modal') || node.classList.contains('menu')) && - !node.closest('.js-swimlanes') && + !node.closest('.js-swimlanes') && !node.closest('.swimlane') && !node.closest('.list') && !node.closest('.minicard')) { @@ -391,23 +390,24 @@ BlazeComponent.extendComponent({ helper(evt, item) { const helper = $(`
`); + max-height: 30vh; + width: 100vw; + overflow: hidden; z-index: 100;"/>`); helper.append(item.clone()); // Also grab the list of lists of cards const list = item.next(); helper.append(list.clone()); return helper; }, - items: '.swimlane:not(.placeholder)', + items: '.swimlane-container', placeholder: 'swimlane placeholder', distance: 7, start(evt, ui) { const listDom = ui.placeholder.next('.js-swimlane'); const parentOffset = ui.item.parent().offset(); - ui.placeholder.height(ui.helper.height()); + height = ui.helper.height(); + ui.placeholder[0].setAttribute('style', `height: ${height}px !important;`); EscapeActions.executeUpTo('popup-close'); listDom.addClass('moving-swimlane'); boardComponent.setIsDragging(true); @@ -415,40 +415,19 @@ BlazeComponent.extendComponent({ ui.placeholder.insertAfter(ui.placeholder.next()); boardComponent.origPlaceholderIndex = ui.placeholder.index(); - // resize all swimlanes + headers to be a total of 150 px per row - // this could be achieved by setIsDragging(true) but we want immediate - // result - ui.item - .siblings('.js-swimlane') - .css('height', `${swimlaneWhileSortingHeight - 26}px`); - - // set the new scroll height after the resize and insertion of - // the placeholder. We want the element under the cursor to stay - // at the same place on the screen - ui.item.parent().get(0).scrollTop = - ui.placeholder.get(0).offsetTop + parentOffset.top - evt.pageY; }, beforeStop(evt, ui) { - const parentOffset = ui.item.parent().offset(); const siblings = ui.item.siblings('.js-swimlane'); siblings.css('height', ''); - // compute the new scroll height after the resize and removal of - // the placeholder - const scrollTop = - ui.placeholder.get(0).offsetTop + parentOffset.top - evt.pageY; - // then reset the original view of the swimlane siblings.removeClass('moving-swimlane'); - - // and apply the computed scrollheight - ui.item.parent().get(0).scrollTop = scrollTop; }, stop(evt, ui) { // To attribute the new index number, we need to get the DOM element // of the previous and the following card -- if any. - const prevSwimlaneDom = ui.item.prevAll('.js-swimlane').get(0); - const nextSwimlaneDom = ui.item.nextAll('.js-swimlane').get(0); + const prevSwimlaneDom = ui.item.prevAll('.swimlane-container').get(0); + const nextSwimlaneDom = ui.item.nextAll('.swimlane-container').get(0); const sortIndex = calculateIndex(prevSwimlaneDom, nextSwimlaneDom, 1); $swimlanesDom.sortable('cancel'); @@ -464,39 +443,7 @@ BlazeComponent.extendComponent({ boardComponent.setIsDragging(false); }, sort(evt, ui) { - // get the mouse position in the sortable - const parentOffset = ui.item.parent().offset(); - const cursorY = - evt.pageY - parentOffset.top + ui.item.parent().scrollTop(); - - // compute the intended index of the placeholder (we need to skip the - // slots between the headers and the list of cards) - const newplaceholderIndex = Math.floor( - cursorY / swimlaneWhileSortingHeight, - ); - let destPlaceholderIndex = (newplaceholderIndex + 1) * 2; - - // if we are scrolling far away from the bottom of the list - if (destPlaceholderIndex >= ui.item.parent().get(0).childElementCount) { - destPlaceholderIndex = ui.item.parent().get(0).childElementCount - 1; - } - - // update the placeholder position in the DOM tree - if (destPlaceholderIndex !== ui.placeholder.index()) { - if (destPlaceholderIndex < boardComponent.origPlaceholderIndex) { - ui.placeholder.insertBefore( - ui.placeholder - .siblings() - .slice(destPlaceholderIndex - 2, destPlaceholderIndex - 1), - ); - } else { - ui.placeholder.insertAfter( - ui.placeholder - .siblings() - .slice(destPlaceholderIndex - 1, destPlaceholderIndex), - ); - } - } + Utils.scrollIfNeeded(evt); }, }); @@ -505,10 +452,10 @@ BlazeComponent.extendComponent({ dragscroll.reset(); if ($swimlanesDom.data('uiSortable') || $swimlanesDom.data('sortable')) { - if (Utils.isTouchScreenOrShowDesktopDragHandles()) { + if (Utils.isMiniScreen()) { $swimlanesDom.sortable('option', 'handle', '.js-swimlane-header-handle'); } else { - $swimlanesDom.sortable('option', 'handle', '.swimlane-header'); + $swimlanesDom.sortable('option', 'handle', '.swimlane-header-wrap'); } // Disable drag-dropping if the current user is not a board member @@ -540,57 +487,57 @@ BlazeComponent.extendComponent({ isViewSwimlanes() { const currentUser = ReactiveCache.getCurrentUser(); let boardView; - + if (currentUser) { boardView = (currentUser.profile || {}).boardView; } else { boardView = window.localStorage.getItem('boardView'); } - + // If no board view is set, default to swimlanes if (!boardView) { boardView = 'board-view-swimlanes'; } - + return boardView === 'board-view-swimlanes'; }, isViewLists() { const currentUser = ReactiveCache.getCurrentUser(); let boardView; - + if (currentUser) { boardView = (currentUser.profile || {}).boardView; } else { boardView = window.localStorage.getItem('boardView'); } - + return boardView === 'board-view-lists'; }, isViewCalendar() { const currentUser = ReactiveCache.getCurrentUser(); let boardView; - + if (currentUser) { boardView = (currentUser.profile || {}).boardView; } else { boardView = window.localStorage.getItem('boardView'); } - + return boardView === 'board-view-cal'; }, isViewGantt() { const currentUser = ReactiveCache.getCurrentUser(); let boardView; - + if (currentUser) { boardView = (currentUser.profile || {}).boardView; } else { boardView = window.localStorage.getItem('boardView'); } - + return boardView === 'board-view-gantt'; }, @@ -602,7 +549,7 @@ BlazeComponent.extendComponent({ } return false; } - + try { const swimlanes = currentBoard.swimlanes(); const hasSwimlanes = swimlanes && swimlanes.length > 0; @@ -638,7 +585,7 @@ BlazeComponent.extendComponent({ const isBoardReady = this.isBoardReady.get(); const isConverting = this.isConverting.get(); const boardView = Utils.boardView(); - + if (process.env.DEBUG === 'true') { console.log('=== BOARD DEBUG STATE ==='); console.log('currentBoardId:', currentBoardId); @@ -648,7 +595,7 @@ BlazeComponent.extendComponent({ console.log('boardView:', boardView); console.log('========================'); } - + return { currentBoardId, hasCurrentBoard: !!currentBoard, @@ -1025,4 +972,3 @@ BlazeComponent.extendComponent({ * Gantt View Component * Displays cards as a Gantt chart with start/due dates */ - diff --git a/client/components/boards/boardColors.css b/client/components/boards/boardColors.css index 641f85ad7..c8aa230ff 100644 --- a/client/components/boards/boardColors.css +++ b/client/components/boards/boardColors.css @@ -8,43 +8,52 @@ THEME - NEPHRITIS .board-list .board-color-nephritis a { background-color: #27ae60; } + .board-color-nephritis .is-selected .minicard { border-left: 3px solid #27ae60; } + .board-color-nephritis .minicard { - border-radius: 7px; - padding: 10px 10px 4px 10px; - box-shadow: 2px 2px 4px 0px rgba(0,0,0,0.15); + border-radius: 0.6ch; + box-shadow: 2px 2px 4px 0px rgba(0, 0, 0, 0.15); } + .board-color-nephritis button[type=submit].primary, .board-color-nephritis input[type=submit].primary, .board-color-nephritis .sidebar .sidebar-content .sidebar-btn { background-color: #1f8b4d; - border-radius: 7px; + border-radius: 0.6ch; } + .board-color-nephritis.pop-over .pop-over-list li a:not(.disabled):hover, .board-color-nephritis .sidebar .sidebar-content .sidebar-btn:hover, .board-color-nephritis .sidebar-list li a:hover { background-color: #2cc66d; } + .board-color-nephritis#header ul li.current, .board-color-nephritis#header-quick-access ul li.current { border-bottom: 2px solid #2cc66d; } + .board-color-nephritis#header-quick-access { background: #239d56; color: #fff; } + .board-color-nephritis#header #header-main-bar .board-header-btn.emphasis { background: #ae2775; } + .board-color-nephritis#header #header-main-bar .board-header-btn.emphasis:hover, .board-color-nephritis#header #header-main-bar .board-header-btn.emphasis .board-header-btn-close { background: #9d2369; } + .board-color-nephritis#header #header-main-bar .board-header-btn.emphasis:hover .board-header-btn-close { background: #8b1f5e; } + .board-color-nephritis .materialCheckBox.is-checked { border-bottom: 2px solid #27ae60; border-right: 2px solid #27ae60; @@ -58,24 +67,30 @@ THEME - NEPHRITIS .board-color-nephritis .is-multiselection-active .multi-selection-checkbox.is-checked + .minicard { background: #e7faef; } -.board-color-nephritis .is-multiselection-active .multi-selection-checkbox:not(.is-checked) + .minicard:hover:not(.minicard-composer) { + +.board-color-nephritis .is-multiselection-active .multi-selection-checkbox:not(.is-checked)+.minicard:hover:not(.minicard-composer) { background: #f8fdfa; } + .board-color-nephritis .toggle-label:after { background-color: #1f8b4d; } -.board-color-nephritis .toggle-switch:checked ~ .toggle-label { + +.board-color-nephritis .toggle-switch:checked~.toggle-label { background-color: #3dd37c; } -.board-color-nephritis .toggle-switch:checked ~ .toggle-label:after { + +.board-color-nephritis .toggle-switch:checked~.toggle-label:after { background-color: #1f8b4d; } + @media screen and (max-width: 800px) { .board-color-nephritis.pop-over .header { background: #27ae60; color: #fff; } } + .board-color-nephritis#header ul li.current, .board-color-nephritis#header-quick-access ul li.current { border-bottom: 4px solid #3dd37c; @@ -96,12 +111,9 @@ THEME - NEPHRITIS .board-color-nephritis .list { border-left: none; - padding-bottom: 8px; } -.board-color-nephritis .list-body { - margin-top: 8px; -} + /* === END NEPHRITIS THEME === */ @@ -115,43 +127,52 @@ THEME - Pomegranate .board-list .board-color-pomegranate a { background-color: #c0392b; } + .board-color-pomegranate .is-selected .minicard { border-left: 3px solid #c0392b; } + .board-color-pomegranate .minicard { - border-radius: 7px; - padding: 10px 10px 4px 10px; - box-shadow: 2px 2px 4px 0px rgba(0,0,0,0.15); + border-radius: 0.6ch; + box-shadow: 2px 2px 4px 0px rgba(0, 0, 0, 0.15); } + .board-color-pomegranate button[type=submit].primary, .board-color-pomegranate input[type=submit].primary, .board-color-pomegranate .sidebar .sidebar-content .sidebar-btn { background-color: #9a2e22; - border-radius: 7px; + border-radius: 0.6ch; } + .board-color-pomegranate.pop-over .pop-over-list li a:not(.disabled):hover, .board-color-pomegranate .sidebar .sidebar-content .sidebar-btn:hover, .board-color-pomegranate .sidebar-list li a:hover { background-color: #d24435; } + .board-color-pomegranate#header ul li.current, .board-color-pomegranate#header-quick-access ul li.current { border-bottom: 2px solid #d24435; } + .board-color-pomegranate#header-quick-access { background: #ad3327; color: #fff; } + .board-color-pomegranate#header #header-main-bar .board-header-btn.emphasis { background: #2bb2c0; } + .board-color-pomegranate#header #header-main-bar .board-header-btn.emphasis:hover, .board-color-pomegranate#header #header-main-bar .board-header-btn.emphasis .board-header-btn-close { background: #27a0ad; } + .board-color-pomegranate#header #header-main-bar .board-header-btn.emphasis:hover .board-header-btn-close { background: #228e9a; } + .board-color-pomegranate .materialCheckBox.is-checked { border-bottom: 2px solid #c0392b; border-right: 2px solid #c0392b; @@ -165,24 +186,30 @@ THEME - Pomegranate .board-color-pomegranate .is-multiselection-active .multi-selection-checkbox.is-checked + .minicard { background: #faeae9; } -.board-color-pomegranate .is-multiselection-active .multi-selection-checkbox:not(.is-checked) + .minicard:hover:not(.minicard-composer) { + +.board-color-pomegranate .is-multiselection-active .multi-selection-checkbox:not(.is-checked)+.minicard:hover:not(.minicard-composer) { background: #fdf9f8; } + .board-color-pomegranate .toggle-label:after { background-color: #9a2e22; } -.board-color-pomegranate .toggle-switch:checked ~ .toggle-label { + +.board-color-pomegranate .toggle-switch:checked~.toggle-label { background-color: #d7584b; } -.board-color-pomegranate .toggle-switch:checked ~ .toggle-label:after { + +.board-color-pomegranate .toggle-switch:checked~.toggle-label:after { background-color: #9a2e22; } + @media screen and (max-width: 800px) { .board-color-pomegranate.pop-over .header { background: #c0392b; color: #fff; } } + .board-color-pomegranate#header ul li.current, .board-color-pomegranate#header-quick-access ul li.current { border-bottom: 4px solid #d7584b; @@ -203,12 +230,9 @@ THEME - Pomegranate .board-color-pomegranate .list { border-left: none; - padding-bottom: 8px; } -.board-color-pomegranate .list-body { - margin-top: 8px; -} + /* === END Pomegranate THEME === */ @@ -222,43 +246,53 @@ THEME - Belize .board-list .board-color-belize a { background-color: #2980b9; } + .board-color-belize .is-selected .minicard { border-left: 3px solid #2980b9; } + .board-color-belize .minicard { - border-radius: 7px; - padding: 10px 10px 4px 10px; - box-shadow: 2px 2px 4px 0px rgba(0,0,0,0.15); + border-radius: 0.6ch; + box-shadow: 2px 2px 4px 0px rgba(0, 0, 0, 0.15); } + .board-color-belize button[type=submit].primary, .board-color-belize input[type=submit].primary, .board-color-belize .sidebar .sidebar-content .sidebar-btn { background-color: #216694; - border-radius: 7px; + border-radius: 0.6ch; + color: #eee; } + .board-color-belize.pop-over .pop-over-list li a:not(.disabled):hover, .board-color-belize .sidebar .sidebar-content .sidebar-btn:hover, .board-color-belize .sidebar-list li a:hover { background-color: #2e90d0; } + .board-color-belize#header ul li.current, .board-color-belize#header-quick-access ul li.current { border-bottom: 2px solid #2e90d0; } + .board-color-belize#header-quick-access { background: #2573a7; color: #fff; } + .board-color-belize#header #header-main-bar .board-header-btn.emphasis { background: #b96229; } + .board-color-belize#header #header-main-bar .board-header-btn.emphasis:hover, .board-color-belize#header #header-main-bar .board-header-btn.emphasis .board-header-btn-close { background: #a75825; } + .board-color-belize#header #header-main-bar .board-header-btn.emphasis:hover .board-header-btn-close { background: #944e21; } + .board-color-belize .materialCheckBox.is-checked { border-bottom: 2px solid #2980b9; border-right: 2px solid #2980b9; @@ -272,24 +306,30 @@ THEME - Belize .board-color-belize .is-multiselection-active .multi-selection-checkbox.is-checked + .minicard { background: #e8f3fa; } -.board-color-belize .is-multiselection-active .multi-selection-checkbox:not(.is-checked) + .minicard:hover:not(.minicard-composer) { + +.board-color-belize .is-multiselection-active .multi-selection-checkbox:not(.is-checked)+.minicard:hover:not(.minicard-composer) { background: #f8fbfd; } + .board-color-belize .toggle-label:after { background-color: #216694; } -.board-color-belize .toggle-switch:checked ~ .toggle-label { + +.board-color-belize .toggle-switch:checked~.toggle-label { background-color: #459cd6; } -.board-color-belize .toggle-switch:checked ~ .toggle-label:after { + +.board-color-belize .toggle-switch:checked~.toggle-label:after { background-color: #216694; } + @media screen and (max-width: 800px) { .board-color-belize.pop-over .header { background: #2980b9; color: #fff; } } + .board-color-belize#header ul li.current, .board-color-belize#header-quick-access ul li.current { border-bottom: 4px solid #459cd6; @@ -310,11 +350,6 @@ THEME - Belize .board-color-belize .list { border-left: none; - padding-bottom: 8px; -} - -.board-color-belize .list-body { - margin-top: 8px; } /* === END Belize THEME === */ @@ -329,43 +364,52 @@ THEME - Wisteria .board-list .board-color-wisteria a { background-color: #8e44ad; } + .board-color-wisteria .is-selected .minicard { border-left: 3px solid #8e44ad; } + .board-color-wisteria .minicard { - border-radius: 7px; - padding: 10px 10px 4px 10px; - box-shadow: 2px 2px 4px 0px rgba(0,0,0,0.15); + border-radius: 0.6ch; + box-shadow: 2px 2px 4px 0px rgba(0, 0, 0, 0.15); } + .board-color-wisteria button[type=submit].primary, .board-color-wisteria input[type=submit].primary, .board-color-wisteria .sidebar .sidebar-content .sidebar-btn { background-color: #72368a; - border-radius: 7px; + border-radius: 0.6ch; } + .board-color-wisteria.pop-over .pop-over-list li a:not(.disabled):hover, .board-color-wisteria .sidebar .sidebar-content .sidebar-btn:hover, .board-color-wisteria .sidebar-list li a:hover { background-color: #9c51bb; } + .board-color-wisteria#header ul li.current, .board-color-wisteria#header-quick-access ul li.current { border-bottom: 2px solid #9c51bb; } + .board-color-wisteria#header-quick-access { background: #803d9c; color: #fff; } + .board-color-wisteria#header #header-main-bar .board-header-btn.emphasis { background: #63ad44; } + .board-color-wisteria#header #header-main-bar .board-header-btn.emphasis:hover, .board-color-wisteria#header #header-main-bar .board-header-btn.emphasis .board-header-btn-close { background: #599c3d; } + .board-color-wisteria#header #header-main-bar .board-header-btn.emphasis:hover .board-header-btn-close { background: #4f8a36; } + .board-color-wisteria .materialCheckBox.is-checked { border-bottom: 2px solid #8e44ad; border-right: 2px solid #8e44ad; @@ -379,24 +423,30 @@ THEME - Wisteria .board-color-wisteria .is-multiselection-active .multi-selection-checkbox.is-checked + .minicard { background: #f4ecf7; } -.board-color-wisteria .is-multiselection-active .multi-selection-checkbox:not(.is-checked) + .minicard:hover:not(.minicard-composer) { + +.board-color-wisteria .is-multiselection-active .multi-selection-checkbox:not(.is-checked)+.minicard:hover:not(.minicard-composer) { background: #fcf9fd; } + .board-color-wisteria .toggle-label:after { background-color: #72368a; } -.board-color-wisteria .toggle-switch:checked ~ .toggle-label { + +.board-color-wisteria .toggle-switch:checked~.toggle-label { background-color: #a765c2; } -.board-color-wisteria .toggle-switch:checked ~ .toggle-label:after { + +.board-color-wisteria .toggle-switch:checked~.toggle-label:after { background-color: #72368a; } + @media screen and (max-width: 800px) { .board-color-wisteria.pop-over .header { background: #8e44ad; color: #fff; } } + .board-color-wisteria#header ul li.current, .board-color-wisteria#header-quick-access ul li.current { border-bottom: 4px solid #a765c2; @@ -417,12 +467,9 @@ THEME - Wisteria .board-color-wisteria .list { border-left: none; - padding-bottom: 8px; } -.board-color-wisteria .list-body { - margin-top: 8px; -} + /* === END Wisteria THEME === */ @@ -436,43 +483,52 @@ THEME - Midnight .board-list .board-color-midnight a { background-color: #2c3e50; } + .board-color-midnight .is-selected .minicard { border-left: 3px solid #2c3e50; } + .board-color-midnight .minicard { - border-radius: 7px; - padding: 10px 10px 4px 10px; - box-shadow: 2px 2px 4px 0px rgba(0,0,0,0.15); + border-radius: 0.6ch; + box-shadow: 2px 2px 4px 0px rgba(0, 0, 0, 0.15); } + .board-color-midnight button[type=submit].primary, .board-color-midnight input[type=submit].primary, .board-color-midnight .sidebar .sidebar-content .sidebar-btn { background-color: #233240; - border-radius: 7px; + border-radius: 0.6ch; } + .board-color-midnight.pop-over .pop-over-list li a:not(.disabled):hover, .board-color-midnight .sidebar .sidebar-content .sidebar-btn:hover, .board-color-midnight .sidebar-list li a:hover { background-color: #3a5169; } + .board-color-midnight#header ul li.current, .board-color-midnight#header-quick-access ul li.current { border-bottom: 2px solid #3a5169; } + .board-color-midnight#header-quick-access { background: #283848; color: #fff; } + .board-color-midnight#header #header-main-bar .board-header-btn.emphasis { background: #503e2c; } + .board-color-midnight#header #header-main-bar .board-header-btn.emphasis:hover, .board-color-midnight#header #header-main-bar .board-header-btn.emphasis .board-header-btn-close { background: #483828; } + .board-color-midnight#header #header-main-bar .board-header-btn.emphasis:hover .board-header-btn-close { background: #403223; } + .board-color-midnight .materialCheckBox.is-checked { border-bottom: 2px solid #2c3e50; border-right: 2px solid #2c3e50; @@ -486,24 +542,30 @@ THEME - Midnight .board-color-midnight .is-multiselection-active .multi-selection-checkbox.is-checked + .minicard { background: #e6ecf1; } -.board-color-midnight .is-multiselection-active .multi-selection-checkbox:not(.is-checked) + .minicard:hover:not(.minicard-composer) { + +.board-color-midnight .is-multiselection-active .multi-selection-checkbox:not(.is-checked)+.minicard:hover:not(.minicard-composer) { background: #f8f9fb; } + .board-color-midnight .toggle-label:after { background-color: #233240; } -.board-color-midnight .toggle-switch:checked ~ .toggle-label { + +.board-color-midnight .toggle-switch:checked~.toggle-label { background-color: #476582; } -.board-color-midnight .toggle-switch:checked ~ .toggle-label:after { + +.board-color-midnight .toggle-switch:checked~.toggle-label:after { background-color: #233240; } + @media screen and (max-width: 800px) { .board-color-midnight.pop-over .header { background: #2c3e50; color: #fff; } } + .board-color-midnight#header ul li.current, .board-color-midnight#header-quick-access ul li.current { border-bottom: 4px solid #476582; @@ -524,12 +586,9 @@ THEME - Midnight .board-color-midnight .list { border-left: none; - padding-bottom: 8px; } -.board-color-midnight .list-body { - margin-top: 8px; -} + /* === END Midnight THEME === */ @@ -543,43 +602,52 @@ THEME - Pumpkin .board-list .board-color-pumpkin a { background-color: #e67e22; } + .board-color-pumpkin .is-selected .minicard { border-left: 3px solid #e67e22; } + .board-color-pumpkin .minicard { - border-radius: 7px; - padding: 10px 10px 4px 10px; - box-shadow: 2px 2px 4px 0px rgba(0,0,0,0.15); + border-radius: 0.6ch; + box-shadow: 2px 2px 4px 0px rgba(0, 0, 0, 0.15); } + .board-color-pumpkin button[type=submit].primary, .board-color-pumpkin input[type=submit].primary, .board-color-pumpkin .sidebar .sidebar-content .sidebar-btn { background-color: #be6415; - border-radius: 7px; + border-radius: 0.6ch; } + .board-color-pumpkin.pop-over .pop-over-list li a:not(.disabled):hover, .board-color-pumpkin .sidebar .sidebar-content .sidebar-btn:hover, .board-color-pumpkin .sidebar-list li a:hover { background-color: #e98b38; } + .board-color-pumpkin#header ul li.current, .board-color-pumpkin#header-quick-access ul li.current { border-bottom: 2px solid #e98b38; } + .board-color-pumpkin#header-quick-access { background: #d57118; color: #fff; } + .board-color-pumpkin#header #header-main-bar .board-header-btn.emphasis { background: #228ae6; } + .board-color-pumpkin#header #header-main-bar .board-header-btn.emphasis:hover, .board-color-pumpkin#header #header-main-bar .board-header-btn.emphasis .board-header-btn-close { background: #187dd5; } + .board-color-pumpkin#header #header-main-bar .board-header-btn.emphasis:hover .board-header-btn-close { background: #156fbe; } + .board-color-pumpkin .materialCheckBox.is-checked { border-bottom: 2px solid #e67e22; border-right: 2px solid #e67e22; @@ -593,24 +661,30 @@ THEME - Pumpkin .board-color-pumpkin .is-multiselection-active .multi-selection-checkbox.is-checked + .minicard { background: #fdf2e9; } -.board-color-pumpkin .is-multiselection-active .multi-selection-checkbox:not(.is-checked) + .minicard:hover:not(.minicard-composer) { + +.board-color-pumpkin .is-multiselection-active .multi-selection-checkbox:not(.is-checked)+.minicard:hover:not(.minicard-composer) { background: #fefbf8; } + .board-color-pumpkin .toggle-label:after { background-color: #be6415; } -.board-color-pumpkin .toggle-switch:checked ~ .toggle-label { + +.board-color-pumpkin .toggle-switch:checked~.toggle-label { background-color: #eb984e; } -.board-color-pumpkin .toggle-switch:checked ~ .toggle-label:after { + +.board-color-pumpkin .toggle-switch:checked~.toggle-label:after { background-color: #be6415; } + @media screen and (max-width: 800px) { .board-color-pumpkin.pop-over .header { background: #e67e22; color: #fff; } } + .board-color-pumpkin#header ul li.current, .board-color-pumpkin#header-quick-access ul li.current { border-bottom: 4px solid #eb984e; @@ -631,12 +705,9 @@ THEME - Pumpkin .board-color-pumpkin .list { border-left: none; - padding-bottom: 8px; } -.board-color-pumpkin .list-body { - margin-top: 8px; -} + /* === END Pumpkin THEME === */ @@ -650,43 +721,52 @@ THEME - Moderate Pink .board-list .board-color-moderatepink a { background-color: #cd5a91; } + .board-color-moderatepink .is-selected .minicard { border-left: 3px solid #cd5a91; } + .board-color-moderatepink .minicard { - border-radius: 7px; - padding: 10px 10px 4px 10px; - box-shadow: 2px 2px 4px 0px rgba(0,0,0,0.15); + border-radius: 0.6ch; + box-shadow: 2px 2px 4px 0px rgba(0, 0, 0, 0.15); } + .board-color-moderatepink button[type=submit].primary, .board-color-moderatepink input[type=submit].primary, .board-color-moderatepink .sidebar .sidebar-content .sidebar-btn { background-color: #b53773; - border-radius: 7px; + border-radius: 0.6ch; } + .board-color-moderatepink.pop-over .pop-over-list li a:not(.disabled):hover, .board-color-moderatepink .sidebar .sidebar-content .sidebar-btn:hover, .board-color-moderatepink .sidebar-list li a:hover { background-color: #d26b9c; } + .board-color-moderatepink#header ul li.current, .board-color-moderatepink#header-quick-access ul li.current { border-bottom: 2px solid #d26b9c; } + .board-color-moderatepink#header-quick-access { background: #c64382; color: #fff; } + .board-color-moderatepink#header #header-main-bar .board-header-btn.emphasis { background: #5acd96; } + .board-color-moderatepink#header #header-main-bar .board-header-btn.emphasis:hover, .board-color-moderatepink#header #header-main-bar .board-header-btn.emphasis .board-header-btn-close { background: #43c688; } + .board-color-moderatepink#header #header-main-bar .board-header-btn.emphasis:hover .board-header-btn-close { background: #37b579; } + .board-color-moderatepink .materialCheckBox.is-checked { border-bottom: 2px solid #cd5a91; border-right: 2px solid #cd5a91; @@ -700,24 +780,30 @@ THEME - Moderate Pink .board-color-moderatepink .is-multiselection-active .multi-selection-checkbox.is-checked + .minicard { background: #faeef4; } -.board-color-moderatepink .is-multiselection-active .multi-selection-checkbox:not(.is-checked) + .minicard:hover:not(.minicard-composer) { + +.board-color-moderatepink .is-multiselection-active .multi-selection-checkbox:not(.is-checked)+.minicard:hover:not(.minicard-composer) { background: #fefafc; } + .board-color-moderatepink .toggle-label:after { background-color: #b53773; } -.board-color-moderatepink .toggle-switch:checked ~ .toggle-label { + +.board-color-moderatepink .toggle-switch:checked~.toggle-label { background-color: #d77ba7; } -.board-color-moderatepink .toggle-switch:checked ~ .toggle-label:after { + +.board-color-moderatepink .toggle-switch:checked~.toggle-label:after { background-color: #b53773; } + @media screen and (max-width: 800px) { .board-color-moderatepink.pop-over .header { background: #cd5a91; color: #fff; } } + .board-color-moderatepink#header ul li.current, .board-color-moderatepink#header-quick-access ul li.current { border-bottom: 4px solid #d77ba7; @@ -738,12 +824,9 @@ THEME - Moderate Pink .board-color-moderatepink .list { border-left: none; - padding-bottom: 8px; } -.board-color-moderatepink .list-body { - margin-top: 8px; -} + /* === END Moderatepink THEME === */ @@ -757,43 +840,52 @@ THEME - Strong Cyan .board-list .board-color-strongcyan a { background-color: #00aecc; } + .board-color-strongcyan .is-selected .minicard { border-left: 3px solid #00aecc; } + .board-color-strongcyan .minicard { - border-radius: 7px; - padding: 10px 10px 4px 10px; - box-shadow: 2px 2px 4px 0px rgba(0,0,0,0.15); + border-radius: 0.6ch; + box-shadow: 2px 2px 4px 0px rgba(0, 0, 0, 0.15); } + .board-color-strongcyan button[type=submit].primary, .board-color-strongcyan input[type=submit].primary, .board-color-strongcyan .sidebar .sidebar-content .sidebar-btn { background-color: #008ba3; - border-radius: 7px; + border-radius: 0.6ch; } + .board-color-strongcyan.pop-over .pop-over-list li a:not(.disabled):hover, .board-color-strongcyan .sidebar .sidebar-content .sidebar-btn:hover, .board-color-strongcyan .sidebar-list li a:hover { background-color: #00c8eb; } + .board-color-strongcyan#header ul li.current, .board-color-strongcyan#header-quick-access ul li.current { border-bottom: 2px solid #00c8eb; } + .board-color-strongcyan#header-quick-access { background: #009db8; color: #fff; } + .board-color-strongcyan#header #header-main-bar .board-header-btn.emphasis { background: #cc1e00; } + .board-color-strongcyan#header #header-main-bar .board-header-btn.emphasis:hover, .board-color-strongcyan#header #header-main-bar .board-header-btn.emphasis .board-header-btn-close { background: #b81b00; } + .board-color-strongcyan#header #header-main-bar .board-header-btn.emphasis:hover .board-header-btn-close { background: #a31800; } + .board-color-strongcyan .materialCheckBox.is-checked { border-bottom: 2px solid #00aecc; border-right: 2px solid #00aecc; @@ -807,24 +899,30 @@ THEME - Strong Cyan .board-color-strongcyan .is-multiselection-active .multi-selection-checkbox.is-checked + .minicard { background: #e0fbff; } -.board-color-strongcyan .is-multiselection-active .multi-selection-checkbox:not(.is-checked) + .minicard:hover:not(.minicard-composer) { + +.board-color-strongcyan .is-multiselection-active .multi-selection-checkbox:not(.is-checked)+.minicard:hover:not(.minicard-composer) { background: #f6feff; } + .board-color-strongcyan .toggle-label:after { background-color: #008ba3; } -.board-color-strongcyan .toggle-switch:checked ~ .toggle-label { + +.board-color-strongcyan .toggle-switch:checked~.toggle-label { background-color: #0adbff; } -.board-color-strongcyan .toggle-switch:checked ~ .toggle-label:after { + +.board-color-strongcyan .toggle-switch:checked~.toggle-label:after { background-color: #008ba3; } + @media screen and (max-width: 800px) { .board-color-strongcyan.pop-over .header { background: #00aecc; color: #fff; } } + .board-color-strongcyan#header ul li.current, .board-color-strongcyan#header-quick-access ul li.current { border-bottom: 4px solid #0adbff; @@ -838,19 +936,16 @@ THEME - Strong Cyan /* Apply scrollbar to sidebar content*/ .board-color-strongcyan .sidebar .sidebar-content { - scrollbar-color: #00aeccf2 #e4e4e400; + scrollbar-color: #00aeccf2 #e4e4e400; } /* Remove margins in between columns/fix spacing */ .board-color-strongcyan .list { border-left: none; - padding-bottom: 8px; } -.board-color-strongcyan .list-body { - margin-top: 8px; -} + /* === END Strongcyan THEME === */ @@ -864,43 +959,52 @@ THEME - Lime Green .board-list .board-color-limegreen a { background-color: #4bbf6b; } + .board-color-limegreen .is-selected .minicard { border-left: 3px solid #4bbf6b; } + .board-color-limegreen .minicard { - border-radius: 7px; - padding: 10px 10px 4px 10px; - box-shadow: 2px 2px 4px 0px rgba(0,0,0,0.15); + border-radius: 0.6ch; + box-shadow: 2px 2px 4px 0px rgba(0, 0, 0, 0.15); } + .board-color-limegreen button[type=submit].primary, .board-color-limegreen input[type=submit].primary, .board-color-limegreen .sidebar .sidebar-content .sidebar-btn { background-color: #389d54; - border-radius: 7px; + border-radius: 0.6ch; } + .board-color-limegreen.pop-over .pop-over-list li a:not(.disabled):hover, .board-color-limegreen .sidebar .sidebar-content .sidebar-btn:hover, .board-color-limegreen .sidebar-list li a:hover { background-color: #5dc57a; } + .board-color-limegreen#header ul li.current, .board-color-limegreen#header-quick-access ul li.current { border-bottom: 2px solid #5dc57a; } + .board-color-limegreen#header-quick-access { background: #3fb15e; color: #fff; } + .board-color-limegreen#header #header-main-bar .board-header-btn.emphasis { background: #bf4b9f; } + .board-color-limegreen#header #header-main-bar .board-header-btn.emphasis:hover, .board-color-limegreen#header #header-main-bar .board-header-btn.emphasis .board-header-btn-close { background: #b13f91; } + .board-color-limegreen#header #header-main-bar .board-header-btn.emphasis:hover .board-header-btn-close { background: #9d3881; } + .board-color-limegreen .materialCheckBox.is-checked { border-bottom: 2px solid #4bbf6b; border-right: 2px solid #4bbf6b; @@ -914,24 +1018,30 @@ THEME - Lime Green .board-color-limegreen .is-multiselection-active .multi-selection-checkbox.is-checked + .minicard { background: #edf9f0; } -.board-color-limegreen .is-multiselection-active .multi-selection-checkbox:not(.is-checked) + .minicard:hover:not(.minicard-composer) { + +.board-color-limegreen .is-multiselection-active .multi-selection-checkbox:not(.is-checked)+.minicard:hover:not(.minicard-composer) { background: #fafdfb; } + .board-color-limegreen .toggle-label:after { background-color: #389d54; } -.board-color-limegreen .toggle-switch:checked ~ .toggle-label { + +.board-color-limegreen .toggle-switch:checked~.toggle-label { background-color: #6fcc89; } -.board-color-limegreen .toggle-switch:checked ~ .toggle-label:after { + +.board-color-limegreen .toggle-switch:checked~.toggle-label:after { background-color: #389d54; } + @media screen and (max-width: 800px) { .board-color-limegreen.pop-over .header { background: #4bbf6b; color: #fff; } } + .board-color-limegreen#header ul li.current, .board-color-limegreen#header-quick-access ul li.current { border-bottom: 4px solid #6fcc89; @@ -952,12 +1062,9 @@ THEME - Lime Green .board-color-limegreen .list { border-left: none; - padding-bottom: 8px; } -.board-color-limegreen .list-body { - margin-top: 8px; -} + /* === END Limegreen THEME === */ @@ -971,44 +1078,53 @@ THEME - Dark .board-list .board-color-dark a { background-color: #2c3e51; } + .board-color-dark .is-selected .minicard { border-left: 3px solid #2c3e51; } + .board-color-dark .minicard { - border-radius: 7px; - padding: 10px 10px 4px 10px; - box-shadow: 2px 2px 4px 0px rgba(0,0,0,0.15); + border-radius: 0.6ch; + box-shadow: 2px 2px 4px 0px rgba(0, 0, 0, 0.15); background-color: rgb(255 255 255 / 90%); } + .board-color-dark button[type=submit].primary, .board-color-dark input[type=submit].primary, .board-color-dark .sidebar .sidebar-content .sidebar-btn { background-color: #233241; - border-radius: 7px; + border-radius: 0.6ch; } + .board-color-dark.pop-over .pop-over-list li a:not(.disabled):hover, .board-color-dark .sidebar .sidebar-content .sidebar-btn:hover, .board-color-dark .sidebar-list li a:hover { background-color: #3a516a; } + .board-color-dark#header ul li.current, .board-color-dark#header-quick-access ul li.current { border-bottom: 2px solid #3a516a; } + .board-color-dark#header-quick-access { background: #283849; color: #fff; } + .board-color-dark#header #header-main-bar .board-header-btn.emphasis { background: #513f2c; } + .board-color-dark#header #header-main-bar .board-header-btn.emphasis:hover, .board-color-dark#header #header-main-bar .board-header-btn.emphasis .board-header-btn-close { background: #493928; } + .board-color-dark#header #header-main-bar .board-header-btn.emphasis:hover .board-header-btn-close { background: #413223; } + .board-color-dark .materialCheckBox.is-checked { border-bottom: 2px solid #2c3e51; border-right: 2px solid #2c3e51; @@ -1022,24 +1138,30 @@ THEME - Dark .board-color-dark .is-multiselection-active .multi-selection-checkbox.is-checked + .minicard { background: #e6ecf1; } -.board-color-dark .is-multiselection-active .multi-selection-checkbox:not(.is-checked) + .minicard:hover:not(.minicard-composer) { + +.board-color-dark .is-multiselection-active .multi-selection-checkbox:not(.is-checked)+.minicard:hover:not(.minicard-composer) { background: #f8f9fb; } + .board-color-dark .toggle-label:after { background-color: #233241; } -.board-color-dark .toggle-switch:checked ~ .toggle-label { + +.board-color-dark .toggle-switch:checked~.toggle-label { background-color: #476483; } -.board-color-dark .toggle-switch:checked ~ .toggle-label:after { + +.board-color-dark .toggle-switch:checked~.toggle-label:after { background-color: #233241; } + @media screen and (max-width: 800px) { .board-color-dark.pop-over .header { background: #2c3e51; color: #fff; } } + .board-color-dark#header ul li.current, .board-color-dark#header-quick-access ul li.current { border-bottom: 4px solid #476483; @@ -1047,13 +1169,13 @@ THEME - Dark /* Board Wrapper background fix for dark theme */ .board-color-dark.board-wrapper { - background-color: #2c3e50; + background-color: #2c3e50; } .board-color-dark .swimlane, -.board-color-dark .swimlane >.swimlane-header-wrap, -.board-color-dark .swimlane >.list.js-list, -.board-color-dark .swimlane >.list-composer.js-list-composer, +.board-color-dark .swimlane>.swimlane-header-wrap, +.board-color-dark .swimlane>.list.js-list, +.board-color-dark .swimlane>.list-composer.js-list-composer, .board-color-dark .list-body, .board-color-dark .list, .board-color-dark .list-composer, @@ -1061,6 +1183,7 @@ THEME - Dark .board-color-dark .card-details { background-color: #2c3e50; } + .board-color-dark .card-details h3, .board-color-dark .card-details-left p, .board-color-dark .card-details-items, @@ -1070,49 +1193,63 @@ THEME - Dark .board-color-dark .material-toggle-switch { color: #bbb; } + .board-color-dark .list-header { background-color: #888; } + .board-color-dark .board-widget, .board-color-dark .board-widget-labels, .board-color-dark .board-widget-members { color: #aaa; } -.board-color-dark .pop-over >.header { + +.board-color-dark .pop-over>.header { display: none; } + .board-color-dark #header-quick-access .fa-plus { display: none; } + .board-color-dark #header-quick-access:hover .fa-plus { display: inherit; } + .board-color-dark .open-minicard-composer { visibility: hidden; } + .board-color-dark .list.js-list:hover .open-minicard-composer { visibility: visible; } + .board-color-dark .list-header-menu { visibility: hidden; } + .board-color-dark .list.js-list:hover .list-header-menu { visibility: visible; } -.board-color-dark .list.js-list-composer >.list-header { + +.board-color-dark .list.js-list-composer>.list-header { visibility: hidden; } -.board-color-dark .list.js-list-composer:hover >.list-header { + +.board-color-dark .list.js-list-composer:hover>.list-header { visibility: visible; } + .board-color-dark #header-quick-access, .board-color-dark #header { - background-color: rgba(0,0,0,0.75) !important; + background-color: rgba(0, 0, 0, 0.75) !important; } + .board-color-dark #header .board-header-btn:hover { - background-color: rgba(255,255,255,0.3) !important; + background-color: rgba(255, 255, 255, 0.3) !important; } -.board-color-dark .list >.list-header, + +.board-color-dark .list>.list-header, /* Comment out, fixed white swimlane text not visible https://github.com/wekan/wekan/issues/4451 .board-color-dark .swimlane-header { color: rgba(255,255,255,0.7); @@ -1122,26 +1259,31 @@ THEME - Dark .board-color-dark .minicard:hover, .board-color-dark .minicard-composer.js-composer, .board-color-dark .open-minicard-composer:hover { - background-color: rgba(255,255,255,0.8) !important; + background-color: rgba(255, 255, 255, 0.8) !important; color: #000; - border-radius: 7px; + border-radius: 0.6ch; } + .board-color-dark .minicard:hover .badge, .board-color-dark .minicard-wrapper.is-selected .badge { color: #000; } + .board-color-dark .card-details .card-details-header { background-color: #ccc; } + .board-color-dark .sidebar-tongue, .board-color-dark .sidebar-shadow { background-color: #666 !important; } + .board-color-dark .sidebar-content h3, .board-color-dark .sidebar-content h2, .board-color-dark .sidebar-content { - color: rgba(255,255,255,0.7) !important; + color: rgba(255, 255, 255, 0.7) !important; } + .board-color-dark .card-details .activities .activity .activity-desc .activity-comment { background-color: #ccc; color: #222; @@ -1161,13 +1303,11 @@ THEME - Dark /* Remove margins in between columns/fix spacing */ .board-color-dark .list { - border-left: none; /* Remove this property to bring back lines in-between columns if needed*/ - padding: 0px 1px 8px 1px; /* Improves spacing between columns due to no borders, 8px padding at bottom to separate horizontal scrollbar/lists */ + border-left: none; + /* Remove this property to bring back lines in-between columns if needed*/ } -.board-color-dark .list-body { - margin-top: 8px; -} + /* === END Dark THEME === */ @@ -1181,43 +1321,52 @@ THEME - Relax .board-list .board-color-relax a { background-color: #27ae61; } + .board-color-relax .is-selected .minicard { border-left: 3px solid #27ae61; } + .board-color-relax .minicard { - border-radius: 7px; - padding: 10px 10px 4px 10px; - box-shadow: 2px 2px 4px 0px rgba(0,0,0,0.15); + border-radius: 0.6ch; + box-shadow: 2px 2px 4px 0px rgba(0, 0, 0, 0.15); } + .board-color-relax button[type=submit].primary, .board-color-relax input[type=submit].primary, .board-color-relax .sidebar .sidebar-content .sidebar-btn { background-color: #1f8b4e; - border-radius: 7px; + border-radius: 0.6ch; } + .board-color-relax.pop-over .pop-over-list li a:not(.disabled):hover, .board-color-relax .sidebar .sidebar-content .sidebar-btn:hover, .board-color-relax .sidebar-list li a:hover { background-color: #2cc66f; } + .board-color-relax#header ul li.current, .board-color-relax#header-quick-access ul li.current { border-bottom: 2px solid #2cc66f; } + .board-color-relax#header-quick-access { background: #239d57; color: #fff; } + .board-color-relax#header #header-main-bar .board-header-btn.emphasis { background: #ae2774; } + .board-color-relax#header #header-main-bar .board-header-btn.emphasis:hover, .board-color-relax#header #header-main-bar .board-header-btn.emphasis .board-header-btn-close { background: #9d2368; } + .board-color-relax#header #header-main-bar .board-header-btn.emphasis:hover .board-header-btn-close { background: #8b1f5d; } + .board-color-relax .materialCheckBox.is-checked { border-bottom: 2px solid #27ae61; border-right: 2px solid #27ae61; @@ -1231,56 +1380,64 @@ THEME - Relax .board-color-relax .is-multiselection-active .multi-selection-checkbox.is-checked + .minicard { background: #e7faef; } -.board-color-relax .is-multiselection-active .multi-selection-checkbox:not(.is-checked) + .minicard:hover:not(.minicard-composer) { + +.board-color-relax .is-multiselection-active .multi-selection-checkbox:not(.is-checked)+.minicard:hover:not(.minicard-composer) { background: #f8fdfa; } + .board-color-relax .toggle-label:after { background-color: #1f8b4e; } -.board-color-relax .toggle-switch:checked ~ .toggle-label { + +.board-color-relax .toggle-switch:checked~.toggle-label { background-color: #3dd37e; } -.board-color-relax .toggle-switch:checked ~ .toggle-label:after { + +.board-color-relax .toggle-switch:checked~.toggle-label:after { background-color: #1f8b4e; } + @media screen and (max-width: 800px) { .board-color-relax.pop-over .header { background: #27ae61; color: #fff; } } + .board-color-relax#header ul li.current, .board-color-relax#header-quick-access ul li.current { border-bottom: 4px solid #3dd37e; } + .board-color-relax .board-wrapper { background-color: #a7e366; } + .board-color-relax .list-header { background-color: #a7e366; } + .board-color-relax .list-body { background-color: #a7e366; } + .board-color-relax .list { border-left: 1px dotted #000; } -.board-color-relax .card-details .card-details-items ~ .js-open-inlined-form .viewer { + +.board-color-relax .card-details .card-details-items~.js-open-inlined-form .viewer { background-color: #fff !important; - padding: 15px !important; border: 1px solid #000 !important; - word-wrap: break-word; + overflow-wrap: break-word; } + .board-color-relax .minicard .badges .badge .badge-icon.badge-comment, .board-color-relax .minicard .badges .badge .badge-text.badge-comment { display: block; - border-radius: 4px; - padding: 1px 3px; - margin-bottom: 0.3rem; + border-radius: 0.4ch; color: #f00; background-color: #fff; font-weight: bold; - font-size: 11pt; } /* Transparent modern scrollbar - relax*/ @@ -1298,123 +1455,133 @@ THEME - Relax .board-color-relax .list { border-left: none; - /* padding-bottom: 8px; - Removed to get rid of grey bars for relax theme */ -} + /* } + -.board-color-relax .list-body { - margin-top: 8px; -} /* === END Relax THEME === */ -/* =============== + /* =============== THEME - Corteza =================*/ -.board-color-corteza#header, -.board-color-corteza.sk-spinner div, -.board-backgrounds-list .board-color-corteza.background-box, -.board-list .board-color-corteza a { - background-color: #568ba2; -} -.board-color-corteza .is-selected .minicard { - border-left: 3px solid #568ba2; -} -.board-color-corteza .minicard { - border-radius: 7px; - padding: 10px 10px 4px 10px; - box-shadow: 2px 2px 4px 0px rgba(0,0,0,0.15); -} -.board-color-corteza button[type=submit].primary, -.board-color-corteza input[type=submit].primary, -.board-color-corteza .sidebar .sidebar-content .sidebar-btn { - background-color: #456f82; - border-radius: 7px; -} -.board-color-corteza.pop-over .pop-over-list li a:not(.disabled):hover, -.board-color-corteza .sidebar .sidebar-content .sidebar-btn:hover, -.board-color-corteza .sidebar-list li a:hover { - background-color: #6597ad; -} -.board-color-corteza#header ul li.current, -.board-color-corteza#header-quick-access ul li.current { - border-bottom: 2px solid #6597ad; -} -.board-color-corteza#header-quick-access { - background: #4d7d92; - color: #fff; -} -.board-color-corteza#header #header-main-bar .board-header-btn.emphasis { - background: #a26d56; -} -.board-color-corteza#header #header-main-bar .board-header-btn.emphasis:hover, -.board-color-corteza#header #header-main-bar .board-header-btn.emphasis .board-header-btn-close { - background: #92624d; -} -.board-color-corteza#header #header-main-bar .board-header-btn.emphasis:hover .board-header-btn-close { - background: #825745; -} -.board-color-corteza .materialCheckBox.is-checked { - border-bottom: 2px solid #568ba2; - border-right: 2px solid #568ba2; -} -.board-color-corteza .checklist-progress-bar { + .board-color-corteza#header, + .board-color-corteza.sk-spinner div, + .board-backgrounds-list .board-color-corteza.background-box, + .board-list .board-color-corteza a { + background-color: #568ba2; + } + + .board-color-corteza .is-selected .minicard { + border-left: 3px solid #568ba2; + } + + .board-color-corteza .minicard { + border-radius: 0.6ch; + box-shadow: 2px 2px 4px 0px rgba(0, 0, 0, 0.15); + } + + .board-color-corteza button[type=submit].primary, + .board-color-corteza input[type=submit].primary, + .board-color-corteza .sidebar .sidebar-content .sidebar-btn { + background-color: #456f82; + border-radius: 0.6ch; + } + + .board-color-corteza.pop-over .pop-over-list li a:not(.disabled):hover, + .board-color-corteza .sidebar .sidebar-content .sidebar-btn:hover, + .board-color-corteza .sidebar-list li a:hover { + background-color: #6597ad; + } + + .board-color-corteza#header ul li.current, + .board-color-corteza#header-quick-access ul li.current { + border-bottom: 2px solid #6597ad; + } + + .board-color-corteza#header-quick-access { + background: #4d7d92; + color: #fff; + } + + .board-color-corteza#header #header-main-bar .board-header-btn.emphasis { + background: #a26d56; + } + + .board-color-corteza#header #header-main-bar .board-header-btn.emphasis:hover, + .board-color-corteza#header #header-main-bar .board-header-btn.emphasis .board-header-btn-close { + background: #92624d; + } + + .board-color-corteza#header #header-main-bar .board-header-btn.emphasis:hover .board-header-btn-close { + background: #825745; + } + + .board-color-corteza .materialCheckBox.is-checked { + 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; -} -.board-color-corteza .is-multiselection-active .multi-selection-checkbox:not(.is-checked) + .minicard:hover:not(.minicard-composer) { - background: #fafcfc; -} -.board-color-corteza .toggle-label:after { - background-color: #456f82; -} -.board-color-corteza .toggle-switch:checked ~ .toggle-label { - background-color: #76a3b6; -} -.board-color-corteza .toggle-switch:checked ~ .toggle-label:after { - background-color: #456f82; -} -@media screen and (max-width: 800px) { - .board-color-corteza.pop-over .header { - background: #568ba2; - color: #fff; +.board-color-corteza .is-multiselection-active .multi-selection-checkbox.is-checked+.minicard { + background: #eef3f6; } -} -.board-color-corteza#header ul li.current, -.board-color-corteza#header-quick-access ul li.current { - border-bottom: 4px solid #76a3b6; -} -/* Transparent modern scrollbar - corteza*/ -.board-color-corteza .board-canvas { + .board-color-corteza .is-multiselection-active .multi-selection-checkbox:not(.is-checked)+.minicard:hover:not(.minicard-composer) { + background: #fafcfc; + } + + .board-color-corteza .toggle-label:after { + background-color: #456f82; + } + + .board-color-corteza .toggle-switch:checked~.toggle-label { + background-color: #76a3b6; + } + + .board-color-corteza .toggle-switch:checked~.toggle-label:after { + background-color: #456f82; + } + + @media screen and (max-width: 800px) { + .board-color-corteza.pop-over .header { + background: #568ba2; + color: #fff; + } + } + + .board-color-corteza#header ul li.current, + .board-color-corteza#header-quick-access ul li.current { + border-bottom: 4px solid #76a3b6; + } + + /* Transparent modern scrollbar - corteza*/ + .board-color-corteza .board-canvas { scrollbar-color: #568ba2f2 #e4e4e400; -} + } -/* Apply scrollbar to sidebar content*/ -.board-color-corteza .sidebar .sidebar-content { - scrollbar-color: #568ba2f2 #e4e4e400; -} + /* Apply scrollbar to sidebar content*/ + .board-color-corteza .sidebar .sidebar-content { + scrollbar-color: #568ba2f2 #e4e4e400; + } -/* Remove margins in between columns/fix spacing */ + /* Remove margins in between columns/fix spacing */ -.board-color-corteza .list { - border-left: none; - padding-bottom: 8px; -} + .board-color-corteza .list { + border-left: none; + } -.board-color-corteza .list-body { - margin-top: 8px; -} -/* === END Corteza THEME === */ -/* =============== + /* === END Corteza THEME === */ + + /* =============== THEME - Clear Blue =================*/ @@ -1452,9 +1619,6 @@ THEME - Clear Blue .board-color-clearblue#header #header-main-bar { background: linear-gradient(180deg, #499bea 0%, #00aecc 100%); } -.board-color-clearblue#header #header-main-bar p { - margin-bottom: 6px; -} .board-color-clearblue#header #header-main-bar .board-header-btn.emphasis { background: #00c8eb; } @@ -1494,16 +1658,10 @@ THEME - Clear Blue background: none; } .board-color-clearblue .swimlane .list:first-child { - min-width: 20px; - margin-left: 10px; /* Added 10px margin left to stop lists being butted up against the edge of the screen */ border-left: none; } -.board-color-clearblue .swimlane .list:nth-child { - flex: 0 0 265px; -} .board-color-clearblue .list { background: rgba(255,255,255,0.35); - margin: 10px 0; border: 0; border-radius: 14px; } @@ -1511,15 +1669,11 @@ THEME - Clear Blue background: rgba(255,255,255,0.1); height: min-content; flex: unset; - padding-bottom: 16px; - min-width: 20px; - margin-left: 0px; border-left: none; } .board-color-clearblue .list.list-composer .open-list-composer { - border-radius: 7px; + border-radius: 0.6ch; color: rgba(0,0,0,0.3); - padding: 7px 10px; display: block; } .board-color-clearblue .list.list-composer .open-list-composer:hover i, @@ -1538,24 +1692,19 @@ THEME - Clear Blue .board-color-clearblue .list-header .list-header-name { color: rgba(0,0,0,0.6); } -.board-color-clearblue .list-body { - padding: 11px; } .board-color-clearblue .minicard { - border-radius: 7px; - padding: 10px 10px 4px 10px; + border-radius: 0.6ch; box-shadow: 2px 2px 4px 0px rgba(0,0,0,0.15); color: #222; } .board-color-clearblue .card-details { border-radius: 0 0 14px 14px; box-shadow: 0 0 7px 0 rgba(0,0,0,0.5); - margin-left: -10px; } .board-color-clearblue .list-body .open-minicard-composer { - border-radius: 7px; + border-radius: 0.6ch; color: rgba(0,0,0,0.3); - margin-bottom: 11px; } .board-color-clearblue .list-body .open-minicard-composer:hover { background: rgba(255,255,255,0.7); @@ -1566,7 +1715,7 @@ THEME - Clear Blue box-shadow: none; background-color: rgba(255,255,255,0.5); color: rgba(0,0,0,0.55); - border-radius: 7px; + border-radius: 0.6ch; border: 0; } .board-color-clearblue button[type="submit"].primary:hover, @@ -1574,7 +1723,7 @@ THEME - Clear Blue background-color: rgba(255,255,255,0.7); color: rgba(0,0,0,0.8); box-shadow: 0 1px 2px rgba(0,0,0,0.2); - border-radius: 7px; + border-radius: 0.6ch; } .board-color-clearblue .quiet, .board-color-clearblue .quiet a { @@ -1583,8 +1732,6 @@ THEME - Clear Blue .board-color-clearblue .list-header .list-header-watch-icon { color: rgba(0,0,0,0.5); position: absolute; - margin-top: -34px; - margin-left: -11px; } .board-color-clearblue a.fa, .board-color-clearblue a i.fa { @@ -1595,13 +1742,13 @@ THEME - Clear Blue .board-color-clearblue a:not(.disabled):hover.fa, .board-color-clearblue a:not(.disabled):hover i.fa { color: rgba(0,0,0,0.6); - border-radius: 7px; + border-radius: 0.6ch; } .board-color-clearblue input[type="email"], .board-color-clearblue input[type="password"], .board-color-clearblue input[type="text"] { border: 0; - border-radius: 7px; + border-radius: 0.6ch; } .board-color-clearblue .sidebar-shadow { box-shadow: none; @@ -1645,12 +1792,6 @@ THEME - Clear Blue display: inline-block; vertical-align: middle; } -.board-color-clearblue .swimlane-header-wrap .primary.confirm { - margin-right: 0; -} -.board-color-clearblue .swimlane-header-wrap .fa.fa-times-thin { - margin-top: 2px; -} .board-color-clearblue .list.ui-sortable-helper, .board-color-clearblue .list.ui-sortable-helper .list-header.ui-sortable-handle, .board-color-clearblue .list.ui-sortable-helper .viewer { @@ -1658,1590 +1799,1570 @@ THEME - Clear Blue cursor: grabbing; } -/* Transparent modern scrollbar - clearblue*/ -.board-color-clearblue .board-canvas { - scrollbar-color: #ffffffdb #ffffff00; - scrollbar-width: thin; -} + /* Transparent modern scrollbar - clearblue*/ + .board-color-clearblue .board-canvas { + scrollbar-color: #ffffffdb #ffffff00; + scrollbar-width: thin; + } -.board-color-clearblue .list-body { - scrollbar-width: thin; -} + .board-color-clearblue .list-body { + scrollbar-width: thin; + } -/* Apply scrollbar to sidebar content*/ -.board-color-clearblue .sidebar .sidebar-content { - scrollbar-color: #00aecc #ffffff00; -} + /* Apply scrollbar to sidebar content*/ + .board-color-clearblue .sidebar .sidebar-content { + scrollbar-color: #00aecc #ffffff00; + } -/* Remove margins in between columns/fix spacing */ + /* Remove margins in between columns/fix spacing */ -.board-color-clearblue .list { - border-left: none; - padding-bottom: 8px; -} + .board-color-clearblue .list { + border-left: none; + } -.board-color-clearblue .list-body { - margin-top: 8px; -} -/* === END Clearblue THEME === */ -/* =============== + /* === END Clearblue THEME === */ + + /* =============== THEME - Natural =================*/ -.board-color-natural#header, -.board-color-natural.sk-spinner div, -.board-backgrounds-list .board-color-natural.background-box, -.board-list .board-color-natural a { - background-color: #596557; -} -.board-color-natural .is-selected .minicard { - border-left: 3px solid #596557; -} -.board-color-natural .minicard { - border-radius: 7px; - padding: 10px 10px 4px 10px; - box-shadow: 2px 2px 4px 0px rgba(0,0,0,0.15); -} -.board-color-natural button[type=submit].primary, -.board-color-natural input[type=submit].primary, -.board-color-natural .sidebar .sidebar-content .sidebar-btn { - background-color: #475146; - border-radius: 7px; -} -.board-color-natural.pop-over .pop-over-list li a:not(.disabled):hover, -.board-color-natural .sidebar .sidebar-content .sidebar-btn:hover, -.board-color-natural .sidebar-list li a:hover { - background-color: #687666; -} -.board-color-natural#header ul li.current, -.board-color-natural#header-quick-access ul li.current { - border-bottom: 2px solid #687666; -} -.board-color-natural#header-quick-access { - background: #505b4e; - color: #fff; -} -.board-color-natural#header #header-main-bar .board-header-btn.emphasis { - background: #635765; -} -.board-color-natural#header #header-main-bar .board-header-btn.emphasis:hover, -.board-color-natural#header #header-main-bar .board-header-btn.emphasis .board-header-btn-close { - background: #594e5b; -} -.board-color-natural#header #header-main-bar .board-header-btn.emphasis:hover .board-header-btn-close { - background: #4f4651; -} -.board-color-natural .materialCheckBox.is-checked { - border-bottom: 2px solid #596557; - border-right: 2px solid #596557; -} + .board-color-natural#header, + .board-color-natural.sk-spinner div, + .board-backgrounds-list .board-color-natural.background-box, + .board-list .board-color-natural a { + background-color: #596557; + } + + .board-color-natural .is-selected .minicard { + border-left: 3px solid #596557; + } + + .board-color-natural .minicard { + border-radius: 0.6ch; + box-shadow: 2px 2px 4px 0px rgba(0, 0, 0, 0.15); + } + + .board-color-natural button[type=submit].primary, + .board-color-natural input[type=submit].primary, + .board-color-natural .sidebar .sidebar-content .sidebar-btn { + background-color: #475146; + border-radius: 0.6ch; + } + + .board-color-natural.pop-over .pop-over-list li a:not(.disabled):hover, + .board-color-natural .sidebar .sidebar-content .sidebar-btn:hover, + .board-color-natural .sidebar-list li a:hover { + background-color: #687666; + } + + .board-color-natural#header ul li.current, + .board-color-natural#header-quick-access ul li.current { + border-bottom: 2px solid #687666; + } + + .board-color-natural#header-quick-access { + background: #505b4e; + color: #fff; + } + + .board-color-natural#header #header-main-bar .board-header-btn.emphasis { + background: #635765; + } + + .board-color-natural#header #header-main-bar .board-header-btn.emphasis:hover, + .board-color-natural#header #header-main-bar .board-header-btn.emphasis .board-header-btn-close { + background: #594e5b; + } + + .board-color-natural#header #header-main-bar .board-header-btn.emphasis:hover .board-header-btn-close { + background: #4f4651; + } + + .board-color-natural .materialCheckBox.is-checked { + 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; -} -.board-color-natural .is-multiselection-active .multi-selection-checkbox:not(.is-checked) + .minicard:hover:not(.minicard-composer) { - background: #fafbfa; -} -.board-color-natural .toggle-label:after { - background-color: #475146; -} -.board-color-natural .toggle-switch:checked ~ .toggle-label { - background-color: #778875; -} -.board-color-natural .toggle-switch:checked ~ .toggle-label:after { - background-color: #475146; -} -@media screen and (max-width: 800px) { - .board-color-natural.pop-over .header { - background: #596557; - color: #fff; + + .board-color-natural .is-multiselection-active .multi-selection-checkbox.is-checked+.minicard { + background: #eef0ee; } -} -.board-color-natural#header ul li.current, -.board-color-natural#header-quick-access ul li.current { - border-bottom: 4px solid #778875; -} -.board-color-natural#header-quick-access { - background-color: #2d392b; -} -.board-color-natural.board-wrapper { - background-color: #dedede; -} -.board-color-natural .swimlane .swimlane-header-wrap { - background-color: #c2c0ab; -} -/* Transparent modern scrollbar - natural*/ -.board-color-natural .board-canvas { - scrollbar-color: #596557f2 #e4e4e400; -} + .board-color-natural .is-multiselection-active .multi-selection-checkbox:not(.is-checked)+.minicard:hover:not(.minicard-composer) { + background: #fafbfa; + } + + .board-color-natural .toggle-label:after { + background-color: #475146; + } + + .board-color-natural .toggle-switch:checked~.toggle-label { + background-color: #778875; + } + + .board-color-natural .toggle-switch:checked~.toggle-label:after { + background-color: #475146; + } + + @media screen and (max-width: 800px) { + .board-color-natural.pop-over .header { + background: #596557; + color: #fff; + } + } + + .board-color-natural#header ul li.current, + .board-color-natural#header-quick-access ul li.current { + border-bottom: 4px solid #778875; + } + + .board-color-natural#header-quick-access { + background-color: #2d392b; + } + + .board-color-natural.board-wrapper { + background-color: #dedede; + } + + .board-color-natural .swimlane .swimlane-header-wrap { + background-color: #c2c0ab; + } + + /* Transparent modern scrollbar - natural*/ + .board-color-natural .board-canvas { + scrollbar-color: #596557f2 #e4e4e400; + } -/* Apply scrollbar to sidebar content*/ -.board-color-natural .sidebar .sidebar-content { - scrollbar-color: #596557f2 #e4e4e400; -} + /* Apply scrollbar to sidebar content*/ + .board-color-natural .sidebar .sidebar-content { + scrollbar-color: #596557f2 #e4e4e400; + } -/* Remove margins in between columns/fix spacing */ + /* Remove margins in between columns/fix spacing */ -.board-color-natural .list { - border-left: none; - padding-bottom: 8px; -} + .board-color-natural .list { + border-left: none; + } -.board-color-natural .list-body { - margin-top: 8px; -} -/* === END Natural THEME === */ -/* =============== + /* === END Natural THEME === */ + + /* =============== THEME - Modern =================*/ -.board-color-modern#header, -.board-color-modern.sk-spinner div, -.board-backgrounds-list .board-color-modern.background-box, -.board-list .board-color-modern a { - background-color: #2a80b8; -} -.board-color-modern .is-selected .minicard { - border-left: 3px solid #2a80b8; -} -.board-color-modern .minicard { - border-radius: 7px; - padding: 10px 10px 4px 10px; - box-shadow: 2px 2px 4px 0px rgba(0,0,0,0.15); -} -.board-color-modern button[type=submit].primary, -.board-color-modern input[type=submit].primary, -.board-color-modern .sidebar .sidebar-content .sidebar-btn { - background-color: #226693; - border-radius: 7px; -} -.board-color-modern.pop-over .pop-over-list li a:not(.disabled):hover, -.board-color-modern .sidebar .sidebar-content .sidebar-btn:hover, -.board-color-modern .sidebar-list li a:hover { - background-color: #2f90cf; -} -.board-color-modern#header ul li.current, -.board-color-modern#header-quick-access ul li.current { - border-bottom: 2px solid #2f90cf; -} -.board-color-modern#header-quick-access { - background: #2673a6; - color: #fff; -} -.board-color-modern#header #header-main-bar .board-header-btn.emphasis { - background: #b8622a; -} -.board-color-modern#header #header-main-bar .board-header-btn.emphasis:hover, -.board-color-modern#header #header-main-bar .board-header-btn.emphasis .board-header-btn-close { - background: #a65826; -} -.board-color-modern#header #header-main-bar .board-header-btn.emphasis:hover .board-header-btn-close { - background: #934e22; -} -.board-color-modern .materialCheckBox.is-checked { - border-bottom: 2px solid #2a80b8; - border-right: 2px solid #2a80b8; -} + .board-color-modern#header, + .board-color-modern.sk-spinner div, + .board-backgrounds-list .board-color-modern.background-box, + .board-list .board-color-modern a { + background-color: #2a80b8; + } + + .board-color-modern .is-selected .minicard { + border-left: 3px solid #2a80b8; + } + + .board-color-modern .minicard { + border-radius: 0.6ch; + box-shadow: 2px 2px 4px 0px rgba(0, 0, 0, 0.15); + } + + .board-color-modern button[type=submit].primary, + .board-color-modern input[type=submit].primary, + .board-color-modern .sidebar .sidebar-content .sidebar-btn { + background-color: #226693; + color: #fff; + } + + .board-color-modern { + + button, + input { + border-radius: 0.6ch; + } + } + + .board-color-modern.pop-over .pop-over-list li a:not(.disabled):hover, + .board-color-modern .sidebar .sidebar-content .sidebar-btn:hover, + .board-color-modern .sidebar-list li a:hover { + background-color: #2f90cf; + } + + .board-color-modern#header ul li.current, + .board-color-modern#header-quick-access ul li.current { + border-bottom: 2px solid #2f90cf; + } + + .board-color-modern#header-quick-access { + background: #2673a6; + color: #fff; + } + + .board-color-modern#header #header-main-bar .board-header-btn.emphasis { + background: #b8622a; + } + + .board-color-modern#header #header-main-bar .board-header-btn.emphasis:hover, + .board-color-modern#header #header-main-bar .board-header-btn.emphasis .board-header-btn-close { + background: #a65826; + } + + .board-color-modern#header #header-main-bar .board-header-btn.emphasis:hover .board-header-btn-close { + background: #934e22; + } + + .board-color-modern .materialCheckBox.is-checked { + 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; -} -.board-color-modern .is-multiselection-active .multi-selection-checkbox:not(.is-checked) + .minicard:hover:not(.minicard-composer) { - background: #f8fbfd; -} -.board-color-modern .toggle-label:after { - background-color: #226693; -} -.board-color-modern .toggle-switch:checked ~ .toggle-label { - background-color: #469cd5; -} -.board-color-modern .toggle-switch:checked ~ .toggle-label:after { - background-color: #226693; -} -@media screen and (max-width: 800px) { - .board-color-modern.pop-over .header { - background: #2a80b8; + + .board-color-modern .is-multiselection-active .multi-selection-checkbox.is-checked+.minicard { + background: #e8f3fa; + } + + .board-color-modern .is-multiselection-active .multi-selection-checkbox:not(.is-checked)+.minicard:hover:not(.minicard-composer) { + background: #f8fbfd; + } + + .board-color-modern .toggle-label:after { + background-color: #226693; + } + + .board-color-modern .toggle-switch:checked~.toggle-label { + background-color: #469cd5; + } + + .board-color-modern .toggle-switch:checked~.toggle-label:after { + background-color: #226693; + } + + @media screen and (max-width: 800px) { + .board-color-modern.pop-over .header { + background: #2a80b8; + color: #fff; + } + } + + .board-color-modern#header ul li.current, + .board-color-modern#header-quick-access ul li.current { + border-bottom: 4px solid #469cd5; + } + + .board-color-modern body { + background: #f5f5f5; + } + + .board-color-modern#header-quick-access { + background: #333 !important; + } + + .board-color-modern#header-quick-access ul { + overflow: visible; + } + + .board-color-modern#header-quick-access ul li.current { + border: 0 !important; + font-weight: bold; + } + + .board-color-modern#header-quick-access ul li.separator { + display: none; + } + + + .board-color-modern#header-quick-access ul li a { + border-radius: 2px; + } + + .board-color-modern#header-quick-access ul li.current a { + border-radius: 2px; + background: rgba(255, 255, 255, 0.2); + } + + .board-color-modern#header #header-main-bar h1 { + /* font-family: Poppins; */ + font-weight: bold; + } + + .board-color-modern section#notifications-drawer { + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1); + max-width: 100%; + } + + .board-color-modern section#notifications-drawer .header { + border-radius: 0 3px; + background: #f7f7f7; + } + + .board-color-modern.board-wrapper { + background: #f5f5f5; + } + + .board-color-modern .swimlane { + background: none; + } + + .board-color-modern .swimlane .swimlane-header-wrap .swimlane-header { + /* font-family: Poppins; */ + } + + + .board-color-modern .list-body .open-minicard-composer:hover { + background: none; + box-shadow: none; + } + + .board-color-modern .swimlane .list:first-child { + border-left: none; + } + + .board-color-modern .swimlane .list:nth-child { + flex: 0 0 265px; + } + + .board-color-modern .list.list-composer.js-list-composer { + transition: all 0.3s ease; + } + + .board-color-modern .open-list-composer.js-open-inlined-form:hover { + color: #222; + } + + .board-color-modern { + + .list-header, + .list-composer { + background: #f5f5f5f2; + /*Added background colour same colour as base board background, prevents poor text visibility when bgd image applied*/ + } + } + + .board-color-modern .list-header .list-header-name { + /* font-family: Poppins; */ + color: #000; + font-weight: 500; + } + + .board-color-modern .minicard { + box-shadow: 0 3px 8px rgba(0, 0, 0, 0.05); + } + + .board-color-modern .minicard-plum:hover:not(.minicard-composer), + .board-color-modern .is-selected .minicard-plum, + .board-color-modern .draggable-hover-card .minicard-plum { + background: none; + } + + .board-color-modern .minicard-title { + line-height: 1.5em; + } + + .board-color-modern .minicard .minicard-cover { + background-size: cover; + } + + .board-color-modern .card-label-orange { color: #fff; } -} -.board-color-modern#header ul li.current, -.board-color-modern#header-quick-access ul li.current { - border-bottom: 4px solid #469cd5; -} -.board-color-modern body { - background: #f5f5f5; -} -.board-color-modern#header-quick-access { - padding: 10px; - font-size: 14px; - background: #333 !important; -} -.board-color-modern#header-quick-access ul { - overflow: visible; -} -.board-color-modern#header-quick-access ul li.current { - border: 0 !important; - font-weight: bold; -} -.board-color-modern#header-quick-access ul li.separator { - display: none; -} -.board-color-modern#header-quick-access ul li:nth-child(3) { - margin-right: 10px; -} -.board-color-modern#header-quick-access ul li a { - padding: 5px 10px; - border-radius: 2px; -} -.board-color-modern#header-quick-access ul li.current a { - border-radius: 2px; - background: rgba(255,255,255,0.2); -} -.board-color-modern#header #header-main-bar h1 { -/* font-family: Poppins; */ - font-weight: bold; -} -.board-color-modern#header-quick-access #header-user-bar { - position: relative; -} -.board-color-modern#header-quick-access #header-user-bar .header-user-bar-name { - margin: 5px 3px 0 0; -} -.board-color-modern section#notifications-drawer { - top: 46px; - box-shadow: 0 4px 20px rgba(0,0,0,0.1); - max-width: 100%; -} -.board-color-modern section#notifications-drawer .header { - top: 46px; - border-radius: 0 3px; - height: 21px; - background: #f7f7f7; -} -.board-color-modern.board-wrapper { - background: #f5f5f5; -} -.board-color-modern .swimlane { - background: none; -} -.board-color-modern .swimlane .swimlane-header-wrap .swimlane-header { - /* font-family: Poppins; */ -} -.board-color-modern .board-list .board-list-item { - padding: 20px; -} -.board-color-modern .board-list-item-name { - /* font-family: Poppins; */ -} -.board-color-modern .list { - background: transparent; - border-left: 0; - margin: 10px 0; - padding: 0px; - border-radius: 5px; - min-width: 300px; -} -.board-color-modern .list-body .open-minicard-composer:hover { - background: none; - box-shadow: none; -} -.board-color-modern .swimlane .list:first-child { - min-width: 20px; - margin-left: 0px; - border-left: none; -} -.board-color-modern .swimlane .list:nth-child { - flex: 0 0 265px; - } -.board-color-modern .list.list-composer.js-list-composer { - transition: all 0.3s ease; - min-width: 20px; -} -.board-color-modern .open-list-composer.js-open-inlined-form:hover { - color: #222; -} -.board-color-modern .list-header { - background: #f5f5f5f2; /*Added background colour same colour as base board background, prevents poor text visibility when bgd image applied*/ -} -.board-color-modern .list-header .list-header-name { - /* font-family: Poppins; */ - color: #000; - font-weight: 500; -} -.board-color-modern .minicard { - padding: 15px 15px 10px; - box-shadow: 0 3px 8px rgba(0,0,0,0.05); -} -.board-color-modern .minicard-plum:hover:not(.minicard-composer), -.board-color-modern .is-selected .minicard-plum, -.board-color-modern .draggable-hover-card .minicard-plum { - background: none; -} -.board-color-modern .minicard-title { - line-height: 1.5em; -} -.board-color-modern .minicard .minicard-cover { - background-size: cover; - margin: -15px -15px 10px; - height: 100px; -} -.board-color-modern .card-label-orange { - color: #fff; -} -.board-color-modern .card-date { - font-size: 12px; - padding: 3px 5px; -} -.board-color-modern .header-title { - /* font-family: Poppins; */ - font-size: 16px; - color: #333; -} -.board-color-modern .pop-over { - box-shadow: 0 4px 20px rgba(0,0,0,0.2); - border: 0; - border-radius: 5px; -} -.board-color-modern .pop-over .header { - padding: 10px; - border-bottom: 0; - border-radius: 5px 5px 0 0; - background: #eee; -} -.board-color-modern .pop-over .header .header-title { - /* font-family: Poppins; */ - font-size: 16px; - color: #333; -} -.board-color-modern .pop-over .header .close-btn { - font-size: 20px; - top: 6px; - right: 8px; -} -.board-color-modern .pop-over .content-container .content { - padding: 5px 20px 20px; - width: 260px; -} -.board-color-modern .pop-over-list li > a { - border-radius: 5px; -} -.board-color-modern .pop-over-list li > a > i { - margin-right: 5px; -} -.board-color-modern .pop-over-list li>a .sub-name { - margin-bottom: 8px; -} -.board-color-modern .sidebar { - box-shadow: 0 0 60px rgba(0,0,0,0.2); -} -.board-color-modern .board-color-modern section#notifications-drawer { - border-radius: 5px; -} -.board-color-modern .board-color-modern section#notifications-drawer .header { - padding: 18px 16px; - border-bottom: 0; - border-radius: 5px 5px 0 0; - background: #eee; -} -.board-color-modern .board-color-modern section#notifications-drawer .header h5 { - /* font-family: Poppins; */ - font-weight: bold; -} -.board-color-modern .board-color-modern section#notifications-drawer .header .close { - font-size: 20px; - top: 14px; -} -.board-color-modern section#notifications-drawer .header .toggle-read { - top: 18px; -} -/* Transparent modern scrollbar - modern*/ -.board-color-modern .board-canvas { - scrollbar-color: #333333f2 #e4e4e400; -} + .board-color-modern .header-title { + /* font-family: Poppins; */ + color: #333; + } + + .board-color-modern .pop-over { + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2); + border: 0; + border-radius: 5px; + } + + .board-color-modern .pop-over .header { + border-bottom: 0; + border-radius: 5px 5px 0 0; + background: #eee; + } + + .board-color-modern .pop-over .header .header-title { + /* font-family: Poppins; */ + color: #333; + } -/* Apply scrollbar to sidebar content*/ -.board-color-modern .sidebar .sidebar-content { - scrollbar-color: #333333f2 #e4e4e400; -} + .board-color-modern .pop-over-list li>a { + border-radius: 5px; + padding: 0.3lh 0; + } -/* Remove margins in between columns/fix spacing */ -.board-color-modern .list { - border-left: none; - padding-bottom: 8px; -} + .board-color-modern .sidebar { + box-shadow: 0 0 60px rgba(0, 0, 0, 0.2); + } -.board-color-modern .list-body { - margin-top: 8px; -} + .board-color-modern .board-color-modern section#notifications-drawer { + border-radius: 5px; + } -/* === END Modern THEME === */ + .board-color-modern .board-color-modern section#notifications-drawer .header { + border-bottom: 0; + border-radius: 5px 5px 0 0; + background: #eee; + } -/* =============== + .board-color-modern .board-color-modern section#notifications-drawer .header h5 { + /* font-family: Poppins; */ + font-weight: bold; + } + + + /* Transparent modern scrollbar - modern*/ + .board-color-modern .board-canvas { + scrollbar-color: #333333f2 #e4e4e400; + } + + + /* Apply scrollbar to sidebar content*/ + .board-color-modern .sidebar .sidebar-content { + scrollbar-color: #333333f2 #e4e4e400; + } + + /* === END Modern THEME === */ + + /* =============== THEME - Modern Dark =================*/ -.board-color-moderndark#header, -.board-color-moderndark.sk-spinner div, -.board-backgrounds-list .board-color-moderndark.background-box, -.board-list .board-color-moderndark a { - background-color: #2a2a2a; -} -.board-color-moderndark .is-selected .minicard { - border-left: 3px solid #2a2a2a; -} -.board-color-moderndark .minicard { - border-radius: 7px; - padding: 10px 10px 4px 10px; - box-shadow: 2px 2px 4px 0px rgba(0,0,0,0.15); -} -.board-color-moderndark button[type=submit].primary, -.board-color-moderndark input[type=submit].primary, -.board-color-moderndark .sidebar .sidebar-content .sidebar-btn { - background-color: #222; - border-radius: 7px; -} -.board-color-moderndark.pop-over .pop-over-list li a:not(.disabled):hover, -.board-color-moderndark .sidebar .sidebar-content .sidebar-btn:hover, -.board-color-moderndark .sidebar-list li a:hover { - background-color: #3f3f3f; -} -.board-color-moderndark#header ul li.current, -.board-color-moderndark#header-quick-access ul li.current { - border-bottom: 2px solid #3f3f3f; -} -.board-color-moderndark#header-quick-access { - background: #262626; - color: #fff; -} -@media screen and (min-width: 801px) { - .board-color-moderndark .js-toggle-desktop-drag-handles { - padding-top: 6px + .board-color-moderndark#header, + .board-color-moderndark.sk-spinner div, + .board-backgrounds-list .board-color-moderndark.background-box, + .board-list .board-color-moderndark a { + background-color: #2a2a2a; + } + + .board-color-moderndark .is-selected .minicard { + border-left: 3px solid #2a2a2a; + } + + .board-color-moderndark .minicard { + border-radius: 0.6ch; + box-shadow: 2px 2px 4px 0px rgba(0, 0, 0, 0.15); + } + + .board-color-moderndark button[type=submit].primary, + .board-color-moderndark input[type=submit].primary, + .board-color-moderndark .sidebar .sidebar-content .sidebar-btn { + background-color: #222; + border-radius: 0.6ch; + } + + .board-color-moderndark.pop-over .pop-over-list li a:not(.disabled):hover, + .board-color-moderndark .sidebar .sidebar-content .sidebar-btn:hover, + .board-color-moderndark .sidebar-list li a:hover { + background-color: #3f3f3f; + } + + .board-color-moderndark#header ul li.current, + .board-color-moderndark#header-quick-access ul li.current { + border-bottom: 2px solid #3f3f3f; + } + + .board-color-moderndark#header-quick-access { + background: #262626; + color: #fff; + } + + .board-color-moderndark#header #header-main-bar .board-header-btn.emphasis { + background: #2a2a2a; + } + + .board-color-moderndark#header #header-main-bar .board-header-btn.emphasis:hover, + .board-color-moderndark#header #header-main-bar .board-header-btn.emphasis .board-header-btn-close { + background: #262626; + } + + .board-color-moderndark#header #header-main-bar .board-header-btn.emphasis:hover .board-header-btn-close { + background: #222; + } + + .board-color-moderndark .materialCheckBox.is-checked { + border-bottom: 2px solid #2a2a2a; + border-right: 2px solid #2a2a2a; } -} -.board-color-moderndark#header #header-main-bar .board-header-btn.emphasis { - background: #2a2a2a; -} -.board-color-moderndark#header #header-main-bar .board-header-btn.emphasis:hover, -.board-color-moderndark#header #header-main-bar .board-header-btn.emphasis .board-header-btn-close { - background: #262626; -} -.board-color-moderndark#header #header-main-bar .board-header-btn.emphasis:hover .board-header-btn-close { - background: #222; -} -.board-color-moderndark .materialCheckBox.is-checked { - 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; -} -.board-color-moderndark .is-multiselection-active .multi-selection-checkbox:not(.is-checked) + .minicard:hover:not(.minicard-composer) { - background: #f9f9f9; -} -.board-color-moderndark .toggle-label:after { - background-color: #222; -} -.board-color-moderndark .toggle-switch:checked ~ .toggle-label { - background-color: #555; -} -.board-color-moderndark .toggle-switch:checked ~ .toggle-label:after { - background-color: #222; -} -@media screen and (max-width: 800px) { - .board-color-moderndark.pop-over .header { + + .board-color-moderndark .is-multiselection-active .multi-selection-checkbox.is-checked + .minicard { + background: #eaeaea; + } + + .board-color-moderndark .is-multiselection-active .multi-selection-checkbox:not(.is-checked) + .minicard:hover:not(.minicard-composer) { + background: #f9f9f9; + } + + .board-color-moderndark .toggle-label:after { + background-color: #222; + } + + .board-color-moderndark .toggle-switch:checked ~ .toggle-label { + background-color: #555; + } + + .board-color-moderndark .toggle-switch:checked ~ .toggle-label:after { + background-color: #222; + } + + @media screen and (max-width: 800px) { + .board-color-moderndark.pop-over .header { + background: #2a2a2a; + color: #fff; + } + + #header.board-color-moderndark #header-main-bar .board-header-btn i.fa {} + } + + .board-color-moderndark#header ul li.current, + .board-color-moderndark#header-quick-access ul li.current { + border-bottom: 4px solid #555; + } + + .board-color-moderndark body { background: #2a2a2a; - color: #fff; } - #header.board-color-moderndark #header-main-bar .board-header-btn i.fa { - margin: 0 8px; + + .board-color-moderndark button[type=submit].primary, + .board-color-moderndark .board-color-modern input[type=submit].primary { + background-color: #777; + border-radius: 0.6ch; } -} -.board-color-moderndark#header ul li.current, -.board-color-moderndark#header-quick-access ul li.current { - border-bottom: 4px solid #555; -} -.board-color-moderndark body { - background: #2a2a2a; -} -.board-color-moderndark .board-wrapper .board-canvas .board-overlay { - opacity: 0.6; -} -.board-color-moderndark button[type=submit].primary, -.board-color-moderndark .board-color-modern input[type=submit].primary { - background-color: #777; - border-radius: 7px; -} -.board-color-moderndark .toggle-switch:checked~.toggle-label { - background-color: #f7f7f7; -} -.board-color-moderndark .toggle-label:after, -.board-color-moderndark .board-color-modern .toggle-switch:checked~.toggle-label:after { - background-color: #777 !important; -} -.board-color-moderndark button, -.board-color-moderndark input:not([type=file]), -.board-color-moderndark select, -.board-color-moderndark textarea { - border-radius: 7px; -} -.board-color-moderndark#header { - background-color: #262626; - border-bottom: 1px solid #555; - border-top: 1px solid #555; -} -.board-color-moderndark#header-quick-access, -.board-color-moderndark .background-box, -.board-color-moderndark #header { - background-color: #333; -} -.board-color-moderndark#header-quick-access { - padding: 4px; - font-size: 14px; -} -@media screen and (max-width: 800px) { - .board-color-moderndark#header-quick-access { - padding: 0; + + .board-color-moderndark .toggle-switch:checked~.toggle-label { + background-color: #f7f7f7; } -} -.board-color-moderndark#header-quick-access .allBoards { - padding: 5px 10px 0 10px; -} -.board-color-moderndark#header-quick-access ul.header-quick-access-list { - margin: -5px 0 -5px 0; -} -.board-color-moderndark#header #header-main-bar { - padding-top: 3px; - padding-bottom: 3px; -} -.board-color-moderndark#header-quick-access ul { - overflow: visible; -} -.board-color-moderndark#header-quick-access ul li.current { - border: 0 !important; - font-weight: bold; -} -.board-color-moderndark#header-quick-access ul li.separator { - display: none; -} -.board-color-moderndark#header-quick-access ul li:nth-child(3) { - margin-right: 10px; -} -.board-color-moderndark#header-quick-access ul li a { - padding: 5px 10px; - border-radius: 2px; -} -.board-color-moderndark#header-quick-access ul li.current a { - border-radius: 2px; - background: rgba(255,255,255,0.2); -} -.board-color-moderndark#header #header-main-bar h1 { - font-weight: bold; - line-height: 0.8em; - padding-top: 10px; -} -.board-color-moderndark.board-wrapper { - background: #2a2a2a; -} -.board-color-moderndark .swimlane .swimlane-header-wrap { - background-color: #494949; - color: #ccc; - padding: 4px 0; -} -.board-color-moderndark .swimlane .swimlane-header-wrap .swimlane-header-menu { - padding: 6px; - font-size: 16px; -} -.board-color-moderndark .swimlane .swimlane-header-wrap .swimlane-header-plus-icon { - font-size: 16px; -} -.board-color-moderndark .swimlane { - background: #2a2a2a; - line-height: 18px; - max-height: 100%; -} -.board-color-moderndark .swimlane .list { - background: #666; - border-radius: 0; - border: 0px solid #666; -} -.board-color-moderndark .swimlane .list:first-child { - color: #eee; - min-width: 20px; - margin-left: 0px; - border-left: none; -} -.board-color-moderndark .swimlane .list-composer .list-header-add .inlined-form .edit-controls .quiet, -.board-color-moderndark .swimlane .list-composer .list-header-add .inlined-form .edit-controls .quiet a.js-list-template { - color: #eee; -} -.board-color-moderndark .swimlane .list:nth-child { - flex: 0 0 265px; -} -.board-color-moderndark .swimlane .list:nth-child(even) .list-header, -.board-color-moderndark .swimlane .list:nth-child(even) .list-body { - background: #6a6a6a; -} -.board-color-moderndark .swimlane .list:nth-child(odd) .list-header, -.board-color-moderndark .swimlane .list:nth-child(odd) .list-body { - background: #555; -} -.board-color-moderndark .list-header { - background: #6a6a6a; -} -.board-color-moderndark .list-header .viewer { - padding-left: 10px; -} -.board-color-moderndark .list-header .list-header-name, -.board-color-moderndark .minicard { - line-height: 14px; - color: #eee; -} -@media screen and (max-width: 800px) { - .board-color-moderndark .list-header .list-header-name { - line-height: unset; - padding-top: 10px; + + .board-color-moderndark .toggle-label:after, + .board-color-moderndark .board-color-modern .toggle-switch:checked~.toggle-label:after { + background-color: #777 !important; } - .board-color-moderndark .list-header-black, .board-color-moderndark .mini-list { + + .board-color-moderndark button, + .board-color-moderndark input:not([type=file]), + .board-color-moderndark select, + .board-color-moderndark textarea { + border-radius: 0.6ch; + } + + .board-color-moderndark#header { + background-color: #262626; + border-bottom: 1px solid #555; + border-top: 1px solid #555; + } + + .board-color-moderndark#header-quick-access, + .board-color-moderndark .background-box, + .board-color-moderndark #header { + background-color: #333; + } + + + @media screen and (max-width: 800px) { + .board-color-moderndark#header-quick-access { + padding: 0; + } + } + + + .board-color-moderndark#header-quick-access ul { + overflow: visible; + } + + .board-color-moderndark#header-quick-access ul li.current { + border: 0 !important; + font-weight: bold; + } + + .board-color-moderndark#header-quick-access ul li.separator { + display: none; + } + + + .board-color-moderndark#header-quick-access ul li a { + border-radius: 2px; + } + + .board-color-moderndark#header-quick-access ul li.current a { + border-radius: 2px; + background: rgba(255, 255, 255, 0.2); + } + + .board-color-moderndark#header #header-main-bar h1 { + font-weight: bold; + line-height: 0.8em; + } + + .board-color-moderndark.board-wrapper { + background: #2a2a2a; + } + + .board-color-moderndark .swimlane .swimlane-header-wrap { + background-color: #494949; + color: #ccc; + } + + + .board-color-moderndark .swimlane { + background: #2a2a2a; + max-height: 100%; + } + + .board-color-moderndark .swimlane .list { + background: #666; + border-radius: 0; + border: 0px solid #666; + } + + .board-color-moderndark .swimlane .list:first-child { + color: #eee; + border-left: none; + } + + .board-color-moderndark .swimlane .list-composer .list-header-add .inlined-form .edit-controls .quiet, + .board-color-moderndark .swimlane .list-composer .list-header-add .inlined-form .edit-controls .quiet a.js-list-template { + color: #eee; + } + + .board-color-moderndark .swimlane .list:nth-child { + flex: 0 0 265px; + } + + .board-color-moderndark .swimlane .list:nth-child(even) .list-header, + .board-color-moderndark .swimlane .list:nth-child(even) .list-body { + background: #6a6a6a; + } + + .board-color-moderndark .swimlane .list:nth-child(odd) .list-header, + .board-color-moderndark .swimlane .list:nth-child(odd) .list-body { + background: #555; + } + + .board-color-moderndark .list-header { + background: #6a6a6a; + } + + + .board-color-moderndark .list-header .list-header-name, + .board-color-moderndark .minicard { + color: #eee; + } + + @media screen and (max-width: 800px) { + .board-color-moderndark .list-header .list-header-name { + line-height: unset; + } + + .board-color-moderndark .list-header-black, .board-color-moderndark .mini-list { + border-bottom: 0; + } + } + + .board-color-moderndark .list-header .list-header-plus-top { + color: #a6a6a6; + } + + .board-color-moderndark .list-body { + scrollbar-width: thin; + scrollbar-color: #343434 #999; + } + + + .board-color-moderndark .list-body::-webkit-scrollbar-track { + background: #343434; + border-radius: 3px; + } + + .board-color-moderndark .list-body::-webkit-scrollbar-thumb { + background-color: #999; + border-radius: 6px; + border: 3px solid #343434; + } + + .board-color-moderndark .list-body .open-minicard-composer:hover { + background: none; + box-shadow: none; border-bottom: 0; } -} -@media screen and (min-width: 801px) { - .board-color-moderndark .list-header .list-header-name { - float: left; + + .board-color-moderndark .list-body a.open-minicard-composer, + .board-color-moderndark .list-body a.open-minicard-composer i, + .board-color-moderndark .list .list-composer .open-list-composer i { + color: #bbb; } - .board-color-moderndark .list-header .list-header-menu { - padding: 0 10px 10px; + + .board-color-moderndark .swimlane .list:first-child .open-list-composer:hover i, + .board-color-moderndark .list-body a.open-minicard-composer:hover, + .board-color-moderndark .list-body a.open-minicard-composer:hover i, + .board-color-moderndark .list .list-composer .open-list-composer:hover i { + color: #fff; + border-radius: 0.6ch; } -} -.board-color-moderndark .list-header .list-header-menu { - top: 0; -} -.board-color-moderndark .list-header .list-header-plus-top { - color: #a6a6a6; -} -.board-color-moderndark .list-body { - scrollbar-width: thin; - scrollbar-color: #343434 #999; -} -.board-color-moderndark .list-body::-webkit-scrollbar { - width: 10px; -} -.board-color-moderndark .list-body::-webkit-scrollbar-track { - background: #343434; - border-radius: 3px; - margin: 4px 0; -} -.board-color-moderndark .list-body::-webkit-scrollbar-thumb { - background-color: #999; - border-radius: 6px; - border: 3px solid #343434; -} -.board-color-moderndark .list-body .open-minicard-composer:hover { - background: none; - box-shadow: none; - border-bottom: 0; -} -.board-color-moderndark .list-body a.open-minicard-composer, -.board-color-moderndark .list-body a.open-minicard-composer i, -.board-color-moderndark .list .list-composer .open-list-composer i { - color: #bbb; -} -.board-color-moderndark .swimlane .list:first-child .open-list-composer:hover i, -.board-color-moderndark .list-body a.open-minicard-composer:hover, -.board-color-moderndark .list-body a.open-minicard-composer:hover i, -.board-color-moderndark .list .list-composer .open-list-composer:hover i { - color: #fff; - border-radius: 7px; -} -.board-color-moderndark .minicard-wrapper { - margin-bottom: 12px; -} -.board-color-moderndark .minicard { - background-color: #444; - color: #ccc; - border-radius: 2px; - font-size: 0.95em; - box-shadow: 0 4px 3px -3px rgba(0,0,0,0.8); - border-bottom: 1px solid #666; - padding: 8px; -} -.board-color-moderndark .minicard:hover { - color: #f7f7f7; - background-color: #4d4d4d !important; -} -.board-color-moderndark .minicard .minicard-labels { - margin: 8px 0 4px; -} -.board-color-moderndark .minicard .card-label { - font-size: 11px; - font-weight: 400; - padding: 1px 6px 0; - border-radius: 2px; - line-height: 18px; -} -.board-color-moderndark .minicard .badges { - color: #bbb; -} -.board-color-moderndark .minicard .date { - margin-bottom: 10px; - font-size: 11px; -} -.board-color-moderndark .card-date { - color: #444; - border-radius: 2px; -} -.board-color-moderndark .card-date.almost-due { - color: #444; -} -.board-color-moderndark .minicard.minicard-composer textarea.minicard-composer-textarea:focus { - background-color: #eee; - color: #333; - padding: 6px; -} -.board-color-moderndark .is-selected .minicard { - background-color: #666; -} -.board-color-moderndark .card-details { - background-color: #454545; - color: #ccc; - box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2), 0 6px 20px 0 rgba(0,0,0,0.19); - border: 1px solid #111; - z-index: 100 !important; -} -@media screen and (max-width: 800px) { + + + .board-color-moderndark .minicard { + background-color: #444; + color: #ccc; + border-radius: 2px; + box-shadow: 0 4px 3px -3px rgba(0, 0, 0, 0.8); + border-bottom: 1px solid #666; + } + + .board-color-moderndark .minicard:hover { + color: #f7f7f7; + background-color: #4d4d4d !important; + } + + + .board-color-moderndark .minicard .card-label { + + font-weight: 400; + border-radius: 2px; + } + + .board-color-moderndark .minicard .badges { + color: #bbb; + } + + + .board-color-moderndark .card-date { + color: #444; + border-radius: 2px; + } + + .board-color-moderndark .card-date.almost-due { + color: #444; + } + + .board-color-moderndark .minicard.minicard-composer textarea.minicard-composer-textarea:focus { + background-color: #eee; + color: #333; + } + + .board-color-moderndark .is-selected .minicard { + background-color: #666; + } + .board-color-moderndark .card-details { - width: 94%; + background-color: #454545; + color: #ccc; + box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); + border: 1px solid #111; + z-index: 100 !important; } - .board-color-moderndark .card-details-popup { - padding: 0; - } - .board-color-moderndark .card-details-left, .board-color-moderndark .card-details-right { - padding: 0px 20px; - } - .board-color-moderndark .card-details .card-details-header .card-details-menu-mobile-web { - margin-right: 0; - } - .board-color-moderndark .pop-over > .content-wrapper > .popup-container-depth-0 > .content { - width: calc(100% - 20px); - } -} -@media screen and (min-width: 801px) { + .board-color-moderndark .card-details { - position: fixed; - top: 82px; - left: calc(50% - 384px); - width: 768px; - max-height: calc(100% - 60px); + scrollbar-width: thin; + scrollbar-color: #343434 #999; } -} -.board-color-moderndark .card-details { - scrollbar-width: thin; - scrollbar-color: #343434 #999; -} -.board-color-moderndark .card-details::-webkit-scrollbar { - width: 16px; -} -.board-color-moderndark .card-details::-webkit-scrollbar-track { - background: #343434; -} -.board-color-moderndark .card-details::-webkit-scrollbar-thumb { - background-color: #999; - border-radius: 6px; - border: 4px solid #343434; -} -.board-color-moderndark .card-details .card-details-header { - background: #333; - color: #ccc; - border-bottom: 2px solid #2d2d2d; -} -.board-color-moderndark .card-details hr { - background: #2d2d2d; -} -.board-color-moderndark .card-details .card-details-item-title { - color: #fff; -} -.board-color-moderndark .card-details .new-description textarea, -.board-color-moderndark .card-details .new-comment textarea { - background-color: #ddd; - color: #111; -} -.board-color-moderndark .card-details .checklist { - background-color: transparent; - margin-bottom: 10px; -} -.board-color-moderndark .card-details .checklist-item { - background-color: rgba(255,255,255,0.1); - padding: 4px 8px; - border-radius: 2px; - font-size: 13px; - margin-top: 5px; -} -.board-color-moderndark .card-details .checklist-item:hover { - background-color: rgba(255,255,255,0.2); -} -.board-color-moderndark .card-details .checklist-item .item-title .viewer p { - max-width: auto; -} -.board-color-moderndark .card-details .check-box.materialCheckBox { - border-color: #fff; -} -.board-color-moderndark .card-details .check-box.materialCheckBox.is-checked { - border-bottom: 2px solid #fff; - border-right: 2px solid #fff; - border-top: 0; - border-left: 0; -} -.board-color-moderndark .card-details .js-add-checklist-item { - margin-top: 4px; -} -.board-color-moderndark .checklist-items .add-checklist-item { - margin-top: 0.7em; -} -.board-color-moderndark .card-details .activities .activity .activity-desc .activity-comment { - background-color: #ccc; - color: #222; -} -.board-color-moderndark .sidebar { - background-color: #222; - box-shadow: -10px 0 5px -10px #444; - border-left: 1px solid #333; - color: #ccc; -} -.board-color-moderndark .activities .activity .activity-desc .activity-comment { - background-color: #ccc; - color: #222; -} -.board-color-moderndark .activities .activity .activity-desc .activity-checklist { - background-color: #ccc; - color: #222; -} -.board-color-moderndark .attachments-gallery .attachment-item { - color: #222; -} -.board-color-moderndark .minicard-description { - color: #222; -} -.pop-over.board-color-moderndark { - background-color: #454545; - color: #ccc; - border: 1px solid #111; - box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2), 0 6px 20px 0 rgba(0,0,0,0.19); -} -.pop-over.board-color-moderndark .header { - background-color: #333; -} -.pop-over.board-color-moderndark .header-title { - /* font-family: Poppins; */ - font-size: 16px; - color: #ccc; -} -.pop-over.board-color-moderndark .pop-over-list li > a:hover { - background-color: rgba(255,255,255,0.2); -} - -/* Transparent moderndark scrollbar - moderndark*/ -.board-color-moderndark .board-canvas { - scrollbar-width: thin; - scrollbar-color: #343434f2 #999999f2; -} -/* Apply scrollbar to sidebar content*/ -.board-color-moderndark .sidebar .sidebar-content { - scrollbar-width: thin; - scrollbar-color: #343434f2 #999999f2; -} + .board-color-moderndark .card-details::-webkit-scrollbar-track { + background: #343434; + } -/* Remove margins in between columns/fix spacing */ + .board-color-moderndark .card-details::-webkit-scrollbar-thumb { + background-color: #999; + border-radius: 6px; + border: 4px solid #343434; + } -.board-color-moderndark .list { - border-left: none; - padding-bottom: 8px; -} + .board-color-moderndark .card-details .card-details-header { + background: #333; + color: #ccc; + border-bottom: 2px solid #2d2d2d; + } -.board-color-moderndark .list-body { - margin-top: 8px; -} + .board-color-moderndark .card-details hr { + background: #2d2d2d; + } -/* === END ModernDark THEME === */ + .board-color-moderndark .card-details .card-details-item-title { + color: #fff; + } + + .board-color-moderndark .card-details .new-description textarea, + .board-color-moderndark .card-details .new-comment textarea { + background-color: #ddd; + color: #111; + } + + .board-color-moderndark .card-details .checklist { + background-color: transparent; + } + + .board-color-moderndark .card-details .checklist-item { + background-color: rgba(255, 255, 255, 0.1); + border-radius: 2px; + + } + + .board-color-moderndark .card-details .checklist-item:hover { + background-color: rgba(255, 255, 255, 0.2); + } + + .board-color-moderndark .card-details .checklist-item .item-title .viewer p { + max-width: auto; + } + + .board-color-moderndark .card-details .check-box.materialCheckBox { + border-color: #fff; + } + + .board-color-moderndark .card-details .check-box.materialCheckBox.is-checked { + border-bottom: 2px solid #fff; + border-right: 2px solid #fff; + border-top: 0; + border-left: 0; + } + + .board-color-moderndark .card-details .activities .activity .activity-desc .activity-comment { + background-color: #ccc; + color: #222; + } + + .board-color-moderndark .sidebar { + background-color: #222; + box-shadow: -10px 0 5px -10px #444; + border-left: 1px solid #333; + color: #ccc; + } + + .board-color-moderndark .activities .activity .activity-desc .activity-comment { + background-color: #ccc; + color: #222; + } + + .board-color-moderndark .activities .activity .activity-desc .activity-checklist { + background-color: #ccc; + color: #222; + } + + .board-color-moderndark .attachments-gallery .attachment-item { + color: #222; + } + + .board-color-moderndark .minicard-description { + color: #222; + } + + .pop-over.board-color-moderndark { + background-color: #454545; + color: #ccc; + border: 1px solid #111; + box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); + } + + .pop-over.board-color-moderndark .header { + background-color: #333; + } + + .pop-over.board-color-moderndark .header-title { + /* font-family: Poppins; */ + + color: #ccc; + } + + .pop-over.board-color-moderndark .pop-over-list li > a:hover { + background-color: rgba(255, 255, 255, 0.2); + } + + /* Transparent moderndark scrollbar - moderndark*/ + .board-color-moderndark .board-canvas { + scrollbar-width: thin; + scrollbar-color: #343434f2 #999999f2; + } -/* =============== + /* Apply scrollbar to sidebar content*/ + .board-color-moderndark .sidebar .sidebar-content { + scrollbar-width: thin; + scrollbar-color: #343434f2 #999999f2; + } + + /* Remove margins in between columns/fix spacing */ + + .board-color-moderndark .list { + border-left: none; + } + + + + /* === END ModernDark THEME === */ + + + /* =============== THEME - Exodark =================*/ -.board-color-exodark#header, -.board-color-exodark.sk-spinner div, -.board-backgrounds-list .board-color-exodark.background-box, -.board-list .board-color-exodark a { - background-color: #222; -} -.board-color-exodark .is-selected .minicard { - border-left: 3px solid #222; -} -.board-color-exodark .minicard { - border-radius: 7px; - padding: 10px 10px 4px 10px; - box-shadow: 2px 2px 4px 0px rgba(0,0,0,0.15); -} -.board-color-exodark button[type=submit].primary, -.board-color-exodark input[type=submit].primary, -.board-color-exodark .sidebar .sidebar-content .sidebar-btn { - background-color: #1b1b1b; - border-radius: 7px; -} -.board-color-exodark.pop-over .pop-over-list li a:not(.disabled):hover, -.board-color-exodark .sidebar .sidebar-content .sidebar-btn:hover, -.board-color-exodark .sidebar-list li a:hover { - background-color: #383838; -} -.board-color-exodark#header ul li.current, -.board-color-exodark#header-quick-access ul li.current { - border-bottom: 2px solid #383838; -} -.board-color-exodark#header-quick-access { - background: #1f1f1f; - color: #fff; -} -.board-color-exodark#header #header-main-bar .board-header-btn.emphasis { - background: #222; -} -.board-color-exodark#header #header-main-bar .board-header-btn.emphasis:hover, -.board-color-exodark#header #header-main-bar .board-header-btn.emphasis .board-header-btn-close { - background: #1f1f1f; -} -.board-color-exodark#header #header-main-bar .board-header-btn.emphasis:hover .board-header-btn-close { - background: #1b1b1b; -} -.board-color-exodark .materialCheckBox.is-checked { - border-bottom: 2px solid #dbdbdb!important;/*Fix contrast of checkbox*/ - border-right: 2px solid #dbdbdb!important; -} + .board-color-exodark#header, + .board-color-exodark.sk-spinner div, + .board-backgrounds-list .board-color-exodark.background-box, + .board-list .board-color-exodark a { + background-color: #222; + } + + .board-color-exodark .is-selected .minicard { + border-left: 3px solid #222; + } + + .board-color-exodark .minicard { + border-radius: 0.6ch; + box-shadow: 2px 2px 4px 0px rgba(0, 0, 0, 0.15); + } + + .board-color-exodark button[type=submit].primary, + .board-color-exodark input[type=submit].primary, + .board-color-exodark .sidebar .sidebar-content .sidebar-btn { + background-color: #1b1b1b; + border-radius: 0.6ch; + } + + .board-color-exodark.pop-over .pop-over-list li a:not(.disabled):hover, + .board-color-exodark .sidebar .sidebar-content .sidebar-btn:hover, + .board-color-exodark .sidebar-list li a:hover { + background-color: #383838; + } + + .board-color-exodark#header ul li.current, + .board-color-exodark#header-quick-access ul li.current { + border-bottom: 2px solid #383838; + } + + .board-color-exodark#header-quick-access { + background: #1f1f1f; + color: #fff; + } + + .board-color-exodark#header #header-main-bar .board-header-btn.emphasis { + background: #222; + } + + .board-color-exodark#header #header-main-bar .board-header-btn.emphasis:hover, + .board-color-exodark#header #header-main-bar .board-header-btn.emphasis .board-header-btn-close { + background: #1f1f1f; + } + + .board-color-exodark#header #header-main-bar .board-header-btn.emphasis:hover .board-header-btn-close { + background: #1b1b1b; + } + + .board-color-exodark .materialCheckBox.is-checked { + 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; -} -.board-color-exodark .is-multiselection-active .multi-selection-checkbox:not(.is-checked) + .minicard:hover:not(.minicard-composer) { - background: #f8f8f8; -} -.board-color-exodark .toggle-label:after { - background-color: #1b1b1b; -} -.board-color-exodark .toggle-switch:checked ~ .toggle-label { - background-color: #4e4e4e; -} -.board-color-exodark .toggle-switch:checked ~ .toggle-label:after { - background-color: #1b1b1b; -} -@media screen and (max-width: 800px) { - .board-color-exodark.pop-over .header { - background: #222; - color: #fff; + + .board-color-exodark .is-multiselection-active .multi-selection-checkbox.is-checked + .minicard { + background: #e9e9e9; } -} -.board-color-exodark#header ul li.current, -.board-color-exodark#header-quick-access ul li.current { - border-bottom: 4px solid #4e4e4e; -} -.board-color-exodark body { - background: #222; -} -/* Uncomment to fix change color selected checkmark not visible + + .board-color-exodark .is-multiselection-active .multi-selection-checkbox:not(.is-checked) + .minicard:hover:not(.minicard-composer) { + background: #f8f8f8; + } + + .board-color-exodark .toggle-label:after { + background-color: #1b1b1b; + } + + .board-color-exodark .toggle-switch:checked ~ .toggle-label { + background-color: #4e4e4e; + } + + .board-color-exodark .toggle-switch:checked ~ .toggle-label:after { + background-color: #1b1b1b; + } + + @media screen and (max-width: 800px) { + .board-color-exodark.pop-over .header { + background: #222; + color: #fff; + } + } + + .board-color-exodark#header ul li.current, + .board-color-exodark#header-quick-access ul li.current { + border-bottom: 4px solid #4e4e4e; + } + + .board-color-exodark body { + background: #222; + } + + /* Uncomment to fix change color selected checkmark not visible .board-color-exodark i { color: #fff !important; } */ -.board-color-exodark.board-wrapper { - background: #222; - /* font-family: Poppins; */ -} -.board-color-exodark .swimlane { - background: #222; -} -.board-color-exodark .list { - margin: 10px 0; - color: #fff; - border-radius: 15px; - background-color: #1c1c1c; - border: none; -} -.board-color-exodark .swimlane .list:first-child { - min-width: 20px; - margin-left: 10px; /*Added 10px margin to prevent butting up against edge of screen */ - border-left: none; -} -.board-color-exodark .swimlane .list:nth-child { - flex: 0 0 265px; -} -.board-color-exodark .list.list-composer.js-list-composer { - transition: all 0.3s ease; - min-width: 0; -} -.board-color-exodark .list-header { - border-top-right-radius: 15px; - border-top-left-radius: 15px; - background: #222; - box-shadow: inset 15px 15px 37px #1c1c1c, inset -15px -15px 37px #282828; -} -.board-color-exodark .list-header-menu a { - color: #00897b !important; -} -.board-color-exodark .is-selected .minicard { - color: #fff; - background: #2b2b2b; - border: 1px solid #00897b; -} -.board-color-exodark .minicard { - color: #fff; - background: #2b2b2b; -} -.board-color-exodark .list-body .open-minicard-composer:hover { - background: #2b2b2b; - border: 1px solid #00897b; - border-radius: 10px; -} -.board-color-exodark .badges { - color: #fff; -} -.board-color-exodark .minicard textarea { - color: #fff; -} -.board-color-exodark .minicard .minicard-description { - background: #2b2b2b; - border: 1px solid #00897b; -} -.board-color-exodark .minicard:hover:not(.minicard-composer) { - border: 1px solid #00897b; - background: #2b2b2b; - padding: 9px 9px 3px 9px; /*because of the 1px border we need to reduce padding by 1px*/ -} -.board-color-exodark .card-details { - background: #2b2b2b !important; - color: #fff; -} -.board-color-exodark .card-details .comment-text { - color:#2b2b2b -} /*Fixes issue with comment text colour blending into background*/ -.board-color-exodark .card-details .card-details-header { - background: #2b2b2b; - color: #fff; -} -.board-color-exodark .sidebar-content { - background: #2b2b2b; - color: #fff; -} -.board-color-exodark .card-details, -.board-color-exodark .sidebar-content { - box-shadow: 0 0 7px 0 #00897b; -} -.board-color-exodark .attachments-gallery .attachment-item { - background: #2b2b2b; -} -.board-color-exodark .attachments-gallery .attachment-item:hover { - border: 1px solid #00897b; - background: #2b2b2b; -} -.board-color-exodark .checklist { - background: #2b2b2b; -} -.board-color-exodark .checklist .checklist-item { - background: #2b2b2b; -} -.board-color-exodark .checklist .checklist-item:hover { - background: #2b2b2b; -} -.board-color-exodark .add-checklist-item.js-open-inlined-form:hover { - background: #2b2b2b; - border: 1px solid #00897b; -} -.board-color-exodark .add-checklist.js-open-inlined-form:hover { - background: #2b2b2b; - border: 1px solid #00897b; -} -.board-color-exodark .card-details > h1, -.board-color-exodark h2, -.board-color-exodark h3, -.board-color-exodark h4, -.board-color-exodark h5, -.board-color-exodark h6, -/* Below added .card-details > to p/a/span to fix white swimlane text not visible + .board-color-exodark.board-wrapper { + background: #222; + /* font-family: Poppins; */ + } + + .board-color-exodark .swimlane { + background: #222; + } + + .board-color-exodark .list { + color: #fff; + border-radius: 15px; + background-color: #1c1c1c; + border: none; + } + + .board-color-exodark .swimlane .list:first-child { + border-left: none; + } + + + .board-color-exodark .list.list-composer.js-list-composer { + transition: all 0.3s ease; + min-width: 0; + } + + .board-color-exodark .list-header { + border-top-right-radius: 15px; + border-top-left-radius: 15px; + background: #222; + box-shadow: inset 15px 15px 37px #1c1c1c, inset -15px -15px 37px #282828; + } + + .board-color-exodark .list-header-menu a { + color: #00897b !important; + } + + .board-color-exodark .is-selected .minicard { + color: #fff; + background: #2b2b2b; + border: 1px solid #00897b; + } + + .board-color-exodark .minicard { + color: #fff; + background: #2b2b2b; + } + + .board-color-exodark .list-body .open-minicard-composer:hover { + background: #2b2b2b; + border: 1px solid #00897b; + border-radius: 10px; + } + + .board-color-exodark .badges { + color: #fff; + } + + .board-color-exodark .minicard textarea { + color: #fff; + } + + .board-color-exodark .minicard .minicard-description { + background: #2b2b2b; + border: 1px solid #00897b; + } + + .board-color-exodark .minicard:hover:not(.minicard-composer) { + border: 1px solid #00897b; + background: #2b2b2b; + } + + .board-color-exodark .card-details { + background: #2b2b2b !important; + color: #fff; + } + + .board-color-exodark .card-details .comment-text { + color:#2b2b2b + } + + /*Fixes issue with comment text colour blending into background*/ + .board-color-exodark .card-details .card-details-header { + background: #2b2b2b; + color: #fff; + } + + .board-color-exodark .sidebar-content { + background: #2b2b2b; + color: #fff; + } + + .board-color-exodark .card-details, + .board-color-exodark .sidebar-content { + box-shadow: 0 0 7px 0 #00897b; + } + + .board-color-exodark .attachments-gallery .attachment-item { + background: #2b2b2b; + } + + .board-color-exodark .attachments-gallery .attachment-item:hover { + border: 1px solid #00897b; + background: #2b2b2b; + } + + .board-color-exodark .checklist { + background: #2b2b2b; + } + + .board-color-exodark .checklist .checklist-item { + background: #2b2b2b; + } + + .board-color-exodark .checklist .checklist-item:hover { + background: #2b2b2b; + } + + .board-color-exodark .add-checklist-item.js-open-inlined-form:hover { + background: #2b2b2b; + border: 1px solid #00897b; + } + + .board-color-exodark .add-checklist.js-open-inlined-form:hover { + background: #2b2b2b; + border: 1px solid #00897b; + } + + .board-color-exodark .card-details > h1, + .board-color-exodark h2, + .board-color-exodark h3, + .board-color-exodark h4, + .board-color-exodark h5, + .board-color-exodark h6, + /* Below added .card-details > to p/a/span to fix white swimlane text not visible https://github.com/wekan/wekan/issues/4451 */ -.board-color-exodark .card-details > p, -.board-color-exodark .card-details > a, -.board-color-exodark .card-details > span { - color: #fff !important; -} -.board-color-exodark .activity-desc { - background-color: #2b2b2b !important; -} -.board-color-exodark .activity-checklist { - background: #2b2b2b !important; - border: 1px solid #00897b; -} -.board-color-exodark .activity-comment { - background: #2b2b2b !important; - border: 1px solid #00897b; -} -.board-color-exodark .toggle-switch:checked ~ .toggle-label { - background-color: #fff !important; -} -.pop-over.board-color-exodark { - background: #2b2b2b; - color: #fff; -} -.pop-over.board-color-exodark .header { - background: #2b2b2b; - color: #fff; -} + .board-color-exodark .card-details > p, + .board-color-exodark .card-details > a, + .board-color-exodark .card-details > span { + color: #fff !important; + } -/* Transparent modern scrollbar - Exodark*/ -.board-color-exodark .list-body { - scrollbar-color: #e4e4e4d4 #202020ba; -} + .board-color-exodark .activity-desc { + background-color: #2b2b2b !important; + } -.board-color-exodark .list { - overflow: hidden; -} + .board-color-exodark .activity-checklist { + background: #2b2b2b !important; + border: 1px solid #00897b; + } -.board-color-exodark .board-canvas { - scrollbar-color: #e4e4e4d4 #202020ba; -} + .board-color-exodark .activity-comment { + background: #2b2b2b !important; + border: 1px solid #00897b; + } -/* Apply scrollbar to sidebar content*/ -.board-color-exodark .sidebar .sidebar-content { - scrollbar-color: #e4e4e4d4 #202020ba; -} + .board-color-exodark .toggle-switch:checked ~ .toggle-label { + background-color: #fff !important; + } -/* === END Exodark THEME === */ + .pop-over.board-color-exodark { + background: #2b2b2b; + color: #fff; + } -/* =============== + .pop-over.board-color-exodark .header { + background: #2b2b2b; + color: #fff; + } + + /* Transparent modern scrollbar - Exodark*/ + .board-color-exodark .list-body { + scrollbar-color: #e4e4e4d4 #202020ba; + } + + .board-color-exodark .list { + overflow: hidden; + } + + .board-color-exodark .board-canvas { + scrollbar-color: #e4e4e4d4 #202020ba; + } + + /* Apply scrollbar to sidebar content*/ + .board-color-exodark .sidebar .sidebar-content { + scrollbar-color: #e4e4e4d4 #202020ba; + } + + /* === END Exodark THEME === */ + + /* =============== THEME - Clean Dark =================*/ -.board-color-cleandark#header ul li, -.board-color-cleandark#header-quick-access ul li { - color: rgba(255, 255, 255, 50%); - font-size: 16px; - font-weight: 400; - line-height: 24px; -} - -.board-color-cleandark#header-main-bar h1 { - font-size: 16px; - font-weight: 500; - line-height: 24px !important; - color: rgba(255, 255, 255, 1); -} - -.board-color-cleandark#header ul li.current, -.board-color-cleandark#header-quick-access ul li.current { - color: rgba(255, 255, 255, 85%); -} - -.board-color-cleandark .swimlane-header { - font-size: 16px; - font-weight: 500; - line-height: 24px; - color: rgba(255, 255, 255, 1); -} - -.board-color-cleandark.board-wrapper { - background: #0A0A14; -} - -.board-color-cleandark .sidebar { - background: rgba(35, 35, 43, 1) !important; - box-shadow: none; -} - -.board-color-cleandark .sidebar hr { - background:rgba(255, 255, 255, 0.05); -} - -.board-color-cleandark .sidebar .tab-item { - border-radius: 16px; - padding: 4px 12px 4px 12px; - font-size: 16px; - font-weight: 400; - line-height: 24px; - color: rgba(255, 255, 255, 0.85); - background: rgba(57, 57, 71, 1); -} - -.board-color-cleandark .sidebar .tab-item.active { - background: rgba(255, 255, 255, 1); - color: rgba(10, 10, 20, 1); - border: none; - padding: 4px 12px 4px 12px !important; -} - -.board-color-cleandark .sidebar .tabs-content-container { - border: none; -} - -.board-color-cleandark .card-details { - background: #23232B; - scrollbar-color: #ffffff #2e2e39; - border-radius: 20px; - box-shadow: none; -} - -.board-color-cleandark .card-details-item a { - font-size: 16px; - font-weight: 400; - line-height: 24px; - color: rgba(255, 255, 255, 0.5); -} - -.board-color-cleandark .add-assignee { - box-shadow: none !important; -} - -.board-color-cleandark .add-assignee:hover { - background: #444455; - border-radius: 8px; -} - -.board-color-cleandark .add-checklist-top { - display: none !important; -} - -.board-color-cleandark .add-checklist { - padding: 8px; - width: min-content !important; -} - -.board-color-cleandark .add-checklist:hover { - background: #444455 !important; - border-radius: 12px !important; -} - -.board-color-cleandark .add-checklist:hover i { - color: #FFFFFF !important; -} - -.board-color-cleandark .add-assignee:hover i { - color: #FFFFFF !important; -} - -.board-color-cleandark .card-time.card-label-green { - background: #009B64; - width: min-content; - color: #FFFFFF; - padding-left: 8px; - padding-right: 8px; - border-radius: 8px; - margin-left: 4px; -} - -.board-color-cleandark .card-details hr { - background: rgba(255, 255, 255, 0.05); -} - -.board-color-cleandark .card-details-canvas { - font-size: 16px; - font-weight: 400; - line-height: 24px; - color: rgba(255, 255, 255, 0.85); -} - -.board-color-cleandark.pop-over { - border-radius: 12px; - border: none; - background: rgba(46, 46, 57, 1); -} - -.board-color-cleandark.pop-over .pop-over-list, -.board-color-cleandark.pop-over .content { - font-size: 16px; - font-weight: 400; - line-height: 24px; - color: rgba(255, 255, 255, 1); -} - -.board-color-cleandark.pop-over .pop-over-list a:hover { - background: #393947 !important; -} - -.board-color-cleandark .member { - box-shadow: none !important; -} - -.board-color-cleandark .add-member:hover { - background: #444455; - border-radius: 8px; -} - -.board-color-cleandark .add-member:hover i { - color: #FFFFFF !important; -} - -.board-color-cleandark .add-label { - box-shadow: none !important; -} - -.board-color-cleandark .add-label:hover { - background: #444455; - border-radius: 8px; -} - -.board-color-cleandark .add-label:hover i { - color: #FFFFFF !important; -} - -.board-color-cleandark.pop-over .content kbd { - background: rgba(46, 46, 57, 1); -} - -.board-color-cleandark .full-name { - font-size: 16px; - font-weight: 500; - line-height: 24px; - - color: rgba(255, 255, 255, 0.85); -} - -.board-color-cleandark .username { - font-size: 16px; - font-weight: 400; - line-height: 24px; - - color: rgba(255, 255, 255, 0.7); -} - -.board-color-cleandark .attachment-item:hover { - background: rgba(46, 46, 57, 1); -} - -.board-color-cleandark .checklist { - background: none; - color: #FFFFFF; -} - -.board-color-cleandark .checklist-item { - background: none; -} - -.board-color-cleandark .checklist-item:hover { - background: rgba(46, 46, 57, 1) !important; -} - -.board-color-cleandark .add-checklist-item { - width: min-content !important; - padding: 8px; -} - -.board-color-cleandark .add-checklist-item:hover { - background: #444455 !important; - border-radius: 12px !important; -} - -.board-color-cleandark .add-checklist-item:hover i { - color: #FFFFFF !important; -} - -.board-color-cleandark .add-attachment { - border-radius: 12px; -} - -.board-color-cleandark .add-attachment:hover i { - color: #FFFFFF !important; -} - -.board-color-cleandark .attachment-actions i, -.board-color-cleandark .attachment-actions a { - font-size: 1em !important; -} - -.board-color-cleandark .activity-desc { - font-size: 16px; - font-weight: 400; - line-height: 24px; - color: rgba(255, 255, 255, 0.5); -} - -.board-color-cleandark .activity-desc .activity-member { - color: rgba(255, 255, 255, 0.85); -} - -.board-color-cleandark .comments .comment .comment-desc .comment-text { - background: transparent; -} - -.board-color-cleandark .activity-checklist, -.board-color-cleandark .activity-comment { - background: none !important; - color: #FFFFFF; - border: 1px solid rgba(0, 155, 100, 1); - border-radius: 12px !important; -} - -.board-color-cleandark button[type=submit].primary, -.board-color-cleandark input[type=submit].primary { - font-size: 16px; - font-weight: 400; - line-height: 24px; - border-radius: 12px; - padding: 6px 12px 6px 12px; - background: #FFFFFF; - color: rgba(10, 10, 20, 0.85); -} - -.board-color-cleandark textarea { - font-size: 16px; - font-weight: 400; - line-height: 24px; - color: rgba(255, 255, 255, 1); - background: rgba(57, 57, 71, 1) !important; - border: none !important; - border-radius: 12px !important; -} - -.board-color-cleandark textarea::placeholder { - color: rgba(255, 255, 255, 0.85) !important; -} - -.board-color-cleandark input { - font-size: 16px; - font-weight: 400; - line-height: 24px; - color: rgba(255, 255, 255, 0.85) !important; - background: rgba(57, 57, 71, 1) !important; - border-radius: 12px !important; - border: none !important; -} - -.board-color-cleandark input::placeholder { - color: rgba(255, 255, 255, 1) !important; -} - -.board-color-cleandark select { - font-size: 16px; - font-weight: 400; - line-height: 24px; - color: rgba(255, 255, 255, 0.85); - background: rgba(57, 57, 71, 1); - border-radius: 12px; - border: none; -} - -.board-color-cleandark button.primary { - padding: 6px 12px 6px 12px; - border-radius: 12px; - border: none; - background: #FFFFFF; - font-size: 16px; - font-weight: 400; - line-height: 24px; - color: rgba(10, 10, 20, 0.85); -} - -.board-color-cleandark button.primary:hover { - background: rgba(255, 255, 255, 0.85); -} - -.board-color-cleandark button.negate { - padding: 6px 12px 6px 12px; - border-radius: 12px; - border: none; - background: #cc003a; - font-size: 16px; - font-weight: 400; - line-height: 24px; - color: #FFFFFF; -} - -.board-color-cleandark button.negate:hover { - background: rgba(204, 0, 58, 0.77); -} - -.board-color-cleandark .card-details .checklist-item { - display: flex; - align-items: center; - gap: 4px; -} - -.board-color-cleandark .card-details .check-box.materialCheckBox { - border-radius: 4px; - border: none; - background: #393947; - height: 24px; - width: 24px; -} - -.board-color-cleandark .card-details .check-box.materialCheckBox.is-checked { - border-bottom: 2px solid #FFFFFF; - border-right: 2px solid #FFFFFF; - width: 11px; - height: 19px; - border-radius: 0; - background: none; -} - -.board-color-cleandark .sidebar .sidebar-content h3, -.board-color-cleandark .sidebar .sidebar-content h2, -.board-color-cleandark .sidebar .sidebar-content h1 { - color: #FFFFFF; -} - -.board-color-cleandark #cards span { - color: #FFFFFF; -} - -.board-color-cleandark #cards .materialCheckBox { - border-radius: 4px; - border: none; - background: #393947; - height: 18px; - width: 18px; -} - -.board-color-cleandark .sidebar-list-item-description { - color: #FFFFFF; -} - -.board-color-cleandark #cards .materialCheckBox.is-checked { - border-bottom: 2px solid #FFFFFF; - border-right: 2px solid #FFFFFF; - width: 5px; - height: 13px; - border-radius: 0; - background: none; - margin-left: 3px; - margin-top: 3px; -} + .board-color-cleandark#header ul li, + .board-color-cleandark#header-quick-access ul li { + color: rgba(255, 255, 255, 50%); + + font-weight: 400; + } + + .board-color-cleandark#header-main-bar h1 { + font-weight: 500; + color: rgba(255, 255, 255, 1); + } + + .board-color-cleandark#header ul li.current, + .board-color-cleandark#header-quick-access ul li.current { + color: rgba(255, 255, 255, 85%); + } + + .board-color-cleandark .swimlane-header { + font-weight: 500; + color: rgba(255, 255, 255, 1); + } + + .board-color-cleandark.board-wrapper { + background: #0A0A14; + } + + .board-color-cleandark .sidebar { + background: rgba(35, 35, 43, 1) !important; + box-shadow: none; + } + + .board-color-cleandark .sidebar hr { + background:rgba(255, 255, 255, 0.05); + } + + .board-color-cleandark .sidebar .tab-item { + border-radius: 16px; + + font-weight: 400; + color: rgba(255, 255, 255, 0.85); + background: rgba(57, 57, 71, 1); + } + + .board-color-cleandark .sidebar .tab-item.active { + background: rgba(255, 255, 255, 1); + color: rgba(10, 10, 20, 1); + border: none; + } + + .board-color-cleandark .sidebar .tabs-content-container { + border: none; + } + + .board-color-cleandark .card-details { + background: #23232B; + scrollbar-color: #ffffff #2e2e39; + border-radius: 20px; + box-shadow: none; + } + + .board-color-cleandark .card-details-item a { + font-weight: 400; + color: rgba(255, 255, 255, 0.5); + } + + .board-color-cleandark .add-assignee { + box-shadow: none !important; + } + + .board-color-cleandark .add-assignee:hover { + background: #444455; + border-radius: 0.8ch; + } + + .board-color-cleandark .add-checklist-top { + display: none !important; + } + + .board-color-cleandark .add-checklist { + width: min-content !important; + } + + .board-color-cleandark .add-checklist:hover { + background: #444455 !important; + border-radius: 12px !important; + } + + .board-color-cleandark .add-checklist:hover i { + color: #FFFFFF !important; + } + + .board-color-cleandark .add-assignee:hover i { + color: #FFFFFF !important; + } + + .board-color-cleandark .card-time.card-label-green { + background: #009B64; + width: min-content; + color: #FFFFFF; + border-radius: 0.8ch; + } + + .board-color-cleandark .card-details hr { + background: rgba(255, 255, 255, 0.05); + } + + .board-color-cleandark .card-details-canvas { + font-weight: 400; + color: rgba(255, 255, 255, 0.85); + } + + .board-color-cleandark.pop-over { + border-radius: 12px; + border: none; + background: rgba(46, 46, 57, 1); + } + + .board-color-cleandark.pop-over .pop-over-list, + .board-color-cleandark.pop-over .content { + + font-weight: 400; + color: rgba(255, 255, 255, 1); + } + + .board-color-cleandark.pop-over .pop-over-list a:hover { + background: #393947 !important; + } + + .board-color-cleandark .member { + box-shadow: none !important; + } + + .board-color-cleandark .add-member:hover { + background: #444455; + border-radius: 0.8ch; + } + + .board-color-cleandark .add-member:hover i { + color: #FFFFFF !important; + } + + .board-color-cleandark .add-label { + box-shadow: none !important; + } + + .board-color-cleandark .add-label:hover { + background: #444455; + border-radius: 0.8ch; + } + + .board-color-cleandark .add-label:hover i { + color: #FFFFFF !important; + } + + .board-color-cleandark.pop-over .content kbd { + background: rgba(46, 46, 57, 1); + } + + .board-color-cleandark .full-name { + + font-weight: 500; + + color: rgba(255, 255, 255, 0.85); + } + + .board-color-cleandark .username { + + font-weight: 400; + + color: rgba(255, 255, 255, 0.7); + } + + .board-color-cleandark .attachment-item:hover { + background: rgba(46, 46, 57, 1); + } + + .board-color-cleandark .checklist { + background: none; + color: #FFFFFF; + } + + .board-color-cleandark .checklist-item { + background: none; + } + + .board-color-cleandark .checklist-item:hover { + background: rgba(46, 46, 57, 1) !important; + } + + .board-color-cleandark .add-checklist-item { + width: min-content !important; + } + + .board-color-cleandark .add-checklist-item:hover { + background: #444455 !important; + border-radius: 12px !important; + } + + .board-color-cleandark .add-checklist-item:hover i { + color: #FFFFFF !important; + } + + .board-color-cleandark .add-attachment { + border-radius: 12px; + } + + .board-color-cleandark .add-attachment:hover i { + color: #FFFFFF !important; + } + + + .board-color-cleandark .activity-desc { + font-weight: 400; + color: rgba(255, 255, 255, 0.5); + } + + .board-color-cleandark .activity-desc .activity-member { + color: rgba(255, 255, 255, 0.85); + } + + .board-color-cleandark .comments .comment .comment-desc .comment-text { + background: transparent; + } + + .board-color-cleandark .activity-checklist, + .board-color-cleandark .activity-comment { + background: none !important; + color: #FFFFFF; + border: 1px solid rgba(0, 155, 100, 1); + border-radius: 12px !important; + } + + .board-color-cleandark button[type=submit].primary, + .board-color-cleandark input[type=submit].primary { + + font-weight: 400; + border-radius: 12px; + background: #FFFFFF; + color: rgba(10, 10, 20, 0.85); + } + + .board-color-cleandark textarea { + font-weight: 400; + color: rgba(255, 255, 255, 1); + background: rgba(57, 57, 71, 1) !important; + border: none !important; + border-radius: 12px !important; + } + + .board-color-cleandark textarea::placeholder { + color: rgba(255, 255, 255, 0.85) !important; + } + + .board-color-cleandark input { + font-weight: 400; + color: rgba(255, 255, 255, 0.85) !important; + background: rgba(57, 57, 71, 1) !important; + border-radius: 12px !important; + border: none !important; + } + + .board-color-cleandark input::placeholder { + color: rgba(255, 255, 255, 1) !important; + } + + .board-color-cleandark select { + font-weight: 400; + color: rgba(255, 255, 255, 0.85); + background: rgba(57, 57, 71, 1); + border-radius: 12px; + border: none; + } + + .board-color-cleandark button.primary { + border-radius: 12px; + border: none; + background: #FFFFFF; + + font-weight: 400; + color: rgba(10, 10, 20, 0.85); + } + + .board-color-cleandark button.primary:hover { + background: rgba(255, 255, 255, 0.85); + } + + .board-color-cleandark button.negate { + border-radius: 12px; + border: none; + background: #cc003a; + + font-weight: 400; + color: #FFFFFF; + } + + .board-color-cleandark button.negate:hover { + background: rgba(204, 0, 58, 0.77); + } + + .board-color-cleandark .card-details .checklist-item { + display: flex; + align-items: center; + } + + .board-color-cleandark .card-details .check-box.materialCheckBox { + border-radius: 0.4ch; + border: none; + background: #393947; + } + + .board-color-cleandark .card-details .check-box.materialCheckBox.is-checked { + border-bottom: 2px solid #FFFFFF; + border-right: 2px solid #FFFFFF; + border-radius: 0; + background: none; + } + + .board-color-cleandark .sidebar .sidebar-content h3, + .board-color-cleandark .sidebar .sidebar-content h2, + .board-color-cleandark .sidebar .sidebar-content h1 { + color: #FFFFFF; + } + + .board-color-cleandark #cards span { + color: #FFFFFF; + } + + .board-color-cleandark #cards .materialCheckBox { + border-radius: 0.4ch; + border: none; + background: #393947; + } + + .board-color-cleandark .sidebar-list-item-description { + color: #FFFFFF; + } + + .board-color-cleandark #cards .materialCheckBox.is-checked { + border-bottom: 2px solid #FFFFFF; + border-right: 2px solid #FFFFFF; + border-radius: 0; + background: none; + } .board-color-cleandark .checklist-progress-bar { background-color: #6b6b78 !important; } @@ -3249,757 +3370,668 @@ THEME - Clean Dark background-color: #23232B !important; } -.board-color-cleandark .allBoards { - white-space: nowrap; -} + .board-color-cleandark .allBoards { + white-space: nowrap; + } -.board-color-cleandark#header-quick-access ul.header-quick-access-list li { - display: inline-flex; - align-items: center; - padding-bottom: 4px; - padding-top: 4px; - margin-right: 10px; -} + .board-color-cleandark#header-quick-access ul.header-quick-access-list li { + display: inline-flex; + align-items: center; + } -.board-color-cleandark#header-quick-access ul.header-quick-access-list { - display: flex; - align-items: center; -} + .board-color-cleandark#header-quick-access ul.header-quick-access-list { + display: flex; + align-items: center; + } -/* Transparent modern scrollbar - cleandark*/ -.board-color-cleandark .board-canvas { - scrollbar-color: #23232be6 #e4e4e400; -} + /* Transparent modern scrollbar - cleandark*/ + .board-color-cleandark .board-canvas { + scrollbar-color: #23232be6 #e4e4e400; + } -/* Apply scrollbar to sidebar content*/ -.board-color-cleandark .sidebar .sidebar-content { - scrollbar-color: #ff6d00 #e4e4e400; -} + /* Apply scrollbar to sidebar content*/ + .board-color-cleandark .sidebar .sidebar-content { + scrollbar-color: #ff6d00 #e4e4e400; + } -/* Remove margins in between columns/fix spacing */ + /* Remove margins in between columns/fix spacing */ -.board-color-cleandark .list { - border-left: none; - padding-bottom: 8px; -} + .board-color-cleandark .list { + border-left: none; + } -.board-color-cleandark .list-body { - margin-top: 8px; -} -.board-color-cleandark.background-box { - background-color:#23232B; -} /*Fixes contrast issues with background box in theme selection list*/ -/* =============== + + .board-color-cleandark.background-box { + background-color:#23232B; + } + + /*Fixes contrast issues with background box in theme selection list*/ + /* =============== THEME - Clean Light =================*/ -/* Please note Clean Light theme elements also contain references to some cleandark theme elements so if unable to find code you're looking for under CleanDark it might be here. This should probably be cleaned up*/ -.board-color-cleanlight.background-box { - background-color:#e0e0e0; - color:#010101!important; -} /*Fixes issues with text colour/background box being similar no contrast */ + /* Please note Clean Light theme elements also contain references to some cleandark theme elements so if unable to find code you're looking for under CleanDark it might be here. This should probably be cleaned up*/ + .board-color-cleanlight.background-box { + background-color:#e0e0e0; + color:#010101 !important; + } -.board-color-cleanlight { - background: #E0E0E0; -} + /*Fixes issues with text colour/background box being similar no contrast */ -.board-color-cleanlight .board-header-btn { - color: rgba(10, 10, 20, 0.85) !important; -} + .board-color-cleanlight { + background: #E0E0E0; + } -.board-color-cleanlight .board-header-btn i { - color: rgba(10, 10, 20, 0.85) !important; -} + .board-color-cleanlight .board-header-btn { + color: rgba(10, 10, 20, 0.85) !important; + } -.board-color-cleanlight .board-header-btns a { - color: rgba(10, 10, 20, 0.85) !important; -} + .board-color-cleanlight .board-header-btn i { + color: rgba(10, 10, 20, 0.85) !important; + } -.board-color-cleanlight .header-user-bar-name { - color: rgba(10, 10, 20, 0.85) !important; -} + .board-color-cleanlight .board-header-btns a { + color: rgba(10, 10, 20, 0.85) !important; + } -.board-color-cleanlight#header ul li, -.board-color-cleanlight#header-quick-access ul li { - color: rgba(10, 10, 20, 0.5) !important; - font-size: 16px; - font-weight: 400; - line-height: 24px; -} + .board-color-cleanlight .header-user-bar-name { + color: rgba(10, 10, 20, 0.85) !important; + } -.board-color-cleanlight#header ul li:hover, -.board-color-cleanlight#header-quick-access ul li:hover { - background: rgba(190, 190, 190, 1) !important; - border-radius: 8px; - color: rgba(10, 10, 20, 0.5) !important; -} + .board-color-cleanlight#header ul li, + .board-color-cleanlight#header-quick-access ul li { + color: rgba(10, 10, 20, 0.5) !important; -.board-color-cleanlight #header-main-bar h1 { - font-size: 16px; - font-weight: 500; - line-height: 24px !important; - color: rgba(10, 10, 20, 1) !important; -} + font-weight: 400; + } -.board-color-cleanlight#header ul li.current, -.board-color-cleanlight#header-quick-access ul li.current { - color: rgba(10, 10, 20, 0.85) !important; -} + .board-color-cleanlight#header ul li:hover, + .board-color-cleanlight#header-quick-access ul li:hover { + background: rgba(190, 190, 190, 1) !important; + border-radius: 0.8ch; + color: rgba(10, 10, 20, 0.5) !important; + } -.board-color-cleanlight .swimlane-header { - font-size: 16px; - font-weight: 500; - line-height: 24px; - color: rgba(10, 10, 20, 1); -} + .board-color-cleanlight #header-main-bar h1 { + font-weight: 500; + color: rgba(10, 10, 20, 1) !important; + } -.board-color-cleanlight.board-wrapper { - background: #FFFFFF; -} + .board-color-cleanlight#header ul li.current, + .board-color-cleanlight#header-quick-access ul li.current { + color: rgba(10, 10, 20, 0.85) !important; + } -.board-color-cleanlight .fa { - color: rgba(10, 10, 20, 1); -} + .board-color-cleanlight .swimlane-header { + font-weight: 500; + color: rgba(10, 10, 20, 1); + } -.board-color-cleandark .fa { - color: #FFFFFF; -} + .board-color-cleanlight.board-wrapper { + background: #FFFFFF; + } -/*fdsfdsfdsfdsfsdddddddddd */ + .board-color-cleanlight .fa { + color: rgba(10, 10, 20, 1); + } -.board-color-cleanlight .list, -.board-color-cleandark .list { - background: none; - border-left: none; -} + .board-color-cleandark .fa { + color: #FFFFFF; + } -.board-color-cleanlight .list .list-header, -.board-color-cleandark .list .list-header { - border-bottom: none; - display: flex; - justify-content: space-between; - align-items: center; - font-size: 16px; - background: none; -} + /*fdsfdsfdsfdsfsdddddddddd */ -.board-color-cleanlight .list .list-header div:has(.list-header-name), -.board-color-cleandark .list .list-header div:has(.list-header-name) { - display: contents; -} + .board-color-cleanlight .list, + .board-color-cleandark .list { + background: none; + border-left: none; + } -.board-color-cleanlight .list .list-header-name { - color: rgba(10, 10, 20, 1); -} + .board-color-cleanlight .list .list-header, + .board-color-cleandark .list .list-header { + border-bottom: none; + display: flex; + justify-content: space-between; + align-items: center; -.board-color-cleandark .list .list-header-name { - color: #FFFFFF; -} + background: none; + } -.board-color-cleanlight .list .list-header .list-header-menu, -.board-color-cleandark .list .list-header .list-header-menu { - display: flex; - gap: 8px; - align-items: center; -} + .board-color-cleanlight .list .list-header div:has(.list-header-name), + .board-color-cleandark .list .list-header div:has(.list-header-name) { + display: contents; + } -.board-color-cleanlight .list .list-header .list-header-menu .js-open-list-menu , -.board-color-cleandark .list .list-header .list-header-menu .js-open-list-menu { - font-size: 16px !important; -} + .board-color-cleanlight .list .list-header-name { + color: rgba(10, 10, 20, 1); + } -.board-color-cleanlight .list .list-header .list-header-menu a, -.board-color-cleandark .list .list-header .list-header-menu a { - margin: 0 !important; -} + .board-color-cleandark .list .list-header-name { + color: #FFFFFF; + } -.board-color-cleanlight .list .list-header .list-header-menu .list-header-plus-top, -.board-color-cleandark .list .list-header .list-header-menu .list-header-plus-top { - color: #FFFFFF; - background: #FF6D00; - padding: 8px; - border-radius: 12px; - font-size: 16px !important; -} + .board-color-cleanlight .list .list-header .list-header-menu, + .board-color-cleandark .list .list-header .list-header-menu { + display: flex; + align-items: center; + } -.board-color-cleanlight .list .list-header .list-header-menu .list-header-plus-top:hover, -.board-color-cleandark .list .list-header .list-header-menu .list-header-plus-top:hover { - background: #d25b02; -} -.board-color-cleanlight .list .list-header .list-header-menu .js-collapse, -.board-color-cleandark .list .list-header .list-header-menu .js-collapse { - /* Make collapse button visible in Clean Light / Clean Dark themes. + .board-color-cleanlight .list .list-header .list-header-menu a, + .board-color-cleandark .list .list-header .list-header-menu a { + margin: 0 !important; + } + + .board-color-cleanlight .list .list-header .list-header-menu .list-header-plus-top, + .board-color-cleandark .list .list-header .list-header-menu .list-header-plus-top { + color: #FFFFFF; + background: #FF6D00; + border-radius: 12px; + + } + + .board-color-cleanlight .list .list-header .list-header-menu .list-header-plus-top:hover, + .board-color-cleandark .list .list-header .list-header-menu .list-header-plus-top:hover { + background: #d25b02; + } + + .board-color-cleanlight .list .list-header .list-header-menu .js-collapse, + .board-color-cleandark .list .list-header .list-header-menu .js-collapse { + /* Make collapse button visible in Clean Light / Clean Dark themes. Previously this was hidden which caused the missing Collapse button when using these themes. Use inline-block so it lines up with other header controls. */ - display: inline-block; - vertical-align: middle; - color: inherit; -} - -.board-color-cleanlight .list-header-add, -.board-color-cleandark .list-header-add { - border-radius: 12px; - margin-top: 18px; - padding: 8px; - margin-right: 8px; - display: flex; - align-items: center; - justify-content: center; - margin-left: 10px; -} - -.board-color-cleanlight .list-header-add:hover { - background: rgba(227, 227, 230, 1); - color: rgba(10, 10, 20, 1); - border-radius: 8px; - cursor: pointer; -} - -.board-color-cleandark .list-header-add:hover { - background: rgba(255, 255, 255, 0.1); - color: #FFFFFF; - border-radius: 8px; - cursor: pointer; -} - -.board-color-cleanlight .list-header-add a:hover i { - color: #FFFFFF !important; -} - -.board-color-cleandark .list-header-add { - background: #23232B !important; - color: #FFFFFF !important; -} - -.board-color-cleanlight .card-label, -.board-color-cleandark .card-label { - border-radius: 18px; - margin-top: 6px; - margin-right: 8px; - border: none; - padding: 4px 12px; -} - -.board-color-cleanlight .swimlane, -.board-color-cleandark .swimlane { - background: none; -} - -.board-color-cleanlight .swimlane-height-apply, -.board-color-cleandark .swimlane-height-apply { - border-radius: 12px !important; -} - -.board-color-cleandark .swimlane-height-apply { - background: #FFFFFF !important; - color: #0A0A14 !important; -} - -.board-color-cleanlight .swimlane-height-apply { - background: rgba(23, 23, 28, 1) !important; - color: rgba(255, 255, 255, 0.85) !important; -} - -.board-color-cleandark .swimlane-height-apply:hover { - background: rgba(255, 255, 255, 0.85) !important; -} - -.board-color-cleanlight .swimlane-height-apply:hover { - background: rgba(227, 227, 230, 1) !important; -} - -.board-color-cleanlight .swimlane .swimlane-header-wrap .swimlane-header, -.board-color-cleandark .swimlane .swimlane-header-wrap .swimlane-header, -.board-color-cleanlight .swimlane .swimlane-header-wrap .swimlane-header-menu .fa, -.board-color-cleandark .swimlane .swimlane-header-wrap .swimlane-header-menu .fa { - font-size: 16px !important; -} - -.board-color-cleanlight .swimlane .swimlane-header-wrap { - background-color: #F1F1F3; -} - -.board-color-cleandark .swimlane .swimlane-header-wrap { - background-color: #2E2E39; -} - -.board-color-cleanlight .swimlane .swimlane-header-wrap .swimlane-header-plus-icon, -.board-color-cleandark .swimlane .swimlane-header-wrap .swimlane-header-plus-icon { - margin-left: 14px; -} - -.board-color-cleanlight .swimlane .swimlane-header-wrap .list-composer, -.board-color-cleandark .swimlane .swimlane-header-wrap .list-composer { - display: flex; - gap: 12px; - margin-left: 20px; -} - -.board-color-cleanlight .swimlane .swimlane-header-wrap .swimlane-header .viewer p, -.board-color-cleandark .swimlane .swimlane-header-wrap .swimlane-header .viewer p { - margin-bottom: 0; -} - -.board-color-cleanlight .js-toggle-desktop-drag-handles, -.board-color-cleandark .js-toggle-desktop-drag-handles { - display: none; -} - -.board-color-cleanlight .sidebar { - background: rgba(248, 248, 249, 1) !important; - box-shadow: none; -} - -.board-color-cleanlight .sidebar hr { - background: rgba(23, 23, 28, 0.05); -} - -.board-color-cleanlight .sidebar .tab-item { - border-radius: 16px; - padding: 4px 12px 4px 12px; - font-size: 16px; - font-weight: 400; - line-height: 24px; - color: rgba(10, 10, 20, 0.85); - background: rgba(234, 234, 237, 1); -} - -.board-color-cleanlight .sidebar .tab-item.active { - background: rgba(23, 23, 28, 1); - color: rgba(255, 255, 255, 1); - border: none; - padding: 4px 12px 4px 12px !important; -} - -.board-color-cleanlight .sidebar .tabs-content-container { - border: none; -} - -.board-color-cleanlight .card-details { - background: rgba(248, 248, 249, 1); - border-radius: 20px; - box-shadow: none; -} - -.board-color-cleanlight .card-details-item a { - font-size: 16px; - font-weight: 400; - line-height: 24px; - color: rgba(10, 10, 20, 0.5); -} - -.board-color-cleanlight .card-details-header, -.board-color-cleandark .card-details-header { - font-size: 24px !important; - font-weight: 600; - line-height: 28px; - border-bottom: none !important; - padding: 12px 20px !important; -} - -.board-color-cleanlight .card-details-header { - background: rgba(241, 241, 243, 1); - color: rgba(10, 10, 20, 1); -} - -.board-color-cleandark .card-details-header { - background: #2E2E39 !important; - color: #FFF !important; -} - -.board-color-cleanlight .card-details-header .card-details-title, -.board-color-cleandark .card-details-header .card-details-title { - font-size: 24px !important; -} - -.board-color-cleanlight .card-details .card-details-item-title, -.board-color-cleandark .card-details .card-details-item-title { - display: flex; - gap: 8px; - align-items: center; - - font-size: 16px; - font-weight: 500; - line-height: 24px; -} - -.board-color-cleanlight .card-details .card-details-item-title { - color: rgba(10, 10, 20, 1); -} - -.board-color-cleandark .card-details .card-details-item-title { - color: rgba(255, 255, 255, 1); -} - -.board-color-cleanlight .add-assignee { - box-shadow: none !important; -} - -.board-color-cleanlight .add-assignee:hover { - background: rgba(227, 227, 230, 1); - border-radius: 8px; -} - -.board-color-cleanlight .add-assignee:hover i { - color: #000000 !important; -} - -.board-color-cleanlight .add-checklist-top { - display: none !important; -} - -.board-color-cleanlight .add-checklist { - padding: 8px; - width: min-content !important; -} - -.board-color-cleanlight .add-checklist:hover { - background: rgba(227, 227, 230, 1) !important; - border-radius: 12px !important; -} - -.board-color-cleanlight .add-checklist:hover i { - color: #000000 !important; -} - -.board-color-cleanlight .card-time.card-label-green { - background: #009B64; - width: min-content; - color: #FFFFFF; - padding-left: 8px; - padding-right: 8px; - border-radius: 8px; - margin-left: 4px; -} - -.board-color-cleanlight .card-details hr { - background: rgba(23, 23, 28, 0.05); -} - -.board-color-cleanlight .card-details-canvas { - font-size: 16px; - font-weight: 400; - line-height: 24px; - color: rgba(10, 10, 20, 0.5); -} - -.board-color-cleanlight.pop-over { - border-radius: 12px; - border: none; - background: rgba(241, 241, 243, 1); -} - -.board-color-cleanlight.pop-over .header, -.board-color-cleandark.pop-over .header { - border-radius: 12px 12px 0 0; - border-bottom: none; - background: inherit; - - font-size: 16px; - font-weight: 500; - line-height: 24px; -} - -.board-color-cleanlight.pop-over .header { - color: rgba(10, 10, 20, 1); -} - - -.board-color-cleandark.pop-over .header { - color: rgba(255, 255, 255, 1);; -} - -.board-color-cleanlight.pop-over .pop-over-list, -.board-color-cleanlight.pop-over .content { - font-size: 16px; - font-weight: 400; - line-height: 24px; - color: rgba(10, 10, 20, 0.8); -} - -.board-color-cleanlight.pop-over .pop-over-list a:hover { - background: #393947 !important; -} - -.board-color-cleanlight .member { - box-shadow: none !important; -} - -.board-color-cleanlight .add-member:hover { - background: rgba(227, 227, 230, 1); - border-radius: 8px; -} - -.board-color-cleanlight .add-member:hover i { - color: #000000 !important; -} - -.board-color-cleanlight .add-label { - box-shadow: none !important; -} - -.board-color-cleanlight .add-label:hover { - background: rgba(227, 227, 230, 1); - border-radius: 8px; -} - -.board-color-cleanlight .add-label:hover i { - color: #000000 !important; -} - -.board-color-cleanlight.pop-over .content kbd { - background: rgba(180, 180, 180, 1); - border-radius: 8px; -} - -.board-color-cleanlight .full-name { - font-size: 16px; - font-weight: 500; - line-height: 24px; - - color: rgba(10, 10, 20, 0.85) !important; -} - -.board-color-cleanlight .username { - font-size: 16px; - font-weight: 400; - line-height: 24px; - - color: rgba(10, 10, 20, 0.5) !important; -} - -.board-color-cleanlight .attachment-item:hover { - background: rgba(227, 227, 230, 1); -} - -.board-color-cleanlight .checklist { - background: none; - color: rgba(10, 10, 20, 0.85); -} - -.board-color-cleanlight .checklist-item { - background: none; -} - -.board-color-cleanlight .checklist-item:hover { - background: rgba(227, 227, 230, 1) !important; -} - -.board-color-cleanlight .add-checklist-item { - width: min-content !important; - padding: 8px; -} - -.board-color-cleanlight .add-checklist-item:hover { - background: rgba(227, 227, 230, 1) !important; - border-radius: 12px !important; -} - -.board-color-cleanlight .add-checklist-item:hover i { - color: #000000 !important; -} - -.board-color-cleanlight .add-attachment { - background: rgba(248, 248, 249, 1) !important; - border-radius: 12px; - border-color: rgba(197, 197, 200, 1); -} - -.board-color-cleanlight .add-attachment:hover { - background: rgba(227, 227, 230, 1) !important; -} - -.board-color-cleanlight .add-attachment:hover i { - color: #000000 !important; -} - -.board-color-cleanlight .attachment-actions i, -.board-color-cleanlight .attachment-actions a { - font-size: 1em !important; -} - -.board-color-cleanlight .activity-desc { - font-size: 16px; - font-weight: 400; - line-height: 24px; - color: rgba(10, 10, 20, 0.5); -} - -.board-color-cleanlight .activity-desc .activity-member { - color: rgba(10, 10, 20, 0.85); -} - -.board-color-cleanlight .activity-checklist, -.board-color-cleanlight .activity-comment { - background: none !important; - color: rgba(10, 10, 20, 0.85); - border: 1px solid rgba(0, 155, 100, 1); - border-radius: 12px !important; -} - -.board-color-cleanlight button[type=submit].primary, -.board-color-cleanlight input[type=submit].primary { - font-size: 16px; - font-weight: 400; - line-height: 24px; - border-radius: 12px; - padding: 6px 12px 6px 12px; - background: rgba(23, 23, 28, 1); - color: rgba(255, 255, 255, 0.85); -} - -.board-color-cleanlight input.primary { - font-size: 16px; - font-weight: 400; - line-height: 24px; - border-radius: 12px; - padding: 6px 12px 6px 12px; - background: rgba(23, 23, 28, 1) !important; - color: rgba(255, 255, 255, 0.85) !important; -} - -.board-color-cleanlight input.primary:hover { - background: #444455 !important; -} - -.board-color-cleanlight textarea { - font-size: 16px; - font-weight: 400; - line-height: 24px; - color: rgba(10, 10, 20, 0.85); - background: rgba(234, 234, 237, 1); - border: none !important; - border-radius: 12px !important; -} - -.board-color-cleanlight textarea::placeholder { - color: rgba(10, 10, 20, 0.5) !important; -} - -.board-color-cleanlight textarea:focus, -.board-color-cleandark textarea:focus { - border: none !important; - box-shadow: none; -} - -.board-color-cleanlight input { - font-size: 16px; - font-weight: 400; - line-height: 24px; - color: rgba(10, 10, 20, 0.85) !important; - background: rgba(234, 234, 237, 1) !important; - border-radius: 12px !important; - border: none !important; -} - -.board-color-cleanlight input::placeholder { - color: rgba(10, 10, 20, 0.5) !important; -} - -.board-color-cleanlight input:focus, -.board-color-cleandark input:focus { - border: none !important; - box-shadow: none !important; -} - -.board-color-cleanlight select { - font-size: 16px; - font-weight: 400; - line-height: 24px; - color: rgba(10, 10, 20, 0.85); - background: rgba(234, 234, 237, 1); - border-radius: 12px; - border: none; -} - -.board-color-cleanlight button.primary { - padding: 6px 12px 6px 12px; - border-radius: 12px; - border: none; - background: rgba(23, 23, 28, 1); - font-size: 16px; - font-weight: 400; - line-height: 24px; - color: rgba(255, 255, 255, 0.85); -} - -.board-color-cleanlight button.primary:hover { - background: #444455; -} - -.board-color-cleanlight button.negate { - padding: 6px 12px 6px 12px; - border-radius: 12px; - border: none; - background: #cc003a; - font-size: 16px; - font-weight: 400; - line-height: 24px; - color: #FFFFFF; -} - -.board-color-cleanlight button.negate:hover { - background: rgba(204, 0, 58, 0.77); -} - -.board-color-cleanlight .card-details .checklist-item { - display: flex; - align-items: center; - gap: 4px; -} - -.board-color-cleanlight .card-details .check-box.materialCheckBox { - border-radius: 4px; - border: none; - background: rgba(234, 234, 237, 1); - height: 24px; - width: 24px; -} - -.board-color-cleanlight .card-details .check-box.materialCheckBox.is-checked { - border-bottom: 2px solid #000000; - border-right: 2px solid #000000; - width: 11px; - height: 19px; - border-radius: 0; - background: none; -} - -.board-color-cleanlight .sidebar-list-item-description { - color: rgba(10, 10, 20, 0.85); -} - -.board-color-cleanlight .sidebar .sidebar-content h3, -.board-color-cleanlight .sidebar .sidebar-content h2, -.board-color-cleanlight .sidebar .sidebar-content h1 { - color: rgba(10, 10, 20, 0.85); -} - -.board-color-cleanlight #cards span { - color: rgba(10, 10, 20, 0.85); -} - -.board-color-cleanlight #cards .materialCheckBox { - border-radius: 4px; - border: none; - background: rgba(234, 234, 237, 1); - height: 18px; - width: 18px; -} - -.board-color-cleanlight #cards .materialCheckBox.is-checked { - border-bottom: 2px solid #000000; - border-right: 2px solid #000000; - width: 5px; - height: 13px; - border-radius: 0; - background: none; - margin-left: 3px; - margin-top: 3px; -} + display: inline-block; + vertical-align: middle; + color: inherit; + } + + .board-color-cleanlight .list-header-add, + .board-color-cleandark .list-header-add { + border-radius: 12px; + display: flex; + align-items: center; + justify-content: center; + } + + .board-color-cleanlight .list-header-add:hover { + background: rgba(227, 227, 230, 1); + color: rgba(10, 10, 20, 1); + border-radius: 0.8ch; + cursor: pointer; + } + + .board-color-cleandark .list-header-add:hover { + background: rgba(255, 255, 255, 0.1); + color: #FFFFFF; + border-radius: 0.8ch; + cursor: pointer; + } + + .board-color-cleanlight .list-header-add a:hover i { + color: #FFFFFF !important; + } + + .board-color-cleandark .list-header-add { + background: #23232B !important; + color: #FFFFFF !important; + } + + .board-color-cleanlight .card-label, + .board-color-cleandark .card-label { + border-radius: 18px; + border: none; + } + + .board-color-cleanlight .swimlane, + .board-color-cleandark .swimlane { + background: none; + } + + .board-color-cleanlight .swimlane-height-apply, + .board-color-cleandark .swimlane-height-apply { + border-radius: 12px !important; + } + + .board-color-cleandark .swimlane-height-apply { + background: #FFFFFF !important; + color: #0A0A14 !important; + } + + .board-color-cleanlight .swimlane-height-apply { + background: rgba(23, 23, 28, 1) !important; + color: rgba(255, 255, 255, 0.85) !important; + } + + .board-color-cleandark .swimlane-height-apply:hover { + background: rgba(255, 255, 255, 0.85) !important; + } + + .board-color-cleanlight .swimlane-height-apply:hover { + background: rgba(227, 227, 230, 1) !important; + } + + + .board-color-cleanlight .swimlane .swimlane-header-wrap { + background-color: #F1F1F3; + } + + .board-color-cleandark .swimlane .swimlane-header-wrap { + background-color: #2E2E39; + } + + + .board-color-cleanlight .swimlane .swimlane-header-wrap .list-composer, + .board-color-cleandark .swimlane .swimlane-header-wrap .list-composer { + display: flex; + } + + .board-color-cleanlight .swimlane .swimlane-header-wrap .swimlane-header .viewer p, + .board-color-cleandark .swimlane .swimlane-header-wrap .swimlane-header .viewer p { + margin-bottom: 0; + } + + .board-color-cleanlight .js-toggle-desktop-drag-handles, + .board-color-cleandark .js-toggle-desktop-drag-handles { + display: none; + } + + .board-color-cleanlight .sidebar { + background: rgba(248, 248, 249, 1) !important; + box-shadow: none; + } + + .board-color-cleanlight .sidebar hr { + background: rgba(23, 23, 28, 0.05); + } + + .board-color-cleanlight .sidebar .tab-item { + border-radius: 16px; + + font-weight: 400; + color: rgba(10, 10, 20, 0.85); + background: rgba(234, 234, 237, 1); + } + + .board-color-cleanlight .sidebar .tab-item.active { + background: rgba(23, 23, 28, 1); + color: rgba(255, 255, 255, 1); + border: none; + } + + .board-color-cleanlight .sidebar .tabs-content-container { + border: none; + } + + .board-color-cleanlight .card-details { + background: rgba(248, 248, 249, 1); + border-radius: 20px; + box-shadow: none; + } + + .board-color-cleanlight .card-details-item a { + font-weight: 400; + color: rgba(10, 10, 20, 0.5); + } + + .board-color-cleanlight .card-details-header, + .board-color-cleandark .card-details-header { + + font-weight: 600; + border-bottom: none !important; + } + + .board-color-cleanlight .card-details-header { + background: rgba(241, 241, 243, 1); + color: rgba(10, 10, 20, 1); + } + + .board-color-cleandark .card-details-header { + background: #2E2E39 !important; + color: #FFF !important; + } + + + .board-color-cleanlight .card-details .card-details-item-title, + .board-color-cleandark .card-details .card-details-item-title { + display: flex; + align-items: center; + + font-weight: 500; + } + + .board-color-cleanlight .card-details .card-details-item-title { + color: rgba(10, 10, 20, 1); + } + + .board-color-cleandark .card-details .card-details-item-title { + color: rgba(255, 255, 255, 1); + } + + .board-color-cleanlight .add-assignee { + box-shadow: none !important; + } + + .board-color-cleanlight .add-assignee:hover { + background: rgba(227, 227, 230, 1); + border-radius: 0.8ch; + } + + .board-color-cleanlight .add-assignee:hover i { + color: #000000 !important; + } + + .board-color-cleanlight .add-checklist-top { + display: none !important; + } + + .board-color-cleanlight .add-checklist { + width: min-content !important; + } + + .board-color-cleanlight .add-checklist:hover { + background: rgba(227, 227, 230, 1) !important; + border-radius: 12px !important; + } + + .board-color-cleanlight .add-checklist:hover i { + color: #000000 !important; + } + + .board-color-cleanlight .card-time.card-label-green { + background: #009B64; + width: min-content; + color: #FFFFFF; + border-radius: 0.8ch; + } + + .board-color-cleanlight .card-details hr { + background: rgba(23, 23, 28, 0.05); + } + + .board-color-cleanlight .card-details-canvas { + font-weight: 400; + color: rgba(10, 10, 20, 0.5); + } + + .board-color-cleanlight.pop-over { + border-radius: 12px; + border: none; + background: rgba(241, 241, 243, 1); + } + + .board-color-cleanlight.pop-over .header, + .board-color-cleandark.pop-over .header { + border-radius: 12px 12px 0 0; + border-bottom: none; + background: inherit; + + font-weight: 500; + } + + .board-color-cleanlight.pop-over .header { + color: rgba(10, 10, 20, 1); + } + + + .board-color-cleandark.pop-over .header { + color: rgba(255, 255, 255, 1); ; + } + + .board-color-cleanlight.pop-over .pop-over-list, + .board-color-cleanlight.pop-over .content { + + font-weight: 400; + color: rgba(10, 10, 20, 0.8); + } + + .board-color-cleanlight.pop-over .pop-over-list a:hover { + background: #393947 !important; + } + + .board-color-cleanlight .member { + box-shadow: none !important; + } + + .board-color-cleanlight .add-member:hover { + background: rgba(227, 227, 230, 1); + border-radius: 0.8ch; + } + + .board-color-cleanlight .add-member:hover i { + color: #000000 !important; + } + + .board-color-cleanlight .add-label { + box-shadow: none !important; + } + + .board-color-cleanlight .add-label:hover { + background: rgba(227, 227, 230, 1); + border-radius: 0.8ch; + } + + .board-color-cleanlight .add-label:hover i { + color: #000000 !important; + } + + .board-color-cleanlight.pop-over .content kbd { + background: rgba(180, 180, 180, 1); + border-radius: 0.8ch; + } + + .board-color-cleanlight .full-name { + + font-weight: 500; + + color: rgba(10, 10, 20, 0.85) !important; + } + + .board-color-cleanlight .username { + + font-weight: 400; + + color: rgba(10, 10, 20, 0.5) !important; + } + + .board-color-cleanlight .attachment-item:hover { + background: rgba(227, 227, 230, 1); + } + + .board-color-cleanlight .checklist { + background: none; + color: rgba(10, 10, 20, 0.85); + } + + .board-color-cleanlight .checklist-item { + background: none; + } + + .board-color-cleanlight .checklist-item:hover { + background: rgba(227, 227, 230, 1) !important; + } + + .board-color-cleanlight .add-checklist-item { + width: min-content !important; + } + + .board-color-cleanlight .add-checklist-item:hover { + background: rgba(227, 227, 230, 1) !important; + border-radius: 12px !important; + } + + .board-color-cleanlight .add-checklist-item:hover i { + color: #000000 !important; + } + + .board-color-cleanlight .add-attachment { + background: rgba(248, 248, 249, 1) !important; + border-radius: 12px; + border-color: rgba(197, 197, 200, 1); + } + + .board-color-cleanlight .add-attachment:hover { + background: rgba(227, 227, 230, 1) !important; + } + + .board-color-cleanlight .add-attachment:hover i { + color: #000000 !important; + } + + + .board-color-cleanlight .activity-desc { + font-weight: 400; + color: rgba(10, 10, 20, 0.5); + } + + .board-color-cleanlight .activity-desc .activity-member { + color: rgba(10, 10, 20, 0.85); + } + + .board-color-cleanlight .activity-checklist, + .board-color-cleanlight .activity-comment { + background: none !important; + color: rgba(10, 10, 20, 0.85); + border: 1px solid rgba(0, 155, 100, 1); + border-radius: 12px !important; + } + + .board-color-cleanlight button[type=submit].primary, + .board-color-cleanlight input[type=submit].primary { + + font-weight: 400; + border-radius: 12px; + background: rgba(23, 23, 28, 1); + color: rgba(255, 255, 255, 0.85); + } + + .board-color-cleanlight input.primary { + + font-weight: 400; + border-radius: 12px; + background: rgba(23, 23, 28, 1) !important; + color: rgba(255, 255, 255, 0.85) !important; + } + + .board-color-cleanlight input.primary:hover { + background: #444455 !important; + } + + .board-color-cleanlight textarea { + font-weight: 400; + color: rgba(10, 10, 20, 0.85); + background: rgba(234, 234, 237, 1); + border: none !important; + border-radius: 12px !important; + } + + .board-color-cleanlight textarea::placeholder { + color: rgba(10, 10, 20, 0.5) !important; + } + + .board-color-cleanlight textarea:focus, + .board-color-cleandark textarea:focus { + border: none !important; + box-shadow: none; + } + + .board-color-cleanlight input { + font-weight: 400; + color: rgba(10, 10, 20, 0.85) !important; + background: rgba(234, 234, 237, 1) !important; + border-radius: 12px !important; + border: none !important; + } + + .board-color-cleanlight input::placeholder { + color: rgba(10, 10, 20, 0.5) !important; + } + + .board-color-cleanlight input:focus, + .board-color-cleandark input:focus { + border: none !important; + box-shadow: none !important; + } + + .board-color-cleanlight select { + font-weight: 400; + color: rgba(10, 10, 20, 0.85); + background: rgba(234, 234, 237, 1); + border-radius: 12px; + border: none; + } + + .board-color-cleanlight button.primary { + border-radius: 12px; + border: none; + background: rgba(23, 23, 28, 1); + + font-weight: 400; + color: rgba(255, 255, 255, 0.85); + } + + .board-color-cleanlight button.primary:hover { + background: #444455; + } + + .board-color-cleanlight button.negate { + border-radius: 12px; + border: none; + background: #cc003a; + + font-weight: 400; + color: #FFFFFF; + } + + .board-color-cleanlight button.negate:hover { + background: rgba(204, 0, 58, 0.77); + } + + .board-color-cleanlight .card-details .checklist-item { + display: flex; + align-items: center; + } + + .board-color-cleanlight .card-details .check-box.materialCheckBox { + border-radius: 0.4ch; + border: none; + background: rgba(234, 234, 237, 1); + } + + .board-color-cleanlight .card-details .check-box.materialCheckBox.is-checked { + border-bottom: 2px solid #000000; + border-right: 2px solid #000000; + border-radius: 0; + background: none; + } + + .board-color-cleanlight .sidebar-list-item-description { + color: rgba(10, 10, 20, 0.85); + } + + .board-color-cleanlight .sidebar .sidebar-content h3, + .board-color-cleanlight .sidebar .sidebar-content h2, + .board-color-cleanlight .sidebar .sidebar-content h1 { + color: rgba(10, 10, 20, 0.85); + } + + .board-color-cleanlight #cards span { + color: rgba(10, 10, 20, 0.85); + } + + .board-color-cleanlight #cards .materialCheckBox { + border-radius: 0.4ch; + border: none; + background: rgba(234, 234, 237, 1); + } + + .board-color-cleanlight #cards .materialCheckBox.is-checked { + border-bottom: 2px solid #000000; + border-right: 2px solid #000000; + border-radius: 0; + background: none; + } .board-color-cleanlight .checklist-progress-bar { background-color: #f5f5f5 !important; } @@ -4008,311 +4040,273 @@ THEME - Clean Light color: #010101 !important; } -.board-color-cleanlight .allBoards { - white-space: nowrap; -} - -.board-color-cleanlight#header-quick-access, -.board-color-cleandark#header-quick-access { - padding: 10px 20px; - padding-top: 12px !important; - gap: 20px; -} - -.board-color-cleandark#header-quick-access { - background: #2E2E39 !important; -} - -.board-color-cleanlight#header-quick-access { - background: #F1F1F3 !important; - color: rgba(10, 10, 20, 0.85); -} - -.board-color-cleanlight#header-quick-access ul.header-quick-access-list li a .viewer, -.board-color-cleandark#header-quick-access ul.header-quick-access-list li a .viewer { - max-width: 400px; - text-overflow: ellipsis; - overflow: hidden; - display: inline-flex; - align-items: center; -} - -.board-color-cleanlight#header-quick-access ul.header-quick-access-list li a .viewer p, -.board-color-cleandark#header-quick-access ul.header-quick-access-list li a .viewer p { - margin-bottom: 0; - overflow: hidden; - text-overflow: ellipsis; -} - -.board-color-cleanlight#header-quick-access ul.header-quick-access-list li { - display: inline-flex; - align-items: center; - padding-bottom: 4px; - padding-top: 4px; - margin-right: 10px; -} - -.board-color-cleanlight#header-quick-access ul.header-quick-access-list { - display: flex; - align-items: center; -} - -.board-color-cleanlight #header-main-bar, -.board-color-cleanlight#header { - background: #F1F1F3 !important; - color: rgba(10, 10, 20, 0.85) !important; -} - -.board-color-cleandark #header-main-bar, -.board-color-cleandark#header { - background: #2E2E39 !important; - color: #FFFFFF; -} - -.board-color-cleanlight .list-body .open-minicard-composer, -.board-color-cleandark .list-body .open-minicard-composer { - display: none !important; -} - -.board-color-cleanlight .minicard, -.board-color-cleandark .minicard { - border-radius: 12px; - font-size: 16px; - font-weight: 400; - line-height: 24px; - padding: 12px; -} - -.board-color-cleanlight .minicard { - background: rgba(248, 248, 249, 1); - color: rgba(10, 10, 20, 0.85); -} - -.board-color-cleandark .minicard { - color: #FFFFFF; - background: #23232B; -} - -.board-color-cleanlight .minicard .minicard-details-menu, -.board-color-cleandark .minicard .minicard-details-menu { - font-size: 16px !important; -} - -.board-color-cleanlight .minicard .date, -.board-color-cleandark .minicard .date, -.board-color-cleanlight .minicard .end-date, -.board-color-cleandark .minicard .end-date { - font-size: 16px; - font-weight: 400; - line-height: 24px; - margin-bottom: 10px; -} - -.board-color-cleanlight .minicard .date a, -.board-color-cleandark .minicard .date a, -.board-color-cleanlight .minicard .end-date, -.board-color-cleandark .minicard .end-date, -.board-color-cleanlight .card-details .card-date, -.board-color-cleandark .card-details .card-date { - padding: 4px 8px 4px 8px; - font-size: 16px; - font-weight: 400; - line-height: 24px; - color: rgba(255, 255, 255, 1); -} - -.board-color-cleanlight .minicard .end-date, -.board-color-cleandark .minicard .end-date, -.board-color-cleanlight .minicard .due-date, -.board-color-cleandark .minicard .due-date, -.board-color-cleanlight .card-details .card-date, -.board-color-cleandark .card-details .card-date { - border-radius: 8px; -} - -.board-color-cleanlight .minicard .end-date, -.board-color-cleanlight .minicard .due-date, -.board-color-cleanlight .card-details .card-date { - background: rgba(227, 227, 230, 1); - color: rgba(10, 10, 20, 1) !important; -} - -.board-color-cleandark .minicard .end-date, -.board-color-cleandark .minicard .due-date, -.board-color-cleandark .card-details .card-date { - background: #444455; -} - -.board-color-cleandark .minicard .end-date:hover, -.board-color-cleandark .minicard .due-date:hover, -.board-color-cleandark .card-details .card-date:hover { - background: rgba(68, 68, 85, 0.73); -} - -.board-color-cleanlight .minicard .end-date:hover, -.board-color-cleanlight .minicard .due-date:hover, -.board-color-cleanlight .card-details .card-date:hover { - background: rgba(207, 207, 210, 1); -} - -.board-color-cleanlight .minicard .date .current, -.board-color-cleandark .minicard .date .current, -.board-color-cleanlight .minicard .current, -.board-color-cleandark .minicard .current, -.board-color-cleanlight .card-details .current, -.board-color-cleandark .card-details .current { - background: #009B64; - border-radius: 8px; - color: rgba(255, 255, 255, 1) !important; -} - -.board-color-cleandark .minicard .date .current:hover, -.board-color-cleanlight .minicard .date .current:hover, -.board-color-cleandark .minicard .current:hover, -.board-color-cleanlight .minicard .current:hover, -.board-color-cleandark .card-details .current:hover, -.board-color-cleanlight .card-details .current:hover { - background: rgba(0, 155, 100, 0.73); - color: rgba(255, 255, 255, 1) !important; -} - -.board-color-cleanlight .minicard .date .due, -.board-color-cleandark .minicard .date .due, -.board-color-cleanlight .minicard .due, -.board-color-cleandark .minicard .due, -.board-color-cleanlight .card-details .due, -.board-color-cleandark .card-details .due { - background: #CC003A; - border-radius: 8px; - color: rgba(255, 255, 255, 1) !important; -} - -.board-color-cleanlight .card-details .due:hover, -.board-color-cleanlight .minicard .date .due:hover, -.board-color-cleanlight .minicard .due:hover, -.board-color-cleandark .minicard .due:hover, -.board-color-cleandark .minicard .date .due:hover, -.board-color-cleandark .card-details .due:hover { - background: rgba(204, 0, 58, 0.73); - color: rgba(255, 255, 255, 1) !important; -} - -.board-color-cleanlight .minicard-assignees, -.board-color-cleandark .minicard-assignees { - border-bottom: none !important; -} - -.board-color-cleanlight .minicard-composer-textarea { - background: #f8f8f9 !important; -} - -.board-color-cleandark .minicard-composer-textarea { - background: #23232B !important; -} - -.board-color-cleanlight .minicard-composer:hover { - background: #f8f8f9 !important; -} - -.board-color-cleandark .minicard-composer:hover { - background: #23232B !important; -} - -.board-color-cleanlight .minicard .badges .badge.is-finished, -.board-color-cleandark .minicard .badges .badge.is-finished { - background: #009B64 !important; - border-radius: 8px; -} - -.board-color-cleanlight .minicard .badges .badge.is-finished .badge-icon { - color: #FFFFFF; -} - -.board-color-cleanlight .card-details-item-customfield:has(.checklist-item), -.board-color-cleandark .card-details-item-customfield:has(.checklist-item) { - display: flex !important; - align-items: center; - gap: 8px; -} - -.board-color-cleanlight .card-details-item-customfield:has(.checklist-item) div, -.board-color-cleandark .card-details-item-customfield:has(.checklist-item) div { - padding-right: 0 !important; -} - -.board-color-cleanlight .card-details .card-details-items .card-details-item.custom-fields, -.board-color-cleanlight .card-details .card-details-items .card-details-item.custom-fields { - margin-left: auto; - flex-grow: 0; - border-radius: 12px; -} - -.board-color-cleanlight .card-details-item-customfield:has(.checklist-item) h3, -.board-color-cleandark .card-details-item-customfield:has(.checklist-item) h3 { - width: min-content !important; - display: flex; - align-items: center; - gap: 8px; - margin: 0 !important; -} - -.board-color-cleanlight .new-description .fa, -.board-color-cleandark .new-description .fa { - display: none; -} - -.board-color-cleanlight .card-details-left .viewer p { - color: rgba(10, 10, 20, 0.85); -} - -.board-color-cleandark .card-details-left .viewer p { - color: #FFFFFF; -} - -.board-color-cleanlight .new-comment .fa, -.board-color-cleandark .new-comment .fa { - display: none; -} - -.board-color-cleanlight .pop-over-list li > a, -.board-color-cleandark .pop-over-list li > a { - font-weight: 500; -} - -.board-color-cleanlight .pop-over-list li > a i, -.board-color-cleandark .pop-over-list li > a i { - margin-right: 6px !important; -} - -.board-color-cleanlight .pop-over .quiet { - margin-left: 100px !important; -} - -.board-color-cleandark .minicard:hover:not(.minicard-composer), -.board-color-cleandark .is-selected .minicard, .draggable-hover-card .minicard { - background: #23232B; -} - -/* Transparent modern scrollbar - cleanlight*/ -.board-color-cleanlight .board-canvas { - scrollbar-color: #0a0a14d1 #e4e4e400; -} + .board-color-cleanlight .allBoards { + white-space: nowrap; + } -/* Apply scrollbar to sidebar content*/ -.board-color-cleanlight .sidebar .sidebar-content { - scrollbar-color: #0a0a14d1 #e4e4e400; -} + .board-color-cleandark#header-quick-access { + background: #2E2E39 !important; + } -/* Remove margins in between columns/fix spacing */ + .board-color-cleanlight#header-quick-access { + background: #F1F1F3 !important; + color: rgba(10, 10, 20, 0.85); + } -.board-color-cleanlight .list { - border-left: none; - padding-bottom: 8px; -} + .board-color-cleanlight#header-quick-access ul.header-quick-access-list li a .viewer, + .board-color-cleandark#header-quick-access ul.header-quick-access-list li a .viewer { + text-overflow: ellipsis; + overflow: hidden; + display: inline-flex; + align-items: center; + } -.board-color-cleanlight .list-body { - margin-top: 8px; -} + .board-color-cleanlight#header-quick-access ul.header-quick-access-list li a .viewer p, + .board-color-cleandark#header-quick-access ul.header-quick-access-list li a .viewer p { + margin-bottom: 0; + overflow: hidden; + text-overflow: ellipsis; + } -/* === END CleanDark/Light THEME === */ + .board-color-cleanlight#header-quick-access ul.header-quick-access-list li { + display: inline-flex; + align-items: center; + } + + .board-color-cleanlight#header-quick-access ul.header-quick-access-list { + display: flex; + align-items: center; + } + + .board-color-cleanlight #header-main-bar, + .board-color-cleanlight#header { + background: #F1F1F3 !important; + color: rgba(10, 10, 20, 0.85) !important; + } + + .board-color-cleandark #header-main-bar, + .board-color-cleandark#header { + background: #2E2E39 !important; + color: #FFFFFF; + } + + .board-color-cleanlight .list-body .open-minicard-composer, + .board-color-cleandark .list-body .open-minicard-composer { + display: none !important; + } + + .board-color-cleanlight .minicard, + .board-color-cleandark .minicard { + border-radius: 12px; + + font-weight: 400; + } + + .board-color-cleanlight .minicard { + background: rgba(248, 248, 249, 1); + color: rgba(10, 10, 20, 0.85); + } + + .board-color-cleandark .minicard { + color: #FFFFFF; + background: #23232B; + } + + + .board-color-cleanlight .minicard .date, + .board-color-cleandark .minicard .date, + .board-color-cleanlight .minicard .end-date, + .board-color-cleandark .minicard .end-date { + + font-weight: 400; + } + + .board-color-cleanlight .minicard .date a, + .board-color-cleandark .minicard .date a, + .board-color-cleanlight .minicard .end-date, + .board-color-cleandark .minicard .end-date, + .board-color-cleanlight .card-details .card-date, + .board-color-cleandark .card-details .card-date { + + font-weight: 400; + color: rgba(255, 255, 255, 1); + } + + .board-color-cleanlight .minicard .end-date, + .board-color-cleandark .minicard .end-date, + .board-color-cleanlight .minicard .due-date, + .board-color-cleandark .minicard .due-date, + .board-color-cleanlight .card-details .card-date, + .board-color-cleandark .card-details .card-date { + border-radius: 0.8ch; + } + + .board-color-cleanlight .minicard .end-date, + .board-color-cleanlight .minicard .due-date, + .board-color-cleanlight .card-details .card-date { + background: rgba(227, 227, 230, 1); + color: rgba(10, 10, 20, 1) !important; + } + + .board-color-cleandark .minicard .end-date, + .board-color-cleandark .minicard .due-date, + .board-color-cleandark .card-details .card-date { + background: #444455; + } + + .board-color-cleandark .minicard .end-date:hover, + .board-color-cleandark .minicard .due-date:hover, + .board-color-cleandark .card-details .card-date:hover { + background: rgba(68, 68, 85, 0.73); + } + + .board-color-cleanlight .minicard .end-date:hover, + .board-color-cleanlight .minicard .due-date:hover, + .board-color-cleanlight .card-details .card-date:hover { + background: rgba(207, 207, 210, 1); + } + + .board-color-cleanlight .minicard .date .current, + .board-color-cleandark .minicard .date .current, + .board-color-cleanlight .minicard .current, + .board-color-cleandark .minicard .current, + .board-color-cleanlight .card-details .current, + .board-color-cleandark .card-details .current { + background: #009B64; + border-radius: 0.8ch; + color: rgba(255, 255, 255, 1) !important; + } + + .board-color-cleandark .minicard .date .current:hover, + .board-color-cleanlight .minicard .date .current:hover, + .board-color-cleandark .minicard .current:hover, + .board-color-cleanlight .minicard .current:hover, + .board-color-cleandark .card-details .current:hover, + .board-color-cleanlight .card-details .current:hover { + background: rgba(0, 155, 100, 0.73); + color: rgba(255, 255, 255, 1) !important; + } + + .board-color-cleanlight .minicard .date .due, + .board-color-cleandark .minicard .date .due, + .board-color-cleanlight .minicard .due, + .board-color-cleandark .minicard .due, + .board-color-cleanlight .card-details .due, + .board-color-cleandark .card-details .due { + background: #CC003A; + border-radius: 0.8ch; + color: rgba(255, 255, 255, 1) !important; + } + + .board-color-cleanlight .card-details .due:hover, + .board-color-cleanlight .minicard .date .due:hover, + .board-color-cleanlight .minicard .due:hover, + .board-color-cleandark .minicard .due:hover, + .board-color-cleandark .minicard .date .due:hover, + .board-color-cleandark .card-details .due:hover { + background: rgba(204, 0, 58, 0.73); + color: rgba(255, 255, 255, 1) !important; + } + + .board-color-cleanlight .minicard-assignees, + .board-color-cleandark .minicard-assignees { + border-bottom: none !important; + } + + .board-color-cleanlight .minicard-composer-textarea { + background: #f8f8f9 !important; + } + + .board-color-cleandark .minicard-composer-textarea { + background: #23232B !important; + } + + .board-color-cleanlight .minicard-composer:hover { + background: #f8f8f9 !important; + } + + .board-color-cleandark .minicard-composer:hover { + background: #23232B !important; + } + + .board-color-cleanlight .minicard .badges .badge.is-finished, + .board-color-cleandark .minicard .badges .badge.is-finished { + background: #009B64 !important; + border-radius: 0.8ch; + } + + .board-color-cleanlight .minicard .badges .badge.is-finished .badge-icon { + color: #FFFFFF; + } + + .board-color-cleanlight .card-details-item-customfield:has(.checklist-item), + .board-color-cleandark .card-details-item-customfield:has(.checklist-item) { + display: flex !important; + align-items: center; + } + + .board-color-cleanlight .card-details .card-details-items .card-details-item.custom-fields, + .board-color-cleanlight .card-details .card-details-items .card-details-item.custom-fields { + margin-left: auto; + flex-grow: 0; + border-radius: 12px; + } + + .board-color-cleanlight .card-details-item-customfield:has(.checklist-item) h3, + .board-color-cleandark .card-details-item-customfield:has(.checklist-item) h3 { + width: min-content !important; + display: flex; + align-items: center; + margin: 0 !important; + } + + .board-color-cleanlight .new-description .fa, + .board-color-cleandark .new-description .fa { + display: none; + } + + .board-color-cleanlight .card-details-left .viewer p { + color: rgba(10, 10, 20, 0.85); + } + + .board-color-cleandark .card-details-left .viewer p { + color: #FFFFFF; + } + + .board-color-cleanlight .new-comment .fa, + .board-color-cleandark .new-comment .fa { + display: none; + } + + .board-color-cleanlight .pop-over-list li > a, + .board-color-cleandark .pop-over-list li > a { + font-weight: 500; + } + + + .board-color-cleandark .minicard:hover:not(.minicard-composer), + .board-color-cleandark .is-selected .minicard, .draggable-hover-card .minicard { + background: #23232B; + } + + /* Transparent modern scrollbar - cleanlight*/ + .board-color-cleanlight .board-canvas { + scrollbar-color: #0a0a14d1 #e4e4e400; + } + + + /* Apply scrollbar to sidebar content*/ + .board-color-cleanlight .sidebar .sidebar-content { + scrollbar-color: #0a0a14d1 #e4e4e400; + } + + /* Remove margins in between columns/fix spacing */ + + .board-color-cleanlight .list { + border-left: none; + } + + + + /* === END CleanDark/Light THEME === */ \ No newline at end of file diff --git a/client/components/boards/boardHeader.css b/client/components/boards/boardHeader.css index faf20e2f5..58445493d 100644 --- a/client/components/boards/boardHeader.css +++ b/client/components/boards/boardHeader.css @@ -22,918 +22,90 @@ padding: 0.7vh 0.7vw; } -/* Zoom and Mobile Mode Controls */ -.board-header-btns.center { +.board-header { + display: grid; + flex: 1; + gap: 0.3lh; +} + +body { + &.mobile-mode { + .board-header { + flex-wrap: wrap; + } + } + &:not(.mobile-mode) { + .header-board-menu { + flex: 1; + } + .board-header { + justify-content: space-between; + grid-auto-flow: column; + } + .board-header-btns-left { + flex: 1; + justify-content: center; + } + .board-header-btns-right { + flex-grow: 0; + justify-content: end; + } + & .board-header-btns-right, + & .board-header-btns-left, + & .header-board-menu { + align-self: center; + align-items: center; + display: flex; + gap: 1.5ch; + overflow-wrap: normal; + } + } +} + +/* Make some space on intermediate layouts */ +@media screen and (max-width: 1200px) { + .board-header-btns-right span { + display: none !important; + } +} +.header-board-menu, .board-header-btns { display: flex; + align-self: center; align-items: center; justify-content: center; - flex: 1; + gap: 1ch; + & p { + margin: 0; + } } -.zoom-controls { +.board-header-btns-right > a { + flex-wrap: no-wrap; +} +body.mobile-mode { + header-board-menu h1 { + font-size: 2em; + } + .board-header-btn { + /* avoid wrapping if possible, at the cost of little icons */ + font-size: 0.5em; + /* no much choice because the way FA icons are inserted */ + padding-top: 0.1lh; + min-height: 0.8lh; + } + .board-header-btns-right { + display: grid; + grid-auto-flow: column; + grid-template-columns: repeat(auto-fit, 1fr); + flex: 1; + gap: 1ch; + justify-content: start; + align-items: center; + } +} +.board-header-btns-left { display: flex; - align-items: center; - gap: 0.5vw; - background: rgba(255, 255, 255, 0.9); - padding: 0.5vh 1vw; - border-radius: 0.5vw; - box-shadow: 0 0.2vh 0.5vh rgba(0,0,0,0.1); -} - -.zoom-controls .board-header-btn { - padding: 0.5vh 0.8vw !important; - border-radius: 0.3vw !important; - background: #fff !important; - border: 1px solid #000 !important; - transition: all 0.2s ease !important; - color: #000 !important; - height: auto !important; - line-height: normal !important; - margin: 0 !important; - float: none !important; - overflow: visible !important; -} - -.zoom-controls .board-header-btn i { - color: #000 !important; - float: none !important; - display: inline !important; - line-height: normal !important; - margin: 0 !important; -} - -.zoom-controls .board-header-btn:hover { - background: #000 !important; - border-color: #000 !important; - color: #fff !important; -} - -.zoom-controls .board-header-btn:hover i { - color: #fff !important; -} - -.zoom-controls .board-header-btn.is-active { - background: #0079bf; - color: white; - border-color: #005a8a; -} - -.zoom-controls .board-header-btn.is-active i { - color: white; -} - -.zoom-level { - font-weight: bold; - color: #333; - min-width: 3vw; - text-align: center; - font-size: clamp(12px, 2vw, 14px); - cursor: pointer; - padding: 0.3vh 0.5vw; - border-radius: 0.3vw; - transition: all 0.2s ease; -} - -.zoom-level:hover { - background: #f0f0f0; - color: #000; -} - -/* Mobile Mode Styles */ -.mobile-mode .board-wrapper { - width: 100%; - height: 100%; -} - -.mobile-mode .board-canvas { - height: 100%; -} - -.mobile-mode .minicard { - font-size: clamp(16px, 4vw, 20px); - padding: 1.2vh 1.5vw 0.5vh; - min-height: 3vh; -} - -.mobile-mode .list-header-name { - font-size: clamp(18px, 4.5vw, 24px); -} - -.mobile-mode .board-header-btn { - padding: 1vh 1.5vw; - font-size: clamp(14px, 3.5vw, 18px); -} - -.mobile-mode .zoom-controls { - padding: 1vh 1.5vw; - gap: 1vw; -} - -.mobile-mode .zoom-controls .board-header-btn { - padding: 1vh 1.5vw !important; - font-size: clamp(14px, 3.5vw, 18px) !important; - background: #fff !important; - border: 1px solid #000 !important; - color: #000 !important; - height: auto !important; - line-height: normal !important; - margin: 0 !important; - float: none !important; - overflow: visible !important; -} - -.mobile-mode .zoom-controls .board-header-btn i { - color: #000 !important; - float: none !important; - display: inline !important; - line-height: normal !important; - margin: 0 !important; -} - -.mobile-mode .zoom-controls .board-header-btn:hover { - background: #000 !important; - border-color: #000 !important; - color: #fff !important; -} - -.mobile-mode .zoom-controls .board-header-btn:hover i { - color: #fff !important; -} - -.mobile-mode .zoom-level { - font-size: clamp(14px, 3.5vw, 18px); - min-width: 4vw; -} - -/* Comprehensive Mobile Mode Styles - Works on all screen sizes */ -.mobile-mode .board-wrapper { - width: 100% !important; - height: 100% !important; - transform: none !important; - transform-origin: initial !important; - max-width: 100% !important; -} - -.mobile-mode .board-canvas { - height: 100% !important; - overflow-x: hidden !important; - overflow-y: auto !important; - width: 100% !important; - max-width: 100% !important; -} - -.mobile-mode .swimlane { - width: 100% !important; - min-width: 100% !important; - max-width: 100% !important; - margin-bottom: 2rem !important; - display: block !important; - float: none !important; -} - -.mobile-mode .swimlane-header { - width: 100% !important; - min-width: 100% !important; - max-width: 100% !important; - font-size: clamp(18px, 2.5vw, 32px) !important; - padding: 1rem !important; - margin-bottom: 1rem !important; - display: block !important; -} - -.mobile-mode .list { - width: 100% !important; - min-width: 100% !important; - max-width: 100% !important; - display: block !important; - float: none !important; - margin-bottom: 2rem !important; - border-left: none !important; - border-bottom: 2px solid #ccc !important; - clear: both !important; -} - -.mobile-mode .list-header { - width: 100% !important; - min-width: 100% !important; - max-width: 100% !important; - padding: 1rem !important; - font-size: clamp(18px, 2.5vw, 32px) !important; - display: grid !important; - grid-template-columns: 30px 1fr auto auto !important; - gap: 10px !important; - align-items: center !important; - position: relative !important; -} - -.mobile-mode .list-header .list-header-name { - font-size: clamp(18px, 2.5vw, 32px) !important; - font-weight: bold !important; - grid-row: 1 !important; - grid-column: 2 !important; - align-self: end !important; - display: block !important; - visibility: visible !important; - opacity: 1 !important; -} - -.mobile-mode .list-header .cardCount { - font-size: clamp(14px, 2vw, 24px) !important; - grid-row: 2 !important; - grid-column: 2 !important; - align-self: start !important; - display: block !important; - visibility: visible !important; - opacity: 1 !important; -} - -.mobile-mode .list-header .list-header-menu-icon { - position: static !important; - right: auto !important; - top: auto !important; - transform: none !important; - grid-row: 1/3 !important; - grid-column: 3 !important; - padding: 14px !important; - font-size: clamp(24px, 3vw, 48px) !important; - text-align: center !important; - display: block !important; - visibility: visible !important; - opacity: 1 !important; -} - -.mobile-mode .list-header .list-header-handle { - position: static !important; - right: auto !important; - top: auto !important; - transform: none !important; - grid-row: 1/3 !important; - grid-column: 4 !important; - padding: 14px !important; - font-size: clamp(28px, 3.5vw, 56px) !important; - text-align: center !important; - display: block !important; - visibility: visible !important; - opacity: 1 !important; -} - -.mobile-mode .list-body { - width: 100% !important; - min-width: 100% !important; - max-width: 100% !important; - padding: 1rem !important; - display: block !important; -} - -.mobile-mode .minicard { - width: 100% !important; - min-width: 100% !important; - max-width: 100% !important; - font-size: clamp(16px, 2vw, 24px) !important; - padding: 1.2vh 1.5vw 0.5vh !important; - min-height: 3vh !important; - margin-bottom: 0.5rem !important; - display: block !important; - float: none !important; -} - -.mobile-mode .minicard .minicard-title { - font-size: clamp(16px, 2vw, 24px) !important; - font-weight: bold !important; -} - -.mobile-mode .minicard .minicard-members { - font-size: clamp(12px, 1.5vw, 18px) !important; -} - -.mobile-mode .minicard .minicard-lists { - font-size: clamp(12px, 1.5vw, 18px) !important; -} - -/* Desktop Mode Styles */ -.desktop-mode .board-wrapper { - width: auto !important; - height: auto !important; -} - -.desktop-mode .swimlane { - width: auto !important; - min-width: auto !important; -} - -.desktop-mode .list { - width: auto !important; - min-width: auto !important; - display: flex !important; - float: left !important; - margin-bottom: 0 !important; - border-left: 1px solid #ccc !important; - border-bottom: none !important; -} - -.desktop-mode .list-header { - width: auto !important; - min-width: auto !important; - padding: 2.5vh 1.5vw 0.5vh !important; - font-size: clamp(14px, 3vw, 18px) !important; - display: block !important; -} - -.desktop-mode .list-header .list-header-name { - font-size: clamp(14px, 3vw, 18px) !important; - display: inline !important; - grid-row: auto !important; - grid-column: auto !important; - align-self: auto !important; -} - -.desktop-mode .list-header .cardCount { - font-size: 12px !important; - grid-row: auto !important; - grid-column: auto !important; - align-self: auto !important; -} - -.desktop-mode .list-header .list-header-menu-icon { - position: absolute !important; - right: 60px !important; - top: 50% !important; - transform: translateY(-50%) !important; - grid-row: auto !important; - grid-column: auto !important; - padding: 14px !important; - font-size: 40px !important; -} - -.desktop-mode .list-header .list-header-handle { - position: absolute !important; - right: 10px !important; - top: 50% !important; - transform: translateY(-50%) !important; - grid-row: auto !important; - grid-column: auto !important; - padding: 7px !important; - font-size: clamp(16px, 3vw, 20px) !important; -} - -.desktop-mode .list-body { - width: auto !important; - min-width: auto !important; - padding: 5px 11px !important; -} - -.desktop-mode .minicard { - width: auto !important; - min-width: auto !important; - font-size: clamp(12px, 2.5vw, 16px) !important; - padding: 0.5vh 0.8vw !important; - min-height: auto !important; - margin-bottom: 9px !important; -} - -.desktop-mode .minicard .minicard-title { - font-size: clamp(12px, 2.5vw, 16px) !important; -} - -.desktop-mode .minicard .minicard-members { - font-size: 10px !important; -} - -.desktop-mode .minicard .minicard-lists { - font-size: 10px !important; -} - -/* Additional Mobile Mode Styles for Other Elements - Works on all screen sizes */ -.mobile-mode .swimlane-header .swimlane-title { - font-size: clamp(18px, 2.5vw, 32px) !important; - font-weight: bold !important; - display: block !important; - visibility: visible !important; - opacity: 1 !important; -} - -.mobile-mode .swimlane-header .swimlane-description { - font-size: clamp(14px, 2vw, 24px) !important; - display: block !important; - visibility: visible !important; - opacity: 1 !important; -} - -.mobile-mode .board-header { - font-size: clamp(18px, 2.5vw, 32px) !important; - padding: 1rem !important; - width: 100% !important; - max-width: 100% !important; -} - -.mobile-mode .board-header .board-header-title { - font-size: clamp(18px, 2.5vw, 32px) !important; - font-weight: bold !important; - display: block !important; - visibility: visible !important; - opacity: 1 !important; -} - -.mobile-mode .board-header .board-header-description { - font-size: clamp(14px, 2vw, 24px) !important; - display: block !important; - visibility: visible !important; - opacity: 1 !important; -} - -.mobile-mode .board-header .board-header-btn { - font-size: clamp(14px, 2vw, 24px) !important; - padding: 1vh 1.5vw !important; - display: inline-block !important; - visibility: visible !important; - opacity: 1 !important; -} - -.mobile-mode .board-header .board-header-btn i { - font-size: clamp(14px, 2vw, 24px) !important; - display: inline !important; - visibility: visible !important; - opacity: 1 !important; -} - -/* Force mobile mode visibility on all screen sizes */ -.mobile-mode .list-header .fa-angle-right, -.mobile-mode .list-header .fa-arrows { - display: block !important; - visibility: visible !important; - opacity: 1 !important; - position: static !important; - right: auto !important; - top: auto !important; - transform: none !important; -} - -.mobile-mode .list-header .fa-angle-right { - grid-row: 1/3 !important; - grid-column: 3 !important; - padding: 14px !important; - font-size: clamp(24px, 3vw, 48px) !important; - text-align: center !important; -} - -.mobile-mode .list-header .fa-arrows { - grid-row: 1/3 !important; - grid-column: 4 !important; - padding: 14px !important; - font-size: clamp(28px, 3.5vw, 56px) !important; - text-align: center !important; -} - -/* Override any media queries that might hide elements in mobile mode */ -.mobile-mode * { - max-width: none !important; -} - -.mobile-mode .list, -.mobile-mode .swimlane, -.mobile-mode .board-wrapper, -.mobile-mode .board-canvas { - max-width: 100% !important; - width: 100% !important; - min-width: 100% !important; -} - -/* Force mobile mode list styling on all screen sizes - override desktop CSS */ -.mobile-mode .board-canvas { - display: block !important; - flex-direction: column !important; - flex-wrap: nowrap !important; - align-items: stretch !important; - justify-content: flex-start !important; - width: 100vw !important; - max-width: 100vw !important; - min-width: 100vw !important; - overflow-x: hidden !important; - overflow-y: auto !important; -} - - .mobile-mode .swimlane { - display: block !important; - width: 100vw !important; - max-width: 100vw !important; - min-width: 100vw !important; - margin: 0 0 2rem 0 !important; - padding: 0 !important; - float: none !important; - clear: both !important; - } - - .mobile-mode .swimlane .swimlane-header { - display: block !important; - width: 100vw !important; - max-width: 100vw !important; - min-width: 100vw !important; - margin: 0 0 1rem 0 !important; - padding: 1rem !important; - font-size: clamp(18px, 2.5vw, 32px) !important; - font-weight: bold !important; - border-bottom: 2px solid #ccc !important; - } - - .mobile-mode .swimlane .lists { - display: block !important; - width: 100vw !important; - max-width: 100vw !important; - min-width: 100vw !important; - margin: 0 !important; - padding: 0 !important; - flex-direction: column !important; - flex-wrap: nowrap !important; - align-items: stretch !important; - justify-content: flex-start !important; - } - - .mobile-mode .list { - display: block !important; - width: 100vw !important; - max-width: 100vw !important; - min-width: 100vw !important; - margin: 0 0 2rem 0 !important; - padding: 0 !important; - float: none !important; - clear: both !important; - border-left: none !important; - border-right: none !important; - border-top: none !important; - border-bottom: 2px solid #ccc !important; - flex: none !important; - flex-basis: auto !important; - flex-grow: 0 !important; - flex-shrink: 0 !important; - position: static !important; - left: auto !important; - right: auto !important; - top: auto !important; - bottom: auto !important; - transform: none !important; - } - -.mobile-mode .list:first-child { - margin-left: 0 !important; - margin-top: 0 !important; -} - -.mobile-mode .list:last-child { - margin-right: 0 !important; - margin-bottom: 0 !important; -} - -.mobile-mode .list.ui-sortable-helper { - display: block !important; - width: 100% !important; - max-width: 100% !important; - min-width: 100% !important; - height: auto !important; - min-height: 60px !important; - margin: 0 0 2rem 0 !important; - padding: 0 !important; - float: none !important; - clear: both !important; - border-left: none !important; - border-right: none !important; - border-top: none !important; - border-bottom: 2px solid #ccc !important; - flex: none !important; -} - -.mobile-mode .list.placeholder { - display: block !important; - width: 100% !important; - max-width: 100% !important; - min-width: 100% !important; - height: auto !important; - min-height: 60px !important; - margin: 0 0 2rem 0 !important; - padding: 0 !important; - float: none !important; - clear: both !important; - border-left: none !important; - border-right: none !important; - border-top: none !important; - border-bottom: 2px solid #ccc !important; - flex: none !important; -} - -/* Override any existing responsive CSS that might interfere with mobile mode */ -.mobile-mode .board-canvas .swimlane .lists { - display: block !important; - width: 100% !important; - max-width: 100% !important; - min-width: 100% !important; - margin: 0 !important; - padding: 0 !important; - flex-direction: column !important; - flex-wrap: nowrap !important; - align-items: stretch !important; - justify-content: flex-start !important; - overflow: visible !important; -} - -.mobile-mode .board-canvas .swimlane .lists .list { - display: block !important; - width: 100% !important; - max-width: 100% !important; - min-width: 100% !important; - margin: 0 0 2rem 0 !important; - padding: 0 !important; - float: none !important; - clear: both !important; - border-left: none !important; - border-right: none !important; - border-top: none !important; - border-bottom: 2px solid #ccc !important; - flex: none !important; - flex-basis: auto !important; - flex-grow: 0 !important; - flex-shrink: 0 !important; - position: static !important; - left: auto !important; - right: auto !important; - top: auto !important; - bottom: auto !important; - transform: none !important; -} - -/* Force mobile mode to override any media query styles */ -@media screen and (min-width: 801px) { - .mobile-mode .board-canvas { - display: block !important; - flex-direction: column !important; - flex-wrap: nowrap !important; - align-items: stretch !important; - justify-content: flex-start !important; - width: 100vw !important; - max-width: 100vw !important; - min-width: 100vw !important; - overflow-x: hidden !important; - overflow-y: auto !important; - } - - .mobile-mode .swimlane { - display: block !important; - width: 100% !important; - max-width: 100% !important; - min-width: 100% !important; - margin: 0 0 2rem 0 !important; - padding: 0 !important; - float: none !important; - clear: both !important; - } - - .mobile-mode .swimlane .lists { - display: block !important; - width: 100% !important; - max-width: 100% !important; - min-width: 100% !important; - margin: 0 !important; - padding: 0 !important; - flex-direction: column !important; - flex-wrap: nowrap !important; - align-items: stretch !important; - justify-content: flex-start !important; - } - - .mobile-mode .list { - display: block !important; - width: 100% !important; - max-width: 100% !important; - min-width: 100% !important; - margin: 0 0 2rem 0 !important; - padding: 0 !important; - float: none !important; - clear: both !important; - border-left: none !important; - border-right: none !important; - border-top: none !important; - border-bottom: 2px solid #ccc !important; - flex: none !important; - flex-basis: auto !important; - flex-grow: 0 !important; - flex-shrink: 0 !important; - position: static !important; - left: auto !important; - right: auto !important; - top: auto !important; - bottom: auto !important; - transform: none !important; - } -} - -/* Hide desktop-only elements in mobile mode (like mobile media queries do) */ -.mobile-mode .board-header-btn i.fa + span { - display: none !important; -} - -.mobile-mode .board-header-btn span { - display: none !important; -} - -.mobile-mode .board-header-btn .fa + span { - display: none !important; -} - -.mobile-mode .board-header-btn .fa + .board-header-btn-text { - display: none !important; -} - -.mobile-mode .board-header-btn .fa + .board-header-btn-label { - display: none !important; -} - -/* Show only icons in mobile mode */ -.mobile-mode .board-header-btn { - width: auto !important; - min-width: auto !important; - padding: 8px !important; - text-align: center !important; -} - -.mobile-mode .board-header-btn i { - display: inline-block !important; - margin: 0 !important; -} - -/* Hide desktop-specific elements that shouldn't show in mobile mode */ -.mobile-mode .desktop-only, -.mobile-mode .board-header .desktop-only { - display: none !important; -} - -.mobile-mode .board-header .board-header-btn.desktop-only { - display: none !important; -} - -/* Hide desktop-specific board header buttons in mobile mode */ -.mobile-mode .board-header-btns.left { - display: none !important; -} - -.mobile-mode .board-header-btns.center { - display: none !important; -} - -/* Show only the right section buttons in mobile mode, but hide text labels */ -.mobile-mode .board-header-btns.right { - display: block !important; -} - -.mobile-mode .board-header-btns.right .board-header-btn span { - display: none !important; -} - -.mobile-mode .board-header-btns.right .board-header-btn .fa + span { - display: none !important; -} - -.mobile-mode .board-header-btns.right .board-header-btn .fa + .board-header-btn-text { - display: none !important; -} - -.mobile-mode .board-header-btns.right .board-header-btn .fa + .board-header-btn-label { - display: none !important; -} - -/* Hide specific desktop-only buttons that shouldn't show in mobile mode */ -.mobile-mode .board-header-btn.js-star-board span, -.mobile-mode .board-header-btn.js-change-visibility span, -.mobile-mode .board-header-btn.js-watch-board span, -.mobile-mode .board-header-btn.js-sort-cards span { - display: none !important; -} - -/* Show only icons for mobile mode buttons */ -.mobile-mode .board-header-btns.right .board-header-btn { - width: auto !important; - min-width: auto !important; - padding: 8px !important; - text-align: center !important; - margin: 0 2px !important; -} - -.mobile-mode .board-header-btns.right .board-header-btn i { - display: inline-block !important; - margin: 0 !important; -} - -/* Ensure mobile mode looks like small screen mobile view */ -.mobile-mode .board-header { - height: 40px !important; -} - -.mobile-mode .board-header .board-header-btns { - margin-top: 0px !important; -} - -.mobile-mode .board-header .board-header-btn { - height: 32px !important; - line-height: 32px !important; - font-size: 15px !important; -} - -.mobile-mode .board-header .board-header-btn i.fa { - line-height: 32px !important; -} - -/* Copy mobile media query styles to mobile mode for consistent appearance */ -.mobile-mode .board-header { - height: 40px !important; - padding: 0 !important; - margin: 0 !important; -} - -.mobile-mode .board-header .board-header-btns { - margin-top: 0px !important; - height: 40px !important; - display: flex !important; - align-items: center !important; - justify-content: flex-end !important; -} - -.mobile-mode .board-header .board-header-btn { - height: 32px !important; - line-height: 32px !important; - font-size: 15px !important; - margin: 0 2px !important; - padding: 4px 8px !important; - border-radius: 4px !important; - background: rgba(255, 255, 255, 0.1) !important; - border: 1px solid rgba(255, 255, 255, 0.2) !important; - color: #fff !important; - text-decoration: none !important; - display: inline-flex !important; - align-items: center !important; - justify-content: center !important; - min-width: 32px !important; - width: auto !important; -} - -.mobile-mode .board-header .board-header-btn:hover { - background: rgba(255, 255, 255, 0.2) !important; - border-color: rgba(255, 255, 255, 0.3) !important; -} - -.mobile-mode .board-header .board-header-btn i.fa { - line-height: 32px !important; - font-size: 15px !important; - margin: 0 !important; - padding: 0 !important; -} - -.mobile-mode .board-header .board-header-btn i.fa + span { - display: none !important; -} - -.mobile-mode .board-header .board-header-btn span { - display: none !important; -} - -/* Hide the board title in mobile mode to match mobile view */ -.mobile-mode .header-board-menu { - display: none !important; -} - -/* Ensure the board header takes full width in mobile mode */ -.mobile-mode .board-header { - width: 100% !important; - max-width: 100% !important; - display: flex !important; - align-items: center !important; - justify-content: space-between !important; - padding: 0 10px !important; -} - -/* Additional Desktop Mode Styles for Other Elements */ -.desktop-mode .swimlane-header .swimlane-title { - font-size: clamp(14px, 3vw, 18px) !important; -} - -.desktop-mode .swimlane-header .swimlane-description { - font-size: 12px !important; -} - -.desktop-mode .board-header { - font-size: clamp(14px, 3vw, 18px) !important; - padding: 2.5vh 1.5vw 0.5vh !important; -} - -.desktop-mode .board-header .board-header-title { - font-size: clamp(14px, 3vw, 18px) !important; -} - -.desktop-mode .board-header .board-header-description { - font-size: 12px !important; -} - -.desktop-mode .board-header .board-header-btn { - font-size: clamp(12px, 2.5vw, 16px) !important; - padding: 0.5vh 0.8vw !important; -} - -.desktop-mode .board-header .board-header-btn i { - font-size: clamp(12px, 2.5vw, 16px) !important; + flex: 1; + gap: 2ch; + padding: 0 0.5ch; } diff --git a/client/components/boards/boardHeader.jade b/client/components/boards/boardHeader.jade index 76fd8a25a..441f821ef 100644 --- a/client/components/boards/boardHeader.jade +++ b/client/components/boards/boardHeader.jade @@ -1,26 +1,67 @@ template(name="boardHeaderBar") - h1.header-board-menu - with currentBoard - if $eq title 'Templates' - | {{_ 'templates'}} - else - +viewer - = title + .board-header + .header-board-menu + with currentBoard + if $eq title 'Templates' + | {{_ 'templates'}} + else + +viewer + = title + if currentBoard + if currentUser + 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 + unless isMiniScreen + .board-header-btns-left + if currentBoard + if currentUser + with currentBoard + a.board-header-btn( + class="{{#if currentUser.isBoardAdmin}}js-change-visibility{{else}}is-disabled{{/if}}" + title="{{_ currentBoard.permission}}") + i.fa(class="{{#if currentBoard.isPublic}}fa-globe{{else}}fa-lock{{/if}}") + span {{_ currentBoard.permission}} - .board-header-btns.left - unless isMiniScreen + 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(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}}") + 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-right + .separator if currentBoard - if currentUser - with currentBoard - if currentUser.isBoardAdmin + if isMiniScreen + 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}}") - i.fa(class="{{#if currentBoard.isPublic}}fa-globe{{else}}fa-lock{{/if}}") - span {{_ currentBoard.permission}} + a.board-header-btn( + class="{{#if currentUser.isBoardAdmin}}js-change-visibility{{else}}is-disabled{{/if}}" + title="{{_ currentBoard.permission}}") + i.fa(class="{{#if currentBoard.isPublic}}fa-globe{{else}}fa-lock{{/if}}") a.board-header-btn.js-watch-board( title="{{_ watchLevel }}") @@ -29,86 +70,43 @@ template(name="boardHeaderBar") 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(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}}") - 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 - - .board-header-btns.right - if currentBoard - if isMiniScreen - 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}}") - 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" - 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}}") 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 + 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 isSandstorm + if currentUser + a.js-open-archived-board + i.fa.fa-archive - //if showSort - // a.board-header-btn.js-open-sort-view(title="{{_ 'sort-desc'}}") - // i.fa(class="{{directionClass}}") - // span {{_ 'sort'}}{{_ listSortShortDesc}} + //if showSort + // a.board-header-btn.js-open-sort-view(title="{{_ 'sort-desc'}}") + // i.fa(class="{{directionClass}}") + // span {{_ 'sort'}}{{_ listSortShortDesc}} - 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-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'}} + 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 @@ -140,9 +138,9 @@ template(name="boardHeaderBar") 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 + .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 @@ -172,26 +170,29 @@ template(name="boardChangeWatchPopup") li with "watching" a.js-select-watch - i.fa.fa-eye - | {{_ 'watching'}} - if watchCheck - i.fa.fa-check + span + 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 + 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 + i.fa.fa-bell-slash + | {{_ 'muted'}} + if watchCheck + i.fa.fa-check span.sub-name {{_ 'muted-info'}} template(name="boardChangeViewPopup") @@ -247,12 +248,13 @@ template(name="createBoard") .materialCheckBox#add-template-container span {{_ 'add-template-container'}} input.primary.wide(type="submit" value="{{_ 'create'}}") - span.quiet - | {{_ 'or'}} - a.js-import-board {{_ 'import'}} - span.quiet - | / - a.js-board-template {{_ 'template'}} + .create-element-foooter + span.quiet + | {{_ 'or'}} + a.js-import-board {{_ 'import'}} + span.quiet + | / + a.js-board-template {{_ 'template'}} template(name="createBoardPopup") form @@ -276,12 +278,13 @@ template(name="createBoardPopup") .materialCheckBox#add-template-container span {{_ 'add-template-container'}} input.primary.wide(type="submit" value="{{_ 'create'}}") - span.quiet - | {{_ 'or'}} - a.js-import-board {{_ 'import'}} - span.quiet - | / - a.js-board-template {{_ 'template'}} + .create-element-foooter + span.quiet + | {{_ 'or'}} + a.js-import-board {{_ 'import'}} + span.quiet + | / + a.js-board-template {{_ 'template'}} // New popup for Template Container creation; shares the same form content template(name="createTemplateContainerPopup") @@ -305,13 +308,14 @@ template(name="createTemplateContainerPopup") a.flex.js-toggle-add-template-container .materialCheckBox#add-template-container span {{_ 'add-template-container'}} - input.primary.wide(type="submit" value="{{_ 'create'}}") - span.quiet - | {{_ 'or'}} - a.js-import-board {{_ 'import'}} - span.quiet - | / - a.js-board-template {{_ 'template'}} + .create-element-foooter + input.primary.wide(type="submit" value="{{_ 'create'}}") + span.quiet + | {{_ 'or'}} + a.js-import-board {{_ 'import'}} + span.quiet + | / + a.js-board-template {{_ 'template'}} //template(name="listsortPopup") // h2 @@ -362,4 +366,3 @@ template(name="cardsSortPopup") a.js-sort-created-asc i.fa.fa-arrow-up | {{_ 'created-at-oldest-first'}} - diff --git a/client/components/boards/boardHeader.js b/client/components/boards/boardHeader.js index 7317a7501..4fef70ef3 100644 --- a/client/components/boards/boardHeader.js +++ b/client/components/boards/boardHeader.js @@ -33,9 +33,6 @@ BlazeComponent.extendComponent({ const currentBoard = Utils.getCurrentBoard(); return currentBoard && currentBoard.getWatchLevel(Meteor.userId()); }, - - - isStarred() { const boardId = Session.get('currentBoard'); const user = ReactiveCache.getCurrentUser(); @@ -182,7 +179,7 @@ Template.boardHeaderBar.helpers({ if (!sortBy) { return '🃏'; // Card icon when nothing is selected } - + // Determine which sort option is active based on sortBy object if (sortBy.dueAt) { return '📅'; // Due date icon @@ -191,7 +188,7 @@ Template.boardHeaderBar.helpers({ } else if (sortBy.createdAt) { return sortBy.createdAt === 1 ? '⬆️' : '⬇️'; // Up/down arrow based on direction } - + return '🃏'; // Default card icon }, }); diff --git a/client/components/boards/boardsList.css b/client/components/boards/boardsList.css index 9ba4ee1c7..66c17404a 100644 --- a/client/components/boards/boardsList.css +++ b/client/components/boards/boardsList.css @@ -1,7 +1,7 @@ @import url("../../../css/reset.css") print, screen; -/* Board List Header with Zoom Controls */ -.board-list-header { +/* Board List Header */ +.board-list-header:not(:empty) { display: flex; justify-content: center; margin: 1vh 0 2vh 0; @@ -11,42 +11,57 @@ /* Two-column layout for All Boards */ .boards-layout { display: grid; - grid-template-columns: 260px 1fr; - gap: 16px; + gap: 1ch; + /* menu takes the space it needs, boards has the rest */ + grid-template-columns: minmax(max-content, 250px) 1fr; + justify-content: stretch; + align-items: stretch; +} + +body:not(.mobile-mode) .boards-layout { + padding: 1vmax; +} + +body.mobile-mode .boards-layout { + grid-auto-flow: row; + grid-template-rows: 1fr auto; + grid-template-columns: minmax(auto, 100vw); } .boards-left-menu { + display: flex; + flex-direction: column; + align-items: stretch; border-right: 1px solid #e0e0e0; - padding-right: 12px; + overflow: visible; + align-self: stretch; + min-width: max-content; + flex: 1; } -.boards-left-menu ul.menu { - list-style: none; - padding: 0; - margin: 0 0 12px 0; -} - -.boards-left-menu .menu-item { - margin: 4px 0; -} .boards-left-menu .menu-item a { display: flex; justify-content: space-between; align-items: center; - padding: 8px 10px; - border-radius: 4px; + border-radius: 0.4ch; cursor: pointer; } .boards-left-menu .menu-item .menu-label { flex: 1; + padding: 0.3lh; } .boards-left-menu .menu-item .menu-count { + display: flex; + align-items: center; + justify-content: center; background: #ddd; - padding: 2px 8px; - border-radius: 12px; - font-size: 12px; + margin-right: 0.4ch; + aspect-ratio: 1 / 1; + border-radius: 50%; + padding: 0.2em; + font-size: 0.8em; + min-width: 3ch; font-weight: bold; - margin-left: 8px; } .boards-left-menu .menu-item.active a, .boards-left-menu .menu-item a:hover { @@ -62,19 +77,29 @@ border: 2px dashed #2196F3; } +.boards-right-grid { + display: flex; + flex-direction: column; + gap: 1vmax; + /* hackish way to make the item grow only when wrapping, i.e. with no + other competing item on the cross axis */ + flex: 10 1 0; +} + .workspaces-header { display: flex; align-items: center; justify-content: space-between; font-weight: bold; - margin-top: 12px; + padding: 0.3lh 0.8ch; + gap: 0.3lh; } .workspaces-header .js-add-space { text-decoration: none; font-weight: bold; border: 1px solid #ccc; padding: 2px 8px; - border-radius: 4px; + border-radius: 0.4ch; } .workspace-tree { @@ -90,9 +115,11 @@ .workspace-node-content { display: flex; align-items: center; - gap: 4px; - padding: 4px; - border-radius: 4px; + gap: 2ch; + justify-content: end; + flex: 1; + padding: 0.3lh 1ch 0 2ch; + border-radius: 0.4ch; transition: background-color 0.2s; } @@ -109,7 +136,6 @@ .workspace-drag-handle { cursor: grab; color: #999; - font-size: 14px; padding: 0 4px; user-select: none; } @@ -123,14 +149,13 @@ align-items: center; gap: 6px; padding: 4px 8px; - border-radius: 4px; + border-radius: 0.4ch; cursor: pointer; flex: 1; text-decoration: none; } .workspace-node .workspace-icon { - font-size: 16px; line-height: 1; } @@ -142,7 +167,6 @@ background: #ddd; padding: 2px 6px; border-radius: 10px; - font-size: 11px; font-weight: bold; min-width: 20px; text-align: center; @@ -154,7 +178,6 @@ border-radius: 3px; cursor: pointer; text-decoration: none; - font-size: 14px; opacity: 0.6; transition: opacity 0.2s; } @@ -174,71 +197,89 @@ background: #bbb; } -.boards-right-grid { - min-height: 200px; +.boards-left-menu .menu { + display: flex; + flex-direction: column; + gap: 0.3lh; + padding-bottom: 0.3lh; } - .boards-path-header { display: flex; - align-items: center; - justify-content: space-between; - gap: 8px; - padding: 12px 16px; - margin-bottom: 16px; + flex-direction: column; background: #f5f5f5; border-radius: 6px; - font-size: 16px; font-weight: 500; + min-height: 2lh; + justify-content: center; + + .path-left { + display: flex; + align-items: center; + gap: 1ch; + flex: 1; + } + .path-top { + display: flex; + flex: 1; + justify-content: center; + gap: 1ch; + } + .path-bottom { + display: flex; + align-items: stretch; + justify-content: space-between; + gap: 1ch; + padding: 0 0.5ch; + } } -.boards-path-header .path-left { - display: flex; - align-items: center; - gap: 8px; - flex: 1; -} - -.boards-path-header .multiselection-hint { +.multiselection-hint { background: #FFF3CD; color: #856404; - padding: 4px 12px; - border-radius: 4px; - font-size: 13px; + border-radius: 0.4ch; + padding: 0.2lh 0.5ch; font-weight: normal; border: 1px solid #FFE69C; animation: pulse 2s ease-in-out infinite; + display: flex; + flex: 1; + font-size: 0.8em; + >span { + flex: 1; + align-self: center; + } } @keyframes pulse { 0%, 100% { opacity: 1; } - 50% { opacity: 0.7; } + 50% { opacity: 0; } } .boards-path-header .path-right { display: flex; align-items: center; - gap: 8px; + gap: 0.5lh; + +} + +.boards-path-header .path-right button { + margin: 0; } .boards-path-header .path-icon { - font-size: 18px; -} + } .boards-path-header .path-text { color: #333; } .boards-path-header .board-header-btn { - padding: 6px 12px; - background: #fff; - border: 1px solid #ddd; - border-radius: 4px; - cursor: pointer; + min-width: 4ch; + min-height: 4ch; display: flex; + justify-content: center; + align-self: center; align-items: center; - gap: 6px; - font-size: 14px; - transition: all 0.2s; } .boards-path-header .board-header-btn:hover { @@ -246,13 +287,22 @@ border-color: #bbb; } -.boards-path-header .board-header-btn.emphasis { - background: #2196F3; - color: #fff; - border-color: #2196F3; +.boards-path-header .board-header-btn.js-multiselection-activate { + &.emphasis { + background: #2196F3; + color: #fff; + border-color: #2196F3; + box-shadow: 0 2px 8px rgba(33, 150, 243, 0.5); + } font-weight: bold; - box-shadow: 0 2px 8px rgba(33, 150, 243, 0.5); - transform: scale(1.05); + align-self: stretch; + align-items: center; + display: flex; + justify-content: center; + flex: 1; + min-width: 4ch; + font-size: 1em; + border-radius: 0.6ch; } .boards-path-header .board-header-btn.emphasis:hover { @@ -261,101 +311,42 @@ } .boards-path-header .board-header-btn-close { - padding: 4px 10px; + align-self: stretch; + align-items: center; + display: flex; + justify-content: center; + flex: 1; + border-radius: 0.6ch; + min-width: 4ch; background: #f44336; color: #000; border: none; - border-radius: 4px; cursor: pointer; - font-size: 16px; - margin-left: 10px; /* Extra space between MultiSelection toggle and Remove Filter */ + font-size: 1em; } .boards-path-header .board-header-btn-close:hover { background: #d32f2f; } -.zoom-controls { - display: flex; - align-items: center; - gap: 0.5vw; - background: rgba(255, 255, 255, 0.9); - padding: 0.5vh 1vw; - border-radius: 0.5vw; - box-shadow: 0 0.2vh 0.5vh rgba(0,0,0,0.1); -} - -.zoom-controls .board-header-btn { - padding: 0.5vh 0.8vw !important; - border-radius: 0.3vw !important; - background: #fff !important; - border: 1px solid #000 !important; - transition: all 0.2s ease !important; - text-decoration: none !important; - color: #000 !important; - display: flex !important; - align-items: center !important; - gap: 0.3vw !important; - height: auto !important; - line-height: normal !important; - margin: 0 !important; - float: none !important; - overflow: visible !important; -} - -.zoom-controls .board-header-btn i { - color: #000 !important; - float: none !important; - display: inline !important; - line-height: normal !important; - margin: 0 !important; -} - -.zoom-controls .board-header-btn:hover { - background: #000 !important; - border-color: #000 !important; - color: #fff !important; -} - -.zoom-controls .board-header-btn:hover i { - color: #fff !important; -} - -.zoom-controls .board-header-btn.is-active { - background: #0079bf; - color: white; - border-color: #005a8a; -} - -.zoom-controls .board-header-btn.is-active i { - color: white; -} - -.zoom-level { - font-weight: bold; - color: #333; - min-width: 3vw; - text-align: center; - font-size: clamp(12px, 2vw, 14px); - cursor: pointer; - padding: 0.3vh 0.5vw; - border-radius: 0.3vw; - transition: all 0.2s ease; -} - -.zoom-level:hover { - background: #f0f0f0; - color: #000; -} - .board-list { - margin: 0 8px; + display: grid; + grid-template-columns: repeat(auto-fill, minmax(30ch, 1fr)); + grid-auto-rows: 7lh; + gap: 0.5lh 0.5lh; + align-items: start; } -.board-list li { - float: left; - width: 20%; - box-sizing: border-box; - position: relative; + +.board-list .details { + height: fit-content; +} + +.board-list .board-list-item-name .viewer { + min-height: 0; +} + +.board-list .board-list-item-name p { + margin: 0; } .board-list li.placeholder:after { content: ''; @@ -380,21 +371,59 @@ .board-list li:hover .is-not-star-active { opacity: 1; } +.board-list { + .js-board, .js-add-board { + display: flex; + overflow: hidden; + background-color: inherit; + min-height: 4lh !important; + min-width: min-content; + height: 100%; + /* Inherit board color from parent li.js-board */ + color: #f6f6f6; + border-radius: 0.5ch; + /* No border-radius - parent .js-board has it */ + font-weight: 700; + position: relative; + text-decoration: none; + overflow-wrap: break-word; + box-sizing: border-box; + justify-content: center; + align-items: stretch; + >a { + display: flex; + align-items: center; + justify-content: stretch; + flex: 1; + } + } + .board-list-item { + display: flex; + text-align: center; + justify-content: center; + align-items: center; + gap: 1ch; + flex: 1; + padding: 0 1ch; + } +} + +.board-list .board-list-item .board-card-header { + display: flex; + justify-content: center; + align-items: center; + gap: 0.3lh; +} + .board-list .board-list-item { - overflow: hidden; - background-color: inherit; /* Inherit board color from parent li.js-board */ - color: #f6f6f6; - min-height: 100px; - font-size: 16px; - line-height: 22px; - border-radius: 0; /* No border-radius - parent .js-board has it */ - display: block; - font-weight: 700; - padding: 36px 8px 32px 8px; /* Top padding for drag handle, bottom for checkbox */ - margin: 0; /* No margin - moved to parent .js-board */ - position: relative; - text-decoration: none; - word-wrap: break-word; + font-size: var(--list-item-size); +} + +.board-list .board-list-item .board-card-footer { + display: flex; + justify-content: center; + box-sizing: border-box; + padding: 0.1ch 0.1lh; } .board-list .board-list-item > .js-open-board { @@ -402,9 +431,6 @@ color: inherit; display: block; } -.board-list .board-list-item.template-container { - border: 4px solid #fff; -} .board-list .board-list-item.tile { background-size: auto; background-repeat: repeat; @@ -412,30 +438,23 @@ .board-list .board-list-item-sub-name { color: rgba(255,255,255,0.5); display: block; - font-size: 14px; font-weight: 400; line-height: 22px; } .board-list .board-list-item-desc { color: #fff; display: block; - font-size: 14px; font-weight: 400; line-height: 18px; } -.board-list .js-add-board { - text-align: center; -} .board-list .js-add-board .label { font-weight: normal; - line-height: 56px; - min-height: 100px; display: flex; align-items: center; + font-size: var(--list-item-size); + font-weight: bold; justify-content: center; 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 { @@ -449,23 +468,12 @@ } .board-list .is-star-active, .board-list .is-not-star-active { - top: 0; - font-size: 14px; - height: 18px; - line-height: 18px; opacity: 0; - padding: 9px 9px; - position: absolute; - right: 0; transition-duration: 0.15s; transition-property: color, font-size, background; } .board-list .fa-circle { bottom: 0; - font-size: 10px; - height: 10px; - line-height: 10px; - padding: 9px 9px; position: absolute; right: 0; transition-duration: 0.15s; @@ -481,26 +489,13 @@ color: #fff; } .board-list .fa-clone { - position: absolute; - bottom: 0; - font-size: 14px; - height: 18px; line-height: 18px; - opacity: 0; - right: 0; - padding: 9px 9px; transition-duration: 0.15s; transition-property: color, font-size, background; } .board-list .fa-archive { position: absolute; - bottom: 0; - font-size: 14px; - height: 18px; - line-height: 18px; opacity: 0; - left: 0; - padding: 9px 9px; transition-duration: 0.15s; transition-property: color, font-size, background; } @@ -521,7 +516,6 @@ .board-list li:hover a .fa-clone:hover, .board-list li:hover a .fa-archive:hover, .board-list li:hover a .is-not-star-active:hover { - font-size: 18px; opacity: 1; } .board-list li:hover a .is-star-active, @@ -533,15 +527,9 @@ /* Board drag handle - always visible and positioned at top */ .board-list .board-handle { - position: absolute; - padding: 4px 6px; - top: 4px; - left: 50%; - transform: translateX(-50%); - font-size: 14px; color: #fff; background: rgba(0,0,0,0.4); - border-radius: 4px; + border-radius: 0.4ch; display: flex; align-items: center; justify-content: center; @@ -561,53 +549,75 @@ color: #000; } -/* Multiselection checkbox on board items */ -.board-list .board-list-item .multi-selection-checkbox { - position: absolute !important; - bottom: 4px !important; - left: 4px !important; - top: auto !important; - width: 24px; - height: 24px; - border: 3px solid #fff; - background: rgba(0,0,0,0.5); - border-radius: 4px; - cursor: pointer; - z-index: 11; - display: flex; - align-items: center; - justify-content: center; - transition: all 0.2s; - box-shadow: 0 2px 4px rgba(0,0,0,0.3); - transform: none !important; - margin: 0 !important; +/* used to animate checkbox when added +without messing with the event/activation system */ +@keyframes revealCheckBox { + from { opacity: 0; } + to { opacity: 1; } } -.board-list .board-list-item .multi-selection-checkbox:hover { - background: rgba(0,0,0,0.7); - transform: scale(1.15) !important; - box-shadow: 0 3px 6px rgba(0,0,0,0.5); +.board-list .board-list-item .multi-selection-checkbox{ + display: flex; + align-self: center; + width: 2ch; + height: 2ch; } .board-list .board-list-item .multi-selection-checkbox.is-checked { background: #3cb500; border-color: #3cb500; box-shadow: 0 2px 8px rgba(60, 181, 0, 0.6); - width: 24px !important; - height: 24px !important; + width: 2ch !important; + height: 2ch !important; top: auto !important; - left: 4px !important; transform: none !important; - border-radius: 4px !important; + border-radius: 0.4ch !important; } .board-list .board-list-item .multi-selection-checkbox.is-checked::after { content: '✓'; color: #fff; - font-size: 16px; font-weight: bold; + position: absolute; + left: 0.4ch; + top: -0.2ch; } +/* Multiselection checkbox on board items */ +.board-list .board-list-item .multi-selection-checkbox:where(.active) { + border: none; + box-shadow: 0 0 0 3px #fff; + /* get back margin from box-shadow */ + background: rgba(0,0,0,0.5); + outline-color: transparent; + border-radius: 0.4ch; + cursor: pointer; + z-index: 11; + align-items: center; + justify-content: center; + animation: 0.2s ease-out 0s 1 revealCheckBox; + + + &:hover { + background: rgba(0, 0, 0, 0.7); + transform: scale(1.15) !important; + box-shadow: 0 3px 6px rgba(0, 0, 0, 0.5); + } + + &.is-checked { + background: #3cb500; + border-color: #3cb500; + box-shadow: 0 3px 6px #3cb500; + + &::after {content: '✅'; + color: #fff; + font-size: 1em; + font-weight: bold; + } + } +} + + /* Grey checkboxes when grey icons setting is enabled */ body.grey-icons-enabled .board-list .board-list-item .multi-selection-checkbox.is-checked { background: #7a7a7a; @@ -622,48 +632,41 @@ body.grey-icons-enabled .board-list.is-multiselection-active .js-board.is-checke .board-list.is-multiselection-active .js-board.is-checked { outline: 4px solid #3cb500; - outline-offset: -4px; + outline-offset: -2px; box-shadow: 0 4px 12px rgba(60, 181, 0, 0.4); } /* Visual hint when multiselection is active */ .board-list.is-multiselection-active .board-list-item { - border: 2px dashed rgba(33, 150, 243, 0.3); + outline: 2px dashed rgba(33, 150, 243, 0.3); +} + +.board-backgrounds-list { + display: grid; + grid-template-columns: 1fr 1fr; + grid-auto-rows: 3lh; + justify-items: stretch; + gap: 1ch; } .board-backgrounds-list .board-background-select { box-sizing: border-box; - display: block; - float: left; - width: 50%; - padding-top: 12px; + display: flex; position: relative; z-index: 1; } -.board-backgrounds-list .board-background-select:nth-child(-n + 2) { - padding-top: 0; -} -.board-backgrounds-list .board-background-select:nth-child(2n) { - padding-left: 6px; -} -.board-backgrounds-list .board-background-select:nth-child(2n+1) { - padding-right: 6px; -} .board-backgrounds-list .board-background-select .background-box { color: #fff; - border-radius: 3px; - background-size: cover; - display: block; - height: 74px; - position: relative; - width: 100%; - cursor: pointer; display: flex; + border-radius: 0.4ch; + flex: 1; align-items: center; justify-content: center; + gap: 1ch; + font-size: 1.1em; + cursor: pointer; } .board-backgrounds-list .board-background-select .background-box i.fa-check { - font-size: 25px; color: #3cb500; } /* Grey check icons when grey icons setting is enabled */ @@ -679,56 +682,20 @@ body.grey-icons-enabled .checkmark-no-grey { /* Mobile view styles - applied when isMiniScreen is true (iPhone, etc.) */ .board-list.mobile-view { - height: calc(100vh - 120px); overflow-y: scroll !important; overflow-x: hidden; - padding: 0 1rem; margin: 0; scrollbar-width: auto !important; scrollbar-color: #888 #f1f1f1; -} -.board-list.mobile-view li { - width: 100%; - float: none; - display: block; - margin-bottom: 1rem; - padding-right: 50px; /* Space for drag handle */ -} -.board-list.mobile-view .board-list-item { - overflow: visible; - height: 8rem; - width: 100%; - margin: 0; - padding-right: 50px; /* Ensure content doesn't overlap with drag handle */ + display: flex; + flex-direction: column; + align-items: stretch; + margin: 0 0.5ch; + gap: 0.3lh; } -.board-list.mobile-view .board-list-item .details { - padding-right: 50px; /* Extra space for drag handle */ - width: 100%; - box-sizing: border-box; -} .board-list.mobile-view .board-list-item-sub-name { - position: relative; - top: -100px; - left: -100px; -} -.board-list.mobile-view .board-handle { - position: absolute; - padding: 7px; - top: 50%; - transform: translateY(-50%); - right: 10px; - font-size: 24px; - color: #fff; - background: rgba(0,0,0,0.3); - border-radius: 50%; - width: 40px; - height: 40px; - display: flex; - align-items: center; - justify-content: center; - z-index: 10; - transition: background-color 0.2s ease; + position: relative;; } .board-list.mobile-view .board-handle:hover { @@ -760,11 +727,6 @@ body.grey-icons-enabled .checkmark-no-grey { background: #555 !important; } -/* Force mobile view to have scrollable content */ -.board-list.mobile-view { - min-height: 100vh; /* Force content to be tall enough to scroll */ -} - /* Hide archive and clone board buttons in mobile view */ .board-list.mobile-view .js-archive-board, .board-list.mobile-view .js-clone-board { @@ -777,368 +739,11 @@ body.grey-icons-enabled .checkmark-no-grey { font-family: inherit !important; } -.board-list.mobile-view::after { - content: ''; - display: block; - height: 100px; -} -@media screen and (max-width: 800px), - screen and (max-device-width: 800px), - screen and (-webkit-min-device-pixel-ratio: 2) and (max-width: 800px), - screen and (max-width: 800px) and (orientation: portrait), - screen and (max-width: 800px) and (orientation: landscape), - screen and (max-device-width: 932px) and (-webkit-min-device-pixel-ratio: 3) { - .board-list { - height: 100%; - overflow-y: auto; - overflow-x: hidden; - padding: 0 1rem; - margin: 0; - } - .board-list li { - width: 100%; - float: none; - display: block; - margin-bottom: 1rem; - padding-right: 50px; /* Space for drag handle */ - } - .board-list .board-list-item { - overflow: visible; - height: 8rem; - width: 100%; - margin: 0; - padding-right: 50px; /* Ensure content doesn't overlap with drag handle */ - } - - .board-list .board-list-item .details { - padding-right: 50px; /* Extra space for drag handle */ - width: 100%; - box-sizing: border-box; - } - .board-list .board-list-item-sub-name { - position: relative; - top: -100px; - left: -100px; - } - .board-list .board-handle { - position: absolute; - padding: 7px; - top: 50%; - transform: translateY(-50%); - right: 10px; - font-size: 24px; - color: #fff; - background: rgba(0,0,0,0.3); - border-radius: 50%; - width: 40px; - height: 40px; - display: flex; - align-items: center; - justify-content: center; - z-index: 10; - transition: background-color 0.2s ease; - } - - .board-list .board-handle:hover { - background: rgba(255, 255, 0, 0.8) !important; /* Yellow hover */ - } -} -/* Very small screens - ensure one board per row */ -@media screen and (max-width: 360px) { - .board-list li { - width: 100% !important; - float: none !important; - display: block !important; - } - .board-list .board-handle { - position: absolute; - padding: 7px; - top: 50%; - transform: translateY(-50%); - right: 10px; - font-size: 24px; - color: #fff; - background: rgba(0,0,0,0.3); - border-radius: 50%; - width: 40px; - height: 40px; - display: flex; - align-items: center; - justify-content: center; - } -} - -/* Mobile - make all text and icons 2x bigger above #content on All Boards page */ -@media screen and (max-width: 800px), - screen and (max-device-width: 800px), - screen and (-webkit-min-device-pixel-ratio: 2) and (max-width: 800px), - screen and (max-width: 800px) and (orientation: portrait), - screen and (max-width: 800px) and (orientation: landscape), - screen and (max-device-width: 932px) and (-webkit-min-device-pixel-ratio: 3) { - .wrapper { - font-size: 2em !important; /* 2x bigger base font size for All Boards page */ - } - - .wrapper * { - font-size: inherit !important; /* Inherit the 2x scaling */ - } - - .wrapper .fa, .wrapper .icon { - font-size: 2em !important; /* 2x bigger icons */ - } - - .board-list-header { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - .board-list-header h1 { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - .AllBoardTeamsOrgs { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - .AllBoardTeamsOrgs select { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - .AllBoardTeamsOrgs input { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - .AllBoardTeamsOrgs .fa { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - .board-list { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - .board-list .board-list-item { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - .board-list .board-list-item-name { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - .board-list .board-list-item-desc { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - .board-list .minicard-members { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - .board-list .minicard-lists { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - .board-list .fa { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - .board-list .board-handle { - font-size: 1em !important; /* Use inherited 2x scaling */ - } -} - -/* Fallback for iPhone devices using JavaScript detection - All Boards page */ -.iphone-device .wrapper { - font-size: 2em !important; /* 2x bigger base font size for All Boards page */ -} - -.iphone-device .wrapper * { - font-size: inherit !important; /* Inherit the 2x scaling */ -} - -.iphone-device .wrapper .fa, .iphone-device .wrapper .icon { - font-size: 2em !important; /* 2x bigger icons */ -} - -.iphone-device .board-list-header { - font-size: 1em !important; /* Use inherited 2x scaling */ -} - -.iphone-device .board-list-header h1 { - font-size: 1em !important; /* Use inherited 2x scaling */ -} - -.iphone-device .AllBoardTeamsOrgs { - font-size: 1em !important; /* Use inherited 2x scaling */ -} - -.iphone-device .AllBoardTeamsOrgs select { - font-size: 1em !important; /* Use inherited 2x scaling */ -} - -.iphone-device .AllBoardTeamsOrgs input { - font-size: 1em !important; /* Use inherited 2x scaling */ -} - -.iphone-device .AllBoardTeamsOrgs .fa { - font-size: 1em !important; /* Use inherited 2x scaling */ -} - -.iphone-device .board-list { - font-size: 1em !important; /* Use inherited 2x scaling */ -} - -.iphone-device .board-list .board-list-item { - font-size: 1em !important; /* Use inherited 2x scaling */ -} - -.iphone-device .board-list .board-list-item-name { - font-size: 1em !important; /* Use inherited 2x scaling */ -} - -.iphone-device .board-list .board-list-item-desc { - font-size: 1em !important; /* Use inherited 2x scaling */ -} - -.iphone-device .board-list .minicard-members { - font-size: 1em !important; /* Use inherited 2x scaling */ -} - -.iphone-device .board-list .minicard-lists { - font-size: 1em !important; /* Use inherited 2x scaling */ -} - -.iphone-device .board-list .fa { - font-size: 1em !important; /* Use inherited 2x scaling */ -} - -.iphone-device .board-list .board-handle { - font-size: 1em !important; /* Use inherited 2x scaling */ -} - -/* iPhone 12 Mini and very small screens - make everything much larger */ -@media screen and (max-width: 400px) and (max-height: 900px) { - .board-list { - height: calc(100vh - 120px) !important; - overflow-y: scroll !important; - overflow-x: hidden !important; - -webkit-overflow-scrolling: touch; - padding: 0 0.5rem; - } - - .board-list li { - width: 100% !important; - float: none !important; - display: block !important; - margin-bottom: 1.5rem !important; - } - - .board-list .board-list-item { - height: 12rem !important; /* Much taller */ - width: 100% !important; - margin: 0 !important; - padding: 1rem !important; /* More padding */ - font-size: 18px !important; /* Much larger text */ - line-height: 1.4 !important; - } - - .board-list .board-list-item .board-list-item-name { - font-size: 20px !important; /* Larger board names */ - font-weight: bold !important; - margin-bottom: 0.5rem !important; - } - - .board-list .board-list-item .board-list-item-desc { - font-size: 16px !important; /* Larger descriptions */ - line-height: 1.3 !important; - } - - .board-list .board-list-item .minicard-members { - font-size: 14px !important; /* Larger member avatars */ - } - - .board-list .board-list-item .minicard-lists { - font-size: 14px !important; /* Larger list counters */ - } - - .board-list .board-handle { - position: absolute; - padding: 10px !important; - top: 50%; - transform: translateY(-50%); - right: 15px !important; - font-size: 28px !important; /* Much larger drag handle */ - color: #fff; - background: rgba(0,0,0,0.4) !important; - border-radius: 50%; - width: 50px !important; /* Larger handle */ - height: 50px !important; - display: flex; - align-items: center; - justify-content: center; - z-index: 10; - transition: background-color 0.2s ease; - } - - .board-list .board-handle:hover { - background: rgba(255, 255, 0, 0.8) !important; /* Yellow hover */ - } - - /* Force scrollbar to be visible and larger */ - .board-list::-webkit-scrollbar { - width: 16px !important; /* Much wider scrollbar */ - display: block !important; - visibility: visible !important; - } - - .board-list::-webkit-scrollbar-track { - background: #f1f1f1 !important; - border-radius: 8px !important; - display: block !important; - visibility: visible !important; - } - - .board-list::-webkit-scrollbar-thumb { - background: #666 !important; /* Darker for better visibility */ - border-radius: 8px !important; - display: block !important; - visibility: visible !important; - min-height: 50px !important; /* Minimum thumb size */ - } - - .board-list::-webkit-scrollbar-thumb:hover { - background: #333 !important; - } - - /* Ensure scrollbar is always visible */ - .board-list { - scrollbar-gutter: stable; - scrollbar-width: auto !important; - min-height: 100vh !important; - } - - .board-list::after { - content: ''; - display: block; - height: 200px !important; /* More space to ensure scrolling */ - } -} .AllBoardTeamsOrgs { list-style-type: none; overflow: hidden; } -.AllBoardTeams, -.AllBoardOrgs, -.AllBoardBtns { - float: left; -} -.js-AllBoardOrgs { - margin-left: 16px; -} -.AllBoardTeams { - margin-left: 16px; -} -.AllBoardButtonsContainer { - margin: 16px; -} #filterBtn, #resetBtn { display: inline; @@ -1148,10 +753,8 @@ body.grey-icons-enabled .checkmark-no-grey { background: #f44336; color: #000; border: none; - border-radius: 4px; - padding: 6px 12px; + border-radius: 0.4ch; cursor: pointer; - font-size: 14px; display: inline-flex; align-items: center; gap: 6px; @@ -1163,21 +766,17 @@ body.grey-icons-enabled .checkmark-no-grey { } #resetBtn.filter-reset-btn .reset-icon { - font-size: 14px; -} + } .js-board { - display: block; background-color: #999; /* Default gray background if no color class is applied */ border-radius: 3px; /* Rounded corners for board items */ overflow: hidden; /* Ensure children respect rounded corners */ - margin: 8px; /* Space between board items */ } /* Reset background for add-board button */ .js-add-board { background-color: transparent !important; - margin: 8px !important; /* Keep margin for add-board */ } /* Apply board colors to li.js-board parent instead of just the link */ @@ -1200,13 +799,10 @@ body.grey-icons-enabled .checkmark-no-grey { .board-list .board-color-exodark { background-color: #222; } .minicard-members { - padding: 6px 0 6px 8px; - width: 100%; - margin-bottom: 2px; - margin-left: -4px; - display: inline-block; + display: flex; + justify-content: stretch; } -.minicard-lists { +.minicard-lists:has(*) { margin: 0 auto; max-width: 95%; height: 100%; @@ -1232,7 +828,6 @@ body.grey-icons-enabled .checkmark-no-grey { screen and (max-device-width: 932px) and (-webkit-min-device-pixel-ratio: 3) { .wrapper { overflow: hidden; - height: 100vh; } .board-list { @@ -1241,7 +836,6 @@ body.grey-icons-enabled .checkmark-no-grey { -webkit-overflow-scrolling: touch; scrollbar-width: thin; scrollbar-color: #888 #f1f1f1; - height: calc(100vh - 120px); /* Ensure there's content to scroll */ } /* Force scrollbar to always be visible */ @@ -1278,14 +872,6 @@ body.grey-icons-enabled .checkmark-no-grey { .board-list { scrollbar-gutter: stable; scrollbar-width: auto !important; - min-height: 100vh; /* Force content to be tall enough to scroll */ - } - - /* Ensure there's always content to scroll */ - .board-list::after { - content: ''; - display: block; - height: 100px; } /* Ensure only one scrollbar is visible */ @@ -1295,6 +881,8 @@ body.grey-icons-enabled .checkmark-no-grey { #content { overflow: hidden; + display: flex; + flex: 1; } /* Hide archive and clone board buttons in mobile view */ @@ -1309,4 +897,3 @@ body.grey-icons-enabled .checkmark-no-grey { font-family: inherit !important; } } - diff --git a/client/components/boards/boardsList.jade b/client/components/boards/boardsList.jade index aea3c2d8a..f9f57edf2 100644 --- a/client/components/boards/boardsList.jade +++ b/client/components/boards/boardsList.jade @@ -67,81 +67,71 @@ template(name="boardList") // Right boards grid .boards-right-grid .boards-path-header - .path-left - span.path-icon.emoji-icon {{currentMenuPath.icon}} - span.path-text {{currentMenuPath.text}} - if BoardMultiSelection.isActive - span.multiselection-hint - 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 + .path-bottom + .path-left + span.path-icon.emoji-icon {{currentMenuPath.icon}} + span.path-text {{currentMenuPath.text}} + .path-right + unless isMiniScreen + +headerMultiSelection + if canModifyBoards + 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 - i.fa.fa-archive - span {{_ 'archive-board'}} - button.js-duplicate-selected-boards.board-header-btn - 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 - i.fa.fa-check-square-o - if BoardMultiSelection.isActive - a.board-header-btn-close.js-multiselection-reset(title="{{_ 'filter-clear'}}") - span.emoji-icon - i.fa.fa-times + i.fa.fa-check-square-o + if BoardMultiSelection.isActive + a.board-header-btn-close.js-multiselection-reset(title="{{_ 'filter-clear'}}") + 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 i.fa.fa-plus - |  {{_ 'add-template-container'}} + | {{_ 'add-template-container'}} else a.board-list-item.label(title="{{_ 'add-board'}}") span.emoji-icon i.fa.fa-plus - |  {{_ 'add-board'}} + | {{_ '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 .board-list-item - if BoardMultiSelection.isActive - .materialCheckBox.multi-selection-checkbox.js-toggle-board-multi-selection( - class="{{#if BoardMultiSelection.isSelected _id}}is-checked{{/if}}") - span.details - span.board-list-item-name= title + .board-card-header 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}}") + .board-card-body + span.details + span.board-list-item-name= title p.board-list-item-desc {{_ 'just-invited'}} button.js-accept-invite.primary {{_ 'accept'}} button.js-decline-invite {{_ 'decline'}} + .board-card-footer + .materialCheckBox.multi-selection-checkbox.js-toggle-board-multi-selection( + class="{{#if BoardMultiSelection.isActive }}active{{/if}} {{#if BoardMultiSelection.isSelected _id}}is-checked{{/if}}") else if $eq type "template-container" - .template-container.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 - i.fa.fa-arrows - - a.js-open-board(href="{{pathFor 'board' id=_id slug=slug}}") + a.js-open-board(href="{{pathFor 'board' id=_id slug=slug}}") + .template-container.board-list-item + if BoardMultiSelection.isActive + .materialCheckBox.multi-selection-checkbox.js-toggle-board-multi-selection( + class="{{#if BoardMultiSelection.isSelected _id}}is-checked{{/if}}") + + span.details span.board-list-item-name(title="{{_ 'template-container'}}") +viewer = title - p.board-list-item-desc - +viewer - = description + //- #FIXME: is this obsolete ? + //- p.board-list-item-desc + //- +viewer + //- = description if hasSpentTimeCards span.js-has-spenttime-cards( class="{{#if hasOvertimeCards}}has-overtime-card-active{{else}}no-overtime-card-active{{/if}}" @@ -154,19 +144,20 @@ template(name="boardList") span.emoji-icon 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 - i.fa.fa-arrows - - a.js-open-board(href="{{pathFor 'board' id=_id slug=slug}}") + a.js-open-board(href="{{pathFor 'board' id=_id slug=slug}}") + .board-list-item + if BoardMultiSelection.isActive + .materialCheckBox.multi-selection-checkbox.js-toggle-board-multi-selection( + class="{{#if BoardMultiSelection.isSelected _id}}is-checked{{/if}}") + + span.details span.board-list-item-name(title="{{_ 'board-drag-drop-reorder-or-click-open'}}") +viewer = title + //- p.board-list-item-desc + //- +viewer + //- = description unless currentSetting.hideBoardMemberList if allowsBoardMemberList .minicard-members @@ -175,34 +166,24 @@ template(name="boardList") +userAvatar(userId=member noRemove=true) unless currentSetting.hideCardCounterList if allowsCardCounterList - .minicard-lists.flex.flex-wrap + .minicard-lists each list in boardLists _id .item | {{ list }} - p.board-list-item-desc - +viewer - = description if hasSpentTimeCards 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 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 - i.fa(class="fa-star{{#unless isStarred}}-o{{/unless}}") + a.js-star-board( + class="{{#if isStarred}}is-star-active{{else}}is-not-star-active{{/if}}" + title="{{_ 'star-board-title'}}") + span.emoji-icon + i.fa(class="fa-star{{#unless isStarred}}-o{{/unless}}") template(name="boardListHeaderBar") h1 {{_ title }} - //.board-header-btns.right - // a.board-header-btn.js-open-archived-board - // i.fa.fa-archive - // span {{_ 'archives'}} - // a.board-header-btn(href="{{pathFor 'board' id=templatesBoardId slug=templatesBoardSlug}}") - // i.fa.fa-clone - // span {{_ 'templates'}} // Recursive template for workspaces tree template(name="workspaceTree") @@ -214,7 +195,7 @@ template(name="workspaceTree") span.workspace-drag-handle span.emoji-icon i.fa.fa-arrows - + a.js-select-workspace(data-id="{{id}}") span.workspace-icon if icon @@ -231,3 +212,16 @@ template(name="workspaceTree") a.js-add-subworkspace(data-id="{{id}}" title="{{_ 'allboards.add-subworkspace'}}") + if children +workspaceTree(nodes=children selectedWorkspaceId=selectedWorkspaceId) + +template(name="headerMultiSelection") + if BoardMultiSelection.isActive + if canModifyBoards + if hasBoardsSelected + button.negate.js-archive-selected-boards.board-header-btn + span.emoji-icon + i.fa.fa-archive + span {{_ 'archive-board'}} + button.negate.js-duplicate-selected-boards.board-header-btn + span.emoji-icon + i.fa.fa-clipboard + span {{_ 'duplicate-board'}} \ No newline at end of file diff --git a/client/components/boards/boardsList.js b/client/components/boards/boardsList.js index fcb2461e6..26c6b532d 100644 --- a/client/components/boards/boardsList.js +++ b/client/components/boards/boardsList.js @@ -108,10 +108,7 @@ BlazeComponent.extendComponent({ const newTree = EJSON.clone(tree); // Remove the dragged space - const { tree: treeAfterRemoval, removed } = removeSpace( - newTree, - draggedSpaceId, - ); + const { tree: treeAfterRemoval, removed } = removeSpace(newTree, draggedSpaceId); if (removed) { // Insert after target @@ -127,46 +124,39 @@ BlazeComponent.extendComponent({ onRendered() { // jQuery sortable is disabled in favor of HTML5 drag-and-drop for space management // The old sortable code has been removed to prevent conflicts - /* OLD SORTABLE CODE - DISABLED - const itemsSelector = '.js-board:not(.placeholder)'; - const $boards = this.$('.js-boards'); - $boards.sortable({ - connectWith: '.js-boards', - tolerance: 'pointer', - appendTo: '.board-list', - helper: 'clone', - distance: 7, - items: itemsSelector, - placeholder: 'board-wrapper placeholder', - start(evt, ui) { - ui.helper.css('z-index', 1000); - ui.placeholder.height(ui.helper.height()); - EscapeActions.executeUpTo('popup-close'); - }, - async stop(evt, ui) { - const prevBoardDom = ui.item.prev('.js-board').get(0); - const nextBoardDom = ui.item.next('.js-board').get(0); - const sortIndex = Utils.calculateIndex(prevBoardDom, nextBoardDom, 1); + // #FIXME OLD SORTABLE CODE - WILL BE DISABLED + // + // const itemsSelector = '.js-board'; - const boardDomElement = ui.item.get(0); - const board = Blaze.getData(boardDomElement); - $boards.sortable('cancel'); - const currentUser = ReactiveCache.getCurrentUser(); - if (currentUser && typeof currentUser.setBoardSortIndex === 'function') { - await currentUser.setBoardSortIndex(board._id, sortIndex.base); - } - }, - }); + // const $boards = this.$('.js-boards'); + // $boards.sortable({ + // connectWith: '.js-boards', + // tolerance: 'pointer', + // appendTo: '.board-list', + // helper: 'clone', + // distance: 7, + // items: itemsSelector, + // placeholder: 'board-wrapper placeholder', + // start(evt, ui) { + // ui.helper.css('z-index', 1000); + // ui.placeholder.height(ui.helper.height()); + // EscapeActions.executeUpTo('popup-close'); + // }, + // async stop(evt, ui) { + // const prevBoardDom = ui.item.prev('.js-board').get(0); + // const nextBoardDom = ui.item.next('.js-board').get(0); + // const sortIndex = Utils.calculateIndex(prevBoardDom, nextBoardDom, 1); - this.autorun(() => { - if (Utils.isTouchScreenOrShowDesktopDragHandles()) { - $boards.sortable({ - handle: '.board-handle', - }); - } - }); - */ + // const boardDomElement = ui.item.get(0); + // const board = Blaze.getData(boardDomElement); + // $boards.sortable('cancel'); + // const currentUser = ReactiveCache.getCurrentUser(); + // if (currentUser && typeof currentUser.setBoardSortIndex === 'function') { + // await currentUser.setBoardSortIndex(board._id, sortIndex.base); + // } + // }, + // }); }, userHasTeams() { if (ReactiveCache.getCurrentUser()?.teams?.length > 0) return true; @@ -357,7 +347,7 @@ BlazeComponent.extendComponent({ const lists = ReactiveCache.getLists({ 'boardId': boardId, 'archived': false },{sort: ['sort','asc']}); const ret = lists.map(list => { let cardCount = ReactiveCache.getCards({ 'boardId': boardId, 'listId': list._id }).length; - return `${list.title}: ${cardCount}`; + return `${list.title}: ${cardCountcardCount}`; }); return ret; */ @@ -535,6 +525,7 @@ BlazeComponent.extendComponent({ 'click .js-multiselection-reset'(evt) { evt.preventDefault(); BoardMultiSelection.disable(); + Popup.close(); }, 'click .js-toggle-board-multi-selection'(evt) { evt.preventDefault(); @@ -708,6 +699,7 @@ BlazeComponent.extendComponent({ icon: newIcon || '📁', }); + Meteor.call('setWorkspacesTree', updatedTree, (err) => { if (err) console.error(err); }); @@ -808,6 +800,7 @@ BlazeComponent.extendComponent({ // Get the workspace ID directly from the dropped workspace-node's data-workspace-id attribute const workspaceId = targetEl.getAttribute('data-workspace-id'); + if (workspaceId) { if (isMultiBoard) { // Multi-board drag @@ -830,6 +823,7 @@ BlazeComponent.extendComponent({ evt.preventDefault(); evt.stopPropagation(); + const menuType = evt.currentTarget.getAttribute('data-type'); // Only allow drop on "remaining" menu to unassign boards from spaces if (menuType === 'remaining') { @@ -844,9 +838,11 @@ BlazeComponent.extendComponent({ evt.preventDefault(); evt.stopPropagation(); + const menuType = evt.currentTarget.getAttribute('data-type'); evt.currentTarget.classList.remove('drag-over'); + // Only handle drops on "remaining" menu if (menuType !== 'remaining') return; @@ -908,6 +904,7 @@ BlazeComponent.extendComponent({ }; const allBoards = ReactiveCache.getBoards(query, {}); + if (type === 'starred') { return allBoards.filter( (b) => currentUser && currentUser.hasStarred(b._id), diff --git a/client/components/boards/originalPositionsView.css b/client/components/boards/originalPositionsView.css index ec3abd4c5..920b3068f 100644 --- a/client/components/boards/originalPositionsView.css +++ b/client/components/boards/originalPositionsView.css @@ -23,7 +23,7 @@ .original-positions-content { background-color: white; border: 1px solid #dee2e6; - border-radius: 4px; + border-radius: 0.4ch; padding: 15px; } @@ -65,7 +65,7 @@ .original-position-item { background-color: #f8f9fa; border: 1px solid #e9ecef; - border-radius: 4px; + border-radius: 0.4ch; margin-bottom: 10px; padding: 12px; transition: all 0.2s ease; @@ -100,7 +100,7 @@ color: white; padding: 2px 6px; border-radius: 3px; - font-size: 11px; + font-weight: 500; text-transform: uppercase; } @@ -112,7 +112,7 @@ .entity-id { color: #6c757d; - font-size: 11px; + font-family: monospace; } @@ -123,12 +123,12 @@ .original-position-description { color: #495057; margin-bottom: 6px; - font-size: 13px; + } .original-title { color: #6c757d; - font-size: 12px; + margin-bottom: 6px; padding: 4px 6px; background-color: #e9ecef; @@ -141,7 +141,7 @@ .original-position-date { color: #6c757d; - font-size: 11px; + } .no-original-positions { @@ -152,7 +152,7 @@ } .no-original-positions i { - font-size: 24px; + margin-bottom: 10px; display: block; color: #adb5bd; @@ -164,32 +164,32 @@ margin: 5px 0; padding: 10px; } - + .original-positions-header { flex-direction: column; align-items: stretch; gap: 8px; } - + .original-positions-header .btn { justify-content: center; } - + .original-positions-filters .btn-group { justify-content: center; } - + .original-position-item-header { flex-wrap: wrap; gap: 6px; } - + .entity-name { flex: 1; min-width: 0; word-break: break-word; } - + .original-position-item-details { margin-left: 0; margin-top: 8px; @@ -203,60 +203,60 @@ border-color: #4a5568; color: #e2e8f0; } - + .original-positions-content { background-color: #1a202c; border-color: #4a5568; } - + .original-position-item { background-color: #2d3748; border-color: #4a5568; color: #e2e8f0; } - + .original-position-item:hover { background-color: #4a5568; border-color: #718096; } - + .original-position-item-header { color: #e2e8f0; } - + .original-position-item-header i { color: #a0aec0; } - + .entity-name { color: #e2e8f0; } - + .entity-id { color: #a0aec0; } - + .original-position-description { color: #e2e8f0; } - + .original-title { background-color: #4a5568; color: #a0aec0; } - + .original-title strong { color: #e2e8f0; } - + .original-position-date { color: #a0aec0; } - + .no-original-positions { color: #a0aec0; } - + .no-original-positions i { color: #718096; } diff --git a/client/components/cards/attachments.css b/client/components/cards/attachments.css index 97039dfe3..31f6747a9 100644 --- a/client/components/cards/attachments.css +++ b/client/components/cards/attachments.css @@ -6,75 +6,80 @@ font-weight: bold; } .attachment-gallery { - display: flex; - flex-direction: column; + display: grid; + grid-auto-flow: row; } .attachment-item { - display: flex; - flex-direction: row; + display: grid; + grid-template-columns: 10ch auto; align-items: center; - margin-top: 16px; + grid-template-rows: repeat(auto-fit, minmax(1.5lh, auto)); + justify-content: stretch; + gap: 2ch; + padding: 2ch; + border-radius: 0.6ch; } + .attachment-item:hover { background: #e0e0e0; } -.attachment-thumbnail-container { - display: block; - width: 150px; - min-width: 150px; - max-height: 150px; - padding-right: 16px; + +.attachment-details-container { + display: flex; + flex: 1; } + +.attachment-thumbnail-container { + display: flex; + flex: 1; + position: relative; +} + .attachment-thumbnail { - max-width: 150px; - max-height: 150px; - min-height: 2em; + /* more deterministic outcome */ + aspect-ratio: 1/1; + object-fit: cover; + max-width: 100%; cursor: pointer; + border-radius: 0.4ch; } .attachment-thumbnail-text { - min-height: 2em; - display: flex; - align-items: center; - justify-content: center; - font-size: 2em; - cursor: pointer; + flex: 1; + text-align: center; + border-radius: 2px; border: 1px solid #ccc; - border-radius: 5px; -} -.attachment-details-container { - display: block; - flex-grow: 1; } .attachment-details { display: flex; - justify-content: space-between; - margin-right: 25px; /* Make sure the icons are not to far to the right */ + flex: 1; + gap: 0.5ch; + align-items: center; } .attachment-actions { display: flex; flex-direction: row; align-items: center; + gap: 1.5ch; } -.attachment-actions a { - margin-left: 16px; -} -.attachment-actions a:first-child { - margin-left: 0; + +body.mobile-mode .attachment-actions { + flex-direction: column; + gap: 0; } + .add-attachment { + border: 1px dashed #555; + border-radius: .5ch; + cursor: pointer; + aspect-ratio: 1/1; + height: 1.5lh; display: flex; align-items: center; justify-content: center; - border: 1px dashed #555; - border-radius: 5px; - padding: 10px; - cursor: pointer; - margin-top: 16px; } .icon { font-size: 1.5em; cursor: pointer; - margin-left: 10px; } .icon:hover { color: #666; @@ -95,26 +100,25 @@ height: 100%; } #viewer-top-bar { - display: flex; - flex-direction: row; - justify-content: space-between; - width: 100%; - padding: 16px; + display: grid; + grid-template-columns: 1fr auto; + justify-content: center; + justify-items: center; + font-size: 2rem; + padding: 0.3lh 0.5ch; } #attachment-name { color: white; - font-size: 1.5em; - max-width: calc( - 100% - 50px - ); /* Make sure the name does not overlap the close button */ + text-overflow: ellipsis; + overflow: hidden; } #viewer-close { color: white; cursor: pointer; - font-size: 4em; position: absolute; right: 50px; top: 16px; + font-size: 2em; } /* Upload progress indicators for drag-and-drop uploads */ @@ -122,30 +126,24 @@ .card-details-upload-progress { background: #f8f9fa; border: 1px solid #e9ecef; - border-radius: 4px; - padding: 12px; - margin: 8px 0; - font-size: 14px; + border-radius: 0.4ch; + } .upload-progress-header { display: flex; align-items: center; - margin-bottom: 8px; font-weight: bold; color: #495057; } .upload-progress-header i { - margin-right: 8px; color: #007bff; } .upload-progress-item { display: flex; flex-direction: column; - margin-bottom: 8px; - padding: 8px; background: white; border-radius: 3px; border: 1px solid #dee2e6; @@ -158,22 +156,17 @@ .upload-progress-filename { font-weight: 500; - margin-bottom: 4px; color: #495057; word-break: break-all; } .upload-progress-bar { - width: 100%; - height: 6px; background: #e9ecef; border-radius: 3px; overflow: hidden; - margin-bottom: 4px; } .upload-progress-fill { - height: 100%; background: linear-gradient(90deg, #007bff, #0056b3); transition: width 0.3s ease; border-radius: 3px; @@ -187,7 +180,6 @@ .upload-progress-success { display: flex; align-items: center; - font-size: 12px; font-weight: 500; } @@ -199,47 +191,6 @@ color: #28a745; } -.upload-progress-error i, -.upload-progress-success i { - margin-right: 4px; -} - -/* Minicard specific styles */ -.minicard-upload-progress { - margin: 4px 0; - padding: 8px; - font-size: 12px; -} - -.minicard-upload-progress .upload-progress-item { - padding: 6px; - margin-bottom: 6px; -} - -.minicard-upload-progress .upload-progress-filename { - font-size: 11px; -} - -/* Card details specific styles */ -.card-details-upload-progress { - margin: 12px 0; - padding: 16px; -} - -.card-details-upload-progress .upload-progress-header { - font-size: 16px; - margin-bottom: 12px; -} - -.card-details-upload-progress .upload-progress-item { - padding: 12px; - margin-bottom: 10px; -} - -.card-details-upload-progress .upload-progress-filename { - font-size: 14px; -} - /* Drag over state for minicards */ .minicard.is-dragging-over { border: 2px dashed #007bff !important; @@ -256,7 +207,6 @@ color: white; cursor: pointer; align-self: center; - margin: 0 20px; } #prev-attachment { font-size: 4em; @@ -322,7 +272,6 @@ position: absolute; bottom: 2.2em; font-size: 1.6em; - padding: 16px; } #prev-attachment { left: 0; @@ -356,19 +305,10 @@ margin-top: 20%; width: 100%; } - .attachment-thumbnail-container { - width: 100px; - min-width: 100px; - } - .attachment-thumbnail { - max-width: 100px; - } .attachment-details { flex-direction: column; - margin-right: 0px; } .attachment-actions { flex-direction: row; - margin-top: 10px; } } diff --git a/client/components/cards/attachments.jade b/client/components/cards/attachments.jade index 054c547d9..d63e9e485 100644 --- a/client/components/cards/attachments.jade +++ b/client/components/cards/attachments.jade @@ -49,15 +49,11 @@ template(name="attachmentViewer") i.fa.fa-caret-right#next-attachment template(name="attachmentGallery") - + if canModifyCard + a.add-attachment.js-add-attachment + i.fa.fa-plus .attachment-gallery - - if canModifyCard - a.attachment-item.add-attachment.js-add-attachment - i.fa.fa-plus - each attachments - .attachment-item(class="{{#if isAttachmentMigrating _id}}migrating{{/if}}") .attachment-thumbnail-container.open-preview(data-attachment-id="{{_id}}" data-card-id="{{ meta.cardId }}") if link diff --git a/client/components/cards/cardDate.css b/client/components/cards/cardDate.css index 4a873e485..09a33aaad 100644 --- a/client/components/cards/cardDate.css +++ b/client/components/cards/cardDate.css @@ -1,6 +1,5 @@ .card-date { display: block; - border-radius: 4px; padding: 1px 3px; background-color: #dbdbdb; } @@ -106,6 +105,10 @@ background-color: #e6c200; } +.date a:has(time) { + text-decoration: none; +} + .card-date.end-date { background-color: #ffb3b3; /* Light red for end */ color: #000; /* Black text for end */ @@ -139,6 +142,6 @@ } .customfield-date { display: block; - border-radius: 4px; + border-radius: 0.4ch; padding: 1px 3px; } diff --git a/client/components/cards/cardDate.js b/client/components/cards/cardDate.js index 5863e8f48..386c78467 100644 --- a/client/components/cards/cardDate.js +++ b/client/components/cards/cardDate.js @@ -1,24 +1,24 @@ import { TAPi18n } from '/imports/i18n'; import { DatePicker } from '/client/lib/datepicker'; -import { - formatDateTime, - formatDate, +import { + formatDateTime, + formatDate, formatDateByUserPreference, - formatTime, - getISOWeek, - isValidDate, - isBefore, - isAfter, - isSame, - add, - subtract, - startOf, - endOf, - format, - parseDate, - now, - createDate, - fromNow, + formatTime, + getISOWeek, + isValidDate, + isBefore, + isAfter, + isSame, + add, + subtract, + startOf, + endOf, + format, + parseDate, + now, + createDate, + fromNow, calendar, diff } from '/imports/lib/dateUtils'; @@ -143,7 +143,7 @@ class CardReceivedDate extends CardDate { const startAt = this.data().getStart(); const theDate = this.date.get(); const now = this.now.get(); - + // Received date logic: if received date is after start, due, or end dates, it's overdue if ( (startAt && isAfter(theDate, startAt)) || @@ -187,7 +187,7 @@ class CardStartDate extends CardDate { const endAt = this.data().getEnd(); const theDate = this.date.get(); const now = this.now.get(); - + // Start date logic: if start date is after due or end dates, it's overdue if ((endAt && isAfter(theDate, endAt)) || (dueAt && isAfter(theDate, dueAt))) { classes += 'overdue'; @@ -230,7 +230,7 @@ class CardDueDate extends CardDate { const endAt = this.data().getEnd(); const theDate = this.date.get(); const now = this.now.get(); - + // If there's an end date and it's before the due date, task is completed early if (endAt && isBefore(endAt, theDate)) { classes += 'completed-early'; @@ -242,7 +242,7 @@ class CardDueDate extends CardDate { // Due date logic based on current time else { const daysDiff = diff(theDate, now, 'days'); - + if (daysDiff < 0) { // Due date is in the past - overdue classes += 'overdue'; @@ -254,7 +254,7 @@ class CardDueDate extends CardDate { classes += 'not-due'; } } - + return classes; } @@ -286,7 +286,7 @@ class CardEndDate extends CardDate { let classes = 'end-date '; const dueAt = this.data().getDue(); const theDate = this.date.get(); - + if (!dueAt) { // No due date set - just show as completed classes += 'completed'; @@ -371,7 +371,7 @@ CardCustomFieldDate.register('cardCustomFieldDate'); template() { return 'minicardReceivedDate'; } - + showDate() { const currentUser = ReactiveCache.getCurrentUser(); const dateFormat = currentUser ? currentUser.getDateFormat() : 'YYYY-MM-DD'; @@ -383,7 +383,7 @@ CardCustomFieldDate.register('cardCustomFieldDate'); template() { return 'minicardStartDate'; } - + showDate() { const currentUser = ReactiveCache.getCurrentUser(); const dateFormat = currentUser ? currentUser.getDateFormat() : 'YYYY-MM-DD'; @@ -395,7 +395,7 @@ CardCustomFieldDate.register('cardCustomFieldDate'); template() { return 'minicardDueDate'; } - + showDate() { const currentUser = ReactiveCache.getCurrentUser(); const dateFormat = currentUser ? currentUser.getDateFormat() : 'YYYY-MM-DD'; @@ -407,7 +407,7 @@ CardCustomFieldDate.register('cardCustomFieldDate'); template() { return 'minicardEndDate'; } - + showDate() { const currentUser = ReactiveCache.getCurrentUser(); const dateFormat = currentUser ? currentUser.getDateFormat() : 'YYYY-MM-DD'; @@ -419,7 +419,7 @@ CardCustomFieldDate.register('cardCustomFieldDate'); template() { return 'minicardCustomFieldDate'; } - + showDate() { const currentUser = ReactiveCache.getCurrentUser(); const dateFormat = currentUser ? currentUser.getDateFormat() : 'YYYY-MM-DD'; diff --git a/client/components/cards/cardDescription.css b/client/components/cards/cardDescription.css index b65e6b65a..55d75fe76 100644 --- a/client/components/cards/cardDescription.css +++ b/client/components/cards/cardDescription.css @@ -1,16 +1,12 @@ .new-description { - position: relative; - margin: 0 0 20px 0; + flex: 1; } -.new-description.is-open .helper { - display: inline-block; -} -.new-description.is-open textarea { - min-height: 100px; +.new-description textarea { + min-height: 1lh; color: #4d4d4d; cursor: auto; overflow: hidden; - word-wrap: break-word; + overflow-wrap: break-word; } .new-description .too-long { margin-top: 8px; @@ -19,9 +15,6 @@ background-color: #fff; border: 0; box-shadow: 0 1px 2px rgba(0,0,0,0.23); - height: 36px; - margin: 4px 4px 6px 0; - padding: 9px 11px; width: 100%; } .new-description textarea:hover, @@ -39,16 +32,12 @@ border: 0; box-shadow: 0 1px 2px rgba(0,0,0,0.23); color: #8c8c8c; - height: 36px; - margin: 4px 4px 6px 0; - width: 92%; } .description-item:hover { background: #e0e0e0; } .description-item.add-description { display: flex; - margin: 5px; } .description-item.add-description a { display: block; diff --git a/client/components/cards/cardDetails.css b/client/components/cards/cardDetails.css index 42821d284..96abf7ff0 100644 --- a/client/components/cards/cardDetails.css +++ b/client/components/cards/cardDetails.css @@ -1,25 +1,18 @@ -/* Date Format Selector */ -.card-details-item-date-format { - margin-bottom: 12px; -} - .card-details-item-date-format .card-details-item-title { - font-size: 15px; font-weight: bold; - margin-bottom: 6px; color: #333; letter-spacing: 0.03em; } .card-details-item-date-format .js-date-format-selector { - width: 100%; - padding: 9px 10px; border: 1px solid #ddd; border-radius: 5px; background-color: #fff; - font-size: 15px; - cursor: pointer; transition: border-color 0.15s, box-shadow 0.15s; + cursor: pointer; + width: 100%; + display: flex; + flex: 1; } .card-details-item-date-format .js-date-format-selector:focus { @@ -28,44 +21,80 @@ box-shadow: 0 0 0 2px rgba(0, 124, 186, 0.2); } -.assignee { - display: block; - position: relative; - float: left; - height: clamp(24px, 3.5vw, 36px); - width: clamp(24px, 3.5vw, 36px); - margin: 0.3vh; - cursor: pointer; - user-select: none; - z-index: 1; - text-decoration: none; - border-radius: 50%; - box-shadow: 0 1px 2px 0 rgba(0,0,0,0.04); +.card-details h3 { + font-size: 1.1em; } -.assignee .avatar { - overflow: hidden; - border-radius: 50%; -} -.assignee .avatar.avatar-assignee-initials { - height: 70%; - width: 70%; - padding: 15%; - background-color: #dbdbdb; - color: #444; - position: absolute; - text-align: center; + +.card-checklists { display: flex; + flex-direction: column; +} + +.card-body { + display: flex; + flex-direction: column; + flex: 1; + padding: 2ch; + align-items: stretch; + gap: 0.5lh; + /* for popups */ + overflow-y: auto; + + &.is-maximized { + display: grid; + /* divide available space; 3/4 for main content, 1/4 for activity feed */ + /* better use a grid, otherwise flexbox will not expand left pane if fullscreen + > max-content, but some users may want to expend elements anyways */ + grid-template-columns: 3fr 1fr; + .card-details-left { + border-right: solid 2px #dbdbdb; + padding-right: 2ch; + } + } +} + +.card-header-content { + display: grid; + margin: 0 1ch; + grid-auto-columns: auto 1fr auto; + grid-auto-flow: column; + justify-content: stretch; align-items: center; + min-height: 2lh; + gap: 1ch; +} + +body.mobile-mode { + .card-header-content { + padding-inline: 0.5ch; + } + .card-header-middle { + padding-inline: 0; + background: unset; + font-size: 1.1em; + } +} + +.card-header-middle { + display: flex; + min-height: 1.5lh; + font-size: 1.3em; justify-content: center; - font-weight: bold; + align-items: center; + background: #dfdfdf; + border-radius: 1ch; + padding-inline: 1ch; + justify-self: stretch; + cursor: grab !important; } -.assignee .avatar.avatar-image { - object-fit: cover; - object-position: center; - height: 100%; - width: 100%; - display: block; +.assignee.add-assignee:hover, +.assignee.add-assignee.is-active { + box-shadow: 0 0 0 2px #666 inset; } +.assignee { + box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.04); +} + .assignee .assignee-presence-status { background-color: #b3b3b3; border: 1px solid #fff; @@ -77,6 +106,7 @@ bottom: -1px; z-index: 15; } + .assignee .assignee-presence-status.active { background: #64c464; border-color: #daf1da; @@ -96,164 +126,153 @@ .assignee.add-assignee { display: flex; align-items: center; - justify-content: center; - box-shadow: 0 0 0 2px #bfbfbf inset; transition: box-shadow 0.12s; } -.assignee.add-assignee:hover, -.assignee.add-assignee.is-active { - box-shadow: 0 0 0 2px #666 inset; + +.card-header-controls-grid { + display: grid; + grid-template-columns: repeat(auto-fill, 2ch); + gap: 0.5ch; + grid-auto-flow: column; + flex-direction: column; + align-items: center; + justify-items: center; } .copied-tooltip { - display: none; - padding: 0 1.3vw; + position: absolute; background-color: rgba(0,0,0,0.875); color: #fff; border-radius: 0.7vw; font-size: 0.98em; } +.copied-tooltip-visible { + visibility: visible; + opacity: 1; + transition: opacity 0.1s linear; +} + +.copied-tooltip-hidden { + visibility: hidden; + opacity: 0; + transition: visibility 0s 0.1s, opacity 0.1s linear; +} .card-details { padding: 0; - flex-shrink: 0; - flex-basis: min(600px, 80vw); - will-change: flex-basis; + display: flex; + flex: 1; overflow-y: auto; overflow-x: hidden; background: #f7f7f7; border-radius: 0 0 0.4vw 0.4vw; - z-index: 30; + z-index: 100; animation: flexGrowIn 0.1s; box-shadow: 0 0 0.9vh 0 #b3b3b3; transition: flex-basis 0.1s, box-shadow 0.15s; box-sizing: border-box; + &:not(.collapsed) { + min-height: 20lh; + /* at this point, popup can still be resized but stops + to shrink content, so the later stays visible */ + min-width: 30vw; + } } -/* Desktop mode: position card below board header */ -body.desktop-mode .card-details:not(.card-details-popup) { - position: fixed; - width: auto; - max-width: 800px; - flex-basis: auto; - border-radius: 8px; - z-index: 100; +.edit-vote-question { + display: flex; + flex-direction: column; + & > .fields { + display: flex; + flex-direction: column; + gap: 0.2lh; + margin: 0.2lh 0; + } } - -/* Default position for first card or when dragged */ -body.desktop-mode .card-details:not(.card-details-popup):not([style*="left"]):not([style*="top"]) { - top: 50px; - left: 20px; - right: 20px; - bottom: 20px; +.card-details .card-details-canvas { + display: grid; + background: #ededed; + border-bottom: 1px solid #dbdbdb; + flex: 1; + grid-template-rows: auto auto; + grid-auto-flow: row; + grid-template-columns: auto; + align-items: stretch; + align-content: center; } - -/* Stagger positions for multiple cards using nth-of-type */ -body.desktop-mode .card-details:not(.card-details-popup):nth-of-type(1) { - top: 50px; - left: 20px; -} -body.desktop-mode .card-details:not(.card-details-popup):nth-of-type(2) { - top: 80px; - left: 50px; -} -body.desktop-mode .card-details:not(.card-details-popup):nth-of-type(3) { - top: 110px; - left: 80px; -} -body.desktop-mode .card-details:not(.card-details-popup):nth-of-type(4) { - top: 140px; - left: 110px; -} -body.desktop-mode .card-details:not(.card-details-popup):nth-of-type(5) { - top: 170px; - left: 140px; -} - -/* For expanded cards, set dimensions */ -body.desktop-mode .card-details:not(.card-details-popup):not(.card-details-collapsed) { - right: 20px; - bottom: 20px; -} - /* Collapsed card state - hide content and set height to title row only */ -.card-details.card-details-collapsed .card-details-canvas > *:not(.card-details-header) { +.card-details.card-details.collapsed .card-details-canvas > *:not(.card-details-header) { display: none !important; } -.card-details.card-details-collapsed { - height: auto !important; - bottom: auto !important; - overflow: visible; -} -body.desktop-mode .card-details.card-details-collapsed { - bottom: auto !important; -} .card-details .mCustomScrollBox { padding-left: 0; } -.card-details .card-details-canvas { - width: auto; - padding: 0 2.5vw; -} -.card-details .card-details-header { - margin: 0 -20px 5px; - padding: 8px 20px; - background: #ededed; - border-bottom: 1px solid #dbdbdb; - position: sticky; - top: 0px; - z-index: 500; - display: flow-root; - min-height: 44px; -} .card-details .card-details-header .card-number { color: #b3b3b3; display: inline-block; - margin-right: 6px; } /* Collapse toggle triangle */ .card-details .card-details-header .card-collapse-toggle { - float: left; - font-size: 20px; - padding: 7px 10px; - margin-left: -10px; - margin-right: 5px; cursor: pointer; user-select: none; color: #000; - vertical-align: middle; - line-height: 1.2; +} + +/* Bring to front / Send to back buttons */ +/* #FIXME see .jade */ +/* .card-details .card-details-header .card-bring-to-front, +.card-details .card-details-header .card-send-to-back { + float: right; + font-size: 18px; + padding: 7px 8px; + margin-right: 5px; + cursor: pointer; + user-select: none; + color: #333; +} */ + +.card-details .card-details-header .card-bring-to-front:hover, +.card-details .card-details-header .card-send-to-back:hover { + color: #000; + background: rgba(0,0,0,0.05); + border-radius: 3px; } .card-details .card-details-header .card-drag-handle { - font-size: 20px; - padding: 8px 10px; - margin-right: 10px; cursor: move; user-select: none; - display: inline-block; - float: right; - vertical-align: middle; - line-height: 1.2; } -.card-details .card-details-header .close-card-details, -.card-details .card-details-header .maximize-card-details, -.card-details .card-details-header .minimize-card-details, -.card-details .card-details-header .card-details-menu, -.card-details .card-details-header .card-copy-button, -.card-details .card-details-header .card-copy-mobile-button, -.card-details .card-details-header .close-card-details-mobile-web, -.card-details .card-details-header .card-details-menu-mobile-web, -.card-details .card-details-header .copied-tooltip { - float: right; -} +.card-details .js-card-details-title { + /* override inlined forms defauts: take all width available + and just what's needed to edit card title */ + width: 100%; + display: flex; + .js-edit-card-title { + height: fit-content; + margin: 0; + } + .edit-controls { + flex: 1; + align-items: center; + button { + margin: 0; + display: flex; + max-width: 20ch; + justify-content: center; + align-items: center; + } + } + .js-submit-edit-card-title-form { + margin: 0.3lh 0; + flex: 1; + display: flex; + } +} + .card-details .card-details-header .close-card-details, .card-details .card-details-header .maximize-card-details, .card-details .card-details-header .minimize-card-details { - font-size: 24px; - padding: 5px 10px 5px 10px; - margin-right: -8px; cursor: pointer; user-select: none; vertical-align: middle; @@ -262,78 +281,155 @@ body.desktop-mode .card-details.card-details-collapsed { } .card-details .card-details-header .close-card-details-mobile-web, .card-details .card-details-header .card-mobile-desktop-toggle { - font-size: 24px; - padding: 5px; - margin-right: 5px; cursor: pointer; user-select: none; } -.card-details .card-details-header .card-copy-button { - font-size: 17px; - padding: 10px; - margin-right: 10px; -} -.card-details .card-details-header .card-copy-mobile-button { - font-size: 17px; - padding: 10px; - margin-right: 10px; -} -.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; - padding: 10px; - margin-right: 30px; -} -.card-details .card-details-header .card-mobile-desktop-toggle, -.card-details .card-details-header .card-zoom-in, -.card-details .card-details-header .card-zoom-out { - font-size: 24px; - padding: 5px 10px 5px 10px; - margin-right: 5px; +.card-details .card-details-header .card-mobile-desktop-toggle { cursor: pointer; user-select: none; float: right; } +body:not(.mobile-mode) { + + .card-details-date-container, + .card-details-user-container, + .card-details-misc-container, + card-details-description { + grid-template-columns: repeat(3, 1fr) !important; + gap: 1ch; + } +} + /* Unify all card text to match title size */ .card-details { font-size: 1em; } -.card-details p, -.card-details span, -.card-details div, -.card-details a, -.card-details label, -.card-details input, -.card-details textarea, -.card-details select, -.card-details button, -.card-details .card-details-item-title, -.card-details .card-label, -.card-details .viewer { - font-size: inherit; - line-height: 1.5; + +.card-details .card-details-header .card-details-watch { + color: #a6a6a6; +} + +.card-details .card-details-header { + & .card-details-title { + display: inline-block; + font-weight: bold; + font-size: 1.33em; + margin: 0; + --overflow-lines: 3; + & p { + margin: 0; + } + } +} + + +.card-add-label, .card-details .js-date-format-selector { + padding: 0.2lh 0.5ch; +} +.card-details-main { + display: flex; + gap: 0.3lh; + flex-direction: column; + hr { + margin: 0; + } + &>div { + display: flex; + gap: 0.2lh; + flex: 1; + } + &>div:empty { + /* to avoid gaps */ + display: none; + } + .card-details-misc-container { + display: flex; + flex-direction: column; + gap: 0.3lh; + } + .card-details-date-container, .card-details-user-container { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 1ch; + align-items: end; + h3 { + + *:not(:has(.member), :is(:hover)) { + background-color: #f7f7f7; + } + + *:not(:is(form)) { + display: flex; + align-items: center; + overflow: hidden; + font-size: 0.8em; + + &:not(.member, :has(.member)) { + border-radius: 5px; + justify-content: start; + height: 1.8lh; + padding: 0.3lh 1ch; + } + + &:has(select) { + padding-inline: 0 !important; + >select { + align-self: stretch; + } + } + + time { + color: black; + } + +form { + height: 3lh; + overflow: visible; + margin: 0.5lh 0; + + > { + width: 100%; + } + } + } + } + } + .card-details-items { + gap: 0.5lh; + } + .card-details-comments { + flex-direction: column; + gap: 0.5lh; + } +} + +.card-details-description { + display: flex; + flex-direction: column; + flex: 1; +} +.card-details-comments { + flex-direction: column; + gap: 0.5lh; } .card-details .card-details-header .card-details-watch { - font-size: 17px; - padding-left: 7px; color: #a6a6a6; } .card-details .card-details-header .card-details-title { font-weight: bold; font-size: 1.35em; - margin: 7px 0 0; padding: 0; display: inline-block; vertical-align: middle; line-height: 1.3; letter-spacing: 0.01em; } + +body.mobile-mode { + .card-details .card-details-header .card-details-title { + --overflow-lines: 2; + font-size: 0.8em; + } +} + .card-details .card-details-header .linked-card-location { font-style: italic; font-size: 1em; @@ -342,283 +438,70 @@ body.desktop-mode .card-details.card-details-collapsed { .card-details .card-details-header .linked-card-location p { margin-bottom: 0; } -.card-details .card-details-header form.inlined-form { - margin-top: 5px; - margin-bottom: 10px; -} -.card-details .card-details-header form.inlined-form .copied-tooltip { - padding: 0 10px; -} -.card-details .card-details-header .card-details-list { - font-size: 0.9em; - margin-bottom: 3px; -} -.card-details .card-details-header .card-details-list a.card-details-list-title { - font-weight: bold; -} -.card-details .card-details-header .card-details-list a.card-details-list-title.is-editable { - display: inline-block; - background: #e6e6e6; - border-radius: 3px; - padding: 0 5px; -} -.card-details .card-details-header .copied-tooltip { - margin-right: 10px; - padding: 10px; -} .card-details .card-description i.fa.fa-pencil-square-o { float: right; } .card-details .card-description textarea { - min-height: 100px; resize: vertical; + min-height: 2lh; } -.card-details .card-details-items { +.card-details { + .card-details-items, .card-details-item { + display: flex; + flex-direction: column; + gap: 0.3lh; + } + .card-details-item { + justify-content: end; + align-self: stretch; + } + .card-details-avatar-container { + display: flex; + justify-content: start; + gap: 0.5ch; + } +} +.card-details-item-labels-container { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(12ch, auto)); + grid-auto-rows: 1.5lh; + align-items: stretch; + justify-content: start; + gap: 1ch; +} + +.card-details .subtask-container { display: flex; - flex-wrap: wrap; - margin: 15px 0; - gap: 0.5em; -} -.card-details .card-details-items .card-details-item { - margin-right: 0.5em; - flex-grow: 1; -} -.card-details .card-details-items .card-details-item:last-child { - margin-right: 0; -} -.card-details .card-details-items .card-details-item.card-details-item-labels { - display: block; - word-wrap: break-word; - max-width: 95%; -} -.card-details .card-details-items .card-details-item.card-details-item-members, -.card-details .card-details-items .card-details-item.card-details-item-assignees, -.card-details .card-details-items .card-details-item.card-details-item-customfield, -.card-details .card-details-items .card-details-item.card-details-item-name { - display: block; - word-wrap: break-word; - max-width: 36%; -} -.card-details .card-details-items .card-details-item.card-details-item-creator, -.card-details .card-details-items .card-details-item.card-details-item-received, -.card-details .card-details-items .card-details-item.card-details-item-start, -.card-details .card-details-items .card-details-item.card-details-item-due, -.card-details .card-details-items .card-details-item.card-details-item-end { - display: block; - word-wrap: break-word; - max-width: 28%; -} -.card-details .card-details-items .card-details-item.custom-fields { - padding-left: 10px; + flex: 1; + flex-wrap: nowrap; + align-items: center; + gap: 1ch; + h2 { + margin: 0; + } + .subtask { + min-height: 1.5lh; + } } .card-details .card-details-item-title { - font-size: 16px; font-weight: bold; color: #4d4d4d; + display: flex; + align-items: center; + gap: 0.8ch; +} + +.card-details .edit-card-details-description { + display: flex; + align-items: center; + gap: .5ch; } .card-details .activities { padding-top: 10px; } -@media screen and (min-width: 801px) { - .card-details { - top: 97px; - left: calc(50% - (600px / 2)); - width: 600px; - bottom: 0; - position: fixed; - resize: both; - } - - /* Override for mobile mode even on larger screens */ - body.mobile-mode .card-details { - width: 100vw !important; - top: 0 !important; - left: 0 !important; - right: 0 !important; - bottom: 0 !important; - height: 100vh !important; - max-height: 100vh !important; - resize: none !important; - } - - .card-details-maximized { - padding: 0; - flex-shrink: 0; - flex-basis: calc(100% - 20px); - will-change: flex-basis; - overflow-y: auto; - overflow-x: auto; - background: #f7f7f7; - border-radius: 0 0 3px 3px; - z-index: 100; - animation: flexGrowIn 0.1s; - box-shadow: 0 0 7px 0 #b3b3b3; - transition: flex-basis 0.1s; - box-sizing: border-box; - top: 97px; - left: 0px; - height: calc(100% - 100px); - width: calc(100% - 20px); - float: left; - } - .card-details-maximized .card-details-left { - float: left; - top: 60px; - left: 20px; - width: 47%; - border-right: solid 2px #dbdbdb; - padding-right: 10px; - } - .card-details-maximized .card-details-right { - position: absolute; - float: right; - left: 50%; - margin: 15px 0; - } - .card-details-maximized .card-details-header { - width: 100%; - } -} -input[type="text"].attachment-add-link-input { - float: left; - margin: 0 0 8px; - width: 80%; -} -input[type="submit"].attachment-add-link-submit { - float: left; - margin: 0 0 8px 4px; - padding: 6px 12px; - width: 18%; -} -@media screen and (max-width: 800px) { - .card-details { - width: 100% !important; - padding: 0 !important; - margin: 0 !important; - transition: none; - overflow-y: auto; - overflow-x: hidden; - -webkit-overflow-scrolling: touch; - position: fixed !important; - top: 0 !important; - left: 0 !important; - right: 0 !important; - bottom: 0 !important; - z-index: 100 !important; - height: 100vh !important; - max-height: 100vh !important; - border-radius: 0 !important; - box-shadow: none !important; - } - - /* Ensure card details are above everything on mobile */ - body.mobile-mode .card-details { - z-index: 100 !important; - width: 100vw !important; - left: 0 !important; - right: 0 !important; - } - .card-details .card-details-canvas { - width: 100%; - padding-left: 0px; - padding: 0 15px; - } - .card-details .card-details-header .close-card-details { - margin-right: 0px; - display: block !important; - } - .card-details .card-details-header .close-card-details-mobile-web { - display: block !important; - margin-right: 5px !important; - } - .card-details .card-details-header .card-mobile-desktop-toggle { - display: block !important; - margin-right: 5px !important; - } - .card-details .card-details-header .card-mobile-desktop-toggle { - display: block !important; - margin-right: 5px !important; - } - .card-details .card-details-header .card-details-menu { - margin-right: 40px; - } - .card-details .card-details-header .maximize-card-details { - margin-right: 40px; - } - .card-details .card-details-header .minimize-card-details { - margin-right: 40px; - } - .card-details-popup { - padding: 0px 10px; - } - .pop-over > .content-wrapper > .popup-container-depth-0 { - width: 100%; - } - .pop-over > .content-wrapper > .popup-container-depth-0 > .content { - width: calc(100% - 10px); - } - .pop-over > .content-wrapper > .popup-container-depth-0 > .content > .card-details-popup hr { - margin: 15px 0px; - } - .pop-over > .content-wrapper > .popup-container-depth-0 .card-details-header { - margin: 0; - } - /* iPhone mobile: enlarge header buttons and increase spacing */ - body.mobile-mode.iphone-device .card-details .card-details-header { - padding-right: 16px; - } - body.mobile-mode.iphone-device .card-details .card-details-header .close-card-details, - body.mobile-mode.iphone-device .card-details .card-details-header .maximize-card-details, - body.mobile-mode.iphone-device .card-details .card-details-header .minimize-card-details, - body.mobile-mode.iphone-device .card-details .card-details-header .card-details-menu-mobile-web, - body.mobile-mode.iphone-device .card-details .card-details-header .card-copy-mobile-button, - body.mobile-mode.iphone-device .card-details .card-details-header .card-mobile-desktop-toggle, - body.mobile-mode.iphone-device .card-details .card-details-header .card-zoom-in, - body.mobile-mode.iphone-device .card-details .card-details-header .card-zoom-out { - font-size: 2em !important; /* 2x bigger */ - padding: 0.3em !important; - margin-right: 0.75em !important; /* 2x space compared to default */ - margin-left: 0 !important; - } - /* Avoid clipping of the close button on the right edge */ - body.mobile-mode.iphone-device .card-details .card-details-header .close-card-details { - margin-right: 0.75em !important; - } - /* Enlarge the header title too */ - body.mobile-mode.iphone-device .card-details .card-details-header .card-details-title { - font-size: 1.2em !important; - font-weight: bold; - } -} - -/* Mobile mode styles - apply when body has mobile-mode class regardless of screen size */ -body.mobile-mode .card-details { - width: 100vw !important; - padding: 0px !important; - margin: 0px !important; - position: fixed !important; - top: 0 !important; - left: 0 !important; - right: 0 !important; - bottom: 0 !important; - z-index: 100 !important; - height: 100vh !important; - max-height: 100vh !important; - border-radius: 0 !important; - box-shadow: none !important; - overflow-y: auto !important; - overflow-x: hidden !important; - -webkit-overflow-scrolling: touch; -} body.mobile-mode .card-details .card-details-canvas { - width: 100% !important; - padding: 0 15px !important; -} - -body.mobile-mode .card-details .card-details-header .close-card-details, -body.mobile-mode .card-details .card-details-header .close-card-details-mobile-web { - display: block !important; + padding: 0 !important; } .card-details-white { background: #fff !important; @@ -727,16 +610,21 @@ body.mobile-mode .card-details .card-details-header .close-card-details-mobile-w .vote-title { display: flex; justify-content: space-between; + & + .viewer { + font-size: 1.1em; + font-weight: bold; + } align-items: center; } .vote-title .js-edit-date { align-self: flex-start; - margin-left: 6px; } .vote-result { display: flex; - gap: 6px; -} + gap: 0.5ch; + .card-label { + min-width: 5ch; + } .js-show-positive-votes { cursor: pointer; } @@ -750,7 +638,6 @@ body.mobile-mode .card-details .card-details-header .close-card-details-mobile-w } .poker-title .js-edit-date { align-self: flex-start; - margin-left: 6px; } .poker-result { display: flex; @@ -837,24 +724,9 @@ body.mobile-mode .card-details .card-details-header .close-card-details-mobile-w .estimation-add { display: block; overflow: auto; - margin-top: 15px; - margin-bottom: 5px; -} -.estimation-add input { - display: inline-block; - float: right; - margin: auto; - margin-right: 10px; - width: 100px; - border-radius: 2px; - padding: 3px 6px; } .estimation-add button { display: inline-block; - float: right; - margin: auto; - border-radius: 2px; - padding: 3px 10px; } .poker-card { width: 48px; @@ -866,7 +738,6 @@ body.mobile-mode .card-details .card-details-header .close-card-details-mobile-w box-sizing: border-box; padding: 5px; margin: 3px; - font-size: 20px; font-weight: bold; text-shadow: #2d2d2d 1px 1px 0; box-shadow: 0 0 5px #aaa; @@ -890,3 +761,13 @@ body.mobile-mode .card-details .card-details-header .close-card-details-mobile-w transform: scale(1.01); transition: all 0.2s ease; } + +.cardMorePopup { + display: flex; + flex-direction: column; + gap: 0.1lh; + .card-add-date { + display: flex; + gap: 0.5ch; + } +} \ No newline at end of file diff --git a/client/components/cards/cardDetails.jade b/client/components/cards/cardDetails.jade index 7adaca873..94f82868d 100644 --- a/client/components/cards/cardDetails.jade +++ b/client/components/cards/cardDetails.jade @@ -1,87 +1,73 @@ + template(name="cardDetailsPopup") - +cardDetails(popupCard) + //- just a proxy so the caller code is almost the same + //- when using popups or inlined element; + with popupArgs + +popup(this) template(name="cardDetails") - +attachmentViewer - - section.card-details.js-card-details.nodragscroll(class='{{#if cardMaximized}}card-details-maximized{{/if}}' class='{{#if isPopup}}card-details-popup{{/if}}' class='{{#unless isVerticalScrollbars}}no-scrollbars{{/unless}}' class='{{#if cardCollapsed}}card-details-collapsed{{/if}}'): .card-details-canvas + section.card-details.js-card-details.nodragscroll(class='{{#if isPopup}}card-details-popup{{/if}}' class='{{#unless isVerticalScrollbars}}no-scrollbars{{/unless}}' class='{{#if cardCollapsed}}collapsed{{/if}}'): .card-details-canvas .card-details-header(class='{{#if colorClass}}card-details-{{colorClass}}{{/if}}') +inlinedForm(classNames="js-card-details-title") +editCardTitleForm else - unless isMiniScreen - unless isPopup + .card-header-content + .card-header-left + //- resizing with the CSS property can achieve the same + //- on desktop; keep this button for mobile where we don't + //- have CSS resize. 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.fa.fa-window-minimize.minimize-card-details.js-minimize-card-details(title="{{_ 'minimize-card'}}") - else - 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 - 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.fa.fa-window-minimize.minimize-card-details.js-minimize-card-details(title="{{_ 'minimize-card'}}") - else - 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 - 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}}") - +viewer - if currentBoard.allowsCardNumber - span.card-number - | ##{getCardNumber} - = getTitle if isWatching i.card-details-watch i.fa.fa-eye - .card-details-path - each parentList - |   >   - a.js-parent-card(href=linkForCard) {{title}} - // else - {{_ 'top-level-card'}} - if isLinkedCard - a.linked-card-location.js-go-to-linked-card - +viewer - | {{getBoardTitle}} > {{getTitle}} + .card-header-middle + h2.card-details-title.js-card-title( + class="{{#if canModifyCard}}js-open-inlined-form is-editable{{/if}}") + +viewer + if currentBoard.allowsCardNumber + span.card-number + | ##{getCardNumber} -  + = getTitle + + .card-details-path + each parentList + |   >   + a.js-parent-card(href=linkForCard) {{title}} + // else + {{_ 'top-level-card'}} + + .card-header-controls-grid + if canModifyCard + unless isMiniScreen + if cardMaximized + a.fa.fa-window-minimize.minimize-card-details.js-minimize-card-details(title="{{_ 'minimize-card'}}") + else + a.fa.fa-window-maximize.maximize-card-details.js-maximize-card-details(title="{{_ 'maximize-card'}}") + span.copied-tooltip.copied-tooltip-hidden {{_ 'copied'}} + a.card-copy-button.js-copy-link.emoji-icon( + id="cardURL_copy" + title="{{_ 'copy-card-link-to-clipboard'}}" + href="{{ originRelativeUrl }}" + ) + i.fa.fa-link + a.card-details-menu.js-open-card-details-menu(title="{{_ 'cardDetailsActionsPopup-title'}}") + i.fa.fa-bars + a.close-card-details.js-close-card-details.js-close-pop-over(title="{{_ 'close-card'}}") + i.fa.fa-times-thin + //- #FIXME removed in upstream? should we make it reactive to the popupcomponent stack for example? + //- a.card-send-to-back.js-card-send-to-back(title="Send to back") + //- | ⏬ + //- a.card-bring-to-front.js-card-bring-to-front(title="Bring to front") + //- | ⏫ + if isLinkedCard + a.linked-card-location.js-go-to-linked-card + +viewer + | {{getBoardTitle}} > {{getTitle}} if getArchived if isLinkedBoard @@ -108,550 +94,547 @@ template(name="cardDetails") .upload-progress-success i.fa.fa-check span {{_ 'upload-completed'}} - - .card-details-left - - .card-details-items - 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 - span.card-label(class="card-label-{{color}}" title=name) - +viewer - = name - 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 - option(value="YYYY-MM-DD" selected="{{#if isDateFormat 'YYYY-MM-DD'}}selected{{/if}}") {{_ 'date-format-yyyy-mm-dd'}} - option(value="DD-MM-YYYY" selected="{{#if isDateFormat 'DD-MM-YYYY'}}selected{{/if}}") {{_ 'date-format-dd-mm-yyyy'}} - option(value="MM-DD-YYYY" selected="{{#if isDateFormat 'MM-DD-YYYY'}}selected{{/if}}") {{_ 'date-format-mm-dd-yyyy'}} - - 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 - else - 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 - else - 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 - else - 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 - else - if canModifyCard - unless currentUser.isWorker - a.card-label.add-label.js-end-date - i.fa.fa-plus - - if currentBoard.hasAnyAllowsUser - hr - - 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) - | {{! XXX Hack to hide syntaxic coloration /// }} - - //.card-details-items - 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) - | {{! XXX Hack to hide syntaxic coloration /// }} - 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 - +inlinedForm(classNames="js-card-details-requester") - +editCardRequesterForm - else - a.js-open-inlined-form - if getRequestedBy + .card-body(class="{{#if cardMaximized}}is-maximized{{/if}}") + .card-details-left + .card-details-main + .card-details-items + if currentBoard.allowsLabels + .card-details-item-labels + h3.card-details-item-title + i.fa.fa-tags + | {{_ 'labels'}} + if canModifyCard + unless currentUser.isWorker + a.card-add-label.js-add-labels(title="{{_ 'card-labels-title'}}") + i.fa.fa-plus + a.card-details-item-labels-container(class="{{#if canModifyCard}}js-add-labels{{else}}is-disabled{{/if}}" title="{{_ 'card-labels-title'}}") + each labels + span.card-label(class="card-label-{{color}}" title=name) +viewer - = getRequestedBy - else - | {{_ 'add'}} - else if getRequestedBy - +viewer - = getRequestedBy + = name + hr + .card-details-date-container + 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 + else + if canModifyCard + unless currentUser.isWorker + a.card-add-label.js-received-date + i.fa.fa-plus - 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 - +inlinedForm(classNames="js-card-details-assigner") - +editCardAssignerForm - else - a.js-open-inlined-form - if getAssignedBy + 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 + else + if canModifyCard + unless currentUser.isWorker + a.card-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 + else + if canModifyCard + unless currentUser.isWorker + a.card-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 + else + if canModifyCard + unless currentUser.isWorker + a.card-add-label.js-end-date + i.fa.fa-plus + if currentBoard.hasAnyAllowsDate + .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 + option(value="YYYY-MM-DD" selected="{{#if isDateFormat 'YYYY-MM-DD'}}selected{{/if}}") {{_ 'date-format-yyyy-mm-dd'}} + option(value="DD-MM-YYYY" selected="{{#if isDateFormat 'DD-MM-YYYY'}}selected{{/if}}") {{_ 'date-format-dd-mm-yyyy'}} + option(value="MM-DD-YYYY" selected="{{#if isDateFormat 'MM-DD-YYYY'}}selected{{/if}}") {{_ 'date-format-mm-dd-yyyy'}} + if currentBoard.hasAnyAllowsUser + hr + .card-details-user-container + 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) + | {{! XXX Hack to hide syntaxic coloration /// }} + + //.card-details-items + if currentBoard.allowsMembers + .card-details-item.card-details-item-members + h3.card-details-item-title + i.fa.fa-users + | {{_ 'members'}} + .card-details-avatar-container + each userId in getMembers + +userAvatar(userId=userId cardId=_id) + | {{! XXX Hack to hide syntaxic coloration /// }} + 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'}} + .card-details-avatar-container + each userId in getAssignees + +userAvatar(userId=userId cardId=_id assignee=true) + | {{! XXX Hack to hide syntaxic coloration /// }} + if canModifyCard + a.member.add-assignee.card-details-item-add-button.js-add-assignees(title="{{_ 'assignee'}}") + i.fa.fa-plus + if currentUser.isWorker + unless assigneeSelected + a.member.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 + +inlinedForm(classNames="js-card-details-requester") + +editCardRequesterForm + else + a.js-open-inlined-form + if getRequestedBy + +viewer + = getRequestedBy + else + | {{_ 'add'}} + else if getRequestedBy + +viewer + = getRequestedBy + + 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 + +inlinedForm(classNames="js-card-details-assigner") + +editCardAssignerForm + else + a.js-open-inlined-form + if getAssignedBy + +viewer + = getAssignedBy + else + | {{_ 'add'}} + else if getRequestedBy +viewer = getAssignedBy - else - | {{_ 'add'}} - else if getRequestedBy - +viewer - = getAssignedBy - if $or currentBoard.allowsCardSortingByNumber getSpentTime - hr - - 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") - +editCardSortOrderForm - else - a.js-open-inlined-form - +viewer - = sort - - 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 - option(value="{{_id}}" selected="{{#if isCurrentListId _id}}selected{{/if}}") {{title}} - - //.card-details-items - if getSpentTime - .card-details-item.card-details-item-spent - if getIsOvertime - h3.card-details-item-title - | {{_ 'overtime-hours'}} - else - h3.card-details-item-title - | {{_ 'spent-time-hours'}} - +cardSpentTime - - //.card-details-items - if customFieldsWD - unless customFieldsGrid + if $or currentBoard.allowsCardSortingByNumber getSpentTime hr - each customFieldsWD - if customFieldsGrid - hr - .card-details-item.card-details-item-customfield + + 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") + +editCardSortOrderForm + else + a.js-open-inlined-form + +viewer + = sort + + if currentBoard.allowsShowLists + .card-details-item.card-details-show-lists h3.card-details-item-title i.fa.fa-list - = definition.name - +cardCustomField + | {{_ 'list'}} + select.js-select-card-details-lists(disabled="{{#unless canModifyCard}}disabled{{/unless}}") + each currentBoard.lists + option(value="{{_id}}" selected="{{#if isCurrentListId _id}}selected{{/if}}") {{title}} - if $gt customFieldsWD.length 1 - .material-toggle-switch(title="{{_ 'change'}} {{_ 'custom-fields'}} {{_ 'layout'}}") - if customFieldsGrid - input.toggle-switch(type="checkbox" id="toggleCustomFieldsGridButton" checked="checked") + //.card-details-items + if getSpentTime + .card-details-item.card-details-item-spent + if getIsOvertime + h3.card-details-item-title + | {{_ 'overtime-hours'}} else - input.toggle-switch(type="checkbox" id="toggleCustomFieldsGridButton") - label.toggle-label(for="toggleCustomFieldsGridButton") - a.js-custom-fields.card-details-item.custom-fields(title="{{_ 'custom-fields'}}") + h3.card-details-item-title + | {{_ 'spent-time-hours'}} + +cardSpentTime - if getVoteQuestion - hr - .vote-title - div.flex - h3 - i.fa.fa-thumbs-up - | {{_ 'vote-question'}} - if getVoteEnd - +voteEndDate - .vote-result - if votePublic - a.card-label.card-label-green.js-show-positive-votes {{ voteCountPositive }} - a.card-label.card-label-red.js-show-negative-votes {{ voteCountNegative }} - else - .card-label.card-label-green {{ voteCountPositive }} - .card-label.card-label-red {{ voteCountNegative }} - unless ($and currentBoard.isPublic voteAllowNonBoardMembers ) - .card-label.card-label-gray {{ voteCount }} {{_ 'r-of' }} {{ currentBoard.activeMembers.length }} - +viewer - = getVoteQuestion - 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 - | 👎 - | {{_ 'vote-against'}} + //.card-details-items + if customFieldsWD + unless customFieldsGrid + hr + each customFieldsWD + if customFieldsGrid + hr + .card-details-item.card-details-item-customfield + h3.card-details-item-title + i.fa.fa-list + = definition.name + +cardCustomField - if getPokerQuestion - hr - .poker-title - div.flex - h3 - i.fa.fa-thumbs-up - | {{_ 'poker-question'}} - if getPokerEnd - +pokerEndDate - div.flex + if $gt customFieldsWD.length 1 + .material-toggle-switch(title="{{_ 'change'}} {{_ 'custom-fields'}} {{_ 'layout'}}") + if customFieldsGrid + input.toggle-switch(type="checkbox" id="toggleCustomFieldsGridButton" checked="checked") + else + input.toggle-switch(type="checkbox" id="toggleCustomFieldsGridButton") + label.toggle-label(for="toggleCustomFieldsGridButton") + a.js-custom-fields.card-details-item.custom-fields(title="{{_ 'custom-fields'}}") + + if getVoteQuestion + hr + .vote-title + div.flex + h3 + i.fa.fa-thumbs-up + | {{_ 'vote-question'}} + if getVoteEnd + +voteEndDate + .vote-result + if votePublic + a.card-label.card-label-green.js-show-positive-votes {{ voteCountPositive }} + a.card-label.card-label-red.js-show-negative-votes {{ voteCountNegative }} + else + .card-label.card-label-green {{ voteCountPositive }} + .card-label.card-label-red {{ voteCountNegative }} + unless ($and currentBoard.isPublic voteAllowNonBoardMembers ) + .card-label.card-label-gray {{ voteCount }} {{_ 'r-of' }} {{ currentBoard.activeMembers.length }} + +viewer + = getVoteQuestion + 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 + i.fa.fa-thumbs-down + | {{_ 'vote-against'}} + + if getPokerQuestion + hr + .poker-title + div.flex + h3 + i.fa.fa-thumbs-up + | {{_ 'poker-question'}} + if getPokerEnd + +pokerEndDate + div.flex + .poker-result + if expiredPoker + unless ($and currentBoard.isPublic pokerAllowNonBoardMembers ) + .card-label.card-label-gray {{ pokerCount }} {{_ 'r-of' }} {{ currentBoard.activeMembers.length }} + if showPlanningPokerButtons .poker-result + .poker-deck + .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'}} + if expiredPoker - unless ($and currentBoard.isPublic pokerAllowNonBoardMembers ) - .card-label.card-label-gray {{ pokerCount }} {{_ 'r-of' }} {{ currentBoard.activeMembers.length }} - if showPlanningPokerButtons - .poker-result - .poker-deck - .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 + .poker-table + .poker-table-side-left + .poker-table-heading-left + .poker-table-row + .poker-table-cell + .poker-table-cell + | {{_ 'poker-result-votes' }} + .poker-table-cell.poker-table-cell-who + | {{_ 'poker-result-who' }} + .poker-table-body + .poker-table-row + .poker-table-cell + button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 1}}winner{{else}}loser{{/if}}") {{_ 'poker-one'}} + .poker-table-cell {{ pokerCountOne }} + .poker-table-cell.poker-table-cell-who + .poker-result + each m in pokerMemberOne + a.name + +userAvatar(userId=m._id noRemove=true) - if currentUser.isBoardAdmin - button.card-details-blue.js-poker-finish(class="{{#if $eq voteState false}}poker-voted{{/if}}") {{_ 'poker-finish'}} + .poker-table-row + .poker-table-cell + button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 2}}winner{{else}}loser{{/if}}") {{_ 'poker-two'}} + .poker-table-cell {{ pokerCountTwo }} + .poker-table-cell.poker-table-cell-who + .poker-result + each m in pokerMemberTwo + a.name + +userAvatar(userId=m._id noRemove=true) - if expiredPoker - .poker-table - .poker-table-side-left - .poker-table-heading-left - .poker-table-row - .poker-table-cell - .poker-table-cell - | {{_ 'poker-result-votes' }} - .poker-table-cell.poker-table-cell-who - | {{_ 'poker-result-who' }} - .poker-table-body - .poker-table-row - .poker-table-cell - button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 1}}winner{{else}}loser{{/if}}") {{_ 'poker-one'}} - .poker-table-cell {{ pokerCountOne }} - .poker-table-cell.poker-table-cell-who - .poker-result - each m in pokerMemberOne - a.name - +userAvatar(userId=m._id noRemove=true) + .poker-table-row + .poker-table-cell + button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 3}}winner{{else}}loser{{/if}}") {{_ 'poker-three'}} + .poker-table-cell {{ pokerCountThree }} + .poker-table-cell.poker-table-cell-who + .poker-result + each m in pokerMemberThree + a.name + +userAvatar(userId=m._id noRemove=true) - .poker-table-row - .poker-table-cell - button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 2}}winner{{else}}loser{{/if}}") {{_ 'poker-two'}} - .poker-table-cell {{ pokerCountTwo }} - .poker-table-cell.poker-table-cell-who - .poker-result - each m in pokerMemberTwo - a.name - +userAvatar(userId=m._id noRemove=true) + .poker-table-row + .poker-table-cell + button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 5}}winner{{else}}loser{{/if}}") {{_ 'poker-five'}} + .poker-table-cell {{ pokerCountFive }} + .poker-table-cell.poker-table-cell-who + .poker-result + each m in pokerMemberFive + a.name + +userAvatar(userId=m._id noRemove=true) - .poker-table-row - .poker-table-cell - button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 3}}winner{{else}}loser{{/if}}") {{_ 'poker-three'}} - .poker-table-cell {{ pokerCountThree }} - .poker-table-cell.poker-table-cell-who - .poker-result - each m in pokerMemberThree - a.name - +userAvatar(userId=m._id noRemove=true) + .poker-table-row + .poker-table-cell + button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 8}}winner{{else}}loser{{/if}}") {{_ 'poker-eight'}} + .poker-table-cell {{ pokerCountEight }} + .poker-table-cell.poker-table-cell-who + .poker-result + each m in pokerMemberEight + a.name + +userAvatar(userId=m._id noRemove=true) - .poker-table-row - .poker-table-cell - button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 5}}winner{{else}}loser{{/if}}") {{_ 'poker-five'}} - .poker-table-cell {{ pokerCountFive }} - .poker-table-cell.poker-table-cell-who - .poker-result - each m in pokerMemberFive - a.name - +userAvatar(userId=m._id noRemove=true) + .poker-table-side-right + .poker-table-heading-right + .poker-table-row + .poker-table-cell + .poker-table-cell + | {{_ 'poker-result-votes' }} + .poker-table-cell.poker-table-cell-who + | {{_ 'poker-result-who' }} + .poker-table-body + .poker-table-row + .poker-table-cell + button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 13}}winner{{else}}loser{{/if}}") {{_ 'poker-thirteen'}} + .poker-table-cell {{ pokerCountThirteen }} + .poker-table-cell.poker-table-cell-who + .poker-result + each m in pokerMemberThirteen + a.name + +userAvatar(userId=m._id noRemove=true) - .poker-table-row - .poker-table-cell - button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 8}}winner{{else}}loser{{/if}}") {{_ 'poker-eight'}} - .poker-table-cell {{ pokerCountEight }} - .poker-table-cell.poker-table-cell-who - .poker-result - each m in pokerMemberEight - a.name - +userAvatar(userId=m._id noRemove=true) + .poker-table-row + .poker-table-cell + button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 20}}winner{{else}}loser{{/if}}") {{_ 'poker-twenty'}} + .poker-table-cell {{ pokerCountTwenty }} + .poker-table-cell.poker-table-cell-who + .poker-result + each m in pokerMemberTwenty + a.name + +userAvatar(userId=m._id noRemove=true) - .poker-table-side-right - .poker-table-heading-right - .poker-table-row - .poker-table-cell - .poker-table-cell - | {{_ 'poker-result-votes' }} - .poker-table-cell.poker-table-cell-who - | {{_ 'poker-result-who' }} - .poker-table-body - .poker-table-row - .poker-table-cell - button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 13}}winner{{else}}loser{{/if}}") {{_ 'poker-thirteen'}} - .poker-table-cell {{ pokerCountThirteen }} - .poker-table-cell.poker-table-cell-who - .poker-result - each m in pokerMemberThirteen - a.name - +userAvatar(userId=m._id noRemove=true) + .poker-table-row + .poker-table-cell + button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 40}}winner{{else}}loser{{/if}}") {{_ 'poker-forty'}} + .poker-table-cell {{ pokerCountForty }} + .poker-table-cell.poker-table-cell-who + .poker-result + each m in pokerMemberForty + a.name + +userAvatar(userId=m._id noRemove=true) - .poker-table-row - .poker-table-cell - button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 20}}winner{{else}}loser{{/if}}") {{_ 'poker-twenty'}} - .poker-table-cell {{ pokerCountTwenty }} - .poker-table-cell.poker-table-cell-who - .poker-result - each m in pokerMemberTwenty - a.name - +userAvatar(userId=m._id noRemove=true) + .poker-table-row + .poker-table-cell + button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 100}}winner{{else}}loser{{/if}}") {{_ 'poker-oneHundred'}} + .poker-table-cell {{ pokerCountOneHundred }} + .poker-table-cell.poker-table-cell-who + .poker-result + each m in pokerMemberOneHundred + a.name + +userAvatar(userId=m._id noRemove=true) - .poker-table-row - .poker-table-cell - button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 40}}winner{{else}}loser{{/if}}") {{_ 'poker-forty'}} - .poker-table-cell {{ pokerCountForty }} - .poker-table-cell.poker-table-cell-who - .poker-result - each m in pokerMemberForty - a.name - +userAvatar(userId=m._id noRemove=true) + .poker-table-row + .poker-table-cell + button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 'unsure'}}winner{{else}}loser{{/if}}") {{_ 'poker-unsure'}} + .poker-table-cell {{ pokerCountUnsure }} + .poker-table-cell.poker-table-cell-who + .poker-result + each m in pokerMemberUnsure + a.name + +userAvatar(userId=m._id noRemove=true) - .poker-table-row - .poker-table-cell - button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 100}}winner{{else}}loser{{/if}}") {{_ 'poker-oneHundred'}} - .poker-table-cell {{ pokerCountOneHundred }} - .poker-table-cell.poker-table-cell-who - .poker-result - each m in pokerMemberOneHundred - a.name - +userAvatar(userId=m._id noRemove=true) + if currentUser.isBoardAdmin + div.estimation-add + 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") - .poker-table-row - .poker-table-cell - button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 'unsure'}}winner{{else}}loser{{/if}}") {{_ 'poker-unsure'}} - .poker-table-cell {{ pokerCountUnsure }} - .poker-table-cell.poker-table-cell-who - .poker-result - each m in pokerMemberUnsure - a.name - +userAvatar(userId=m._id noRemove=true) - - if currentUser.isBoardAdmin - div.estimation-add - 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") - - //- XXX We should use "editable" to avoid repetiting ourselves - if canModifyCard - unless currentUser.isWorker + //- XXX We should use "editable" to avoid repetiting ourselves + if canModifyCard + unless currentUser.isWorker + 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") + +descriptionForm + .edit-controls.clearfix + button.primary(type="submit") {{_ 'save'}} + a.js-close-inlined-form + else + if currentBoard.allowsDescriptionText + .edit-card-details-description + 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 + = getDescription + if (hasUnsavedValue 'cardDescription' _id) + p.quiet + | {{_ 'unsaved-description'}} + a.js-open-inlined-form {{_ 'view-it'}} + = ' - ' + a.js-close-inlined-form {{_ 'discard'}} + else if getDescription if currentBoard.allowsDescriptionTitle hr - h3.card-details-item-title - i.fa.fa-file-text-o - | {{_ 'description'}} + h3.card-details-item-title {{_ 'description'}} if currentBoard.allowsDescriptionText - +inlinedCardDescription(classNames="card-description js-card-description") - +descriptionForm - .edit-controls.clearfix - button.primary(type="submit") {{_ 'save'}} - a.js-close-inlined-form - 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 - = getDescription - if (hasUnsavedValue 'cardDescription' _id) - p.quiet - | {{_ 'unsaved-description'}} - a.js-open-inlined-form {{_ 'view-it'}} - = ' - ' - a.js-close-inlined-form {{_ 'discard'}} - else if getDescription - if currentBoard.allowsDescriptionTitle - hr - h3.card-details-item-title {{_ 'description'}} - if currentBoard.allowsDescriptionText - +viewer - = getDescription + +viewer + = getDescription - .card-checklist-attachmentGalleries - .card-checklist-attachmentGallery.card-checklists - if currentBoard.allowsChecklists + .card-checklist-attachmentGalleries + .card-checklist-attachmentGallery.card-checklists + if currentBoard.allowsChecklists + hr + +checklists(cardId = _id card = this) + if currentBoard.allowsSubtasks + hr + +subtasks(cardId = _id) + if currentBoard.allowsAttachments hr - +checklists(cardId = _id card = this) - if currentBoard.allowsSubtasks - hr - +subtasks(cardId = _id) - 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}} - br - if Meteor.settings.public.attachmentsUploadMimeTypes - | {{_ 'allowed-upload-filetypes'}} {{Meteor.settings.public.attachmentsUploadMimeTypes}} - br - | {{_ 'invalid-file'}} - .card-checklist-attachmentGallery.card-attachmentGallery - +attachmentGallery - hr + h3.card-details-item-title + i.fa.fa-paperclip + | {{_ 'attachments'}} + if Meteor.settings.public.attachmentsUploadMaxSize + | {{_ 'max-upload-filesize'}} {{Meteor.settings.public.attachmentsUploadMaxSize}} + br + if Meteor.settings.public.attachmentsUploadMimeTypes + | {{_ 'allowed-upload-filetypes'}} {{Meteor.settings.public.attachmentsUploadMimeTypes}} + br + | {{_ 'invalid-file'}} + .card-checklist-attachmentGallery.card-attachmentGallery + +attachmentGallery + hr - unless currentUser.isNoComments - .comment-title - h3.card-details-item-title - i.fa.fa-comment-o - | {{_ 'comments'}} + unless currentUser.isNoComments + .comment-title + h3.card-details-item-title + i.fa.fa-comment-o + | {{_ 'comments'}} - if currentBoard.allowsComments - if currentUser.isBoardMember - unless currentUser.isNoComments - unless currentUser.isReadOnly - unless currentUser.isReadAssignedOnly - +commentForm - +comments - hr + if currentBoard.allowsComments + if currentUser.isBoardMember + unless currentUser.isNoComments + +commentForm + +comments + hr - .card-details-right - - if currentUser.isBoardAdmin - .activity-title - h3.card-details-item-title - i.fa.fa-history - | {{ _ 'activities'}} - if currentUser.isBoardMember - .material-toggle-switch(title="{{_ 'show-activities'}}") - if showActivities - input.toggle-switch(type="checkbox" id="toggleShowActivitiesCard" checked="checked") - else - input.toggle-switch(type="checkbox" id="toggleShowActivitiesCard") - label.toggle-label(for="toggleShowActivitiesCard") + .card-details-right + unless currentUser.isNoComments + .activity-title + h3.card-details-item-title + i.fa.fa-history + | {{ _ 'activities'}} + if currentUser.isBoardMember + .material-toggle-switch(title="{{_ 'show-activities'}}") + if showActivities + input.toggle-switch(type="checkbox" id="toggleShowActivitiesCard" checked="checked") + else + input.toggle-switch(type="checkbox" id="toggleShowActivitiesCard") + label.toggle-label(for="toggleShowActivitiesCard") if currentUser.isBoardAdmin if isLoaded.get @@ -662,32 +645,36 @@ template(name="cardDetails") else +activities(card=this mode="card") + template(name="editCardTitleForm") a(title="{{_ 'copy-text-to-clipboard'}}") - span.copied-tooltip {{_ 'copied'}} - textarea.js-edit-card-title(rows='1' autofocus dir="auto") + span.copied-tooltip.copied-tooltip-hidden {{_ 'copied'}} + textarea.js-edit-card-title(rows='1' dir="auto") = getTitle .edit-controls.clearfix + button.negate.js-back-view(type="submit") {{_ 'cancel'}} button.primary.confirm.js-submit-edit-card-title-form(type="submit") {{_ 'save'}} - a.js-close-inlined-form template(name="editCardRequesterForm") - input.js-edit-card-requester(type='text' autofocus value=getRequestedBy dir="auto") + input.js-edit-card-requester(type='text' value=getRequestedBy dir="auto") .edit-controls.clearfix button.primary.confirm.js-submit-edit-card-requester-form(type="submit") {{_ 'save'}} a.js-close-inlined-form + i.fa.fa-times-thin template(name="editCardAssignerForm") - input.js-edit-card-assigner(type='text' autofocus value=getAssignedBy dir="auto") + input.js-edit-card-assigner(type='text' value=getAssignedBy dir="auto") .edit-controls.clearfix button.primary.confirm.js-submit-edit-card-assigner-form(type="submit") {{_ 'save'}} a.js-close-inlined-form + i.fa.fa-times-thin template(name="editCardSortOrderForm") - input.js-edit-card-sort(type='text' autofocus value=sort dir="auto") + input.js-edit-card-sort(type='text' value=sort dir="auto") .edit-controls.clearfix button.primary.confirm.js-submit-edit-card-sort-form(type="submit") {{_ 'save'}} a.js-close-inlined-form + i.fa.fa-times-thin template(name="cardDetailsActionsPopup") ul.pop-over-list @@ -880,7 +867,7 @@ template(name="moveCardPopup") template(name="copyCardPopup") label(for='copy-card-title') {{_ 'title'}}: - textarea#copy-card-title.minicard-composer-textarea.js-card-title(autofocus) + textarea#copy-card-title.minicard-composer-textarea.js-card-title = getTitle unless currentUser.isWorker label {{_ 'boards'}}: @@ -915,7 +902,7 @@ template(name="copyCardPopup") template(name="copyManyCardsPopup") label(for='copy-checklist-cards-title') {{_ 'copyManyCardsPopup-instructions'}}: - textarea#copy-card-title.minicard-composer-textarea.js-card-title(autofocus) + textarea#copy-card-title.minicard-composer-textarea.js-card-title | {{_ 'copyManyCardsPopup-format'}} unless currentUser.isWorker label {{_ 'boards'}}: @@ -950,11 +937,11 @@ template(name="copyManyCardsPopup") template(name="convertChecklistItemToCardPopup") label(for='convert-checklist-item-to-card-title') {{_ 'title'}}: - textarea#copy-card-title.minicard-composer-textarea.js-card-title(autofocus) + textarea#copy-card-title.minicard-composer-textarea.js-card-title = item.title unless currentUser.isWorker label {{_ 'boards'}}: - select.js-select-boards(autofocus) + select.js-select-boards each boards option(value="{{_id}}" selected="{{#if isDialogOptionBoardId _id}}selected{{/if}}") {{add @index 1}}. {{title}} @@ -1039,14 +1026,14 @@ template(name="cardAssigneePopup") li: a.js-edit-profile {{_ 'edit-profile'}} template(name="cardMorePopup") - p.quiet + p.quiet.cardMorePopup span.clearfix span {{_ 'link-card'}} = ' ' i.fa(class="{{#if currentBoard.isPublic}}fa-globe{{else}}fa-lock{{/if}}") - input.inline-input(type="text" id="cardURL" readonly value="{{ originRelativeUrl }}" autofocus="autofocus") + input.inline-input(type="text" id="cardURL" readonly value="{{ originRelativeUrl }}" ) button.js-copy-card-link-to-clipboard(class="btn" id="clipboard") {{_ 'copy-card-link-to-clipboard'}} - .copied-tooltip {{_ 'copied'}} + span.copied-tooltip.copied-tooltip-hidden {{_ 'copied'}} span.clearfix br h2 {{_ 'change-card-parent'}} @@ -1073,22 +1060,22 @@ template(name="cardMorePopup") option(value="{{_id}}" selected) {{title}} else option(value="{{_id}}") {{title}} - br - | {{_ 'added'}} - span.date(title=card.createdAt) {{ moment createdAt 'LLL' }} - if currentUser.isBoardAdmin - a.js-delete(title="{{_ 'card-delete-notice'}}") {{_ 'delete'}} + .card-add-date + | {{_ 'added'}} + span.date(title=card.createdAt) {{ moment createdAt 'LLL' }} + if currentUser.isBoardAdmin + a.js-delete(title="{{_ 'card-delete-notice'}}") {{_ 'delete'}} 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) - i.fa.fa-check - 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 + .form-buttons + button.primary.confirm.js-submit {{_ 'save'}} + button.js-remove-color.negate.wide.right {{_ 'unset-color'}} template(name="cardDeletePopup") p {{_ "card-delete-pop"}} @@ -1110,7 +1097,7 @@ template(name="cardStartVotingPopup") form.edit-vote-question .fields label(for="vote") {{_ 'vote-question'}} - input.js-vote-field#vote(type="text" name="vote" value="{{getVoteQuestion}}" autofocus disabled="{{#if getVoteQuestion}}disabled{{/if}}") + input.js-vote-field#vote(type="text" name="vote" value="{{getVoteQuestion}}" disabled="{{#if getVoteQuestion}}disabled{{/if}}") .check-div a.flex(class="{{#if getVoteQuestion}}is-disabled{{else}}js-toggle-vote-allow-non-members{{/if}}") .materialCheckBox#vote-allow-non-members(name="vote-allow-non-members" class="{{#if voteAllowNonBoardMembers}}is-checked{{/if}}") @@ -1178,4 +1165,4 @@ template(name="cardStartPlanningPokerPopup") button.primary.js-submit {{_ 'save'}} if getPokerQuestion if currentUser.isBoardAdmin - button.js-remove-poker.negate.wide.right {{_ 'delete'}} + button.js-remove-poker.negate.wide.right {{_ 'delete'}} \ No newline at end of file diff --git a/client/components/cards/cardDetails.js b/client/components/cards/cardDetails.js index 5f69d4bd8..2a7a3b480 100644 --- a/client/components/cards/cardDetails.js +++ b/client/components/cards/cardDetails.js @@ -2,25 +2,25 @@ import { ReactiveCache } from '/imports/reactiveCache'; import { TAPi18n } from '/imports/i18n'; import { FlowRouter } from 'meteor/ostrio:flow-router-extra'; import { DatePicker } from '/client/lib/datepicker'; -import { - formatDateTime, - formatDate, - formatTime, - getISOWeek, - isValidDate, - isBefore, - isAfter, - isSame, - add, - subtract, - startOf, - endOf, - format, - parseDate, - now, - createDate, - fromNow, - calendar +import { + formatDateTime, + formatDate, + formatTime, + getISOWeek, + isValidDate, + isBefore, + isAfter, + isSame, + add, + subtract, + startOf, + endOf, + format, + parseDate, + now, + createDate, + fromNow, + calendar } from '/imports/lib/dateUtils'; import Cards from '/models/cards'; import Boards from '/models/boards'; @@ -35,6 +35,7 @@ import { DialogWithBoardSwimlaneList } from '/client/lib/dialogWithBoardSwimlane import { DialogWithBoardSwimlaneListCard } from '/client/lib/dialogWithBoardSwimlaneListCard'; import { handleFileUpload } from './attachments'; import uploadProgressManager from '../../lib/uploadProgressManager'; +import PopupComponent from '../main/popup'; const subManager = new SubsManager(); const { calculateIndexData } = Utils; @@ -60,19 +61,8 @@ BlazeComponent.extendComponent({ onCreated() { this.currentBoard = Utils.getCurrentBoard(); this.isLoaded = new ReactiveVar(false); + this.dep = new Tracker.Dependency(); - if (this.parentComponent() && this.parentComponent().parentComponent()) { - const boardBody = this.parentComponent().parentComponent(); - //in Miniview parent is Board, not BoardBody. - if (boardBody !== null) { - // Only show overlay in mobile mode, not in desktop mode - const isMobile = Utils.getMobileMode(); - if (isMobile) { - boardBody.showOverlay.set(true); - } - boardBody.mouseHasEnterCardDetails = false; - } - } this.calculateNextPeak(); Meteor.subscribe('unsaved-edits'); @@ -85,6 +75,18 @@ BlazeComponent.extendComponent({ // }); }, + onRendered() { + const boardOverlay = document.getElementsByClassName('board-overlay')?.[0]; + this.boardBody = BlazeComponent.getComponentForElement(boardOverlay); + if (this.boardBody) { + this.boardBody.mouseHasEnterCardDetails = false; + } + const isMobile = Utils.getMobileMode(); + if (isMobile && Session.get('currentCard')) { + //this.boardBody?.showOverlay.set(true); + } + }, + isWatching() { const card = this.currentData(); if (!card || typeof card.findWatcher !== 'function') return false; @@ -95,8 +97,8 @@ BlazeComponent.extendComponent({ return ReactiveCache.getCurrentUser().hasCustomFieldsGrid(); }, - cardMaximized() { + this.dep.depend(); return !Utils.getPopupCardId() && ReactiveCache.getCurrentUser().hasCardMaximized(); }, @@ -175,6 +177,11 @@ BlazeComponent.extendComponent({ }, onRendered() { + // #FIXME hackish; if accepted tweak static funcs + if (this.cardMaximized()) { + PopupComponent.maximize({target: this.firstNode()}); + } + if (Meteor.settings.public.CARD_OPENED_WEBHOOK_ENABLED) { // Send Webhook but not create Activities records --- const card = this.currentData(); @@ -209,11 +216,11 @@ BlazeComponent.extendComponent({ } const $checklistsDom = this.$('.card-checklist-items'); - + const sortableSelector = Utils.isMiniScreen() ? '.checklist-handle' : '.checklist-title'; $checklistsDom.sortable({ tolerance: 'pointer', helper: 'clone', - handle: '.checklist-title', + handle: sortableSelector, items: '.js-checklist', placeholder: 'checklist placeholder', distance: 7, @@ -282,6 +289,8 @@ BlazeComponent.extendComponent({ return ReactiveCache.getCurrentUser()?.isBoardMember(); } + + // Disable sorting if the current user is not a board member this.autorun(() => { const disabled = !userIsMember(); @@ -289,10 +298,7 @@ BlazeComponent.extendComponent({ $checklistsDom.data('uiSortable') || $checklistsDom.data('sortable') ) { - $checklistsDom.sortable('option', 'disabled', disabled); - if (Utils.isTouchScreenOrShowDesktopDragHandles()) { - $checklistsDom.sortable({ handle: '.checklist-handle' }); - } + $checklistsDom.sortable('option', 'handle', sortableSelector); } if ($subtasksDom.data('uiSortable') || $subtasksDom.data('sortable')) { $subtasksDom.sortable('option', 'disabled', disabled); @@ -301,11 +307,7 @@ BlazeComponent.extendComponent({ }, onDestroyed() { - if (this.parentComponent() === null) return; - const parentComponent = this.parentComponent().parentComponent(); - //on mobile view parent is Board, not board body. - if (parentComponent === null) return; - parentComponent.showOverlay.set(false); + this.boardBody?.showOverlay.set(false); }, events() { @@ -332,59 +334,11 @@ BlazeComponent.extendComponent({ }, 'mousedown .js-card-drag-handle'(event) { event.preventDefault(); - const $card = $(event.target).closest('.card-details'); - const startX = event.clientX; - const startY = event.clientY; - const startLeft = $card.offset().left; - const startTop = $card.offset().top; - - const onMouseMove = (e) => { - const deltaX = e.clientX - startX; - const deltaY = e.clientY - startY; - $card.css({ - left: startLeft + deltaX + 'px', - top: startTop + deltaY + 'px' - }); - }; - - const onMouseUp = () => { - $(document).off('mousemove', onMouseMove); - $(document).off('mouseup', onMouseUp); - }; - - $(document).on('mousemove', onMouseMove); - $(document).on('mouseup', onMouseUp); + PopupComponent.toFront(event); }, - 'mousedown .js-card-title-drag-handle'(event) { - // Allow dragging from title for ReadOnly users - // Don't interfere with text selection - if (event.target.tagName === 'A' || $(event.target).closest('a').length > 0) { - return; // Don't drag if clicking on links - } - + 'click .js-card-send-to-back'(event) { event.preventDefault(); - const $card = $(event.target).closest('.card-details'); - const startX = event.clientX; - const startY = event.clientY; - const startLeft = $card.offset().left; - const startTop = $card.offset().top; - - const onMouseMove = (e) => { - const deltaX = e.clientX - startX; - const deltaY = e.clientY - startY; - $card.css({ - left: startLeft + deltaX + 'px', - top: startTop + deltaY + 'px' - }); - }; - - const onMouseUp = () => { - $(document).off('mousemove', onMouseMove); - $(document).off('mouseup', onMouseUp); - }; - - $(document).on('mousemove', onMouseMove); - $(document).on('mouseup', onMouseUp); + PopupComponent.toBack(event); }, 'click .js-close-card-details'() { // Get board ID from either the card data or current board in session @@ -392,26 +346,21 @@ BlazeComponent.extendComponent({ const boardId = (card && card.boardId) || Utils.getCurrentBoard()._id; const cardId = card && card._id; - if (boardId) { - // In desktop mode, remove from openCards array - const isMobile = Utils.getMobileMode(); - if (!isMobile && cardId) { - const openCards = Session.get('openCards') || []; - const filtered = openCards.filter(id => id !== cardId); - Session.set('openCards', filtered); - - // If this was the current card, clear it - if (Session.get('currentCard') === cardId) { - Session.set('currentCard', null); - } - // Don't navigate away in desktop mode - just close the card - return; + if (boardId && cardId) { + const openCards = Session.get('openCards') || []; + const filtered = openCards.filter(id => id !== cardId); + // If this was the current card, clear it + if (openCards.length === filtered.length) { + Session.set('currentCard', null); } + else { + Session.set('currentCard', filtered[0]); + } + Session.set('openCards', filtered); - // Mobile mode: Clear the current card session to close the card - Session.set('currentCard', null); - - // Navigate back to board without card + // Navigate back to board without card: must be done at the time of writing + // otherwise the route for the card is disabled until another + // card is opened const board = ReactiveCache.getBoard(boardId); if (board) { FlowRouter.go('board', { @@ -434,34 +383,6 @@ BlazeComponent.extendComponent({ Meteor.call('changeDateFormat', dateFormat); }, 'click .js-open-card-details-menu': Popup.open('cardDetailsActions'), - // Mobile: switch to desktop popup view (maximize) - 'click .js-mobile-switch-to-desktop'(event) { - event.preventDefault(); - // Switch global mode to desktop so the card appears as desktop popup - Utils.setMobileMode(false); - }, - 'click .js-card-zoom-in'(event) { - event.preventDefault(); - const current = Utils.getCardZoom(); - const newZoom = Math.min(3.0, current + 0.1); - Utils.setCardZoom(newZoom); - }, - 'click .js-card-zoom-out'(event) { - event.preventDefault(); - const current = Utils.getCardZoom(); - const newZoom = Math.max(0.5, current - 0.1); - Utils.setCardZoom(newZoom); - }, - 'click .js-card-mobile-desktop-toggle'(event) { - event.preventDefault(); - const currentMode = Utils.getMobileMode(); - Utils.setMobileMode(!currentMode); - }, - 'click .js-card-mobile-desktop-toggle'(event) { - event.preventDefault(); - const currentMode = Utils.getMobileMode(); - Utils.setMobileMode(!currentMode); - }, async 'submit .js-card-description'(event) { event.preventDefault(); const description = this.currentComponent().getValue(); @@ -525,7 +446,7 @@ BlazeComponent.extendComponent({ 'click .js-add-members': Popup.open('cardMembers'), 'click .js-assignee': Popup.open('cardAssignee'), 'click .js-add-assignees': Popup.open('cardAssignees'), - 'click .js-add-labels': Popup.open('cardLabels'), + 'click .js-add-labels'(event) {Popup.open('cardLabels')(event, { dataContextIfCurrentDataIsUndefined: this.currentData() })}, 'click .js-received-date': Popup.open('editCardReceivedDate'), 'click .js-start-date': Popup.open('editCardStartDate'), 'click .js-due-date': Popup.open('editCardDueDate'), @@ -534,12 +455,10 @@ BlazeComponent.extendComponent({ 'click .js-show-negative-votes': Popup.open('negativeVoteMembers'), 'click .js-custom-fields': Popup.open('cardCustomFields'), 'mouseenter .js-card-details'() { - if (this.parentComponent() === null) return; - const parentComponent = this.parentComponent().parentComponent(); - //on mobile view parent is Board, not BoardBody. - if (parentComponent === null) return; - parentComponent.showOverlay.set(true); - parentComponent.mouseHasEnterCardDetails = true; + if (this.boardBody) { + this.boardBody.showOverlay.set(true); + this.boardBody.mouseHasEnterCardDetails = true; + } }, 'mousedown .js-card-details'() { Session.set('cardDetailsIsDragging', false); @@ -560,13 +479,13 @@ BlazeComponent.extendComponent({ 'click #toggleCustomFieldsGridButton'() { Meteor.call('toggleCustomFieldsGrid'); }, - 'click .js-maximize-card-details'() { + 'click .js-maximize-card-details'(e) { + PopupComponent.maximize(e); Meteor.call('toggleCardMaximized'); - autosize($('.card-details')); }, - 'click .js-minimize-card-details'() { + 'click .js-minimize-card-details'(e) { + PopupComponent.minimize(e); Meteor.call('toggleCardMaximized'); - autosize($('.card-details')); }, 'click .js-vote'(e) { const forIt = $(e.target).hasClass('js-vote-positive'); @@ -737,16 +656,6 @@ Template.cardDetails.helpers({ return uploadProgressManager.getUploadCountForCard(this._id); } }); -Template.cardDetailsPopup.onDestroyed(() => { - Session.delete('popupCardId'); - Session.delete('popupCardBoardId'); -}); -Template.cardDetailsPopup.helpers({ - popupCard() { - const ret = Utils.getPopupCard(); - return ret; - }, -}); BlazeComponent.extendComponent({ template() { @@ -883,9 +792,7 @@ Template.cardDetailsActionsPopup.events({ 'click .js-toggle-watch-card'() { const currentCard = this; const level = currentCard.findWatcher(Meteor.userId()) ? null : 'watching'; - Meteor.call('watch', 'card', currentCard._id, level, (err, ret) => { - if (!err && ret) Popup.close(); - }); + Meteor.call('watch', 'card', currentCard._id, level) }, 'click .js-toggle-show-list-on-minicard'() { const currentCard = this; @@ -896,9 +803,6 @@ Template.cardDetailsActionsPopup.events({ }); BlazeComponent.extendComponent({ - onRendered() { - autosize(this.$('textarea.js-edit-card-title')); - }, events() { return [ { @@ -979,10 +883,6 @@ const filterMembers = (filterTerm) => { return members; } -Template.editCardRequesterForm.onRendered(function () { - autosize(this.$('.js-edit-card-requester')); -}); - Template.editCardRequesterForm.events({ 'keydown .js-edit-card-requester'(event) { // If enter key was pressed, submit the data @@ -992,10 +892,6 @@ Template.editCardRequesterForm.events({ }, }); -Template.editCardAssignerForm.onRendered(function () { - autosize(this.$('.js-edit-card-assigner')); -}); - Template.editCardAssignerForm.events({ 'keydown .js-edit-card-assigner'(event) { // If enter key was pressed, submit the data @@ -1469,13 +1365,13 @@ BlazeComponent.extendComponent({ 'DD/MM/YYYY HH:mm', 'DD-MM-YYYY HH:mm' ]; - + let parsedDate = null; for (const format of formats) { parsedDate = parseDate(dateString, [format], true); if (parsedDate) break; } - + // Fallback to native Date parsing if (!parsedDate) { parsedDate = new Date(dateString); @@ -1721,13 +1617,13 @@ BlazeComponent.extendComponent({ 'DD/MM/YYYY HH:mm', 'DD-MM-YYYY HH:mm' ]; - + let parsedDate = null; for (const format of formats) { parsedDate = parseDate(dateString, [format], true); if (parsedDate) break; } - + // Fallback to native Date parsing if (!parsedDate) { parsedDate = new Date(dateString); @@ -1905,9 +1801,6 @@ EscapeActions.register( () => { return !Session.equals('currentCard', null); }, - { - noClickEscapeOn: '.js-card-details,.board-sidebar,#header', - }, ); Template.cardAssigneesPopup.onCreated(function () { @@ -1985,3 +1878,16 @@ Template.cardAssigneePopup.events({ }, 'click .js-edit-profile': Popup.open('editProfile'), }); + +Template.cardDetailsPopup.helpers({ + popupArgs() { + return { + name: "cardDetails", + showHeader: false, + closeDOMs: ["click .js-close-card-details"], + followDOM: ".card-details", + handleDOM: ".card-header-middle", + closeVar: "currentCard" + } + }, +}); \ No newline at end of file diff --git a/client/components/cards/cardTime.css b/client/components/cards/cardTime.css index ab8f2fae1..77586ac86 100644 --- a/client/components/cards/cardTime.css +++ b/client/components/cards/cardTime.css @@ -1,6 +1,6 @@ .card-time { display: block; - border-radius: 4px; + border-radius: 0.4ch; padding: 1px 3px; color: #fff; background-color: #dbdbdb; diff --git a/client/components/cards/checklists.css b/client/components/cards/checklists.css index 073e7ec79..83dabf68b 100644 --- a/client/components/cards/checklists.css +++ b/client/components/cards/checklists.css @@ -4,7 +4,7 @@ textarea.js-add-checklist-item, textarea.js-edit-checklist-item { overflow: hidden; - word-wrap: break-word; + overflow-wrap: break-word; resize: none; height: 34px; } @@ -13,7 +13,7 @@ textarea.js-edit-checklist-item { .js-convert-checklist-item-to-card { color: #8c8c8c; text-decoration: underline; - word-wrap: break-word; + overflow-wrap: break-word; float: right; padding-top: 6px; } @@ -25,6 +25,7 @@ textarea.js-edit-checklist-item { .checklists-title { display: flex; justify-content: space-between; + align-items: center; } .checklist-progress-bar-container { display: flex; @@ -35,7 +36,7 @@ textarea.js-edit-checklist-item { margin-right: 10px; } .checklist-progress-bar-container .checklist-progress-bar { - width: 80%; + flex: 1; height: 10px; background-color: #e0e0e0; border-radius: 16px; @@ -47,19 +48,29 @@ textarea.js-edit-checklist-item { border-radius: 16px; height: 100%; } -.checklist-title { - padding: 10px; + +.checklist-controls { + display: flex; + gap: 0.25lh; } + +.checklist-title { + display: flex; + align-items: center; + justify-content: space-between; +} + .checklist-title .checkbox { float: left; width: 30px; height: 30px; - font-size: 18px; + line-height: 30px; } -.checklist-title .title { - font-size: 18px; - line-height: 25px; +.checklist-title p, .title { + font-size: 1em; + line-height: 1; + margin: 0; } .checklist-title .checklist-stat { margin: 0 0.5em; @@ -79,29 +90,31 @@ textarea.js-edit-checklist-item { bottom: -600px; right: 0; } + .checklist { - background: #f7f7f7; + padding: 0.5lh; + margin: 0.5lh 0; + background-color: #f7f7f7; } + + .checklist.placeholder { background: #ccc; border-radius: 2px; } .checklist.ui-sortable-helper { box-shadow: -2px 2px 8px rgba(0,0,0,0.3), 0 0 1px rgba(0,0,0,0.5); - transform: rotate(4deg); cursor: grabbing; } .checklist-item { - margin: 0 0 0 0.1em; - line-height: 18px; - font-size: 1.1em; - margin-top: 3px; display: flex; - background: #f7f7f7; + gap: 0.25lh; opacity: 1; transition: height 0ms 400ms, opacity 400ms 0ms; - height: auto; overflow: hidden; + align-items: center; + min-height: 1.5lh; + padding: 0 1ch; } .checklist-item.is-checked.invisible { opacity: 0; @@ -114,26 +127,21 @@ textarea.js-edit-checklist-item { background: #ccc; border-radius: 2px; } -.checklist-item.ui-sortable-helper { - box-shadow: -2px 2px 8px rgba(0,0,0,0.3), 0 0 1px rgba(0,0,0,0.5); - transform: rotate(4deg); - cursor: grabbing; -} .checklist-item:hover { background-color: #ebebeb; } -.checklist-item .check-box-container { - padding-right: 10px; -} .checklist-item .check-box { margin: 0.1em 0 0 0; } .checklist-item .check-box.is-checked { - border-bottom: 2px solid #3cb500; - border-right: 2px solid #3cb500; + border-bottom: 0.2ch solid #3cb500; + border-right: 0.2ch solid #3cb500; } .checklist-item .item-title { + display: flex; + justify-content: start; flex: 1; + cursor: grab; } .checklist-item .item-title.is-checked { color: #8c8c8c; @@ -141,27 +149,18 @@ textarea.js-edit-checklist-item { text-decoration: line-through; } .checklist-item .item-title .viewer p { - margin-bottom: 2px; - display: block; - word-wrap: break-word; + display: flex; + overflow-wrap: break-word; max-width: 420px; } -.checklist-item span.fa.checklistitem-handle { - padding-top: 2px; - padding-right: 10px; -} .js-delete-checklist-item, .js-convert-checklist-item-to-card { margin: 0 0 0.5em 1.33em; padding: 12px 0 0 0; } -.add-checklist-item { - margin: 0.2em 0 0.5em 1.33em; -} .add-checklist-item.js-open-inlined-form, .add-checklist.js-open-inlined-form { - display: block; - width: 50%; + display: inline-block; } .add-checklist-item.js-open-inlined-form:hover, .add-checklist.js-open-inlined-form:hover { @@ -169,25 +168,13 @@ textarea.js-edit-checklist-item { color: #222; box-shadow: 0 1px 2px rgba(0,0,0,0.2); } -.add-checklist-top { - /* more space to checklists title */ - padding-left: 20px; - /* + is easier clickable */ - padding-right: 20px; -} + .add-checklist-top.js-open-inlined-form:hover { background: #dbdbdb; color: #222; box-shadow: 0 1px 2px rgba(0,0,0,.2); } -.card-details-item-title { - /* max width for adding checklist at top */ - width: 100%; -} -.checklist-details-menu { - float: right; - padding: 6px 10px 6px 10px; -} + .edit-controls label.toggle-label { margin-left: 2px; } diff --git a/client/components/cards/checklists.jade b/client/components/cards/checklists.jade index e943e338f..c9bbf9f66 100644 --- a/client/components/cards/checklists.jade +++ b/client/components/cards/checklists.jade @@ -36,26 +36,31 @@ template(name="checklistDetail") +editChecklistItemForm(checklist = checklist) else .checklist-title - span - if canModifyCard - 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.fa.checklist-handle(class="fa-arrows" title="{{_ 'dragChecklist'}}") + h4.title + if canModifyCard + a.js-open-inlined-form.is-editable(title="{{_ 'moveChecklistPopup-title'}}") + +viewer + = checklist.title + else +viewer = checklist.title - else - h4.title - +viewer + .checklist-controls + if canModifyCard + a.fa.fa-navicon.checklist-details-menu.js-open-checklist-details-menu(title="{{_ 'checklistActionsPopup-title'}}") + if isMiniScreen + span.fa.checklist-handle(class="fa-arrows" title="{{_ 'dragChecklist'}}") + +viewer = checklist.title - if $gt finishedPercent 0 - .checklist-progress-bar-container - .checklist-progress-text {{finishedPercent}}% - .checklist-progress-bar + //- jumps where checking the first item is not comfortable; + //- so try to show it anytime. also, it helps to separate the checklists. + .checklist-progress-bar-container + .checklist-progress-text {{finishedPercent}}% + .checklist-progress-bar + if $gt finishedPercent 0 .checklist-progress(style="width:{{finishedPercent}}%") + else + .checklist-progress(style="visibility:hidden") +checklistItems(checklist = checklist card = card) template(name="checklistDeletePopup") @@ -64,7 +69,7 @@ template(name="checklistDeletePopup") template(name="addChecklistItemForm") a.fa.fa-copy(title="{{_ 'copy-text-to-clipboard'}}") - span.copied-tooltip {{_ 'copied'}} + span.copied-tooltip.copied-tooltip-hidden {{_ 'copied'}} textarea.js-add-checklist-item(rows='1' autofocus) .edit-controls.clearfix button.primary.confirm.js-submit-add-checklist-item-form(type="submit") {{_ 'save'}} @@ -73,16 +78,12 @@ template(name="addChecklistItemForm") .material-toggle-switch(title="{{_ 'newlineBecomesNewChecklistItem'}}") input.toggle-switch(type="checkbox" id="toggleNewlineBecomesNewChecklistItem") label.toggle-label(for="toggleNewlineBecomesNewChecklistItem") + span.toggle-switch-desc | {{_ 'newLineNewItem'}} - if $eq position 'top' - .material-toggle-switch(title="{{_ 'newlineBecomesNewChecklistItemOriginOrder'}}") - input.toggle-switch(type="checkbox" id="toggleNewlineBecomesNewChecklistItemOriginOrder") - label.toggle-label(for="toggleNewlineBecomesNewChecklistItemOriginOrder") - | {{_ 'originOrder'}} template(name="editChecklistItemForm") a.fa.fa-copy(title="{{_ 'copy-text-to-clipboard'}}") - span.copied-tooltip {{_ 'copied'}} + span.copied-tooltip.copied-tooltip-hidden {{_ 'copied'}} textarea.js-edit-checklist-item(rows='1' autofocus dir="auto") if $eq type 'item' = item.title @@ -99,13 +100,6 @@ template(name="editChecklistItemForm") | {{_ 'convertChecklistItemToCardPopup-title'}} template(name="checklistItems") - if checklist.items.length - if canModifyCard - +inlinedForm(autoclose=false classNames="js-add-checklist-item" checklist = checklist position="top") - +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) @@ -118,14 +112,15 @@ template(name="checklistItems") else a.add-checklist-item.js-open-inlined-form(title="{{_ 'add-checklist-item'}}") i.fa.fa-plus + +inlinedForm(autoclose=false classNames="js-add-checklist-item" checklist = checklist) + +addChecklistItemForm(checklist=checklist showNewlineBecomesNewChecklistItem=true position="top") 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") + .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 .check-box-container .check-box.materialCheckBox(class="{{#if item.isFinished }}is-checked{{/if}}") - if isTouchScreenOrShowDesktopDragHandles + if isMiniScreen 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 @@ -141,16 +136,16 @@ template(name="checklistActionsPopup") li a.js-delete-checklist.delete-checklist i.fa.fa-trash - | {{_ "delete"}} ... + | {{_ "delete"}} a.js-move-checklist.move-checklist i.fa.fa-arrow-right - | {{_ "moveChecklist"}} ... + | {{_ "moveChecklist"}} a.js-copy-checklist.copy-checklist i.fa.fa-copy - | {{_ "copyChecklist"}} ... + | {{_ "copyChecklist"}} a.js-hide-checked-checklist-items i.fa.fa-eye-slash - | {{_ "hideCheckedChecklistItems"}} ... + | {{_ "hideCheckedChecklistItems"}} .material-toggle-switch(title="{{_ 'hide-checked-items'}}") if checklist.hideCheckedChecklistItems input.toggle-switch(type="checkbox" id="toggleHideCheckedChecklistItems_{{checklist._id}}" checked="checked") @@ -158,7 +153,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 diff --git a/client/components/cards/checklists.js b/client/components/cards/checklists.js index 16fd74402..c016f9902 100644 --- a/client/components/cards/checklists.js +++ b/client/components/cards/checklists.js @@ -7,7 +7,7 @@ import { DialogWithBoardSwimlaneListCard } from '/client/lib/dialogWithBoardSwim const subManager = new SubsManager(); const { calculateIndexData, capitalize } = Utils; -function initSorting(items) { +function initSorting(items, handleSelector) { items.sortable({ tolerance: 'pointer', helper: 'clone', @@ -16,6 +16,7 @@ function initSorting(items) { appendTo: 'parent', distance: 7, placeholder: 'checklist-item placeholder', + handle: handleSelector, scroll: true, start(evt, ui) { ui.placeholder.height(ui.helper.height()); @@ -48,8 +49,9 @@ function initSorting(items) { BlazeComponent.extendComponent({ onRendered() { const self = this; + this.handleSelector = Utils.isMiniScreen() ? 'span.fa.checklistitem-handle' : '.item-title'; self.itemsDom = this.$('.js-checklist-items'); - initSorting(self.itemsDom); + initSorting(self.itemsDom, this.handleSelector); self.itemsDom.mousedown(function (evt) { evt.stopPropagation(); }); @@ -63,11 +65,9 @@ BlazeComponent.extendComponent({ const $itemsDom = $(self.itemsDom); if ($itemsDom.data('uiSortable') || $itemsDom.data('sortable')) { $(self.itemsDom).sortable('option', 'disabled', !userIsMember()); - if (Utils.isTouchScreenOrShowDesktopDragHandles()) { - $(self.itemsDom).sortable({ - handle: 'span.fa.checklistitem-handle', - }); - } + $(self.itemsDom).sortable({ + handle: this.handleSelector, + }); } }); }, diff --git a/client/components/cards/labels.css b/client/components/cards/labels.css index 19a8746a8..03f6fc4c7 100644 --- a/client/components/cards/labels.css +++ b/client/components/cards/labels.css @@ -1,20 +1,20 @@ .card-label { - border: 1px solid #000; - border-radius: 4px; + border-radius: 0.4ch; color: #fff; display: inline-block; font-weight: 700; - font-size: 13px; - margin-right: 4px; - margin-bottom: 5px; - padding: 3px 8px; - max-width: 210px; - min-width: 8px; - word-wrap: break-word; - min-height: 18px; - vertical-align: middle; - white-space: initial; - overflow: initial; + font-size: 0.9em; + display: flex; + /* prefer not using padding/margin but let outer grids + position/size labels (see e.g. minicards), otherwise we get + inconsistencies */ + align-self: stretch; + justify-content: center; + align-items: center; + text-align: center; + padding: 0 0.5ch; + height: var(--label-height); + min-width: 8ch; } .card-label:hover { color: #fff; @@ -34,6 +34,7 @@ } .card-label p { margin: 0px; + --overflow-lines: 1; } .palette-colors { display: flex; @@ -138,37 +139,22 @@ .card-label-indigo { background-color: #4b0082; } -.edit-label .card-label, -.create-label .card-label { - float: left; - height: 25px; - margin: 0px 3% 7px 0px; - width: 10.5%; - max-width: 10.5%; - cursor: pointer; -} -.edit-labels input[type="text"] { - margin: 4px 0 6px 38px; - width: 243px; -} -.edit-labels .card-label { - height: 30px; - left: 0; - padding: 1px 5px; - position: absolute; - top: 0; - width: 24px; -} -.edit-labels .labels-static .card-label { - line-height: 30px; - margin-bottom: 4px; - position: relative; - top: auto; - left: 0; - width: 260px; -} .edit-labels-pop-over { - margin-bottom: 8px; + display: grid; + /* so that inner elements, align nicely */ + grid-template-columns: 1fr; + gap: 0.1lh; + >li { + display: flex; + flex-direction: row-reverse; + gap: 1ch; + align-items: center; + } + .card-label-selectable { + flex: 1; + display: flex; + gap: 1ch; + } } .edit-labels-pop-over .card-label .viewer p { margin: 0; @@ -176,34 +162,6 @@ .edit-labels-pop-over .shortcut { display: inline-block; } -.card-label-selectable { - border-radius: 3px; - cursor: pointer; - margin: 0; - margin-bottom: 3px; - width: 190px; - min-height: 18px; - padding: 8px; - position: relative; - transition: margin-right 0.1s; -} -.card-label-selectable .card-label-selectable-icon { - position: absolute; - top: 8px; - right: -20px; -} -.card-label-selectable.active:hover, -.card-label-selectable.active, -.card-label-selectable.active.selected:hover, -.card-label-selectable.active.selected { - padding-right: 32px; -} -.card-label-selectable.active:hover .card-label-selectable-icon, -.card-label-selectable.active .card-label-selectable-icon, -.card-label-selectable.active.selected:hover .card-label-selectable-icon, -.card-label-selectable.active.selected .card-label-selectable-icon { - right: 6px; -} .card-label-selectable.selected, .card-label-selectable:hover { opacity: 0.8; @@ -212,24 +170,6 @@ .active .card-label-selectable:hover { margin-right: 0; } -.active .card-label-selectable .card-label-selectable-icon { - right: 8px; -} -.card-label-edit-button { - border-radius: 3px; - float: right; - padding: 8px; -} .card-label-edit-button:hover { background: #dbdbdb; -} -ul.edit-labels-pop-over span.label-handle { - padding-right: 10px; - display: inline-block; - width: 1.2em; - text-align: center; - color: #999; -} -ul.edit-labels-pop-over span.label-handle + .card-label { - max-width: 180px; -} +} \ No newline at end of file diff --git a/client/components/cards/minicard.css b/client/components/cards/minicard.css index 32dea839d..80facfb8e 100644 --- a/client/components/cards/minicard.css +++ b/client/components/cards/minicard.css @@ -1,10 +1,32 @@ +.minicard-body { + display: flex; + flex-direction: column; + padding: 0 1ch 0.2lh 1ch; + gap: 0.2lh; +} + .minicard-wrapper { cursor: pointer; position: relative; display: flex; align-items: center; - margin-bottom: 1.2vh; + height: min-content; } +.minicard-header { + display: flex; + align-items: center; + padding: 0 1ch; + gap: 1ch; +} + +.minicard > hr { + margin: 0; +} + +.minicard-add-form { + width: auto; +} + .minicard-wrapper.placeholder { background: #ccc; border-radius: 1.2vw; @@ -28,32 +50,25 @@ .minicard-wrapper .multi-selection-checkbox + .minicard { margin-left: 1vw; } -@media only screen { - .minicard { - padding: 0.8vh 1vw 0.3vh; - position: relative; - flex: 1; - flex-wrap: wrap; - background-color: #fff; - min-height: 2.5vh; - box-shadow: 0 0.2vh 0.3vh rgba(0,0,0,0.15); - border-radius: 0.3vw; - color: #4d4d4d; - overflow: hidden; - transition: transform 0.2s, border-radius 0.2s; - } +.minicard { + display: grid; + grid-auto-flow: row; + grid-template-rows: min-content 1fr auto auto; + gap: 0.4lh; + background-color: #fff; + box-shadow: 0 0.2vh 0.3vh rgba(0,0,0,0.15); + border-radius: 0.3vw; + color: #4d4d4d; + overflow: hidden; + transition: transform 0.2s, border-radius 0.2s; + flex: 1; } -.minicard-details-menu-with-handle { - float: right; - padding-left: 0.7vw; - font-size: clamp(14px, 3vw, 18px); - padding: 0; - z-index: 1; -} -.minicard-details-menu { - float: right; - font-size: clamp(14px, 3vw, 18px); - padding-left: 0.7vw; + +.minicard-actions-right { + justify-content: end; + display: flex; + align-items: end; + gap: .5lh; } @media print { .minicard-details-menu, @@ -76,7 +91,6 @@ transform: translateX(1.5vw); border-bottom-right-radius: 0; border-top-right-radius: 0; - z-index: 25; box-shadow: -0.3vw 0.2vh 0.3vh rgba(0,0,0,0.2); } .minicard:hover:not(.minicard-composer), @@ -96,20 +110,30 @@ margin: 0.8vh -1vw 0.8vh -1vw; border-radius: top 0.3vw; } -.minicard .minicard-labels { - float: none; - margin-right: 6vw; -} -.minicard .minicard-labels .minicard-label { - width: clamp(12px, 1.5vw, 16px); - height: clamp(12px, 1.5vw, 16px); - border-radius: 0.3vw; - margin-right: 0.4vw; - margin-bottom: 0.4vh; -} -.minicard .minicard-labels-no-text { - display: flex; - flex-wrap: wrap; +.minicard { + .minicard-labels, .dates { + display: grid; + grid-auto-rows: min-content; + justify-content: stretch; + font-size: 0.8em; + grid-auto-rows: minmax(1.3lh, auto); + } + .minicard-labels { + grid-template-columns: repeat(auto-fill, minmax(12ch, auto)); + gap: 0.2lh 0.5ch; + } + .minicard-labels-no-text { + grid-template-columns: repeat(auto-fill, 4ch); + grid-template-rows: 4ch; + font-size: 0.4em; + .minicard-label { + border-radius: 1ch; + } + } + .dates { + height: min-content; + grid-template-columns: repeat(auto-fit, minmax(15ch, auto)); + } } .minicard .minicard-custom-fields { display: block; @@ -121,26 +145,22 @@ .minicard .minicard-custom-field-item { flex-grow: 1; display: block; - word-wrap: break-word; + overflow-wrap: break-word; max-width: 13vw; margin-right: 0.5vw; } .minicard .minicard-custom-field-item-fullwidth { flex-grow: 1; display: block; - word-wrap: break-word; + overflow-wrap: break-word; max-width: 100%; margin-right: 0.5vw; } .minicard .handle { - width: clamp(20px, 2.5vw, 28px); - height: clamp(20px, 2.5vw, 28px); - position: absolute; - right: 0vw; - top: 4vh; display: none; z-index: 1; } + @media only screen { .minicard .handle { display: block; @@ -154,58 +174,34 @@ text-align: center; } .minicard .minicard-title { - margin-right: 1.5vw; + display: flex; + max-width: 100%; + flex: 1; + cursor: grab; + .viewer { + --overflow-lines: 2; + } + } .minicard .minicard-title .card-number { color: #b3b3b3; display: inline-block; margin-right: 0.7vw; } -@media only screen { - .minicard .minicard-title p:last-child { - margin-bottom: 0; - } - .minicard .minicard-title .viewer { - display: block; - word-wrap: break-word; - } -} -.minicard .dates { - display: flex; - flex-direction: row; - flex-wrap: wrap; - position: relative; - z-index: 5; - margin-right: 6vw; - clear: both; -} .minicard .date { - margin-right: 0.4vw; + display: flex; + &>a { + display: flex; + justify-content: center; + flex: 1; + align-items: center; + text-align: center; + align-self: stretch; + } } - -/* Unicode icons for minicard dates - matching cardDate.css */ -.minicard .card-date.end-date time::before { - content: "🏁"; /* Finish flag - represents end/completion */ -} -.minicard .card-date.due-date time::before { - content: "⏰"; /* Alarm clock - represents due/deadline */ -} -.minicard .card-date.start-date time::before { - content: "🚀"; /* Rocket - represents start/launch */ -} -.minicard .card-date.received-date time::before { - content: "📥"; /* Inbox tray - represents received/incoming */ -} - -.minicard .card-date time::before { - font-size: inherit; - margin-right: 0.3em; - display: inline-block; -} - /* Date type specific colors for minicards - matching cardDate.css */ .minicard .card-date.received-date { - background-color: #dbdbdb; /* Grey for received - same as base card-date */ + background-color: #d3d3d3; /* Grey for received - a bit darker than base card-date */ } .minicard .card-date.received-date:hover, @@ -311,102 +307,134 @@ background-color: #1976d2 !important; } +.minicard .minicard-badges-and-creator { + display: flex; + flex-direction: row-reverse; + justify-content: end; + gap: 0 0.5ch;; +} + +.minicard-people-grid { + display: grid; + grid-template-columns: 1fr auto; + grid-auto-rows: auto; +} + +.minicard-people-wrapper { + display: flex; + justify-content: end; + gap: 0.1lh; +} .minicard .badges { - float: left; - margin-top: 1vh; + display: flex; + align-items: center; + gap: 1.5ch; color: #808080; + /* this avoid padding-ish at the bottom of the card */ + font-size: 0.8rem; } -.minicard .badges:empty { - display: none; -} -.minicard .badges .badge { - float: left; - margin-right: 1.5vw; - margin-bottom: 0.4vh; - font-size: 0.9em; -} + .minicard .badges .badge.is-finished { background: #3cb500; - padding: 0 0.4vw; + padding: 0.3lh 0.8ch; border-radius: 0.4vw; - color: #fff; + &, .fa { + color: #fff; + } } .minicard .badges .badge:last-of-type { margin-right: 0; } -.minicard .badges .badge .badge-icon, -.minicard .badges .badge .badge-text { - vertical-align: middle; -} -.minicard .badges .badge .badge-icon.badge-comment, -.minicard .badges .badge .badge-text.badge-comment { - margin-bottom: 0.1rem; -} -.minicard .badges .badge .badge-text { - font-size: 0.9em; - padding-left: 0.3vw; - line-height: 1.2; -} -.minicard .badges .badge .check-list-text { - padding-left: 0px; - line-height: 1.1; -} -.minicard .minicard-members, -.minicard .minicard-assignees, -.minicard .minicard-creator { - float: right; - margin-left: 0.7vw; - margin-bottom: 0.5vh; -} .minicard .minicard-members .member, .minicard .minicard-assignees .member, .minicard .minicard-creator .member { - float: right; + display: flex; border-radius: 50%; - height: clamp(24px, 3.5vw, 32px); - width: clamp(24px, 3.5vw, 32px); - margin-bottom: 0.5vh; + font-size: 0.8em; + margin-bottom: 0.2lh; } -.minicard .minicard-members .assignee, -.minicard .minicard-assignees .assignee, -.minicard .minicard-creator .assignee { - float: right; - border-radius: 50%; - height: clamp(24px, 3.5vw, 32px); - width: clamp(24px, 3.5vw, 32px); + +.minicard .minicard-assignees .member { + border: 2px solid rgb(180, 87, 87); } -.minicard .minicard-members + .badges, -.minicard .minicard-assignees + .badges, -.minicard .minicard-creator + .badges { - margin-top: 0.7vh; + +.minicard .minicard-creator .member { + border: 2px solid #7fd67f; +} + +.minicard .minicard-members .member { + border: 2px solid #5a5ac6; } .minicard .minicard-assignees { - border-bottom: 1px solid #f00; -} -.minicard .minicard-creator { - border-bottom: 1px solid #008000; + display: flex; } + .minicard .minicard-members:empty, .minicard .minicard-assignees:empty { display: none; } .minicard .minicard-description { - padding: 0.8vh 0 0 1vw; color: #000; background-color: #eee; - width: 100%; - margin-bottom: 0.3vh; - margin-left: -0.5vw; - border-radius: 0.4vw; - overflow: hidden; - text-overflow: ellipsis; - display: -webkit-box; - -webkit-line-clamp: 3; - -webkit-box-orient: vertical; + padding: 0.5lh 1ch; + --overflow-lines: 2; + .viewer { + font-size: 0.9em; + ul { + padding-bottom: 0; + } + } } + +.minicard .minicard-description p { + margin: 0; +} + +.minicard-composer { + display: flex; + flex-direction: column; + + .minicard-composer-icons { + display: flex; + flex-direction: column; + align-items: center; + gap: 0.2lh; + } + + .minicard-bottom { + display: flex; + justify-content: end; + align-items: center; + gap: 1ch; + + .minicard-composer-icons { + display: flex; + flex: 1; + flex-wrap: wrap; + flex-direction: row-reverse; + } + + .add-controls { + display: flex; + align-self: start; + } + + textarea { + display: flex; + flex: 1; + } + } +} + .minicard.minicard-composer { - margin-bottom: 1.3vh; + flex-wrap: wrap; + flex: 1; + align-self: stretch; + gap: 0.3lh; + padding: 0.5lh 1ch; + position: relative; } + .minicard.minicard-composer textarea.minicard-composer-textarea, .minicard.minicard-composer textarea.minicard-composer-textarea:focus { resize: none; @@ -415,11 +443,11 @@ box-shadow: none; height: auto; margin: 0; - padding: 0; - max-height: 22vh; - min-height: 5vh; - margin-bottom: 2.5vh; + padding: 1ch; + min-height: 5lh; overflow-y: auto; + flex: 1; + width: 100%; } .parent-prefix { color: #b3b3b3; @@ -734,30 +762,12 @@ /* List name display on minicard */ .minicard-list-name { - font-size: 0.75em; + font-size: inherit; color: #8c8c8c; - margin-top: 0.2vh; display: flex; - align-items: center; - gap: 0.3vw; -} - -/* Checklist display on minicard */ -.minicard-checklist { - width: 100%; - margin-top: 0.5vh; - margin-bottom: 0.5vh; - padding: 0.3vh 0.5vw; - background-color: rgba(255, 255, 255, 0.8); - border-radius: 0.3vw; - border: 1px solid #e0e0e0; -} - -.minicard-checklist .checklist-header { + padding: 0 0.5ch; display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 0.3vh; + gap: 0.5ch; } .minicard-checklist .checklist-title { diff --git a/client/components/cards/minicard.jade b/client/components/cards/minicard.jade index 2a1d4162d..c00974b0b 100644 --- a/client/components/cards/minicard.jade +++ b/client/components/cards/minicard.jade @@ -1,226 +1,236 @@ template(name="minicard") + if isSelected + +cardDetailsPopup(this) .minicard.nodragscroll( class="{{#if isLinkedCard}}linked-card{{/if}}" class="{{#if isLinkedBoard}}linked-board{{/if}}" class="{{#if colorClass}}minicard-{{colorClass}}{{/if}}") - 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'}}") - i.fa.fa-bars .dates - if getReceived - .date - +minicardReceivedDate - if getStart - .date - +minicardStartDate - if getDue - .date - +minicardDueDate - if getEnd - +minicardEndDate + if allowsReceivedDate + if getReceived + .date.viewer + +minicardReceivedDate + if allowsStartDate + if getStart + .date.viewer + +minicardStartDate + if allowsDueDate + if getDue + .date.viewer + +minicardDueDate + if allowsEndDate + if getEnd + .date.viewer + +minicardEndDate if getSpentTime - .date + .date.viewer +cardSpentTime - if cover - if currentBoard.allowsCoverAttachmentOnMinicard - .minicard-cover(style="background-image: url('{{cover.link 'original'}}?dummyReloadAfterSessionEstablished={{sess}}');") + .minicard-header + .minicard-title + if $eq 'prefix-with-full-path' currentBoard.presentParentTask + .parent-prefix + | {{ parentString ' > ' }} + if $eq 'prefix-with-parent' currentBoard.presentParentTask + .parent-prefix + | {{ parentCardName }} + if isLinkedBoard + a.js-linked-link + span.linked-icon + i.fa.fa-folder + else if isLinkedCard + a.js-linked-link + span.linked-icon + i.fa.fa-id-card + if getArchived + span.linked-icon.linked-archived + i.fa.fa-archive + +viewer + if allowsCardNumber + span.card-number + | ##{getCardNumber}  + = getTitle + div.minicard-actions-right + if canModifyCard + a.minicard-details-menu-with-handle.js-open-minicard-details-menu(title="{{_ 'cardDetailsActionsPopup-title'}}") + i.fa.fa-bars + if isMiniScreen + if canMoveCard + .handle + i.fa.fa-arrows + hr + .minicard-body + if cover + if allowsCoverAttachmentOnMinicard + .minicard-cover(style="background-image: url('{{cover.link 'original'}}?dummyReloadAfterSessionEstablished={{sess}}');") - // Upload progress indicator for drag-and-drop uploads - 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}}") - .upload-progress-filename {{file.name}} - .upload-progress-bar - .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 - i.fa.fa-check - span {{_ 'upload-completed'}} + //- Upload progress indicator for drag-and-drop uploads + 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}}") + .upload-progress-filename {{file.name}} + .upload-progress-bar + .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 + i.fa.fa-check + span {{_ 'upload-completed'}} - .minicard-title - if $eq 'prefix-with-full-path' currentBoard.presentParentTask - .parent-prefix - | {{ parentString ' > ' }} - if $eq 'prefix-with-parent' currentBoard.presentParentTask - .parent-prefix - | {{ parentCardName }} - if isLinkedBoard - a.js-linked-link - span.linked-icon - i.fa.fa-folder - else if isLinkedCard - a.js-linked-link - span.linked-icon - i.fa.fa-id-card - if getArchived - span.linked-icon.linked-archived - i.fa.fa-archive - +viewer - if currentBoard.allowsCardNumber - span.card-number - | ##{getCardNumber} - = getTitle - if labels - .minicard-labels(class="{{#if hiddenMinicardLabelText}}minicard-labels-no-text{{/if}}") - each labels - unless hiddenMinicardLabelText - span.js-card-label.card-label(class="card-label-{{color}}" title=name) - +viewer - = name - if hiddenMinicardLabelText - .minicard-label(class="card-label-{{color}}" title="{{name}}") + if labels + .minicard-labels(class="{{#if hiddenMinicardLabelText}}minicard-labels-no-text{{/if}}") + each labels + unless hiddenMinicardLabelText + span.js-card-label.card-label(class="card-label-{{color}}" title=name) + +viewer + = name + if hiddenMinicardLabelText + .minicard-label(class="card-label-{{color}}" title="{{name}}") - .minicard-custom-fields - each customFieldsWD - if definition.showOnCard - if trueValue - .minicard-custom-field - // If there is custom field label, show label at left, - // and value at right - if definition.showLabelOnMiniCard - .minicard-custom-field-item - +viewer - = definition.name - .minicard-custom-field-item - if $eq definition.type "currency" + .minicard-custom-fields + each customFieldsWD + if definition.showOnCard + if trueValue + .minicard-custom-field + // If there is custom field label, show label at left, + // and value at right + if definition.showLabelOnMiniCard + .minicard-custom-field-item +viewer - = formattedCurrencyCustomFieldValue(definition) - else if $eq definition.type "date" - .date - +minicardCustomFieldDate - else if $eq definition.type "checkbox" - .materialCheckBox(class="{{#if value }}is-checked{{/if}}") - else if $eq definition.type "stringtemplate" - +viewer - = formattedStringtemplateCustomFieldValue(definition) - else - +viewer - = trueValue - else - // If there is no custom field label, - // show value full width - .minicard-custom-field-item-fullwidth - if $eq definition.type "currency" - +viewer - = formattedCurrencyCustomFieldValue(definition) - else if $eq definition.type "date" - .date - +minicardCustomFieldDate - else if $eq definition.type "checkbox" - .materialCheckBox(class="{{#if value }}is-checked{{/if}}") - else if $eq definition.type "stringtemplate" - +viewer - = formattedStringtemplateCustomFieldValue(definition) - else - +viewer - = trueValue + = definition.name + .minicard-custom-field-item + if $eq definition.type "currency" + +viewer + = formattedCurrencyCustomFieldValue(definition) + else if $eq definition.type "date" + .date + +minicardCustomFieldDate + else if $eq definition.type "checkbox" + .materialCheckBox(class="{{#if value }}is-checked{{/if}}") + else if $eq definition.type "stringtemplate" + +viewer + = formattedStringtemplateCustomFieldValue(definition) + else + +viewer + = trueValue + else + // If there is no custom field label, + // show value full width + .minicard-custom-field-item-fullwidth + if $eq definition.type "currency" + +viewer + = formattedCurrencyCustomFieldValue(definition) + else if $eq definition.type "date" + .date + +minicardCustomFieldDate + else if $eq definition.type "checkbox" + .materialCheckBox(class="{{#if value }}is-checked{{/if}}") + else if $eq definition.type "stringtemplate" + +viewer + = formattedStringtemplateCustomFieldValue(definition) + else + +viewer + = trueValue + .minicard-people-grid + if allowsAssignee + if getAssignees + .minicard-people-wrapper + .minicard-assignees.js-minicard-assignees + each getAssignees + +userAvatar(userId=this) - if showAssignee - if getAssignees - .minicard-assignees.js-minicard-assignees - each getAssignees - +userAvatar(userId=this) + if allowsMembers + if getMembers + .minicard-people-wrapper + .minicard-members.js-minicard-members + each getMembers + +userAvatar(userId=this) - if showMembers - if getMembers - .minicard-members.js-minicard-members - each getMembers - +userAvatar(userId=this) + .minicard-badges-and-creator + if allowsCreatorOnMinicard + .minicard-creator + +userAvatar(userId=this.userId noRemove=true) - if showCreatorOnMinicard - .minicard-creator - +userAvatar(userId=this.userId noRemove=true) - - .badges - if canModifyCard - if comments.length - .badge(title="{{_ 'card-comments-title' comments.length }}") - span.badge-icon.badge-comment.badge-text - i.fa.fa-comment-o - = ' ' - = comments.length - //span.badge-comment.badge-text - //| {{_ 'comment'}} - if getDescription - unless currentBoard.allowsDescriptionTextOnMinicard - .badge.badge-state-image-only(title=getDescription) - 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}}") - i.fa.fa-thumbs-up - span.badge-text {{ voteCountPositive }} - 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}}") - i.fa.fa-check-square - if expiredPoker - span.badge-text {{ getPokerEstimation }} - if attachments.length - if currentBoard.allowsBadgeAttachmentOnMinicard - .badge - span.badge-icon - i.fa.fa-paperclip - span.badge-text= attachments.length - if allSubtasks.count - .badge - 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 - i.fa.fa-sort-numeric-asc - span.badge-text.check-list-sort {{ sort }} - if shouldShowChecklistAtMinicard - each shouldShowChecklistAtMinicard - +minicardChecklist(checklist=. card=..) - if currentBoard.allowsDescriptionTextOnMinicard + .badges + if canModifyCard + if allowsComments + if comments.length + .badge(title="{{_ 'card-comments-title' comments.length }}") + span.badge-icon.badge-comment.badge-text + i.fa.fa-comment-o + = ' ' + = comments.length + //span.badge-comment.badge-text + //| {{_ 'comment'}} + if getDescription + unless allowsDescriptionTextOnMinicard + .badge.badge-state-image-only(title=getDescription) + 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}}") + i.fa.fa-thumbs-up + span.badge-text {{ voteCountPositive }} + 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}}") + i.fa.fa-check-square + if expiredPoker + span.badge-text {{ getPokerEstimation }} + if attachments.length + if allowsBadgeAttachmentOnMinicard + .badge + span.badge-icon + i.fa.fa-paperclip + span.badge-text= attachments.length + if checklists.length + if allowsChecklists + .badge(class="{{#if checklistFinished}}is-finished{{/if}}") + span.badge-icon + i.fa.fa-check + span.badge-text.check-list-text {{checklistFinishedCount}}/{{checklistItemCount}} + if allSubtasks.count + if allowsSubtasks + .badge + 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 allowsCardSortingByNumber + if allowsCardSortingByNumberOnMinicard + .badge + span.badge-icon + i.fa.fa-sort-numeric-asc + span.badge-text.check-list-sort {{ sort }} + if shouldShowListOnMinicard + .minicard-list-name + span + i.fa.fa-list + span + | {{ listName }} + if $eq 'subtext-with-full-path' presentParentTask + .parent-subtext + | {{ parentString ' > ' }} + if $eq 'subtext-with-parent' presentParentTask + .parent-subtext + | {{ parentCardName }} + if allowsDescriptionTextOnMinicard if getDescription .minicard-description +viewer | {{ getDescription }} - if shouldShowListOnMinicard - .minicard-list-name - i.fa.fa-list - | {{ listName }} - if $eq 'subtext-with-full-path' currentBoard.presentParentTask - .parent-subtext - | {{ parentString ' > ' }} - if $eq 'subtext-with-parent' currentBoard.presentParentTask - .parent-subtext - | {{ parentCardName }} template(name="editCardSortOrderPopup") - input.js-edit-card-sort-popup(type='text' autofocus value=sort dir="auto") + input.js-edit-card-sort-popup(type='text' value=sort dir="auto") .edit-controls.clearfix - button.primary.confirm.js-submit-edit-card-sort-popup(type="submit") {{_ 'save'}} - -template(name="minicardChecklist") - .minicard-checklist - .checklist-header - .checklist-title= checklist.title - if canModifyCard - a.checklist-menu.js-open-checklist-menu(title="{{_ 'checklistActionsPopup-title'}}") - i.fa.fa-bars - each visibleItems - +checklistItemDetail(item = . checklist = checklist card = card) - + button.primary.confirm.js-submit-edit-card-sort-popup(type="submit") {{_ 'save'}} \ No newline at end of file diff --git a/client/components/cards/minicard.js b/client/components/cards/minicard.js index 8be2ed4be..75b7858e3 100644 --- a/client/components/cards/minicard.js +++ b/client/components/cards/minicard.js @@ -13,6 +13,24 @@ BlazeComponent.extendComponent({ return 'minicard'; }, + onRendered() { + // cannot be done with CSS because newlines + // rendered by the JADE engine count as non empty + // and some "empty" divs are nested + // this is not very robust and could probably be + // done with a helper, but it could be in fact worse + // because we would need to to if (allowsX() && X() && ...) + const body = $(this.find('.minicard-body')); + if (!body) {return} + let emptyChildren; + do { + emptyChildren = body.find('*').filter((_, e) => !e.classList.contains('fa') && $(e).html().trim().length === 0).remove(); + } while (emptyChildren.length > 0) + if (body.html().trim().length === 0) { + body.parent().find('hr:has(+ .minicard-body)').remove(); + } + }, + formattedCurrencyCustomFieldValue(definition) { const customField = this.data() .customFieldsWD() @@ -39,46 +57,14 @@ BlazeComponent.extendComponent({ return ret; }, - showCreatorOnMinicard() { - // cache "board" to reduce the mini-mongodb access - const board = this.data().board(); - let ret = false; - if (board) { - ret = board.allowsCreatorOnMinicard ?? false; - } - return ret; - }, isWatching() { const card = this.currentData(); return card.findWatcher(Meteor.userId()); }, - showMembers() { - // cache "board" to reduce the mini-mongodb access - const board = this.data().board(); - let ret = false; - if (board) { - ret = - board.allowsMembers === null || - board.allowsMembers === undefined || - board.allowsMembers - ; - } - return ret; - }, - - showAssignee() { - // cache "board" to reduce the mini-mongodb access - const board = this.data().board(); - let ret = false; - if (board) { - ret = - board.allowsAssignee === null || - board.allowsAssignee === undefined || - board.allowsAssignee - ; - } - return ret; + isSelected() { + const card = this.currentData(); + return Session.get('currentCard') === card._id; }, /** opens the card label popup only if clicked onto a label @@ -87,6 +73,8 @@ BlazeComponent.extendComponent({ */ cardLabelsPopup(event) { if (this.find('.js-card-label:hover')) { + event.preventDefault(); + event.stopPropagation(); Popup.open("cardLabels")(event, {dataContextIfCurrentDataIsUndefined: this.currentData()}); } }, @@ -203,7 +191,7 @@ BlazeComponent.extendComponent({ visibleItems() { const checklist = this.currentData().checklist || this.currentData(); const items = checklist.items(); - + return items.filter(item => { // Hide finished items if hideCheckedChecklistItems is true if (item.isFinished && checklist.hideCheckedChecklistItems) { @@ -254,33 +242,8 @@ Template.minicard.helpers({ }, shouldShowListOnMinicard() { - // Show list name if either: - // 1. Board-wide setting is enabled, OR - // 2. This specific card has the setting enabled - const currentBoard = this.board(); - if (!currentBoard) return false; - return currentBoard.allowsShowListsOnMinicard || this.showListOnMinicard; + return Utils.allowsShowLists(); }, - - shouldShowChecklistAtMinicard() { - // Return checklists that should be shown on minicard - const currentBoard = this.board(); - if (!currentBoard) return []; - - const checklists = this.checklists(); - const visibleChecklists = []; - - checklists.forEach(checklist => { - // Show checklist if either: - // 1. Board-wide setting is enabled, OR - // 2. This specific checklist has the setting enabled - if (currentBoard.allowsChecklistAtMinicard || checklist.showChecklistAtMinicard) { - visibleChecklists.push(checklist); - } - }); - - return visibleChecklists; - } }); BlazeComponent.extendComponent({ diff --git a/client/components/cards/resultCard.css b/client/components/cards/resultCard.css index e47e929c7..0b5e0e9ee 100644 --- a/client/components/cards/resultCard.css +++ b/client/components/cards/resultCard.css @@ -18,7 +18,8 @@ font-weight: bold; } .result-card-context-list { - margin-bottom: 0.7rem; + display: flex; + gap: 0.2ch; } .result-card-block-wrapper { display: inline-block; diff --git a/client/components/cards/resultCard.js b/client/components/cards/resultCard.js index 8e04f1654..ad9a249a2 100644 --- a/client/components/cards/resultCard.js +++ b/client/components/cards/resultCard.js @@ -14,17 +14,10 @@ BlazeComponent.extendComponent({ onReady() { Session.set('popupCardId', cardId); Session.set('popupCardBoardId', boardId); - this_.cardDetailsPopup(evt); }, }); }, - cardDetailsPopup(event) { - if (!Popup.isOpen()) { - Popup.open("cardDetails")(event); - } - }, - events() { return [ { diff --git a/client/components/cards/subtasks.css b/client/components/cards/subtasks.css index ba89ad2b0..2d9a7fcf4 100644 --- a/client/components/cards/subtasks.css +++ b/client/components/cards/subtasks.css @@ -4,19 +4,14 @@ textarea.js-add-subtask-item, textarea.js-edit-subtask-item { overflow: hidden; - word-wrap: break-word; + overflow-wrap: break-word; resize: none; - height: 34px; } .delete-text, .subtask-title .js-delete-subtask, .subtask-title .js-view-subtask, .js-delete-subtask-item { color: #8c8c8c; - text-decoration: underline; - word-wrap: break-word; - float: right; - padding-top: 6px; } .delete-text:hover, .subtask-title .js-delete-subtask:hover, @@ -28,11 +23,11 @@ textarea.js-edit-subtask-item { float: left; width: 30px; height: 30px; - font-size: 18px; + line-height: 30px; } .subtask-title .title { - font-size: 18px; + line-height: 25px; } .subtask-title .subtasks-stat { @@ -133,7 +128,7 @@ textarea.js-edit-subtask-item { margin: 0.1em 0 0 0; } .subtasks-item .check-box.is-checked { - border-bottom: 2px solid #3cb500; + border-bottom: 0.2ch solid #3cb500; border-right: 2px solid #3cb500; } /* Unicode checkbox icons styling */ @@ -165,16 +160,4 @@ body.grey-icons-enabled .subtasks-item .check-box-unicode { } .subtasks-item .item-title .viewer p { margin-bottom: 2px; -} -.js-delete-subtask-item { - margin: 0 0 0.5em 1.33em; - padding: 12px 0 0 0; -} -.add-subtask-item { - margin: 0.2em 0 0.5em 1.33em; - display: inline-block; -} -.subtask-details-menu { - float: right; - padding: 6px 10px 6px 10px; -} +} \ No newline at end of file diff --git a/client/components/cards/subtasks.jade b/client/components/cards/subtasks.jade index 3ea5ec5e3..2210c94b1 100644 --- a/client/components/cards/subtasks.jade +++ b/client/components/cards/subtasks.jade @@ -4,12 +4,20 @@ template(name="subtasks") | {{_ 'subtasks'}} if currentUser.isBoardAdmin if toggleDeleteDialog.get - .board-overlay#card-details-overlay +subtaskDeleteDialog(subtask = subtaskToDelete) - .card-subtasks-items - each subtask in currentCard.subtasks - +subtaskDetail(subtask = subtask) + if currentCard.subtasks + .card-subtasks-items + each subtask in currentCard.subtasks + .subtask-container + +subtaskDetail(subtask = subtask) + if canModifyCard + a.subtask-details-menu.js-open-subtask-details-menu(title="{{_ 'subtaskActionsPopup-title'}}") + | ☰ + if currentUser.isBoardAdmin + a.js-delete-subtask-item + | ❌ + if canModifyCard +inlinedForm(autoclose=false classNames="js-add-subtask" cardId = cardId) @@ -24,9 +32,6 @@ template(name="subtaskDetail") +editSubtaskItemForm(subtask = subtask) else .subtask-title - span - if canModifyCard - a.subtask-details-menu.js-open-subtask-details-menu(title="{{_ 'subtaskActionsPopup-title'}}") if canModifyCard h2.title.js-open-inlined-form.is-editable +viewer @@ -37,13 +42,13 @@ template(name="subtaskDetail") = subtask.title template(name="addSubtaskItemForm") - textarea.js-add-subtask-item(rows='1' autofocus dir="auto") + textarea.js-add-subtask-item(rows='1' dir="auto") .edit-controls.clearfix button.primary.confirm.js-submit-add-subtask-item-form(type="submit") {{_ 'save'}} a.js-close-inlined-form template(name="editSubtaskItemForm") - textarea.js-edit-subtask-item(rows='1' autofocus dir="auto") + textarea.js-edit-subtask-item(rows='1' dir="auto") if $eq type 'item' = item.title else @@ -52,9 +57,6 @@ template(name="editSubtaskItemForm") button.primary.confirm.js-submit-edit-subtask-item-form(type="submit") {{_ 'save'}} a.js-close-inlined-form span(title=createdAt) {{ moment createdAt }} - if canModifyCard - if currentUser.isBoardAdmin - a.js-delete-subtask-item {{_ "delete"}}... template(name="subtasksItems") .subtasks-items.js-subtasks-items @@ -100,4 +102,3 @@ template(name="subtaskActionsPopup") a.js-delete-subtask.delete-subtask i.fa.fa-trash | {{_ "delete"}} ... - diff --git a/client/components/common/originalPosition.css b/client/components/common/originalPosition.css index 1c31c4860..9825716ca 100644 --- a/client/components/common/originalPosition.css +++ b/client/components/common/originalPosition.css @@ -2,8 +2,8 @@ .original-position-info { margin: 5px 0; padding: 8px; - border-radius: 4px; - font-size: 12px; + border-radius: 0.4ch; + line-height: 1.4; } @@ -57,7 +57,7 @@ .original-title { color: #6c757d; - font-size: 11px; + margin-top: 4px; padding-top: 4px; border-top: 1px solid #e9ecef; @@ -78,14 +78,14 @@ /* Responsive adjustments */ @media (max-width: 768px) { .original-position-info { - font-size: 11px; + padding: 6px; } - + .original-position-details { padding: 4px 6px; } - + .original-position-moved, .original-position-unchanged { padding: 3px 5px; @@ -99,24 +99,24 @@ border-color: #4a5568; color: #e2e8f0; } - + .original-position-moved { background-color: #744210; border-color: #b7791f; color: #fbd38d; } - + .original-position-unchanged { background-color: #22543d; border-color: #38a169; color: #9ae6b4; } - + .original-title { color: #a0aec0; border-color: #4a5568; } - + .original-title strong { color: #e2e8f0; } diff --git a/client/components/forms/datepicker.css b/client/components/forms/datepicker.css index f0adcab6c..0be169357 100644 --- a/client/components/forms/datepicker.css +++ b/client/components/forms/datepicker.css @@ -1,22 +1,18 @@ -.datepicker-container .fields .left { - width: 56%; -} -.datepicker-container .fields .right { - width: 38%; -} -.datepicker-container .datepicker { - width: 100%; -} -.datepicker-container .datepicker table { - width: 100%; - border: none; - border-spacing: 0; - border-collapse: collapse; -} -.datepicker-container .datepicker table thead { - background: none; -} -.datepicker-container .datepicker table td, -.datepicker-container .datepicker table th { - box-sizing: border-box; -} +.datepicker-container { + form { + display: flex; + gap: 0.3lh; + padding: 0.3lh 1ch; + } + .fields { + display: flex; + justify-content: stretch; + gap: 1ch; + .left, .right { + display: flex; + flex: 1; + flex-direction: column; + align-items: stretch; + } + } +} \ No newline at end of file diff --git a/client/components/forms/forms.css b/client/components/forms/forms.css index ed26361bf..e2aaa7d75 100644 --- a/client/components/forms/forms.css +++ b/client/components/forms/forms.css @@ -1,3 +1,16 @@ +select, button, input { + font-size: 1rem !important; +} + +form { + /* 🛑 remove me if it causes a significant issue. + this can be overidden and otherwise allow forms to + scale with their parent. */ + display: flex; + flex-direction: column; + flex: 1; +} + select, textarea, input:not([type=file]), @@ -7,9 +20,8 @@ button { border: 1px solid #ccc; border-radius: 0.4vw; display: block; - margin-bottom: 1.5vh; - min-height: 4.5vh; - padding: 1vh 1vw; + padding: 0.3lh 1ch; + max-width: clamp(30vw, 100%, 800px); } select.full, textarea.full, @@ -42,18 +54,6 @@ input[type="text"], input[type="password"], input[type="email"] { transition: background 85ms ease-in, border-color 85ms ease-in; - width: min(250px, 30vw); -} -input[type="text"].inline-input, -input[type="password"].inline-input, -input[type="email"].inline-input { - background: none; - border: 0; - margin: 0; - padding: 0.3vh; - min-height: 0; - height: 2.5vh; - width: min(200px, 25vw); } input[type="text"].full-line, input[type="password"].full-line, @@ -102,11 +102,6 @@ textarea:disabled { -webkit-user-select: none; user-select: none; } -select { - max-height: 40vh; - width: min(256px, 32vw); - margin-bottom: 1vh; -} select.inline { width: 100%; } @@ -114,14 +109,11 @@ option[disabled] { color: #222; } textarea { - height: 20vh; transition: background 85ms ease-in, border-color 85ms ease-in; resize: vertical; - width: 100%; -} -textarea.editor { - resize: none; - padding-bottom: 3vh; + width: auto; + font-size: 0.9em; + min-height: 3lh; } .button { border-radius: 3px; @@ -137,9 +129,16 @@ button { display: inline-block; font-weight: 700; line-height: 1.3; - padding: 1vh 2.5vw; + /* in flex layouts, padding often disturbs computations. rather rarely have + two lines, so setting relative-unit min-height works better */ + min-height: 1.8lh; + padding: 0 2ch; text-align: center; color: #fff; + z-index: 1; + :not(.password-toggle-btn) { + margin-top: 0.1lh; + } } input[type="submit"] .wide, button .wide { @@ -241,9 +240,9 @@ input[type="hidden"] { } .radio-div, .check-div { - display: block; - margin: 0 0 0.5vh 2.5vw; - min-height: 2.5vh; + display: flex; + align-items: center; + gap: 0.2lh; position: relative; } .radio-div input, @@ -260,9 +259,10 @@ input[type="hidden"] { font-weight: 400; } label { - display: block; + display: flex; + flex-direction: column; + flex: 1; font-weight: 700; - margin-bottom: 0.5vh; } label.form-error { color: #d32f2f; @@ -274,11 +274,32 @@ textarea::-moz-placeholder { color: #333 !important; } .edit-controls, -.add-controls { +.add-controls, +.links-controls { display: flex; align-items: center; - margin-top: 0px; - margin-bottom: 1.5vh; + gap: 1ch; + button { + display: flex; + justify-content: center; + align-items: center; + } +} + +.edit-controls { + grid-area: main-controls; +} + +.add-controls { + grid-area: main-controls; +} + +.links-controls { + grid-area: links-controls +} + +.links-controls span.quiet { + margin: auto; } @media print { .add-controls { @@ -289,14 +310,7 @@ textarea::-moz-placeholder { .add-controls button[type=submit], .edit-controls input[type=button], .add-controls input[type=button] { - float: left; - height: 4.5vh; - margin-bottom: 0px; -} -.edit-controls .fa-times-thin, -.add-controls .fa-times-thin { - font-size: clamp(20px, 4vw, 26px); - margin: 0.5vh 1.5vw; + margin: 0; } [type="checkbox"]:not(:checked), [type="checkbox"]:checked { @@ -306,6 +320,18 @@ textarea::-moz-placeholder { display: none; } .materialCheckBox { + position: relative; + width: 0.5lh; + height: 0.5lh; + z-index: 0; + border: 0.2ch solid #5a5a5a; + border-radius: 1px; + transition: 0.2s; + margin: 0; + margin-left: 0px; + cursor: pointer; +} +.materialCheckBox:is(.active) { position: relative; width: 13px; height: 13px; @@ -317,19 +343,33 @@ textarea::-moz-placeholder { cursor: pointer; } .materialCheckBox.is-checked { - top: -4px; - left: -3px; - width: 7px; - height: 15px; - margin-right: 6px; - border-top: 2px solid transparent; - border-left: 2px solid transparent; - border-bottom: 2px solid #3cb500; - border-right: 2px solid #3cb500; - transform: rotate(40deg); + top: 0.3lh; + left: 0.25lh; + width: 0.25lh; + height: 0.5lh; + margin-right: 0.6lh; + border-top: 0 solid transparent; + border-left: 0 solid transparent; + border-bottom: 0.3ch solid #3cb500; + border-right: 0.3ch solid #3cb500; -webkit-backface-visibility: hidden; backface-visibility: hidden; - transform-origin: 100% 100%; + transform: rotate(50deg); + backface-visibility: hidden; + transform-origin: 0.5lh 0; +} + +form .form-buttons { + display: flex; + flex: 1; + align-self: stretch; + justify-content: stretch; + gap: 0.5ch; + &>button { + display: flex; + flex: 1; + justify-content: center; + } } /* Grey checkmarks when grey icons setting is enabled */ body.grey-icons-enabled .materialCheckBox.is-checked { @@ -362,7 +402,7 @@ body.grey-icons-enabled .materialCheckBox.is-checked { border-radius: 3px; color: #fff; display: none; - font-size: 12px; + font-weight: 700; height: 17px; line-height: 17px; @@ -419,7 +459,7 @@ body.grey-icons-enabled .materialCheckBox.is-checked { .button-link.setting .label { color: #222; display: block; - font-size: 12px; + line-height: 14px; margin-bottom: 0; } @@ -428,7 +468,7 @@ body.grey-icons-enabled .materialCheckBox.is-checked { } .button-link.setting .value { display: block; - font-size: 18px; + line-height: 24px; overflow: hidden; text-overflow: ellipsis; @@ -572,7 +612,7 @@ button.loud-text-button:hover { padding: 11px; position: relative; text-decoration: none; - font-size: 16px; + line-height: 20px; } .big-link .text { @@ -615,7 +655,7 @@ button.loud-text-button:hover { width: 40px; } .big-link.avatar-changer .member .member-initials { - font-size: 16px; + height: 40px; line-height: 40px; max-height: 40px; @@ -655,7 +695,7 @@ button.loud-text-button:hover { left: 0; width: 100%; z-index: 2; - font-size: 23px; + } .uploader .realfile input[type="file"] { cursor: pointer; @@ -666,7 +706,7 @@ button.loud-text-button:hover { padding: 0; width: 100%; z-index: 2; - font-size: 23px; + } .uploader:hover .fakefile { background: #318ec4; @@ -705,13 +745,13 @@ button.loud-text-button:hover { color: #fff; } .material-toggle-switch { - display: flex; + padding: 0.2rlh 1ch; + align-self: center; } .toggle-label { + height: 0.6rlh; + width: 1.3rlh; position: relative; - display: block; - height: 20px; - width: 44px; background-color: #a6a6a6; border-radius: 100px; cursor: pointer; @@ -719,11 +759,13 @@ button.loud-text-button:hover { } .toggle-label:after { position: absolute; - left: -2px; - top: -3px; - display: block; - width: 26px; - height: 26px; + /* ensure vertical centering */ + margin: auto; + top: 0; + bottom: 0; + left: -0.2rlh; + width: .8rlh; + height: .8rlh; border-radius: 100px; background-color: #fff; box-shadow: 0px 3px 3px rgba(0,0,0,0.05); @@ -737,7 +779,7 @@ button.loud-text-button:hover { background-color: #6fbeb5; } .toggle-switch:checked ~ .toggle-label:after { - left: 20px; + left: 1.5ch; background-color: #179588; } .toggle-switch:checked:disabled ~ .toggle-label { diff --git a/client/components/gantt/gantt.css b/client/components/gantt/gantt.css index 81139f07b..f9bf0ad16 100644 --- a/client/components/gantt/gantt.css +++ b/client/components/gantt/gantt.css @@ -52,7 +52,7 @@ min-width: 800px; border: 2px solid #666; font-family: sans-serif; - font-size: 13px; + background-color: #fff; } @@ -81,7 +81,7 @@ padding: 2px 1px; /* half */ text-align: center; background-color: #f5f5f5; - font-size: 11px; + min-width: 15px; /* half of 30px */ font-weight: bold; height: auto; @@ -112,7 +112,7 @@ vertical-align: middle; line-height: 28px; background-color: #ffffff; - font-size: 18px; + font-weight: bold; } @@ -162,7 +162,7 @@ .gantt-container tbody td.ganttview-block { background-color: #4CAF50 !important; color: #fff !important; - font-size: 18px !important; + font-weight: bold !important; padding: 2px !important; border-radius: 2px; @@ -171,7 +171,7 @@ /* Responsive adjustments */ @media (max-width: 768px) { .gantt-container table { - font-size: 11px; + } .gantt-container thead td { @@ -187,7 +187,7 @@ .gantt-container tbody td:first-child { width: 100px; - font-size: 12px; + } } diff --git a/client/components/lists/list.css b/client/components/lists/list.css index 1cfd6ca6f..d2270cc9a 100644 --- a/client/components/lists/list.css +++ b/client/components/lists/list.css @@ -1,50 +1,77 @@ -.list { +.list:not(.mobile-view, .list-composer) { box-sizing: border-box; display: flex; flex-direction: column; + align-self: start; position: relative; background: #dedede; border-left: 1px solid #ccc; padding: 0; - float: left; + /* so we get the computed minimal width, if no setting exist */ + width: var(--list-width, min-content) !important; + min-width: var(--list-min-width, 200) !important; + max-width: var(--list-max-width, auto) !important; + /* Both needs to be set to 0 so that resize works; but implies overflowing without size constraints */ + flex-grow: 0; + flex-shrink: 0; + z-index: 0; + /* So that sortable area is the tallest possible + ⚠️ This will make swimlane resizes less fluid, because height + is re-applied in realtime, rather than the list being hidden + by swimlane. Maybe there is another way.*/ + height: var(--swimlane-height, 100%); +} + +.list.mobile-view { + max-height: 100%; } /* List resize handle */ .list-resize-handle { position: absolute; top: 0; - right: -3px; - width: 6px; - height: 100%; + right: 0; + width: max(0.7ch, 0.3lh); cursor: col-resize; - z-index: 10; - background: transparent; - transition: background-color 0.2s ease; - border-radius: 2px; + z-index: 0; /* Ensure the handle is clickable */ pointer-events: auto; + height: 100%; + transition: all 0.2s ease-out; + box-sizing: border-box; } -.list-resize-handle:hover { - background: rgba(0, 123, 255, 0.4); - box-shadow: 0 0 4px rgba(0, 123, 255, 0.3); -} - -.list-resize-handle:active { - background: rgba(0, 123, 255, 0.6); - box-shadow: 0 0 6px rgba(0, 123, 255, 0.4); +.add-card-wrapper { + display: flex; + flex: 1; + justify-content: center; + align-items: stretch; + min-height: 2lh; + > { + display: flex; + align-items: center; + } } /* Show resize handle only on hover */ -.list:hover .list-resize-handle { - background: rgba(0, 0, 0, 0.1); +.list:hover .list-resize-handle, .list.list-resizing .list-resize-handle { + background: rgba(0, 123, 255, 0.2); + border-left: 1px solid rgba(0, 123, 255, 0.5); } -.list:hover .list-resize-handle:hover { - background: rgba(0, 123, 255, 0.4); - box-shadow: 0 0 4px rgba(0, 123, 255, 0.3); + +.list:not(.cannot-resize) { + &:hover + .list-resize-handle, + .list-resize-handle:hover { + border-left: 1px solid rgba(0, 123, 255, 0.5); + background: rgba(0, 123, 255, 0.2); + border-radius: 0; + } + .list-resize-handle:hover, &.list-resizing .list-resize-handle { + background: rgba(0, 123, 255, 0.3); + } } + /* Add a subtle indicator line */ .list-resize-handle::before { content: ''; @@ -57,10 +84,11 @@ background: rgba(0, 0, 0, 0.2); border-radius: 1px; opacity: 0; - transition: opacity 0.2s ease; + transition: opacity 0.2s ease-out; + } -.list-resize-handle:hover::before { +.list-resize-handle:hover::before, .list.list-resizing + .list-resize-handle:hover::before { opacity: 1; } @@ -75,163 +103,144 @@ display: none; } -/* Visual feedback during resize */ -.list.list-resizing { - transition: none !important; - box-shadow: 0 0 10px rgba(0, 123, 255, 0.3); - /* Ensure the list maintains its new width during resize */ - flex: none !important; - flex-basis: auto !important; - flex-grow: 0 !important; - flex-shrink: 0 !important; - /* Override any conflicting layout properties */ - float: left !important; - display: block !important; - position: relative !important; - /* Force width to be respected */ - width: var(--list-width, auto) !important; - min-width: var(--list-width, auto) !important; - max-width: var(--list-width, auto) !important; - /* Ensure the width is applied immediately */ - overflow: visible !important; +.list.list-resizing.cannot-resize .list-resize-handle { + background: rgba(227, 64, 83, 0.5) !important; + border-left: 1px solid rgba(155, 32, 46, 0.5); } body.list-resizing-active { cursor: col-resize !important; + user-select: none !important; } body.list-resizing-active * { cursor: col-resize !important; + user-select: none !important; } -/* Ensure swimlane container doesn't interfere with list resizing */ -.swimlane .list.list-resizing { - /* Override any swimlane flex properties */ - flex: none !important; - flex-basis: auto !important; - flex-grow: 0 !important; - flex-shrink: 0 !important; - /* Ensure width is respected */ - width: var(--list-width, auto) !important; - min-width: var(--list-width, auto) !important; - max-width: var(--list-width, auto) !important; + +body.mobile-mode { + .list-header:not(.open-list-composer) { + .list-header-name-container { + justify-content: start; + } + } } -/* More aggressive override for any container that might interfere */ -.js-swimlane .list.list-resizing, -.dragscroll .list.list-resizing, -[id^="swimlane-"] .list.list-resizing { - /* Force the width to be applied */ - width: var(--list-width, auto) !important; - min-width: var(--list-width, auto) !important; - max-width: var(--list-width, auto) !important; - flex: none !important; - flex-basis: auto !important; - flex-grow: 0 !important; - flex-shrink: 0 !important; - float: left !important; - display: block !important; +.list-header-add { + display: flex; + justify-content: center; + >.inlined-form { + padding: 1ch; + } +} +.list-header:not(.open-list-composer) { + overflow: hidden !important; + display: flex; + align-items: center; + justify-content: center; + column-gap: 0.5lh; + row-gap: 0.5lh; + flex-shrink: 0; + background-color: #e4e4e4; + padding: 0.5lh; + .list-header-name-container { + display: grid; + /* by default, grid fill row before columns */ + grid-auto-flow: column; + align-items: center; + justify-content: center; + flex: 1; /* so we can see the ellipsis */ + max-width: 90%; + gap: 0.5ch; + flex-shrink: 0; + cursor: grab; + } + .list-header-menu { + width: max-content; + align-items: center; + gap: .5rlh; + } + &:not(:has(.list-rotated), :is(.list-header-name-container)) { + .list-header-name-container { + display: flex; + flex-wrap: wrap; + gap: 1ch; + align-items: center; + } + } + &:has(.list-rotated) { + .list-header-name-container { + /* this time we switch to a vertical layout, justified "top" */ + grid-auto-flow: row; + align-items: start; + align-content: start; + justify-items: center; + flex: 0; + gap: 0.3lh; + } + } + .viewer p { + /* cf https://developer.mozilla.org/fr/docs/Web/CSS/Reference/Properties/text-overflow */ + white-space: nowrap; + overflow: scroll; + text-overflow: ellipsis; + } } -/* Ensure the width persists after resize is complete */ -.js-swimlane .list[style*="--list-width"], -.dragscroll .list[style*="--list-width"], -[id^="swimlane-"] .list[style*="--list-width"] { - /* Maintain the width after resize */ - width: var(--list-width, auto) !important; - min-width: var(--list-width, auto) !important; - max-width: var(--list-width, auto) !important; - flex: none !important; - flex-basis: auto !important; - flex-grow: 0 !important; - flex-shrink: 0 !important; - float: left !important; - display: block !important; -} - -/* Ensure consistent header height for all lists */ -.list-header { - /* Maintain consistent height and padding for all lists */ - min-height: 2.5vh !important; - height: auto !important; - padding: 2.5vh 1.5vw 0.5vh !important; - /* Make sure the background covers the full height */ - background-color: #e4e4e4 !important; - border-bottom: 0.8vh solid #e4e4e4 !important; - /* Use original display for consistent button positioning */ - display: block !important; - position: relative !important; - /* Allow overflow for text wrapping and forms */ - overflow: visible !important; -} - -/* Clearfix for floated buttons */ -.list-header::after { - content: ""; - display: table; - clear: both; +.mini-list { + .list-header { + padding: 0.5lh 2ch; + } + .list-header-name-container { + /* on mobile, put card count below list name for a nice alignement effect */ + grid-auto-flow: row; + gap: 0; + } } /* Ensure title text doesn't cause height changes for all lists */ .list-header .list-header-name { - /* 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 horizontally */ - overflow-wrap: break-word !important; - word-wrap: break-word !important; - /* Full width since buttons are now absolutely positioned above */ - width: 100% !important; + font-weight: bold; + /* Ensure it doesn't overflow */ + overflow: hidden !important; } -/* Position elements at top aligned with collapse button */ -.list-header .js-open-list-menu { - position: absolute !important; - top: 5px !important; - right: 10px !important; - z-index: 15 !important; - display: inline-block !important; - padding: 4px !important; +.list-header .list-header-name p { + margin: 0; } -.list-header .list-header-plus-top { - position: absolute !important; - top: 5px !important; - right: 30px !important; - z-index: 15 !important; - display: inline-block !important; - padding: 4px !important; +.list-header .list-header-wrap { + display: flex; } -.list-header .list-header-handle-desktop { - position: absolute !important; - top: 5px !important; - right: 80px !important; - z-index: 15 !important; - display: inline-block !important; +/* Position drag handle at top-right corner for ALL lists */ +.list-header .list-header-handle { + align-self: end; + /* Ensure it's clickable and shows proper cursor */ cursor: move !important; pointer-events: auto !important; - padding: 4px !important; } -/* Anchor header action buttons within header during resize */ -.list .list-header { position: relative; z-index: 5; } -.list .list-header .js-open-list-menu, -.list .list-header .list-header-plus-top, -.list .list-header .list-header-handle-desktop { - position: absolute !important; +.list:not:has(.list-header-add) { + /* so that absolute handle is positionned relative to the list */ + position: relative; + &:last-child { + /* hackisk compensation of the handle "gap" effect; to be done better */ + border-right: 1px solid #bbb; + } + height: 100%; } -[id^="swimlane-"] .list:first-child { - min-width: 2.5vw; + +.list.list-composer { + display: flex; + justify-content: center; + min-width: 4ch; + padding-top: 0.5lh; } .list.list-auto-width { flex: 1; } -.list:first-child { - border-left: none; - flex: none; -} .card-details + .list { border-left: none; } @@ -250,184 +259,53 @@ body.list-resizing-active * { height: 15vh; } .list.list-collapsed { - flex: none; - min-width: 30px; - max-width: 30px; - width: 30px; - min-height: 60vh; - height: 60vh; - overflow: visible; - position: relative; + overflow: hidden !important; + /* strict sizing when collapsed because no resizing + and constant, vertical layout */ + min-width: fit-content !important; + width: fit-content !important; + max-width: fit-content !important; } + .list.list-collapsed .list-header { - padding: 5px 0; - min-height: 100% !important; - height: 100% !important; - display: flex; - flex-direction: column; - align-items: center; - justify-content: flex-start; - position: relative; + flex-direction: column !important; overflow: visible !important; - width: 30px; - max-width: 30px; - margin: 0; -} -.list.list-collapsed .list-header .js-collapse { - position: relative !important; - left: -10px !important; - margin: 5px auto; - z-index: 10; - padding: 5px; - font-size: 16px; - white-space: nowrap; - display: block; - width: auto; - left: auto !important; - top: auto !important; -} -.list.list-collapsed .list-header .list-header-handle { - 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; - height: auto !important; - margin: 20px 0 0 0 !important; - position: relative !important; - overflow: visible !important; - transform: rotate(90deg); - transform-origin: center center; + gap: 0.2lh !important; + justify-content: flex-start !important; + min-width: 5ch; + /* spans the whole swimlane */ flex: 1; - display: flex; - align-items: center; - justify-content: center; -} -.list.list-collapsed .list-header .list-rotated h2.list-header-name { - text-align: center; - overflow: visible; - white-space: nowrap; - display: block !important; - font-size: 12px; - line-height: 1.2; - color: #333; - padding: 4px 8px; - margin: 0; - width: auto; - height: auto; - position: static; - left: auto; - top: auto; - transform: none; - z-index: 10; - visibility: visible !important; - opacity: 1 !important; - 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, .list .list-composer .open-list-composer { color: #8c8c8c; + min-width: max-content; } .list.list-composer .list-name-input, .list .list-composer .list-name-input { background: #fff; - margin: -0.4vh 0 1vh; -} -.list-header-add { - flex: 0 0 auto; - padding: 1.5vh 1.5vw; - position: relative; - min-height: 2.5vh; -} -.list-header { - flex: 0 0 auto; - padding: 2.5vh 1.5vw 0.5vh; - position: relative; - min-height: 2.5vh; - background-color: #e4e4e4; - border-bottom: 0.8vh solid #e4e4e4; -} -.list-header.list-header-card-count { - min-height: 4.5vh; - height: auto; -} -.list-header.ui-sortable-handle { - cursor: grab; -} -.list-header .list-header-left-icon { - display: none; -} -.list-header .list-header-name { - 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-wrap: break-word; - word-wrap: break-word; - vertical-align: top; - width: 100%; -} -/* Sum badge shown before list title */ -.list-header .list-sum-badge { - display: inline-block; - margin-right: 8px; - padding: 0; - border-radius: 0; - background: transparent; - color: #8c8c8c; - font-weight: bold; - font-size: 12px; - vertical-align: middle; + display: flex; + flex: 1; + max-height: 2lh; } .list-rotated { - width: 1.3vw; - height: 35vh; - margin-top: -12vh; - margin-left: -14vw; - margin-right: 0; - transform: rotate(90deg); - position: relative; - text-overflow: ellipsis; - white-space: nowrap; + flex: 1; + writing-mode: vertical-rl; } + +body.mobile-mode .list-collapsed:nth-child(2n-1) > .list-header{ + background-color: #f1f1f1; +} + +body.mobile-mode .list-collapsed:nth-child(2n-2) > .list-header { + background-color: #f7f7f7; +} + .list-header .list-header-watch-icon { padding-left: 10px; color: #a6a6a6; } -.list-header .list-header-menu { - float: right; -} @media print { .list-header .list-header-menu, .list-header .list-header-menu-icon { @@ -436,7 +314,6 @@ form.inlined-form .list-composer { } .list-header .list-header-plus-top { color: #a6a6a6; - margin-right: 15px; vertical-align: middle; line-height: 1.2; } @@ -447,39 +324,25 @@ form.inlined-form .list-composer { color: #a6a6a6; margin-right: 15px; } -/* List header collapse button styling - positioned at top left */ +.list-header .list-header-name-container p { + margin: 0; +} + .list-header .js-collapse { position: absolute !important; top: 5px !important; left: 10px !important; color: #a6a6a6; - display: inline-block; - vertical-align: top; - padding: 5px 8px; border: none; border-radius: 0; background-color: transparent; - cursor: pointer; - font-size: 18px; - line-height: 1.2; - min-width: 30px; - text-align: center; text-decoration: none; - margin: 0; - z-index: 15; } .list-header .js-collapse:hover { background-color: transparent; color: #333; } -/* 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; visibility: visible !important; @@ -492,214 +355,89 @@ form.inlined-form .list-composer { display: none !important; } -/* Responsive adjustments for collapsed lists */ -@media (min-width: 768px) { - .list.list-collapsed { - min-width: 30px; - max-width: 30px; - width: 30px; - min-height: 60vh; - height: 60vh; - } - .list.list-collapsed .list-header { - 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: auto; - font-size: 12px; - height: auto; - line-height: 1.2; - padding: 4px 8px; - margin: 0; - overflow: visible; - position: static; - left: auto; - top: auto; - transform: none; - text-align: center; - visibility: visible !important; - opacity: 1 !important; - display: block !important; - background-color: transparent; - border: none; - color: #333; - z-index: 10; - } - .list.list-collapsed .list-header .js-collapse { - 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 { - 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: auto; - font-size: 12px; - height: auto; - line-height: 1.2; - padding: 4px 8px; - margin: 0; - overflow: visible; - position: static; - left: auto; - top: auto; - transform: none; - text-align: center; - visibility: visible !important; - opacity: 1 !important; - display: block !important; - background-color: transparent; - border: none; - color: #333; - z-index: 10; - } - .list.list-collapsed .list-header .js-collapse { - 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 { - 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: auto; - font-size: 12px; - height: auto; - line-height: 1.2; - padding: 4px 8px; - margin: 0; - overflow: visible; - position: static; - left: auto; - top: auto; - transform: none; - text-align: center; - visibility: visible !important; - opacity: 1 !important; - display: block !important; - background-color: transparent; - border: none; - color: #333; - z-index: 10; - } - .list.list-collapsed .list-header .js-collapse { - margin: 5px auto; - } -} -.list-header .list-header-collapse { - color: #a6a6a6; - margin-right: 15px; -} .list-header .highlight { color: #ce1414; } .list-header .cardCount { color: #8c8c8c; - font-size: 12px; - font-weight: bold; + font-size: 0.9em; + font-weight: normal; + text-wrap: nowrap; } -.list-header .list-header-plus-top, +.list-header, .js-open-list-menu, .list-header-menu a { color: #4d4d4d; - padding-left: 4px; -} -.js-open-list-menu { - font-size: 18px; vertical-align: middle; line-height: 1.2; } .list-body { - flex: 1 1 auto; + /* do not set flex to avoid bad visual effects when resizing swimlanes */ flex-direction: column; display: flex; overflow-y: auto; - padding: 5px 11px; + padding: 0.4lh 1ch; + flex: 1; } +.minilists { + display: flex; + flex-direction: column; + gap: 0.5lh; +} +.minilist-wrapper > .minicard { + padding: 0.3lh 1ch; + .handle { + display: none; + } +} +.mobile-view { + .list-body { + flex: 1 0; + overflow-y: scroll; + } + &.list:not:has(.list-header-add) { + min-height: 50; + display: flex !important; + flex-direction: column; + align-items: stretch; + align-self: stretch; + justify-content: start; + } +} + .list-body .minicards { flex-grow: 1; flex-shrink: 0; + gap: 0.5lh; + display: flex; + flex-direction: column; /** get card drag/drop working for empty swimlanes */ - min-height: 32px; + min-height: 10vh; } .list-body .minicards form { - margin-bottom: 9px; -} -.list-body .minicards .add-controls button { - min-height: 50px; -} -.list-body .open-minicard-composer { - border-radius: 2px; - color: #8c8c8c; - display: block; - padding: 7px 10px; - position: relative; - text-decoration: none; - animation: fadeIn 0.3s; + display: flex; + flex-direction: column; + align-items: center; + flex: 1; } @media print { .list-body .open-minicard-composer { display: none; } } -.list-body .open-minicard-composer i.fa { - margin-right: 7px; + +.list-body .open-minicard-composer { + display: flex; + flex: 1; + border-radius: 0.4ch; + justify-content: center; + align-items: center; + font-size: 1.4em; } -.list-body .open-minicard-composer:hover { +body.mobile-mode .list-body .open-minicard-composer, .list-body .open-minicard-composer:hover { background: #fafafa; color: #222; - box-shadow: 0 1px 2px rgba(0,0,0,0.2); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2); } #js-wip-limit-edit { padding-top: 2%; @@ -726,280 +464,9 @@ form.inlined-form .list-composer { #js-list-width-edit .list-width-error { display: none; } -/* Mobile view styles - applied when isMiniScreen is true (iPhone, etc.) */ -.mini-list.mobile-view { - flex: 0 0 60px; - height: auto; - width: 100vw; - max-width: 100vw; - min-width: 100vw; - border-left: 0px !important; - border-bottom: 1px solid #ccc; - display: block !important; -} -.list.mobile-view { - display: block !important; - flex-basis: auto; - width: 100vw; - max-width: 100vw; - min-width: 100vw; - border-left: 0px !important; - margin: 0 !important; - padding: 0 !important; -} -.list.mobile-view:first-child { - margin-left: 0px; -} -.list.mobile-view.ui-sortable-helper { - flex: 0 0 60px; - height: 60px; - width: 100vw; - max-width: 100vw; - border-left: 0px !important; - border-bottom: 1px solid #ccc; - display: block !important; -} -.list.mobile-view.ui-sortable-helper .list-header.ui-sortable-handle { - cursor: grabbing; -} -.list.mobile-view.placeholder { - flex: 0 0 60px; - height: 60px; - width: 100vw; - max-width: 100vw; - border-left: 0px !important; - border-bottom: 1px solid #ccc; - display: block !important; -} -.list.mobile-view .list-body { - padding: 15px 19px; - width: 100vw; - max-width: 100vw; - min-width: 100vw; -} -.list.mobile-view .list-header { - /*Updated padding values for mobile devices, this should fix text grouping issue*/ - padding: 20px 0px 20px 0px; - border-bottom: 0px solid #e4e4e4; - min-height: 30px; - margin-top: 10px; - align-items: center; - width: 100vw; - max-width: 100vw; - min-width: 100vw; - /* Force grid layout for iPhone */ - display: grid !important; - grid-template-columns: 30px 1fr auto auto !important; - gap: 10px !important; -} -.list.mobile-view .list-header .list-header-left-icon { - padding: 7px; - padding-right: 27px; - margin-top: 1px; - top: -7px; - left: -7px; -} -.list.mobile-view .list-header .list-header-menu-icon { - padding: 14px; - font-size: 40px !important; - text-align: center; - /* Force positioning for iPhone */ - position: absolute !important; - right: 60px !important; - top: 50% !important; - transform: translateY(-50%) !important; - z-index: 10; -} -.list.mobile-view .list-header .list-header-handle { - padding: 14px; - font-size: 48px !important; - text-align: center; - /* Force positioning for iPhone */ - position: absolute !important; - right: 10px !important; - top: 50% !important; - transform: translateY(-50%) !important; - z-index: 10; -} -.list.mobile-view .list-header .list-header-left-icon { - display: grid; - grid-row: 1/3; - grid-column: 1; -} -.list.mobile-view .list-header .list-header-name { - grid-row: 1; - grid-column: 2; - align-self: end; - font-size: 20px !important; - font-weight: bold; - line-height: 1.2; - padding-bottom: 2px; -} -.list.mobile-view .list-header .cardCount { - grid-row: 2; - grid-column: 2; - align-self: start; - text-align: left; - padding-left: 0; - margin-left: 0; - font-size: 16px !important; - line-height: 1.2; -} -.list.mobile-view .list-header .list-header-menu { - grid-row: 1/3; - grid-column: 3; -} -.list.mobile-view .list-header .list-header-menu-icon { - grid-row: 1/3; - grid-column: 3; -} -.list.mobile-view .list-header .list-header-handle { - grid-row: 1/3; - grid-column: 4; -} -.list.mobile-view .list-header .inlined-form { - grid-row: 1/3; - grid-column: 1/4; -} -.list.mobile-view .list-header .edit-controls { - align-items: initial; -} - -@media screen and (max-width: 800px), - screen and (max-device-width: 932px) and (-webkit-min-device-pixel-ratio: 3) { - .mini-list { - flex: 0 0 60px; - height: auto; - width: 100vw; - max-width: 100vw; - min-width: 100vw; - border-left: 0px !important; - border-bottom: 1px solid #ccc; - display: block !important; - } - .list { - display: block !important; - flex-basis: auto; - width: 100vw; - max-width: 100vw; - min-width: 100vw; - border-left: 0px !important; - margin: 0 !important; - padding: 0 !important; - } - .list:first-child { - margin-left: 0px; - } - .list.ui-sortable-helper { - flex: 0 0 60px; - height: 60px; - width: 100vw; - max-width: 100vw; - border-left: 0px !important; - border-bottom: 1px solid #ccc; - display: block !important; - } - .list.ui-sortable-helper .list-header.ui-sortable-handle { - cursor: grabbing; - } - .list.placeholder { - flex: 0 0 60px; - height: 60px; - width: 100vw; - max-width: 100vw; - border-left: 0px !important; - border-bottom: 1px solid #ccc; - display: block !important; - } - .list-body { - padding: 15px 19px; - width: 100vw; - max-width: 100vw; - min-width: 100vw; - } - .list-header { - /*Updated padding values for mobile devices, this should fix text grouping issue*/ - padding: 20px 0px 20px 0px; - border-bottom: 0px solid #e4e4e4; - min-height: 30px; - margin-top: 10px; - align-items: center; - width: 100vw; - max-width: 100vw; - min-width: 100vw; - } - .list-header .list-header-left-icon { - padding: 7px; - padding-right: 27px; - margin-top: 1px; - top: -7px; - left: -7px; - } - .list-header .list-header-menu-icon { - padding: 14px; - font-size: 40px; - text-align: center; - /* iOS Safari fallback positioning */ - position: absolute; - right: 60px; - top: 50%; - transform: translateY(-50%); - } - .list-header .list-header-handle { - padding: 14px; - font-size: 48px; - text-align: center; - /* iOS Safari fallback positioning */ - position: absolute; - right: 10px; - top: 50%; - transform: translateY(-50%); - } - .list-header { - display: grid; - grid-template-columns: 30px 1fr auto auto; - gap: 10px; - } - .list-header .list-header-left-icon { - display: grid; - grid-row: 1/3; - grid-column: 1; - } - .list-header .list-header-name { - grid-row: 1; - grid-column: 2; - align-self: end; - font-size: 20px; - font-weight: bold; - line-height: 1.2; - padding-bottom: 2px; - } - .list-header .cardCount { - grid-row: 2; - grid-column: 2; - align-self: start; - font-size: 16px; - line-height: 1.2; - } - .list-header .list-header-menu { - grid-row: 1/3; - grid-column: 3; - } - .list-header .list-header-menu-icon { - grid-row: 1/3; - grid-column: 3; - } - .list-header .list-header-handle { - grid-row: 1/3; - grid-column: 4; - } - .list-header .inlined-form { - grid-row: 1/3; - grid-column: 1/4; - } - .list-header .edit-controls { - align-items: initial; - } +.js-select-cards { + max-width: 30ch; + text-overflow: ellipsis; } /* iPhone 12 Mini specific - fix icon positioning in stacked lists view */ @@ -1024,7 +491,7 @@ form.inlined-form .list-composer { grid-row: 1/3 !important; grid-column: 3 !important; padding: 14px !important; - font-size: 40px !important; + text-align: center !important; } @@ -1038,7 +505,7 @@ form.inlined-form .list-composer { grid-row: 1/3 !important; grid-column: 4 !important; padding: 14px !important; - font-size: 48px !important; + text-align: center !important; } @@ -1046,7 +513,7 @@ form.inlined-form .list-composer { grid-row: 1 !important; grid-column: 2 !important; align-self: end !important; - font-size: 20px !important; + font-weight: bold !important; line-height: 1.2 !important; padding-bottom: 2px !important; @@ -1059,14 +526,8 @@ form.inlined-form .list-composer { text-align: left !important; padding-left: 0 !important; margin-left: 0 !important; - font-size: 16px !important; - line-height: 1.2 !important; - } - .list.mobile-view .list-header .list-header-left-icon { - display: grid !important; - grid-row: 1/3 !important; - grid-column: 1 !important; + line-height: 1.2 !important; } } @@ -1089,7 +550,7 @@ form.inlined-form .list-composer { grid-row: 1/3 !important; grid-column: 3 !important; padding: 14px !important; - font-size: 40px !important; + text-align: center !important; } @@ -1103,7 +564,7 @@ form.inlined-form .list-composer { grid-row: 1/3 !important; grid-column: 4 !important; padding: 14px !important; - font-size: 48px !important; + text-align: center !important; } @@ -1111,7 +572,7 @@ form.inlined-form .list-composer { grid-row: 1 !important; grid-column: 2 !important; align-self: end !important; - font-size: 20px !important; + font-weight: bold !important; line-height: 1.2 !important; padding-bottom: 2px !important; @@ -1121,7 +582,7 @@ form.inlined-form .list-composer { grid-row: 2 !important; grid-column: 2 !important; align-self: start !important; - font-size: 16px !important; + line-height: 1.2 !important; } @@ -1131,28 +592,42 @@ form.inlined-form .list-composer { grid-column: 1 !important; } -/* Allow long list titles to expand on desktop (non-mobile, non-collapsed) */ -.list:not(.mobile-view):not(.list-collapsed) .list-header { - overflow: visible !important; -} - .list:not(.mobile-view):not(.list-collapsed) .list-header .list-header-name { /* Permit wrapping and full visibility */ - white-space: normal !important; - overflow: visible !important; - text-overflow: clip !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; + white-space: nowrap; + overflow: scroll; + overflow-wrap: break-word !important; + text-overflow: clip; } .link-board-wrapper { display: flex; - align-items: baseline; + flex-direction: column; + padding: 0.3lh 1ch; + >form { + display: flex; + flex-direction: column; + align-items: stretch; + flex: 1; + } } -.link-board-wrapper .js-link-board { - margin-left: 15px; + +.link-board-dropdown { + display: grid; + grid-template-columns: 10ch auto; + gap: 0 1ch; + margin: 0.3lh 0; + grid-auto-columns: auto; + grid-auto-flow: column; + + + .edit-controls { + flex: 1; + justify-content: stretch; + >input { + flex: 1; + } + } } .search-card-results { max-height: 250px; @@ -1260,24 +735,4 @@ form.inlined-form .list-composer { 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; -} +} \ No newline at end of file diff --git a/client/components/lists/list.jade b/client/components/lists/list.jade index c28dd1a9c..67ab132d1 100644 --- a/client/components/lists/list.jade +++ b/client/components/lists/list.jade @@ -1,12 +1,13 @@ template(name='list') .list.js-list(id="js-list-{{_id}}" - style="{{#unless collapsed}}min-width:{{listWidth}}px;max-width:{{listConstraint}}px;{{/unless}}" class="{{#if collapsed}}list-collapsed{{/if}} {{#if autoWidth}}list-auto-width{{/if}} {{#if isMiniScreen}}mobile-view{{/if}}") +listHeader unless collapsed +listBody - .list-resize-handle.js-list-resize-handle.nodragscroll + .list-resize-handle.js-list-resize-handle.nodragscroll template(name='miniList') a.mini-list.js-select-list.js-list(id="js-list-{{_id}}" class="{{#if isMiniScreen}}mobile-view{{/if}}") +listHeader + if isCurrentList + +listBody \ No newline at end of file diff --git a/client/components/lists/list.js b/client/components/lists/list.js index 0c084a45c..667050def 100644 --- a/client/components/lists/list.js +++ b/client/components/lists/list.js @@ -4,6 +4,8 @@ require('/client/lib/jquery-ui.js') const { calculateIndex } = Utils; +export const itemsSelector = '.js-minicard:not(.placeholder, .js-card-composer)'; + BlazeComponent.extendComponent({ // Proxy openForm(options) { @@ -12,6 +14,7 @@ BlazeComponent.extendComponent({ onCreated() { this.newCardFormIsVisible = new ReactiveVar(true); + this.collapse = new ReactiveVar(Utils.getListCollapseState(this.data())); }, // The jquery UI sortable library is the best solution I've found so far. I @@ -22,183 +25,37 @@ BlazeComponent.extendComponent({ // callback, we basically solve all issues related to reactive updates. A // comment below provides further details. onRendered() { - const boardComponent = this.parentComponent().parentComponent(); - - // Initialize list resize functionality immediately + this.list = this.firstNode(); + this.resizeHandle = this.find('.js-list-resize-handle'); this.initializeListResize(); - const itemsSelector = '.js-minicard:not(.placeholder, .js-card-composer)'; - const $cards = this.$('.js-minicards'); - - $cards.sortable({ - connectWith: '.js-minicards:not(.js-list-full)', - tolerance: 'pointer', - appendTo: '.board-canvas', - helper(evt, item) { - const helper = item.clone(); - if (MultiSelection.isActive()) { - const andNOthers = $cards.find('.js-minicard.is-checked').length - 1; - if (andNOthers > 0) { - helper.append( - $( - Blaze.toHTML( - HTML.DIV( - { class: 'and-n-other' }, - TAPi18n.__('and-n-other-card', { count: andNOthers }), - ), - ), - ), - ); - } - } - return helper; - }, - distance: 7, - items: itemsSelector, - placeholder: 'minicard-wrapper placeholder', - scrollSpeed: 10, - start(evt, ui) { - ui.helper.css('z-index', 1000); - ui.placeholder.height(ui.helper.height()); - EscapeActions.executeUpTo('popup-close'); - boardComponent.setIsDragging(true); - }, - stop(evt, ui) { - // To attribute the new index number, we need to get the DOM element - // of the previous and the following card -- if any. - const prevCardDom = ui.item.prev('.js-minicard').get(0); - const nextCardDom = ui.item.next('.js-minicard').get(0); - const nCards = MultiSelection.isActive() ? MultiSelection.count() : 1; - const sortIndex = calculateIndex(prevCardDom, nextCardDom, nCards); - const listId = Blaze.getData(ui.item.parents('.list').get(0))._id; - const currentBoard = Utils.getCurrentBoard(); - const defaultSwimlaneId = currentBoard.getDefaultSwimline()._id; - let targetSwimlaneId = null; - - // only set a new swimelane ID if the swimlanes view is active - if ( - Utils.boardView() === 'board-view-swimlanes' || - currentBoard.isTemplatesBoard() - ) - targetSwimlaneId = Blaze.getData(ui.item.parents('.swimlane').get(0)) - ._id; - - // Normally the jquery-ui sortable library moves the dragged DOM element - // to its new position, which disrupts Blaze reactive updates mechanism - // (especially when we move the last card of a list, or when multiple - // users move some cards at the same time). To prevent these UX glitches - // we ask sortable to gracefully cancel the move, and to put back the - // DOM in its initial state. The card move is then handled reactively by - // Blaze with the below query. - $cards.sortable('cancel'); - - if (MultiSelection.isActive()) { - ReactiveCache.getCards(MultiSelection.getMongoSelector(), { sort: ['sort'] }).forEach((card, i) => { - const newSwimlaneId = targetSwimlaneId - ? targetSwimlaneId - : card.swimlaneId || defaultSwimlaneId; - card.move( - currentBoard._id, - newSwimlaneId, - listId, - sortIndex.base + i * sortIndex.increment, - ); - }); - } else { - const cardDomElement = ui.item.get(0); - const card = Blaze.getData(cardDomElement); - const newSwimlaneId = targetSwimlaneId - ? targetSwimlaneId - : card.swimlaneId || defaultSwimlaneId; - card.move(currentBoard._id, newSwimlaneId, listId, sortIndex.base); - } - boardComponent.setIsDragging(false); - }, - sort(event, ui) { - const $boardCanvas = $('.board-canvas'); - const boardCanvas = $boardCanvas[0]; - - if (event.pageX < 10) { // scroll to the left - boardCanvas.scrollLeft -= 15; - ui.helper[0].offsetLeft -= 15; - } - if ( - event.pageX > boardCanvas.offsetWidth - 10 && - boardCanvas.scrollLeft < $boardCanvas.data('scrollLeftMax') // don't scroll more than possible - ) { // scroll to the right - boardCanvas.scrollLeft += 15; - } - if ( - event.pageY > boardCanvas.offsetHeight - 10 && - event.pageY + boardCanvas.scrollTop < $boardCanvas.data('scrollTopMax') // don't scroll more than possible - ) { // scroll to the bottom - boardCanvas.scrollTop += 15; - } - if (event.pageY < 10) { // scroll to the top - boardCanvas.scrollTop -= 15; - } - }, - activate(event, ui) { - const $boardCanvas = $('.board-canvas'); - const boardCanvas = $boardCanvas[0]; - // scrollTopMax and scrollLeftMax only available at Firefox (https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollTopMax) - // https://www.it-swarm.com.de/de/javascript/so-erhalten-sie-den-maximalen-dokument-scrolltop-wert/1069126844/ - $boardCanvas.data('scrollTopMax', boardCanvas.scrollHeight - boardCanvas.clientTop); - // https://stackoverflow.com/questions/5138373/how-do-i-get-the-max-value-of-scrollleft/5704386#5704386 - $boardCanvas.data('scrollLeftMax', boardCanvas.scrollWidth - boardCanvas.clientWidth); - }, - }); - - this.autorun(() => { - if ($cards.data('uiSortable') || $cards.data('sortable')) { - if (Utils.isTouchScreenOrShowDesktopDragHandles()) { - $cards.sortable('option', 'handle', '.handle'); - } else { - $cards.sortable('option', 'handle', '.minicard'); - } - - $cards.sortable( - 'option', - 'disabled', - // Disable drag-dropping when user is not member - !Utils.canModifyBoard(), - // Not disable drag-dropping while in multi-selection mode - // MultiSelection.isActive() || !Utils.canModifyBoard(), - ); + const ensureCollapseState = (collapsed) => { + if (this.collapse.get() === collapsed) return; + if (this.autoWidth() || collapsed) { + $(this.resizeHandle).hide(); + } else { + $(this.resizeHandle).show(); } - }); + this.collapse.set(collapsed); + this.initializeListResize(); + } - // We want to re-run this function any time a card is added. + // Reactively update collapse appearance and resize handle visibility when auto-width or collapse changes this.autorun(() => { - const currentBoardId = Tracker.nonreactive(() => { - return Session.get('currentBoard'); - }); - Tracker.afterFlush(() => { - $cards.find(itemsSelector).droppable({ - hoverClass: 'draggable-hover-card', - accept: '.js-member,.js-label', - drop(event, ui) { - const cardId = Blaze.getData(this)._id; - const card = ReactiveCache.getCard(cardId); - - if (ui.draggable.hasClass('js-member')) { - const memberId = Blaze.getData(ui.draggable.get(0)).userId; - card.assignMember(memberId); - } else { - const labelId = Blaze.getData(ui.draggable.get(0))._id; - card.addLabel(labelId); - } - }, - }); - }); + ensureCollapseState(Utils.getListCollapseState(this.data())); }); }, + collapsed() { + return this.collapse.get(); + }, + + listWidth() { const user = ReactiveCache.getCurrentUser(); const list = Template.currentData(); if (!list) return 270; // Return default width if list is not available - + if (user) { // For logged-in users, get from user profile return user.getListWidthFromStorage(list.boardId, list._id); @@ -222,8 +79,8 @@ BlazeComponent.extendComponent({ listConstraint() { const user = ReactiveCache.getCurrentUser(); const list = Template.currentData(); - if (!list) return 550; // Return default constraint if list is not available - + if (!list) return 0; + if (user) { // For logged-in users, get from user profile return user.getListConstraintFromStorage(list.boardId, list._id); @@ -240,7 +97,7 @@ BlazeComponent.extendComponent({ } catch (e) { console.warn('Error reading list constraint from localStorage:', e); } - return 550; // Return default constraint if not found + return 0; } }, @@ -256,18 +113,14 @@ BlazeComponent.extendComponent({ initializeListResize() { // Check if we're still in a valid template context - if (!Template.currentData()) { + if (!this.data()) { console.warn('No current template data available for list resize initialization'); return; } - - const list = Template.currentData(); - const $list = this.$('.js-list'); - const $resizeHandle = this.$('.js-list-resize-handle'); - + // Check if elements exist - if (!$list.length || !$resizeHandle.length) { - console.warn('List or resize handle not found, retrying in 100ms'); + if (!this.list || !this.resizeHandle) { + console.info('List or resize handle not found, retrying in 100ms'); Meteor.setTimeout(() => { if (!this.isDestroyed) { this.initializeListResize(); @@ -275,107 +128,129 @@ BlazeComponent.extendComponent({ }, 100); 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 = 270; // Minimum width matching system default - let listConstraint = this.listConstraint(); // Store constraint value for use in event handlers - const component = this; // Store reference to component for use in event handlers + let previousLimit = false; + // seems reasonable; better let user shrink too much that too little + const minWidth = 280; + // stored width + const width = this.listWidth(); + // min-width is initially min-content; a good start + let maxWidth = this.listConstraint() || parseInt(this.list.style.getProperty('--list-min-width', `${(minWidth)}px`), 10) || width + 100; + if (!width || width > maxWidth) { + width = (maxWidth + minWidth) / 2; + } + this.list.style.setProperty('--list-min-width', `${Math.round(minWidth)}px`); + // actual size before fitting (usually max-content equivalent) + this.list.style.setProperty('--list-max-width', `${Math.round(maxWidth)}px`); + // avoid jump effect and ensure width stays consistent + this.list.style.setProperty('--list-width', `${Math.round(width)}px`); + + const component = this; + + // wait for click to add other events const startResize = (e) => { - isResizing = true; - startX = e.pageX || e.originalEvent.touches[0].pageX; - startWidth = $list.outerWidth(); - - - // Add visual feedback - $list.addClass('list-resizing'); - $('body').addClass('list-resizing-active'); - - - // Prevent text selection during resize - $('body').css('user-select', 'none'); - + // gain access to modern attributes e.g. isPrimary + e = e.originalEvent; + + if (isResizing || Utils.shouldIgnorePointer(e)) { + return; + } + e.preventDefault(); e.stopPropagation(); + + $(document).on('pointermove', doResize); + // e.g. debugger can cancel event without pointerup being fired + $(document).on('pointercancel', stopResize); + $(document).on('pointerup', stopResize); + + // --list-width can be either a stored size or "auto"; get actual computed size + component.currentWidth = component.list.offsetWidth; + component.list.classList.add('list-resizing'); + document.body.classList.add('list-resizing-active'); + + isResizing = true; }; const doResize = (e) => { - if (!isResizing) { - return; - } - - const currentX = e.pageX || e.originalEvent.touches[0].pageX; - const deltaX = currentX - startX; - const newWidth = Math.max(minWidth, startWidth + deltaX); - - // Apply the new width immediately for real-time feedback - $list[0].style.setProperty('--list-width', `${newWidth}px`); - $list[0].style.setProperty('width', `${newWidth}px`); - $list[0].style.setProperty('min-width', `${newWidth}px`); - $list[0].style.setProperty('max-width', `${newWidth}px`); - $list[0].style.setProperty('flex', 'none'); - $list[0].style.setProperty('flex-basis', 'auto'); - $list[0].style.setProperty('flex-grow', '0'); - $list[0].style.setProperty('flex-shrink', '0'); - - + e = e.originalEvent; + e.preventDefault(); e.stopPropagation(); + + if (!isResizing || !e.isPrimary) { + return; + } + + if (!previousLimit && component.collapsed()) { + previousLimit = true; + component.list.classList.add('cannot-resize'); + return; + } + + // relative to document, always >0 because pointer sticks to the right of list + const deltaX = e.clientX - component.list.getBoundingClientRect().right; + const candidateWidth = component.currentWidth + deltaX; + component.currentWidth = Math.max(minWidth, Math.min(maxWidth, candidateWidth)); + const reachingMax = (maxWidth - component.currentWidth - 20) <= 0 + const reachingMin = (component.currentWidth - 20 - minWidth) <= 0 + // visual indicator to avoid trying too hard; try not to apply each tick + if (!previousLimit && (reachingMax && deltaX > 0 || reachingMin && deltaX < 0)) { + component.list.classList.add('cannot-resize'); + previousLimit = true; + } else if (previousLimit && !reachingMax && !reachingMin) { + component.list.classList.remove('cannot-resize'); + previousLimit = false; + } + // Apply the new width immediately for real-time feedback + component.list.style.setProperty('--list-width', `${component.currentWidth}px`); }; const stopResize = (e) => { - if (!isResizing) return; - + e = e.originalEvent; + + e.preventDefault(); + e.stopPropagation(); + + if (!isResizing || !e.isPrimary) { + return; + } + + // hopefully be gentler on cpu + $(document).off('pointermove', doResize); + $(document).off('pointercancel', stopResize); + $(document).off('pointerup', stopResize); isResizing = false; - - // Calculate final width - const currentX = e.pageX || e.originalEvent.touches[0].pageX; - const deltaX = currentX - startX; - const finalWidth = Math.max(minWidth, startWidth + deltaX); - - // Ensure the final width is applied - $list[0].style.setProperty('--list-width', `${finalWidth}px`); - $list[0].style.setProperty('width', `${finalWidth}px`); - $list[0].style.setProperty('min-width', `${finalWidth}px`); - $list[0].style.setProperty('max-width', `${finalWidth}px`); - $list[0].style.setProperty('flex', 'none'); - $list[0].style.setProperty('flex-basis', 'auto'); - $list[0].style.setProperty('flex-grow', '0'); - $list[0].style.setProperty('flex-shrink', '0'); - - // Remove visual feedback but keep the width - $list.removeClass('list-resizing'); - $('body').removeClass('list-resizing-active'); - $('body').css('user-select', ''); - - // Keep the CSS custom property for persistent width - // The CSS custom property will remain on the element to maintain the width - + + if (previousLimit) { + component.list.classList.remove('cannot-resize'); + } + + const finalWidth = parseInt(component.list.style.getPropertyValue('--list-width'), 10); + + // Remove visual feedback but keep the height + component.list.classList.remove('list-resizing'); + document.body.classList.remove('list-resizing-active'); + + if (component.collapse.get()) { + return; + } + // Save the new width using the existing system + const list = component.data(); const boardId = list.boardId; const listId = list._id; - + // Use the new storage method that handles both logged-in and non-logged-in users if (process.env.DEBUG === 'true') { } - + const currentUser = ReactiveCache.getCurrentUser(); if (currentUser) { // For logged-in users, use server method - Meteor.call('applyListWidthToStorage', boardId, listId, finalWidth, listConstraint, (error, result) => { + Meteor.call('applyListWidthToStorage', boardId, listId, finalWidth, maxWidth, (error, result) => { if (error) { console.error('Error saving list width:', error); } else { @@ -389,61 +264,37 @@ BlazeComponent.extendComponent({ // Save list width const storedWidths = localStorage.getItem('wekan-list-widths'); let widths = storedWidths ? JSON.parse(storedWidths) : {}; - + if (!widths[boardId]) { widths[boardId] = {}; } widths[boardId][listId] = finalWidth; - + localStorage.setItem('wekan-list-widths', JSON.stringify(widths)); - + // Save list constraint const storedConstraints = localStorage.getItem('wekan-list-constraints'); let constraints = storedConstraints ? JSON.parse(storedConstraints) : {}; - + if (!constraints[boardId]) { constraints[boardId] = {}; } constraints[boardId][listId] = listConstraint; - + localStorage.setItem('wekan-list-constraints', JSON.stringify(constraints)); - + if (process.env.DEBUG === 'true') { } } catch (e) { console.warn('Error saving list width/constraint to localStorage:', e); } } - + e.preventDefault(); }; - // Mouse events - $resizeHandle.on('mousedown', startResize); - $(document).on('mousemove', doResize); - $(document).on('mouseup', stopResize); - - // Touch events for mobile - $resizeHandle.on('touchstart', startResize, { passive: false }); - $(document).on('touchmove', doResize, { passive: false }); - $(document).on('touchend', stopResize, { passive: false }); - - - // Prevent dragscroll interference - $resizeHandle.on('mousedown', (e) => { - e.stopPropagation(); - }); - - - // Reactively update resize handle visibility when auto-width or collapse changes - component.autorun(() => { - const collapsed = Utils.getListCollapseState(list); - if (component.autoWidth() || collapsed) { - $resizeHandle.hide(); - } else { - $resizeHandle.show(); - } - }); + // handle both pointer and touch + $(this.resizeHandle).on("pointerdown", startResize); // Clean up on component destruction component.onDestroyed(() => { @@ -455,12 +306,6 @@ BlazeComponent.extendComponent({ }, }).register('list'); -Template.list.helpers({ - collapsed() { - return Utils.getListCollapseState(this); - }, -}); - Template.miniList.events({ 'click .js-select-list'() { const listId = this._id; @@ -468,15 +313,10 @@ Template.miniList.events({ }, }); -// 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); - } - }); +Template.miniList.helpers({ + isCurrentList() { + const currentList = Utils.getCurrentList(); + const list = Template.currentData(); + return currentList && currentList._id == list._id; + }, +}); \ No newline at end of file diff --git a/client/components/lists/listBody.jade b/client/components/lists/listBody.jade index 3d23a49ce..42914a82c 100644 --- a/client/components/lists/listBody.jade +++ b/client/components/lists/listBody.jade @@ -4,17 +4,18 @@ template(name="listBody") .minicards.clearfix.js-minicards(class="{{#if reachedWipLimit}}js-list-full{{/if}}") +inlinedForm(autoclose=false position="top") +addCardForm(listId=_id position="top") - ul.sidebar-list - each customFieldsSum - li - +viewer - = name - if $eq customFieldsSum.type "number" + if customFieldSum.lenght + ul.sidebar-list + each customFieldsSum + li +viewer - = value - if $eq customFieldsSum.type "currency" - +viewer - = formattedCurrencyCustomFieldValue(value) + = name + if $eq customFieldsSum.type "number" + +viewer + = value + if $eq customFieldsSum.type "currency" + +viewer + = formattedCurrencyCustomFieldValue(value) each (cardsWithLimit (idOrNull ../../_id)) a.minicard-wrapper.js-minicard(href=originRelativeUrl class="{{#if cardIsSelected}}is-selected{{/if}}" @@ -25,15 +26,15 @@ 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'}}") - i.fa.fa-plus - | {{_ 'add-card'}} - +inlinedForm(autoclose=false position="bottom") - +addCardForm(listId=_id position="bottom") + a.minicard-wrapper.minicard-add-form + +inlinedForm(autoclose=false position="bottom") + +addCardForm(listId=_id position="bottom") + else + .add-card-wrapper + a.open-minicard-composer.js-card-composer.js-open-inlined-form(title="{{_ 'add-card-to-bottom-of-list'}}") + i.fa.fa-plus template(name="spinnerList") .sk-spinner.sk-spinner-list( @@ -43,33 +44,30 @@ template(name="spinnerList") template(name="addCardForm") .minicard.minicard-composer.js-composer - if getLabels - .minicard-labels - each getLabels - .minicard-label(class="card-label-{{color}}" title="{{name}}") textarea.minicard-composer-textarea.js-card-title(autofocus dir="auto") - if members.get - .minicard-members.js-minicard-composer-members - each members.get - +userAvatar(userId=this) + .minicard-bottom + .minicard-composer-icons + if getLabels + each getLabels + .minicard-label(class="card-label-{{color}}" title="{{name}}") + if members.get + each members.get + +userAvatar(userId=this) + .add-controls.clearfix + a.js-close-inlined-form + i.fa.fa-times-thin - .add-controls.clearfix - button.primary.confirm(type="submit") {{_ 'add'}} - a.js-close-inlined-form - i.fa.fa-times-thin - .add-controls.clearfix + button.primary.confirm(type="submit") {{_ 'add'}} + + .links-controls.clearfix unless currentBoard.isTemplatesBoard unless currentBoard.isTemplateBoard span.quiet | {{_ 'or'}} a.js-link {{_ 'link'}} span.quiet - |   - | / a.js-search {{_ 'search'}} span.quiet - |   - | / a.js-card-template {{_ 'template'}} template(name="autocompleteLabelLine") @@ -77,70 +75,73 @@ template(name="autocompleteLabelLine") span(class="{{#if hasNoName}}quiet{{/if}}")= labelName template(name="linkCardPopup") - label {{_ 'boards'}}: .link-board-wrapper - select.js-select-boards - option(value="") - each boards - option(value="{{_id}}") {{isTitleDefault title}} - input.primary.confirm.js-link-board(type="button" value="{{_ 'link'}}") - - label {{_ 'swimlanes'}}: - select.js-select-swimlanes - option(value="") {{_ 'custom-field-dropdown-none'}} - each swimlanes - option(value="{{_id}}") {{isTitleDefault title}} - - label {{_ 'lists'}}: - select.js-select-lists - option(value="") {{_ 'custom-field-dropdown-none'}} - each lists - option(value="{{_id}}") {{isTitleDefault title}} - - label {{_ 'cards'}}: - select.js-select-cards - option(value="") {{_ 'custom-field-dropdown-none'}} - each cards - option(value="{{getRealId}}") {{getTitle}} - - .edit-controls.clearfix - input.primary.confirm.js-done(type="button" value="{{_ 'link'}}") - -template(name="searchElementPopup") - form - label - | {{_ 'title'}} - input.js-element-title(type="text" placeholder="{{_ 'title'}}" autofocus required dir="auto") - unless isTemplateSearch - label {{_ 'boards'}}: - .link-board-wrapper + .link-board-dropdown + label {{_ 'boards'}}: select.js-select-boards option(value="") each boards - option(value="{{_id}}") {{title}} - form.js-search-term-form - label - | {{_ 'template'}} - input(type="text" name="searchTerm" placeholder="{{_ 'search-example'}}" autofocus dir="auto") - .list-body.search-card-results - .minicards.clearfix.js-minicards - if isBoardTemplateSearch - each results - a.minicard-wrapper.js-minicard - +miniboard(this) - if isListTemplateSearch - each results - a.minicard-wrapper.js-minicard - +minilist(this) - if isSwimlaneTemplateSearch - each results - a.minicard-wrapper.js-minicard - +miniswimlane(this) - if isCardTemplateSearch - each results - a.minicard-wrapper.js-minicard - +minicard(this) - unless isTemplateSearch - each results - a.minicard-wrapper.js-minicard - +minicard(this) + option(value="{{_id}}") {{isTitleDefault title}} + input.primary.confirm.js-link-board(type="button" value="{{_ 'link'}}") + + .link-board-dropdown + label {{_ 'swimlanes'}}: + select.js-select-swimlanes + option(value="") {{_ 'custom-field-dropdown-none'}} + each swimlanes + option(value="{{_id}}") {{isTitleDefault title}} + .link-board-dropdown + label {{_ 'lists'}}: + select.js-select-lists + option(value="") {{_ 'custom-field-dropdown-none'}} + each lists + option(value="{{_id}}") {{isTitleDefault title}} + + .link-board-dropdown + label {{_ 'cards'}}: + select.js-select-cards + option(value="") {{_ 'custom-field-dropdown-none'}} + each cards + option(value="{{getRealId}}") {{getTitle}} + + .edit-controls.clearfix + input.primary.confirm.js-done(type="button" value="{{_ 'link'}}") + +template(name="searchElementPopup") + .link-board-wrapper + form + label + | {{_ 'title'}} + input.js-element-title(type="text" placeholder="{{_ 'title'}}" autofocus required dir="auto") + unless isTemplateSearch + label {{_ 'boards'}}: + select.js-select-boards + option(value="") + each (boards) + option(value="{{_id}}") {{title}} + form.js-search-term-form + label + | {{_ 'template'}} + input(type="text" name="searchTerm" placeholder="{{_ 'search-example'}}" autofocus dir="auto") + .list-body.search-card-results + .minicards.clearfix.js-minicards + if isBoardTemplateSearch + each (results) + a.minicard-wrapper.js-minicard + +miniboard(this) + if isListTemplateSearch + each (results) + a.minicard-wrapper.js-minicard + +minilist(this) + if isSwimlaneTemplateSearch + each (results) + a.minicard-wrapper.js-minicard + +miniswimlane(this) + if isCardTemplateSearch + each (results) + a.minicard-wrapper.js-minicard + +minicard(this) + unless isTemplateSearch + each (results) + a.minicard-wrapper.js-minicard + +minicard(this) diff --git a/client/components/lists/listBody.js b/client/components/lists/listBody.js index 3e2612424..12ebc8edb 100644 --- a/client/components/lists/listBody.js +++ b/client/components/lists/listBody.js @@ -3,16 +3,168 @@ import { TAPi18n } from '/imports/i18n'; import { FlowRouter } from 'meteor/ostrio:flow-router-extra'; import { Spinner } from '/client/lib/spinner'; import getSlug from 'limax'; +import { itemsSelector } from './list'; const subManager = new SubsManager(); const InfiniteScrollIter = 10; + +function sortableCards(boardComponent, $cards) { + return { + connectWith: '.js-minicards:not(.js-list-full)', + tolerance: 'pointer', + appendTo: '.board-canvas', + helper(evt, item) { + const helper = item.clone(); + const cardHeight = item.height(); + const cardWidth = item.width(); + helper[0].setAttribute('style', `height: ${cardHeight}px !important; width: ${cardWidth}px !important;`); + + if (MultiSelection.isActive()) { + const andNOthers = $cards.find('.js-minicard.is-checked').length - 1; + if (andNOthers > 0) { + helper.append( + $( + Blaze.toHTML( + HTML.DIV( + { class: 'and-n-other' }, + TAPi18n.__('and-n-other-card', { count: andNOthers }), + ), + ), + ), + ); + } + } + return helper; + }, + distance: 7, + items: itemsSelector, + placeholder: 'minicard-wrapper placeholder', + /* cursor must be tied to smaller objects, position approximately from the button + (can be computed if visually confusing) */ + cursorAt: { right: 20, top: 30 }, + start(evt, ui) { + const cardHeight = ui.helper.height(); + ui.placeholder[0].setAttribute('style', `height: ${cardHeight}px !important;`); + EscapeActions.executeUpTo('popup-close'); + boardComponent.setIsDragging(true); + }, + stop(evt, ui) { + // To attribute the new index number, we need to get the DOM element + // of the previous and the following card -- if any. + const prevCardDom = ui.item.prev('.js-minicard').get(0); + const nextCardDom = ui.item.next('.js-minicard').get(0); + const nCards = MultiSelection.isActive() ? MultiSelection.count() : 1; + const sortIndex = Utils.calculateIndex(prevCardDom, nextCardDom, nCards); + const listId = Blaze.getData(ui.item.parents('.list-body').get(0))._id; + const currentBoard = Utils.getCurrentBoard(); + const defaultSwimlaneId = currentBoard.getDefaultSwimline()._id; + let targetSwimlaneId = null; + + // only set a new swimelane ID if the swimlanes view is active + if ( + Utils.boardView() === 'board-view-swimlanes' || + currentBoard.isTemplatesBoard() + ) + targetSwimlaneId = Blaze.getData(ui.item.parents('.swimlane').get(0)) + ._id; + + // Normally the jquery-ui sortable library moves the dragged DOM element + // to its new position, which disrupts Blaze reactive updates mechanism + // (especially when we move the last card of a list, or when multiple + // users move some cards at the same time). To prevent these UX glitches + // we ask sortable to gracefully cancel the move, and to put back the + // DOM in its initial state. The card move is then handled reactively by + // Blaze with the below query. + $cards.sortable('cancel'); + + if (MultiSelection.isActive()) { + ReactiveCache.getCards(MultiSelection.getMongoSelector(), { sort: ['sort'] }).forEach((card, i) => { + const newSwimlaneId = targetSwimlaneId + ? targetSwimlaneId + : card.swimlaneId || defaultSwimlaneId; + card.move( + currentBoard._id, + newSwimlaneId, + listId, + sortIndex.base + i * sortIndex.increment, + ); + }); + } else { + const cardDomElement = ui.item.get(0); + const card = Blaze.getData(cardDomElement); + const newSwimlaneId = targetSwimlaneId + ? targetSwimlaneId + : card.swimlaneId || defaultSwimlaneId; + card.move(currentBoard._id, newSwimlaneId, listId, sortIndex.base); + } + boardComponent.setIsDragging(false); + }, + sort(event, ui) { + Utils.scrollIfNeeded(event); + }, + }; +}; + BlazeComponent.extendComponent({ onCreated() { // for infinite scrolling this.cardlimit = new ReactiveVar(InfiniteScrollIter); }, + onRendered() { + // Prefer handling drag/sort in listBody rather than list as + // it is shared between mobile and desktop view + const boardComponent = BlazeComponent.getComponentForElement(document.getElementsByClassName('board-canvas')[0]); + const $cards = this.$('.js-minicards'); + $cards.sortable(sortableCards(boardComponent, $cards)); + + this.autorun(() => { + if ($cards.data('uiSortable') || $cards.data('sortable')) { + // Use handle button on mobile, classic move otherwise + if (Utils.isMiniScreen()) { + $cards.sortable('option', 'handle', '.handle'); + } else { + $cards.sortable('option', 'handle', '.minicard'); + } + + $cards.sortable( + 'option', + 'disabled', + // Disable drag-dropping when user is not member + !Utils.canModifyBoard(), + // Not disable drag-dropping while in multi-selection mode + // MultiSelection.isActive() || !Utils.canModifyBoard(), + ); + } + }); + + // We want to re-run this function any time a card is added. + this.autorun(() => { + const currentBoardId = Tracker.nonreactive(() => { + return Session.get('currentBoard'); + }); + Tracker.afterFlush(() => { + $cards.find(itemsSelector).droppable({ + hoverClass: 'draggable-hover-card', + accept: '.js-member,.js-label', + drop(event, ui) { + const cardId = Blaze.getData(this)._id; + const card = ReactiveCache.getCard(cardId); + + if (ui.draggable.hasClass('js-member')) { + const memberId = Blaze.getData(ui.draggable.get(0)).userId; + card.assignMember(memberId); + } else { + const labelId = Blaze.getData(ui.draggable.get(0))._id; + card.addLabel(labelId); + } + }, + }); + }); + }); + }, + mixins() { return []; }, @@ -82,9 +234,10 @@ BlazeComponent.extendComponent({ evt.preventDefault(); const firstCardDom = this.find('.js-minicard:first'); const lastCardDom = this.find('.js-minicard:last'); - const textarea = $(evt.currentTarget).find('textarea'); + // more robust to start from the form + const textarea = $(evt.currentTarget).closest('.inlined-form').find('textarea'); const position = this.currentData().position; - const title = textarea.val().trim(); + const title = $(textarea).val().trim(); let sortIndex; if (position === 'top') { @@ -168,7 +321,6 @@ BlazeComponent.extendComponent({ // We keep the form opened, empty it, and scroll to it. textarea.val('').focus(); - autosize.update(textarea); if (position === 'bottom') { this.scrollToBottom(); } @@ -194,21 +346,19 @@ BlazeComponent.extendComponent({ clickOnMiniCard(evt) { if (MultiSelection.isActive() || evt.shiftKey) { - evt.stopImmediatePropagation(); - evt.preventDefault(); const methodName = evt.shiftKey ? 'toggleRange' : 'toggle'; MultiSelection[methodName](this.currentData()._id); - // If the card is already selected, we want to de-select it. // XXX We should probably modify the minicard href attribute instead of // overwriting the event in case the card is already selected. - } else if (Utils.isMiniScreen()) { - evt.preventDefault(); - Session.set('popupCardId', this.currentData()._id); - this.cardDetailsPopup(evt); } else if (Session.equals('currentCard', this.currentData()._id)) { - evt.stopImmediatePropagation(); - evt.preventDefault(); + // We need to wait a little because router gets called first, + // we probably need a level of indirection + // #FIXME remove if it works with commits we rebased on, + // which change the route declaration order + Meteor.setTimeout(() => { + Session.set('currentCard', null) + }, 50); Utils.goBoardId(Session.get('currentBoard')); } else { // Allow normal href navigation, but if it's the same card URL, @@ -283,12 +433,6 @@ BlazeComponent.extendComponent({ return user && user.isVerticalScrollbars(); }, - cardDetailsPopup(event) { - if (!Popup.isOpen()) { - Popup.open("cardDetails")(event); - } - }, - events() { return [ { @@ -296,6 +440,8 @@ BlazeComponent.extendComponent({ 'click .js-toggle-multi-selection': this.toggleMultiSelection, 'click .open-minicard-composer': this.scrollToBottom, submit: this.addCard, + // #FIXME remove in final MR if it works + 'click .confirm': this.addCard }, ]; }, @@ -401,6 +547,17 @@ BlazeComponent.extendComponent({ 'click .js-link': Popup.open('linkCard'), 'click .js-search': Popup.open('searchElement'), 'click .js-card-template': Popup.open('searchElement'), + submit: this.addCard, + 'click .minicard-label': (event) => { + const clickedData = BlazeComponent.getComponentForElement(event.target).currentData?.() + this.labels.set(this.labels.get().filter(e => e !== clickedData?._id)); + }, + 'click .member': (event) => { + const clickedData = BlazeComponent.getComponentForElement(event.target).currentData?.() + this.members.set(this.members.get().filter(e => e !== clickedData?.userId)); + e.preventDefault(); + e.stopPropagation(); + }, }, ]; }, @@ -409,8 +566,6 @@ BlazeComponent.extendComponent({ const editor = this; const $textarea = this.$('textarea'); - autosize($textarea); - $textarea.escapeableTextComplete( [ // User mentions @@ -421,7 +576,9 @@ BlazeComponent.extendComponent({ callback( $.map(currentBoard.activeMembers(), member => { const user = ReactiveCache.getUser(member.userId); - return user.username.indexOf(term) === 0 ? user : null; + return user.username.indexOf(term) === 0 && + // don't show already selected members + !editor.members.get().find((e) => e === member.userId) ? user : null; }), ); }, @@ -445,8 +602,12 @@ BlazeComponent.extendComponent({ const currentBoard = Utils.getCurrentBoard(); callback( $.map(currentBoard.labels, label => { - if (label.name == undefined) { - label.name = ""; + if ( + label.name == undefined || + // don't show already selected labels + editor.getLabels().find((e) => e._id === label._id) + ) { + return null; } if ( label.name.indexOf(term) > -1 || @@ -503,10 +664,10 @@ BlazeComponent.extendComponent({ subManager.subscribe('board', this.boardId, false); this.board = ReactiveCache.getBoard(this.boardId); // List where to insert card - this.list = $(Popup._getTopStack().openerElement).closest('.js-list'); + this.list = $(PopupComponent.stack[0].openerElement).closest('.js-list'); this.listId = Blaze.getData(this.list[0])._id; // Swimlane where to insert card - const swimlane = $(Popup._getTopStack().openerElement).closest( + const swimlane = $(PopupComponent.stack[0].openerElement).closest( '.js-swimlane', ); this.swimlaneId = ''; @@ -539,10 +700,10 @@ BlazeComponent.extendComponent({ if (!board) { return []; } - + // Ensure default swimlane exists board.getDefaultSwimline(); - + const swimlanes = ReactiveCache.getSwimlanes( { boardId: this.selectedBoardId.get() @@ -559,7 +720,8 @@ BlazeComponent.extendComponent({ } const lists = ReactiveCache.getLists( { - boardId: this.selectedBoardId.get() + boardId: this.selectedBoardId.get(), + swimlaneId: this.selectedSwimlaneId?.get?.() }, { sort: { sort: 1 }, @@ -703,16 +865,16 @@ BlazeComponent.extendComponent({ }, onCreated() { - this.isCardTemplateSearch = $(Popup._getTopStack().openerElement).hasClass( + this.isCardTemplateSearch = $(PopupComponent.stack[0].openerElement).hasClass( 'js-card-template', ); - this.isListTemplateSearch = $(Popup._getTopStack().openerElement).hasClass( + this.isListTemplateSearch = $(PopupComponent.stack[0].openerElement).hasClass( 'js-list-template', ); this.isSwimlaneTemplateSearch = $( - Popup._getTopStack().openerElement, + PopupComponent.stack[0].openerElement, ).hasClass('js-open-add-swimlane-menu'); - this.isBoardTemplateSearch = $(Popup._getTopStack().openerElement).hasClass( + this.isBoardTemplateSearch = $(PopupComponent.stack[0].openerElement).hasClass( 'js-add-board', ); this.isTemplateSearch = @@ -731,20 +893,16 @@ BlazeComponent.extendComponent({ } else { this.board = Utils.getCurrentBoard(); } - if (!this.board) { - Popup.back(); - return; - } - this.boardId = this.board._id; + this.boardId = this.board?._id; // Subscribe to this board subManager.subscribe('board', this.boardId, false); this.selectedBoardId = new ReactiveVar(this.boardId); - this.list = $(Popup._getTopStack().openerElement).closest('.js-list'); if (!this.isBoardTemplateSearch) { + this.list = $(PopupComponent.stack[0].openerElement).closest('.js-list'); this.swimlaneId = ''; // Swimlane where to insert card - const swimlane = $(Popup._getTopStack().openerElement).parents( + const swimlane = $(PopupComponent.stack[0].openerElement).parents( '.js-swimlane', ); if (Utils.boardView() === 'board-view-swimlanes') @@ -783,11 +941,7 @@ BlazeComponent.extendComponent({ } else if (this.isSwimlaneTemplateSearch) { return board.searchSwimlanes(this.term.get()); } else if (this.isBoardTemplateSearch) { - const boards = board.searchBoards(this.term.get()); - boards.forEach(board => { - subManager.subscribe('board', board.linkedId, false); - }); - return boards; + return board.searchBoards(this.term.get()); } else { return []; } diff --git a/client/components/lists/listHeader.jade b/client/components/lists/listHeader.jade index 2dee5749f..3f8dc5c86 100644 --- a/client/components/lists/listHeader.jade +++ b/client/components/lists/listHeader.jade @@ -9,66 +9,68 @@ template(name="listHeader") if currentList a.list-header-left-icon.js-unselect-list i.fa.fa-caret-left - else - if collapsed - if showCardsCountForList cards.length - br - span.cardCount {{cardsCount}} - if isMiniScreen - 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}) - if showCardsCountForList cards.length - span.cardCount {{cardsCount}} {{cardsCountForListIsOne cards.length}} - if hasNumberFieldsSum - |   - span.list-sum-badge(title="{{_ 'sum-of-number-fields'}}") ∑ {{numberFieldsSum}} - else - a.list-collapse-indicator.js-collapse(title="{{_ 'collapse'}}") - if collapsed + else + //- start by this on mobile to have cohesion with other views + a.list-header-menu-icon.js-select-list i.fa.fa-caret-right - else - i.fa.fa-caret-down - div(class="{{#if collapsed}}list-rotated{{/if}}") + .list-header-name-container 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}}") + 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}) + | ( + span(class="{{#if exceededWipLimit}}highlight{{/if}}") {{cards.length}} + |/#{wipLimit.value}) + if showCardsCountForList cards.length + span.cardCount {{cardsCount}} {{cardsCountForListIsOne cards.length}} + if hasNumberFieldsSum + |   + span.list-sum-badge(title="{{_ 'sum-of-number-fields'}}") ∑ {{numberFieldsSum}} + else + div.list-header-name-container + unless isMiniScreen + 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}}").list-header-wrap + h2.list-header-name( + title="{{ moment modifiedAt 'LLL' }}" + class="{{#if currentUser.isBoardMember}}{{#unless currentUser.isCommentOnly}}{{#unless currentUser.isWorker}}js-open-inlined-form is-editable{{/unless}}{{/unless}}{{/if}}") + +viewer + = title + if wipLimit.enabled + | ( + span(class="{{#if exceededWipLimit}}highlight{{/if}}") {{cards.length}} + |/#{wipLimit.value}) unless collapsed if showCardsCountForList cards.length span.cardCount {{cardsCount}} {{cardsCountForListIsOne cards.length}} if hasNumberFieldsSum |   span.list-sum-badge(title="{{_ 'sum-of-number-fields'}}") ∑ {{numberFieldsSum}} + div.list-header-menu + unless currentUser.isCommentOnly + unless currentUser.isReadOnly + unless currentUser.isReadAssignedOnly + a.js-open-list-menu(title="{{_ 'listActionPopup-title'}}") + i.fa.fa-bars if isMiniScreen if currentList if isWatching - i.list-header-watch-icon i.fa.fa-eye + 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'}}") - i.fa.fa-plus a.js-open-list-menu(title="{{_ 'listActionPopup-title'}}") i.fa.fa-bars else - a.list-header-menu-icon.js-select-list - i.fa.fa-caret-right unless currentUser.isWorker - if isTouchScreenOrShowDesktopDragHandles + if isMiniScreen a.list-header-handle.handle.js-list-handle i.fa.fa-arrows else if currentUser.isBoardMember @@ -77,24 +79,13 @@ template(name="listHeader") unless currentUser.isCommentOnly unless currentUser.isReadOnly unless currentUser.isReadAssignedOnly - if isTouchScreenOrShowDesktopDragHandles + if isMiniScreen 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 - unless currentUser.isReadOnly - 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'}}") - i.fa.fa-arrows - if canSeeAddCard - a.js-add-card.list-header-plus-top(title="{{_ 'add-card-to-top-of-list'}}") - i.fa.fa-plus - a.js-open-list-menu(title="{{_ 'listActionPopup-title'}}") - i.fa.fa-bars + unless isMiniScreen + if collapsed + if showCardsCountForList cards.length + span.cardCount {{cardsCount}} template(name="editListTitleForm") .list-composer @@ -224,14 +215,14 @@ template(name="wipLimitErrorPopup") .wip-limit-invalid p {{_ 'wipLimitErrorPopup-dialog-pt1'}} p {{_ 'wipLimitErrorPopup-dialog-pt2'}} - button.full.js-back-view(type="submit") {{_ 'cancel'}} + button.negate.js-back-view(type="submit") {{_ 'cancel'}} template(name="setListWidthPopup") #js-list-width-edit label {{_ 'set-list-width-value'}} p - input.list-width-value(type="number" value="{{ listWidthValue }}" min="270") - input.list-constraint-value(type="number" value="{{ listConstraintValue }}" min="270") + input.list-width-value(type="number" value="{{ listWidthValue }}" min="100") + input.list-constraint-value(type="number" value="{{ listConstraintValue }}" min="100") input.list-width-apply(type="submit" value="{{_ 'apply'}}") input.list-width-error br @@ -242,8 +233,8 @@ template(name="setListWidthPopup") template(name="listWidthErrorPopup") .list-width-invalid - p {{_ 'list-width-error-message'}} '>=270' - button.full.js-back-view(type="submit") {{_ 'cancel'}} + p {{_ 'list-width-error-message'}} '>=100' + button.negate.js-back-view(type="submit") {{_ 'cancel'}} template(name="setListColorPopup") form.edit-label diff --git a/client/components/lists/listHeader.js b/client/components/lists/listHeader.js index 90e5a0b3f..f3319b1e9 100644 --- a/client/components/lists/listHeader.js +++ b/client/components/lists/listHeader.js @@ -9,6 +9,15 @@ Meteor.startup(() => { }); BlazeComponent.extendComponent({ + onRendered() { + /* #FIXME I have no idea why this exact same + event won't fire when in event maps */ + $(this.find('.js-collapse')).on('click', (e) => { + e.preventDefault(); + this.collapsed(!this.collapsed()); + }); + }, + canSeeAddCard() { const list = Template.currentData(); return ( @@ -34,7 +43,7 @@ BlazeComponent.extendComponent({ } }, collapsed(check = undefined) { - const list = Template.currentData(); + const list = this.data(); const status = Utils.getListCollapseState(list); if (check === undefined) { // just check @@ -110,7 +119,11 @@ BlazeComponent.extendComponent({ return TAPi18n.__('cards-count'); } }, - + currentList() { + const currentList = Utils.getCurrentList(); + const list = Template.currentData(); + return currentList && currentList._id == list._id; + }, events() { return [ { @@ -118,10 +131,6 @@ BlazeComponent.extendComponent({ event.preventDefault(); this.starred(!this.starred()); }, - 'click .js-collapse'(event) { - event.preventDefault(); - 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( @@ -459,10 +468,10 @@ BlazeComponent.extendComponent({ 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; @@ -554,4 +563,3 @@ BlazeComponent.extendComponent({ ]; }, }).register('addListPopup'); - diff --git a/client/components/main/accessibility.css b/client/components/main/accessibility.css index aa6244a58..dfedd0650 100644 --- a/client/components/main/accessibility.css +++ b/client/components/main/accessibility.css @@ -1,6 +1,6 @@ .my-cards-board-wrapper { border-radius: 0 0 0.5vw 0.5vw; - min-width: min(400px, 52vw); + min-width: min(100%, 400px, 52vw); margin-bottom: 2.5vh; margin-right: auto; margin-left: auto; @@ -33,13 +33,6 @@ text-align: center; margin-bottom: 0.9vh; } -.my-cards-list-wrapper { - margin: 1.3vh 1.3vw; - border-radius: 0.7vw; - display: inline-grid; - min-width: min(250px, 32vw); - max-width: min(350px, 45vw); -} .my-cards-card-wrapper { margin-top: 0; margin-bottom: 1.3vh; @@ -81,7 +74,7 @@ } .accessibility-page h2 { - font-size: 24px; + margin-bottom: 20px; color: #4d4d4d; } diff --git a/client/components/main/editor.css b/client/components/main/editor.css index ac832de59..c9604cece 100644 --- a/client/components/main/editor.css +++ b/client/components/main/editor.css @@ -1,19 +1,18 @@ -.new-comment a.fa.fa-brands.fa-markdown, -.inlined-form a.fa.fa-brands.fa-markdown { - float: right; - position: absolute; - top: -10px; - right: 60px; +.new-comment, .inlined-form { + a.fa.fa-brands.fa-markdown, a.fa.fa-copy { + display: flex; + justify-content: end; + } } -.new-comment a.fa.fa-copy, -.inlined-form a.fa.fa-copy { - float: right; - position: relative; - top: -10px; - right: 5px; -} -.js-inlined-form.viewer.btn-sm { - position: absolute; - top: 20px; - right: 6px; +.editor-controls { + display: flex; + justify-content: end; + grid-area: editor-controls; + align-items: center; + align-self: start; + gap: 1ch; } + +.editor { + grid-area: editor; +} \ No newline at end of file diff --git a/client/components/main/editor.jade b/client/components/main/editor.jade index 4d7117ca3..d45ee2fb4 100644 --- a/client/components/main/editor.jade +++ b/client/components/main/editor.jade @@ -1,12 +1,12 @@ template(name="editor") - a.fa.fa-brands.fa-markdown(title="{{_ 'convert-to-markdown'}}") - a.fa.fa-copy(title="{{_ 'copy-text-to-clipboard'}}") - span.copied-tooltip {{_ 'copied'}} + .editor-controls + a.fa.fa-brands.fa-markdown(title="{{_ 'convert-to-markdown'}}") + a.fa.fa-copy(title="{{_ 'copy-text-to-clipboard'}}") + span.copied-tooltip.copied-tooltip-hidden {{_ 'copied'}} textarea.editor( dir="auto" class="{{class}}" id=id - autofocus=autofocus placeholder="{{_ 'comment-placeholder'}}") +Template.contentBlock diff --git a/client/components/main/editor.js b/client/components/main/editor.js index 8b2c03a03..e27f9bc9f 100644 --- a/client/components/main/editor.js +++ b/client/components/main/editor.js @@ -90,7 +90,6 @@ BlazeComponent.extendComponent({ const enableTextarea = function() { const $textarea = this.$(textareaSelector); - autosize($textarea); $textarea.escapeableTextComplete(mentions); }; if (Meteor.settings.public.RICHER_CARD_COMMENT_EDITOR === true || Meteor.settings.public.RICHER_CARD_COMMENT_EDITOR === 'true') { diff --git a/client/components/main/globalSearch.css b/client/components/main/globalSearch.css index c5a09060f..c07497dd2 100644 --- a/client/components/main/globalSearch.css +++ b/client/components/main/globalSearch.css @@ -1,6 +1,6 @@ .global-search-board-wrapper { - border-radius: 8px; - min-width: 400px; + border-radius: 0.8ch; + min-width: min(100%, 400px); border-width: 8px; border-color: #808080; border-style: solid; @@ -67,8 +67,6 @@ color: #8b0000; } .global-search-page { - width: 40%; - min-width: 400px; margin-right: auto; margin-left: auto; line-height: 150%; @@ -91,6 +89,13 @@ font-family: Courier; font-style: italic; } + +.lists-wrapper { + display: flex; + flex-wrap: wrap; + gap: 1ch 0.3lh; + +} code { color: #000; background-color: #d3d3d3; diff --git a/client/components/main/header.css b/client/components/main/header.css index 450a72aeb..cff98a907 100644 --- a/client/components/main/header.css +++ b/client/components/main/header.css @@ -1,21 +1,19 @@ #header { + display: flex; + justify-content: stretch; + align-items: center; color: #fff; transition: background-color 0.4s; background: #2980b9; - z-index: 17; } #header #header-main-bar { - height: 40px; - padding: 7px 10px 0; + padding: 0.3lh 0.5ch; + display: flex; + flex: 1; } #header #header-main-bar h1 { - font-size: 20px; - line-height: 1.7em; - padding: 0 10px; margin: 0; - margin-right: 10px; - float: left; - border-radius: 3px; + line-height: unset; } #header #header-main-bar h1 .board-header-watch-icon { padding-left: 7px; @@ -25,7 +23,6 @@ color: #fff; } #header #header-main-bar h1 .back-btn { - font-size: 0.9em; margin-right: 10px; } #header #header-main-bar .wekan-logo { @@ -38,27 +35,14 @@ #header #header-main-bar .wekan-logo:hover { opacity: 0.9; } -#header #header-main-bar .board-header-btns { - display: block; - margin-top: 3px; - width: auto; -} -#header #header-main-bar .board-header-btns.left { - float: left; -} -#header #header-main-bar .board-header-btns.right { - float: right; -} #header #header-main-bar .board-header-btn { - border-radius: 3px; color: #f2f2f2; - padding: 0; - height: 28px; - font-size: 13px; - float: left; + display: flex; + flex-wrap: wrap; + column-gap: 0.5ch; + justify-content: center; overflow: hidden; - line-height: 28px; - margin: 0 12px; + text-align: center; } #header #header-main-bar .board-header-btn i.fa { float: left; @@ -68,8 +52,8 @@ margin: 0 10px; } #header #header-main-bar .board-header-btn i.fa + span { - display: inline-block; - margin-top: 1px; + display: flex; + align-items: center; margin-right: 10px; } #header #header-main-bar .board-header-btn .board-header-btn-close { @@ -99,55 +83,140 @@ background: #0f3a5f; } #header #header-main-bar .separator { - margin: 2px 4px; - border-left: 1px solid rgba(255,255,255,0.3); - height: 24px; - float: left; + border-left: 0.2ch solid rgba(255,255,255,0.3); + display: flex; + align-self: stretch; + flex: 0; } + +/* those are default values, some overriden from mobile below */ #header-quick-access { color: #fff; transition: background-color 0.4s; background: #2573a7; - height: 28px; - font-size: 12px; - display: flex; - z-index: 1000; - padding: 10px 0px; - align-items: center; - flex-wrap: nowrap; /* Prevent wrapping to keep single row */ - min-height: 28px; - overflow: hidden; /* Prevent content from overflowing */ + padding: clamp(2vh, 0.5lh, 2%) 0.8rlh; + font-size: var(--quick-header-scale); + + /* the grid template is different for mobile */ + display: grid; + grid-template-areas: + "logo left right"; + grid-template-columns: 1fr 10fr auto; + justify-content: space-between; + + gap: 2ch; + + + #header-quick-access-left { + display: flex; + flex: 0; + overflow-x: auto; + align-items: center; + justify-content: start; + gap: 10ch; + } + .header-quick-access-list { + display: flex; + padding: 0 1ch; + gap: 2ch; + /* this makes sure the scrollbar is at the bottom of header, + not right below text */ + align-self: stretch; + align-items: center; + + scrollbar-width: thin; + scrollbar-color: rgba(255, 255, 255, 0.3) transparent; + justify-content: start; + transition: opacity 0.2s; + overflow-x: auto; + overflow-y: hidden; + } + + .logo-container { + grid-area: logo; + display: flex; + /* that is, related to the whole grid, not taking account other column's width */ + align-self: stretch; + /* elegant solution to force the row to force the image + to adopt the height of other columns */ + min-height: 100%; + height: 0; + a, img { + display: flex; + align-self: stretch; + width: auto; + } + } + #header-quick-access-right { + grid-area: right; + display: flex; + justify-content: end; + } + + #header-quick-access-icons { + display: flex; + justify-content: start; + align-items: center; + gap: 1ch; + } + + #header-quick-access-left { + grid-area: left; + display: grid; + text-decoration: none; + color: #fff; + border-radius: 0.4ch; + transition: background-color 0.2s ease; + gap: 2ch; + grid-auto-flow: column; + + } +} + +body.mobile-mode { + #header-quick-access { + row-gap: 0.5lh; + grid-template-areas: + "logo icons" + "board board"; + grid-template-columns: 1fr 1fr; + justify-content: center; + align-items: center; + + #header-quick-access-left { + grid-area: board; + justify-self: center; + } + + #header-quick-access-right { + grid-area: icons; + } + } + + .separator { + display: none !important; + } + + .logo-container { + img { + max-height: max(1lh, 5vmax, 3ch); + } + } +} + +#header-quick-access.mobile-view .header-quick-access-list { + display: none; } #header-quick-access .home-icon { display: flex; - align-items: center; - margin-right: 1rem; + /* prevents wrap */ flex-shrink: 0; } -#header-quick-access .home-icon a { - display: flex; - align-items: center; - text-decoration: none; - color: #fff; - padding: 4px 8px; - border-radius: 4px; - transition: background-color 0.2s ease; -} - #header-quick-access .home-icon a:hover { background-color: rgba(255, 255, 255, 0.1); } -#header-quick-access .home-icon .fa-home { - font-size: 16px; - margin-right: 4px; -} - -#header-quick-access .allBoards { - font-size: 14px; - padding: 4px 15px; -} #header-quick-access a { text-decoration: none; } @@ -179,8 +248,6 @@ transition: opacity 0.2s; overflow: hidden; white-space: nowrap; - padding: 10px; - margin: -10px; flex: 1; /* Take up available space */ min-width: 0; /* Allow shrinking below content size */ display: flex; /* Use flexbox for better control */ @@ -200,15 +267,9 @@ display: inline-block; /* Keep inline-block for proper spacing */ width: auto; color: #d9d9d9; - padding: 12px 0px; - margin: -10px 0px; flex-shrink: 0; /* Prevent items from shrinking */ white-space: nowrap; /* Prevent text wrapping within items */ } -#header-quick-access ul.header-quick-access-list li a { - padding: 12px 10px; - margin: -10px 0px; -} #header-quick-access ul.header-quick-access-list li a .viewer { display: inline; white-space: nowrap; @@ -241,225 +302,20 @@ #header-quick-access #header-new-board-icon { flex-shrink: 0; } -#header-quick-access #header-user-bar { - margin: 2px 0; -} -#header-quick-access #header-user-bar .header-user-bar-avatar { - float: left; - position: relative; - top: -5px; - margin-right: 5px; -} -#header-quick-access #header-user-bar .header-user-bar-avatar .member, -#header-quick-access #header-help { - width: 24px; - height: 24px; - margin: 0; - margin-top: 1px; -} #header-quick-access #header-user-bar .header-user-bar-name, #header-quick-access #header-help { - margin: 4px 8px 0 0; - float: left; -} - -/* Zoom Controls in Header */ -#header-quick-access .zoom-controls { display: flex; align-items: center; - gap: 0.5vw; - background: rgba(255, 255, 255, 0.9); - padding: 0.5vh 1vw; - border-radius: 0.5vw; - box-shadow: 0 0.2vh 0.5vh rgba(0,0,0,0.1); - margin: 0 1vw; - float: left; + gap: 0.2lh; } -#header-quick-access .zoom-controls .board-header-btn { - padding: 0.5vh 0.8vw !important; - border-radius: 0.3vw !important; - background: #fff !important; - border: 1px solid #000 !important; - transition: all 0.2s ease !important; - color: #000 !important; - height: auto !important; - line-height: normal !important; - margin: 0 !important; - float: none !important; - overflow: visible !important; - text-decoration: none !important; - display: flex !important; - align-items: center !important; - gap: 0.3vw !important; +#header { + font-size: var(--header-scale); + padding: 0.2lh 1ch; } -#header-quick-access .zoom-controls .board-header-btn i { - color: #000 !important; - float: none !important; - display: inline !important; - line-height: normal !important; - margin: 0 !important; -} -#header-quick-access .zoom-controls .board-header-btn:hover { - background: #000 !important; - border-color: #000 !important; - color: #fff !important; -} - -#header-quick-access .zoom-controls .board-header-btn:hover i { - color: #fff !important; -} - -#header-quick-access .zoom-controls .zoom-level { - font-weight: bold; - color: #333; - min-width: 3vw; - text-align: center; - font-size: clamp(12px, 2vw, 14px); - cursor: pointer; - padding: 0.3vh 0.5vw; - border-radius: 0.3vw; - transition: all 0.2s ease; - position: relative; - display: flex; - align-items: center; - justify-content: center; -} - -#header-quick-access .zoom-controls .zoom-level:hover { - background: #f0f0f0; - color: #000; -} - -#header-quick-access .zoom-controls .zoom-display { - display: inline-block; -} - - #header-quick-access .zoom-controls .zoom-input { - background: #fff; - color: #000; - border: 1px solid #ccc; - border-radius: 0.3vw; - padding: 0.3vh 0.5vw; - font-weight: bold; - text-align: center; - width: 100%; - min-width: 3vw; - font-size: clamp(12px, 2vw, 14px); - box-sizing: border-box; - -webkit-appearance: none; - appearance: none; - flex: 0 0 auto; - } - - /* Make zoom input wider on all mobile screens */ - @media screen and (max-width: 800px), - screen and (max-device-width: 932px) and (-webkit-min-device-pixel-ratio: 3) { - #header-quick-access .zoom-controls .zoom-input { - min-width: 80px !important; /* Wider on mobile to show 3 digits */ - width: 80px !important; /* Fixed width to show 100 fully */ - font-size: 16px !important; /* Slightly larger text */ - flex: 0 0 80px !important; /* Prevent shrinking in flex */ - } - } - -#header-quick-access .zoom-controls .zoom-input:focus { - outline: 2px solid #005fcc; - outline-offset: 1px; -} - -/* Mobile Mode Toggle in Header */ -#header-quick-access .mobile-mode-toggle { - display: flex; - align-items: center; - margin: 0 1vw; - float: left; -} - -#header-quick-access .mobile-mode-toggle .board-header-btn { - padding: 0.5vh 0.8vw !important; - border-radius: 0.3vw !important; - background: #fff !important; - border: 1px solid #000 !important; - transition: all 0.2s ease !important; - color: #000 !important; - height: auto !important; - line-height: normal !important; - margin: 0 !important; - float: none !important; - overflow: visible !important; - text-decoration: none !important; - display: flex !important; - align-items: center !important; - justify-content: center !important; - gap: 6px !important; - position: relative !important; -} - -#header-quick-access .mobile-mode-toggle .board-header-btn i { - color: #666 !important; - float: none !important; - display: inline !important; - line-height: normal !important; - margin: 0 !important; - transition: all 0.2s ease !important; - font-size: clamp(14px, 2.8vw, 18px) !important; -} - -#header-quick-access .mobile-mode-toggle .board-header-btn i.active { - color: #000 !important; - font-weight: bold !important; - transform: scale(1.1) !important; -} - -#header-quick-access .mobile-mode-toggle .board-header-btn:hover { - background: #000 !important; - border-color: #000 !important; - color: #fff !important; -} - -#header-quick-access .mobile-mode-toggle .board-header-btn:hover i { - color: #ccc !important; -} - -#header-quick-access .mobile-mode-toggle .board-header-btn:hover i.active { - color: #fff !important; -} - -#header-quick-access .mobile-mode-toggle .board-header-btn.mobile-active { - background: #fff !important; - border-color: #000 !important; - color: #000 !important; -} - -#header-quick-access .mobile-mode-toggle .board-header-btn.mobile-active i.mobile-icon { - color: #000 !important; - font-weight: bold !important; - transform: scale(1.1) !important; -} - -#header-quick-access .mobile-mode-toggle .board-header-btn.mobile-active i.desktop-icon { - color: #666 !important; -} - -#header-quick-access .mobile-mode-toggle .board-header-btn.desktop-active { - background: #fff !important; - border-color: #000 !important; - color: #000 !important; -} - -#header-quick-access .mobile-mode-toggle .board-header-btn.desktop-active i.mobile-icon { - color: #666 !important; -} - -#header-quick-access .mobile-mode-toggle .board-header-btn.desktop-active i.desktop-icon { - color: #000 !important; - font-weight: bold !important; - transform: scale(1.1) !important; -} #header-quick-access #header-user-bar .header-user-bar-name i.fa-chevron-down { margin-right: 4px; } @@ -468,697 +324,7 @@ margin: 6px 5px 0; width: 12px; } -@media screen and (max-width: 800px), - screen and (max-device-width: 932px) and (-webkit-min-device-pixel-ratio: 3) { - #header #header-main-bar { - height: 40px; - } - #header #header-main-bar .board-header-btns { - margin-top: 0px; - } - #header #header-main-bar .board-header-btn { - height: 32px; - line-height: 32px; - font-size: 15px; - } - #header #header-main-bar .board-header-btn i.fa { - line-height: 32px; - } - #header #header-main-bar .board-header-btn i.fa + span { - display: none; - } - #header-quick-access { - transition: background-color 0.4s; - width: 100%; - z-index: 30; - flex-wrap: nowrap !important; /* Force single row on mobile */ - overflow: hidden; /* Prevent content overflow */ - } - /* Mobile home icon styling */ - #header-quick-access .home-icon { - margin-right: 0.5rem; - } - - #header-quick-access .home-icon .fa-home { - font-size: 16px; - margin-right: 4px; - } - - #header-quick-access .home-icon a { - padding: 4px 8px; - font-size: 12px; - } - - /* Ensure All Boards text is visible on mobile */ - #header-quick-access .home-icon.allBoards { - display: flex; - align-items: center; - } - - /* Adjust for very small screens */ - @media screen and (max-width: 480px) { - #header-quick-access .home-icon a { - font-size: 11px; - padding: 3px 6px; - } - - #header-quick-access .home-icon .fa-home { - font-size: 14px; - margin-right: 3px; - } - } - - /* Mobile - make all text and icons 2x bigger above #content by default */ - @media screen and (max-width: 800px), - screen and (max-device-width: 800px), - screen and (-webkit-min-device-pixel-ratio: 2) and (max-width: 800px), - screen and (max-width: 800px) and (orientation: portrait), - screen and (max-width: 800px) and (orientation: landscape) { - #header-quick-access { - height: 48px !important; /* Fixed height for mobile */ - min-height: 48px !important; /* Minimum height for mobile */ - flex-wrap: nowrap !important; /* Force single row */ - align-items: center !important; /* Center align items */ - padding: 8px 0px !important; /* Adjust padding for mobile */ - overflow: hidden !important; /* Prevent content overflow */ - } - #header-quick-access { - font-size: 2em !important; /* 2x bigger base font size */ - } - - #header-quick-access * { - font-size: inherit !important; /* Inherit the 2x scaling */ - } - - #header-quick-access .fa, - #header-quick-access .icon { - font-size: 2em !important; /* 2x bigger icons */ - } - - #header-quick-access .home-icon a { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - #header-quick-access .home-icon .fa-home { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - #header-quick-access .zoom-controls { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - #header-quick-access .zoom-controls .zoom-level { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - #header-quick-access .zoom-controls .zoom-input { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - #header-quick-access .mobile-mode-toggle .board-header-btn { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - #header-quick-access .mobile-mode-toggle .board-header-btn i { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - /* Mobile header wrapping and spacing */ - #header-quick-access .home-icon { - flex-shrink: 0 !important; - margin-right: 0.5rem !important; - margin-bottom: 4px !important; - } - - #header-quick-access .zoom-controls { - flex-shrink: 0 !important; - margin: 0 0.5rem !important; - margin-bottom: 4px !important; - } - - #header-quick-access .mobile-mode-toggle { - flex-shrink: 0 !important; - margin: 0 0.5rem !important; - margin-bottom: 4px !important; - } - - #header-quick-access #notifications { - flex-shrink: 0 !important; - margin: 0 0.5rem !important; - margin-bottom: 4px !important; - } - - #header-quick-access #header-user-bar { - flex-shrink: 0 !important; - margin: 0 0.5rem !important; - margin-bottom: 4px !important; - } - - #header-quick-access ul.header-quick-access-list { - flex-shrink: 0 !important; - margin: 0 0.5rem !important; - margin-bottom: 4px !important; - width: auto !important; - } - } - - /* Mobile All Boards page - make logo row elements 2x bigger */ - @media screen and (max-width: 800px), - screen and (max-device-width: 800px), - screen and (-webkit-min-device-pixel-ratio: 2) and (max-width: 800px), - screen and (max-width: 800px) and (orientation: portrait), - screen and (max-width: 800px) and (orientation: landscape) { - .wrapper ~ #header-quick-access, - body:not(.board-view) #header-quick-access { - font-size: 2em !important; /* 2x bigger base font size for logo row */ - } - - /* iPhone 12 Mini specific - 3x bigger for All Boards page */ - @media screen and (device-width: 375px) and (device-height: 812px), /* iPhone 12 Mini exact */ - screen and (max-width: 375px) and (max-height: 812px), /* iPhone 12 Mini viewport */ - screen and (-webkit-min-device-pixel-ratio: 3) and (max-width: 375px) /* iPhone 12 Mini Retina */ { - .wrapper ~ #header-quick-access, - body:not(.board-view) #header-quick-access { - font-size: 3em !important; /* 3x bigger base font size for iPhone 12 Mini All Boards page */ - } - } - - .wrapper ~ #header-quick-access *, - body:not(.board-view) #header-quick-access * { - font-size: inherit !important; /* Inherit the 2x scaling */ - } - - .wrapper ~ #header-quick-access .fa, - .wrapper ~ #header-quick-access .icon, - body:not(.board-view) #header-quick-access .fa, - body:not(.board-view) #header-quick-access .icon { - font-size: 2em !important; /* 2x bigger icons in logo row */ - } - - .wrapper ~ #header-quick-access .home-icon a, - body:not(.board-view) #header-quick-access .home-icon a { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - .wrapper ~ #header-quick-access .home-icon .fa-home, - body:not(.board-view) #header-quick-access .home-icon .fa-home { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - .wrapper ~ #header-quick-access .zoom-controls, - body:not(.board-view) #header-quick-access .zoom-controls { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - .wrapper ~ #header-quick-access .zoom-controls .zoom-level, - body:not(.board-view) #header-quick-access .zoom-controls .zoom-level { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - .wrapper ~ #header-quick-access .zoom-controls .zoom-input, - body:not(.board-view) #header-quick-access .zoom-controls .zoom-input { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - .wrapper ~ #header-quick-access .mobile-mode-toggle .board-header-btn, - body:not(.board-view) #header-quick-access .mobile-mode-toggle .board-header-btn { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - .wrapper ~ #header-quick-access .mobile-mode-toggle .board-header-btn i, - body:not(.board-view) #header-quick-access .mobile-mode-toggle .board-header-btn i { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - .wrapper ~ #header-quick-access #notifications, - body:not(.board-view) #header-quick-access #notifications { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - .wrapper ~ #header-quick-access #notifications .fa, - body:not(.board-view) #header-quick-access #notifications .fa { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - .wrapper ~ #header-quick-access #header-user-bar, - body:not(.board-view) #header-quick-access #header-user-bar { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - .wrapper ~ #header-quick-access #header-user-bar .fa, - body:not(.board-view) #header-quick-access #header-user-bar .fa { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - } - - /* iPhone 12 Mini specific - make header elements 3x bigger */ - @media screen and (device-width: 375px) and (device-height: 812px), /* iPhone 12 Mini exact */ - screen and (max-width: 375px) and (max-height: 812px), /* iPhone 12 Mini viewport */ - screen and (-webkit-min-device-pixel-ratio: 3) and (max-width: 375px), /* iPhone 12 Mini Retina */ - screen and (max-width: 375px) and (orientation: portrait), /* iPhone 12 Mini portrait */ - screen and (max-width: 375px) and (orientation: landscape) /* iPhone 12 Mini landscape */ { - #header-quick-access { - font-size: 3em !important; /* 3x bigger base font size for iPhone 12 Mini */ - height: auto !important; /* Allow height to grow */ - min-height: 84px !important; /* Much taller minimum height for iPhone 12 Mini */ - flex-wrap: wrap !important; /* Force wrapping */ - align-items: flex-start !important; /* Align to top when wrapping */ - padding: 18px 0px !important; /* More padding for iPhone 12 Mini */ - } - - #header-quick-access * { - font-size: inherit !important; /* Inherit the 2x scaling */ - } - - #header-quick-access .fa, - #header-quick-access .icon { - font-size: 3em !important; /* 3x bigger icons for iPhone 12 Mini */ - } - - #header-quick-access .home-icon a { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - #header-quick-access .home-icon .fa-home { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - #header-quick-access .zoom-controls { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - #header-quick-access .zoom-controls .zoom-level { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - #header-quick-access .zoom-controls .zoom-input { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - #header-quick-access .mobile-mode-toggle .board-header-btn { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - #header-quick-access .mobile-mode-toggle .board-header-btn i { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - #header-quick-access #notifications { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - #header-quick-access #notifications .fa { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - #header-quick-access #header-user-bar { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - #header-quick-access #header-user-bar .fa { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - /* iPhone 12 Mini header wrapping and spacing */ - #header-quick-access .home-icon { - flex-shrink: 0 !important; - margin-right: 0.5rem !important; - margin-bottom: 6px !important; - } - - #header-quick-access .zoom-controls { - flex-shrink: 0 !important; - margin: 0 0.5rem !important; - margin-bottom: 6px !important; - } - - #header-quick-access .mobile-mode-toggle { - flex-shrink: 0 !important; - margin: 0 0.5rem !important; - margin-bottom: 6px !important; - } - - #header-quick-access #notifications { - flex-shrink: 0 !important; - margin: 0 0.5rem !important; - margin-bottom: 6px !important; - } - - #header-quick-access #header-user-bar { - flex-shrink: 0 !important; - margin: 0 0.5rem !important; - margin-bottom: 6px !important; - } - - #header-quick-access ul.header-quick-access-list { - flex-shrink: 0 !important; - margin: 0 0.5rem !important; - margin-bottom: 6px !important; - width: auto !important; - } - } - - /* iPhone 12 Mini and very small screens - make header elements much larger */ - @media screen and (max-width: 400px) and (max-height: 900px), - screen and (max-device-width: 400px) and (max-device-height: 900px), - screen and (-webkit-min-device-pixel-ratio: 2) and (max-width: 400px), - screen and (max-width: 400px) and (orientation: portrait), - screen and (max-width: 400px) and (orientation: landscape), - screen and (max-width: 430px) and (max-height: 950px), /* iPhone 12 Mini range */ - screen and (max-width: 450px) and (max-height: 1000px), /* iPhone range */ - screen and (-webkit-min-device-pixel-ratio: 3) and (max-width: 450px), /* Retina displays */ - screen and (device-width: 375px) and (device-height: 812px), /* iPhone 12 Mini exact */ - screen and (device-width: 390px) and (device-height: 844px), /* iPhone 12/13 */ - screen and (device-width: 428px) and (device-height: 926px) /* iPhone 12 Pro Max */ { - #header-quick-access { - height: 40px !important; /* Taller header */ - padding: 12px 0px !important; - } - - #header-quick-access .home-icon a { - font-size: 16px !important; /* Much larger text */ - padding: 8px 12px !important; - } - - #header-quick-access .home-icon .fa-home { - font-size: 20px !important; /* Much larger icon */ - margin-right: 6px !important; - } - - #header-quick-access .home-icon { - margin-right: 1rem !important; - } - - /* Make zoom controls larger */ - #header-quick-access .zoom-controls { - padding: 0.8vh 1.5vw !important; - margin: 0 1.5vw !important; - } - - #header-quick-access .zoom-controls .zoom-level { - font-size: 16px !important; /* Larger zoom text */ - padding: 0.5vh 0.8vw !important; - min-width: 4vw !important; - } - - #header-quick-access .zoom-controls .zoom-input { - font-size: 16px !important; /* Larger input text */ - padding: 0.5vh 0.8vw !important; - min-width: 80px !important; /* Wider to fit 100 */ - width: 80px !important; /* Fixed width to show 100 fully */ - flex: 0 0 80px !important; /* Prevent shrinking in flex */ - } - - /* Make mobile mode toggle larger */ - #header-quick-access .mobile-mode-toggle .board-header-btn { - padding: 0.8vh 1.2vw !important; - font-size: 16px !important; - } - - #header-quick-access .mobile-mode-toggle .board-header-btn i { - font-size: 18px !important; - } - } - - /* Fallback for iPhone devices using JavaScript detection */ - .iphone-device #header-quick-access { - font-size: 2em !important; /* 2x bigger base font size */ - height: auto !important; /* Allow height to grow */ - min-height: 48px !important; /* Minimum height for mobile */ - flex-wrap: wrap !important; /* Force wrapping */ - align-items: flex-start !important; /* Align to top when wrapping */ - padding: 8px 0px !important; /* Adjust padding for mobile */ - } - - .iphone-device #header-quick-access * { - font-size: inherit !important; /* Inherit the 2x scaling */ - } - - .iphone-device #header-quick-access .fa, - .iphone-device #header-quick-access .icon { - font-size: 2em !important; /* 2x bigger icons */ - } - - .iphone-device #header-quick-access .home-icon a { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - .iphone-device #header-quick-access .home-icon .fa-home { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - .iphone-device #header-quick-access .zoom-controls { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - .iphone-device #header-quick-access .zoom-controls .zoom-level { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - .iphone-device #header-quick-access .zoom-controls .zoom-input { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - .iphone-device #header-quick-access .mobile-mode-toggle .board-header-btn { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - .iphone-device #header-quick-access .mobile-mode-toggle .board-header-btn i { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - /* iPhone device header wrapping and spacing */ - .iphone-device #header-quick-access .home-icon { - flex-shrink: 0 !important; - margin-right: 0.5rem !important; - margin-bottom: 4px !important; - } - - .iphone-device #header-quick-access .zoom-controls { - flex-shrink: 0 !important; - margin: 0 0.5rem !important; - margin-bottom: 4px !important; - } - - .iphone-device #header-quick-access .mobile-mode-toggle { - flex-shrink: 0 !important; - margin: 0 0.5rem !important; - margin-bottom: 4px !important; - } - - .iphone-device #header-quick-access #notifications { - flex-shrink: 0 !important; - margin: 0 0.5rem !important; - margin-bottom: 4px !important; - } - - .iphone-device #header-quick-access #header-user-bar { - flex-shrink: 0 !important; - margin: 0 0.5rem !important; - margin-bottom: 4px !important; - } - - .iphone-device #header-quick-access ul.header-quick-access-list { - flex-shrink: 0 !important; - margin: 0 0.5rem !important; - margin-bottom: 4px !important; - width: auto !important; - } - - /* iPhone 12 Mini specific - JavaScript detection fallback */ - .iphone-device #header-quick-access { - font-size: 3em !important; /* 3x bigger base font size for iPhone 12 Mini */ - height: auto !important; /* Allow height to grow */ - min-height: 84px !important; /* Much taller minimum height for iPhone 12 Mini */ - flex-wrap: wrap !important; /* Force wrapping */ - align-items: flex-start !important; /* Align to top when wrapping */ - padding: 18px 0px !important; /* More padding for iPhone 12 Mini */ - } - - .iphone-device #header-quick-access * { - font-size: inherit !important; /* Inherit the 2x scaling */ - } - - .iphone-device #header-quick-access .fa, - .iphone-device #header-quick-access .icon { - font-size: 3em !important; /* 3x bigger icons for iPhone 12 Mini */ - } - - .iphone-device #header-quick-access .home-icon a { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - .iphone-device #header-quick-access .home-icon .fa-home { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - .iphone-device #header-quick-access .zoom-controls { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - .iphone-device #header-quick-access .zoom-controls .zoom-level { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - .iphone-device #header-quick-access .zoom-controls .zoom-input { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - .iphone-device #header-quick-access .mobile-mode-toggle .board-header-btn { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - .iphone-device #header-quick-access .mobile-mode-toggle .board-header-btn i { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - .iphone-device #header-quick-access #notifications { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - .iphone-device #header-quick-access #notifications .fa { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - .iphone-device #header-quick-access #header-user-bar { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - .iphone-device #header-quick-access #header-user-bar .fa { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - /* iPhone 12 Mini header wrapping and spacing - JavaScript fallback */ - .iphone-device #header-quick-access .home-icon { - flex-shrink: 0 !important; - margin-right: 0.5rem !important; - margin-bottom: 6px !important; - } - - .iphone-device #header-quick-access .zoom-controls { - flex-shrink: 0 !important; - margin: 0 0.5rem !important; - margin-bottom: 6px !important; - } - - .iphone-device #header-quick-access .mobile-mode-toggle { - flex-shrink: 0 !important; - margin: 0 0.5rem !important; - margin-bottom: 6px !important; - } - - .iphone-device #header-quick-access #notifications { - flex-shrink: 0 !important; - margin: 0 0.5rem !important; - margin-bottom: 6px !important; - } - - .iphone-device #header-quick-access #header-user-bar { - flex-shrink: 0 !important; - margin: 0 0.5rem !important; - margin-bottom: 6px !important; - } - - .iphone-device #header-quick-access ul.header-quick-access-list { - flex-shrink: 0 !important; - margin: 0 0.5rem !important; - margin-bottom: 6px !important; - width: auto !important; - } - - /* iPhone 12 Mini All Boards page - make logo row elements 3x bigger */ - .iphone-device .wrapper ~ #header-quick-access, - .iphone-device body:not(.board-view) #header-quick-access { - font-size: 3em !important; /* 3x bigger base font size for logo row */ - } - - .iphone-device .wrapper ~ #header-quick-access *, - .iphone-device body:not(.board-view) #header-quick-access * { - font-size: inherit !important; /* Inherit the 2x scaling */ - } - - .iphone-device .wrapper ~ #header-quick-access .fa, - .iphone-device .wrapper ~ #header-quick-access .icon, - .iphone-device body:not(.board-view) #header-quick-access .fa, - .iphone-device body:not(.board-view) #header-quick-access .icon { - font-size: 2em !important; /* 2x bigger icons in logo row */ - } - - .iphone-device .wrapper ~ #header-quick-access .home-icon a, - .iphone-device body:not(.board-view) #header-quick-access .home-icon a { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - .iphone-device .wrapper ~ #header-quick-access .home-icon .fa-home, - .iphone-device body:not(.board-view) #header-quick-access .home-icon .fa-home { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - .iphone-device .wrapper ~ #header-quick-access .zoom-controls, - .iphone-device body:not(.board-view) #header-quick-access .zoom-controls { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - .iphone-device .wrapper ~ #header-quick-access .zoom-controls .zoom-level, - .iphone-device body:not(.board-view) #header-quick-access .zoom-controls .zoom-level { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - .iphone-device .wrapper ~ #header-quick-access .zoom-controls .zoom-input, - .iphone-device body:not(.board-view) #header-quick-access .zoom-controls .zoom-input { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - .iphone-device .wrapper ~ #header-quick-access .mobile-mode-toggle .board-header-btn, - .iphone-device body:not(.board-view) #header-quick-access .mobile-mode-toggle .board-header-btn { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - .iphone-device .wrapper ~ #header-quick-access .mobile-mode-toggle .board-header-btn i, - .iphone-device body:not(.board-view) #header-quick-access .mobile-mode-toggle .board-header-btn i { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - .iphone-device .wrapper ~ #header-quick-access #notifications, - .iphone-device body:not(.board-view) #header-quick-access #notifications { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - .iphone-device .wrapper ~ #header-quick-access #notifications .fa, - .iphone-device body:not(.board-view) #header-quick-access #notifications .fa { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - .iphone-device .wrapper ~ #header-quick-access #header-user-bar, - .iphone-device body:not(.board-view) #header-quick-access #header-user-bar { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - .iphone-device .wrapper ~ #header-quick-access #header-user-bar .fa, - .iphone-device body:not(.board-view) #header-quick-access #header-user-bar .fa { - font-size: 1em !important; /* Use inherited 2x scaling */ - } - - #header-quick-access ul { - width: calc(100% - 60px); - margin-right: 10px; - } - #header-quick-access ul li { - height: 100%; - } - #header-quick-access ul li a { - height: 100%; - } - #header-quick-access #header-new-board-icon { - display: none; - } - #header-quick-access #header-user-bar { - right: 0px; - padding: 10px; - margin: -8px 0 -10px -10px; - } -} @media print { #header-quick-access .allBoards, #header-quick-access ul, @@ -1190,5 +356,8 @@ padding: 0; } #headerIsSettingDatabaseCallDone { - display: none; + display: flex; + visibility: hidden; + flex: 1; + align-items: center; } diff --git a/client/components/main/header.jade b/client/components/main/header.jade index 7f62889fb..32c3f0b27 100644 --- a/client/components/main/header.jade +++ b/client/components/main/header.jade @@ -5,100 +5,81 @@ template(name="header") Reddit "subreddit" bar. The first link goes to the boards page. if currentUser - #header-quick-access(class=currentBoard.colorClass) + #header-quick-access(class="currentBoard.colorClass {{#if isMiniScreen}}mobile-view{{/if}}") // Home icon - always at left side of logo - span.home-icon.allBoards - a(href="{{pathFor 'home'}}") - i.fa.fa-home - | {{_ 'all-boards'}} + #header-quick-access-left + span.home-icon.allBoards + a(href="{{pathFor 'home'}}") + span.emoji-icon + i.fa.fa-home + span + | {{_ 'all-boards'}} - // Logo - visible; on mobile constrained by CSS - unless currentSetting.hideLogo - if currentSetting.customTopLeftCornerLogoImageUrl - if currentSetting.customTopLeftCornerLogoLinkUrl - a(href="{{currentSetting.customTopLeftCornerLogoLinkUrl}}" alt="{{currentSetting.productName}}" title="{{currentSetting.productName}}") - img(src="{{currentSetting.customTopLeftCornerLogoImageUrl}}" height="{{#if currentSetting.customTopLeftCornerLogoHeight}}#{currentSetting.customTopLeftCornerLogoHeight}{{else}}27{{/if}}" width="auto" margin="0" padding="0") - unless currentSetting.customTopLeftCornerLogoLinkUrl - img(src="{{currentSetting.customTopLeftCornerLogoImageUrl}}" height="{{#if currentSetting.customTopLeftCornerLogoHeight}}#{currentSetting.customTopLeftCornerLogoHeight}{{else}}27{{/if}}" width="auto" margin="0" padding="0" alt="{{currentSetting.productName}}" title="{{currentSetting.productName}}") - unless currentSetting.customTopLeftCornerLogoImageUrl - div#headerIsSettingDatabaseCallDone - img(src="{{pathFor '/logo-header.png'}}" alt="{{currentSetting.productName}}" title="{{currentSetting.productName}}") - - // Zoom controls - always visible - .zoom-controls - span.zoom-level.js-zoom-level-click(title="{{_ 'click-to-change-zoom'}}") - span.zoom-display {{zoomLevel}}% - input.zoom-input.js-zoom-input(type="number" value=zoomLevel min="50" max="300" step="10" style="display: none;") - - // 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 - if currentList - each currentBoard.lists - li(class="{{#if $.Session.equals 'currentList' _id}}current{{/if}}") - a.js-select-list - +viewer - = title - else + if isMiniScreen + ul.header-quick-access-list + if currentList + each currentBoard.lists + li(class="{{#if $.Session.equals 'currentList' _id}}current{{/if}}") + a.js-select-list. + +viewer + = title + else + each currentUser.starredBoards + li(class="{{#if $.Session.equals 'currentBoard' _id}}current{{/if}}") + a(href="{{pathFor 'board' id=_id slug=slug}}") + +viewer + = title + else + ul.header-quick-access-list + //li + // a(href="{{pathFor 'public'}}") + // span.fa.fa-globe + // | {{_ 'public'}} each currentUser.starredBoards li(class="{{#if $.Session.equals 'currentBoard' _id}}current{{/if}}") a(href="{{pathFor 'board' id=_id slug=slug}}") +viewer = title + else + li.current.empty(title="{{_ 'quick-access-description'}}") + | {{_ 'quick-access-description'}} + #header-new-board-icon + // Next line is used only for spacing at header, + // there is no visible clickable icon. #header-new-board-icon - else - ul.header-quick-access-list - //li - // a(href="{{pathFor 'public'}}") - // span.fa.fa-globe - // | {{_ 'public'}} - each currentUser.starredBoards - li(class="{{#if $.Session.equals 'currentBoard' _id}}current{{/if}}") - a(href="{{pathFor 'board' id=_id slug=slug}}") - +viewer - = title + // Hide duplicate create board button, + // because it did not show board templates correctly. + //a#header-new-board-icon.js-create-board + // i.fa.fa-plus(title="Create a new board") + // Logo - visible; on mobile constrained by CSS + unless currentSetting.hideLogo + .logo-container + if currentSetting.customTopLeftCornerLogoImageUrl + if currentSetting.customTopLeftCornerLogoLinkUrl + a.logo(href="{{currentSetting.customTopLeftCornerLogoLinkUrl}}" alt="{{currentSetting.productName}}" title="{{currentSetting.productName}}") + +logo + else + +logo else - li.current.empty(title="{{_ 'quick-access-description'}}") - | {{_ 'quick-access-description'}} - #header-new-board-icon - // Next line is used only for spacing at header, - // there is no visible clickable icon. - #header-new-board-icon - // Hide duplicate create board button, - // because it did not show board templates correctly. - //a#header-new-board-icon.js-create-board - // i.fa.fa-plus(title="Create a new board") + div#headerIsSettingDatabaseCallDone.logo + img(src="{{pathFor '/logo-header.png'}}" alt="{{currentSetting.productName}}" title="{{currentSetting.productName}}") - .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.fa.fa-mobile - i.desktop-icon(class="{{#unless mobileMode}}active{{/unless}}") - i.fa.fa-desktop - - // Notifications - +notifications - - if currentSetting.customHelpLinkUrl - #header-help - a(href="{{currentSetting.customHelpLinkUrl}}", title="{{_ 'help'}}", target="_blank", rel="noopener noreferrer") - i.fa.fa-question-circle - - +headerUserBar + #header-quick-access-right + if currentSetting.customHelpLinkUrl + #header-help + a(href="{{currentSetting.customHelpLinkUrl}}", title="{{_ 'help'}}", target="_blank", rel="noopener noreferrer") + i.fa.fa-question-circle + #header-quick-access-icons + +headerUserBar + // Notifications + +notifications #header(class=currentBoard.colorClass) //- The main bar is a colorful bar that provide all the meta-data for the current page. This bar is contextual based. If the user is not connected we display "sign in" and "log in" buttons. - #header-main-bar(class="{{#if wrappedHeader}}wrapper{{/if}}") + #header-main-bar(class="{{#if isMiniScreen}}mobile-view{{/if}} {{#if wrappedHeader}}wrapper{{/if}}") +Template.dynamic(template=headerBar) if appIsOffline @@ -122,3 +103,7 @@ template(name="offlineWarning") | {{_ 'app-is-offline'}} a.app-try-reconnect {{_ 'app-try-reconnect'}} + +//- a little helper to avoid duplication +template(name="logo") + img(src="{{currentSetting.customTopLeftCornerLogoImageUrl}}" style="{{#if currentSetting.customTopLeftCornerLogoHeight}}min-height: #{currentSetting.customTopLeftCornerLogoHeight};{{/if}}" alt="{{currentSetting.productName}}" title="{{currentSetting.productName}}") \ No newline at end of file diff --git a/client/components/main/header.js b/client/components/main/header.js index a0c451f4b..0b551f1fe 100644 --- a/client/components/main/header.js +++ b/client/components/main/header.js @@ -22,13 +22,13 @@ Template.header.onCreated(function () { ) document.getElementById( 'headerIsSettingDatabaseCallDone', - ).style.display = 'none'; + ).style.visibility = 'hidden'; else if ( document.getElementById('headerIsSettingDatabaseCallDone') != null ) document.getElementById( 'headerIsSettingDatabaseCallDone', - ).style.display = 'block'; + ).style.visibility = 'visible'; return this.stop(); }, }); @@ -57,14 +57,6 @@ Template.header.helpers({ return announcements && announcements.body; }, - zoomLevel() { - const sessionZoom = Session.get('wekan-zoom-level'); - if (sessionZoom !== undefined) { - return Math.round(sessionZoom * 100); - } - return Math.round(Utils.getZoomLevel() * 100); - }, - mobileMode() { const sessionMode = Session.get('wekan-mobile-mode'); if (sessionMode !== undefined) { @@ -76,51 +68,6 @@ Template.header.helpers({ Template.header.events({ 'click .js-create-board': Popup.open('headerBarCreateBoard'), - 'click .js-zoom-level-click'(evt) { - const $zoomDisplay = $(evt.currentTarget).find('.zoom-display'); - const $zoomInput = $(evt.currentTarget).find('.zoom-input'); - - // Hide display, show input - $zoomDisplay.hide(); - $zoomInput.show().focus().select(); - }, - - 'keypress .js-zoom-input'(evt) { - if (evt.which === 13) { - // Enter key - const newZoomPercent = parseInt(evt.target.value); - - if ( - !isNaN(newZoomPercent) && - newZoomPercent >= 50 && - newZoomPercent <= 300 - ) { - const newZoom = newZoomPercent / 100; - Utils.setZoomLevel(newZoom); - - // Hide input, show display - const $zoomDisplay = $(evt.target).siblings('.zoom-display'); - const $zoomInput = $(evt.target); - $zoomInput.hide(); - $zoomDisplay.show(); - } else { - alert('Please enter a zoom level between 50% and 300%'); - evt.target.focus().select(); - } - } - }, - - 'blur .js-zoom-input'(evt) { - // When input loses focus, hide it and show display - const $zoomDisplay = $(evt.target).siblings('.zoom-display'); - const $zoomInput = $(evt.target); - $zoomInput.hide(); - $zoomDisplay.show(); - }, - 'click .js-mobile-mode-toggle'() { - const currentMode = Utils.getMobileMode(); - Utils.setMobileMode(!currentMode); - }, 'click .js-open-bookmarks'(evt) { // Already added but ensure single definition -- safe guard }, diff --git a/client/components/main/keyboardShortcuts.css b/client/components/main/keyboardShortcuts.css index 3391dcfc1..359cbf04b 100644 --- a/client/components/main/keyboardShortcuts.css +++ b/client/components/main/keyboardShortcuts.css @@ -12,7 +12,7 @@ .shortcuts-list .shortcuts-list-item .shortcuts-list-item-keys kbd { padding: 5px 8px; margin: 5px; - font-size: 18px; + } .shortcuts-list .shortcuts-list-item .shortcuts-list-item-action { font-size: 1.4em; diff --git a/client/components/main/layouts.css b/client/components/main/layouts.css index e646e1b78..7ea06d886 100644 --- a/client/components/main/layouts.css +++ b/client/components/main/layouts.css @@ -1,7 +1,33 @@ -* { - -webkit-box-sizing: unset; - box-sizing: unset; +/* Global variables that we can use to easily test and change layout +Later it could be useful to use a CSS superset */ +/* this makes the property computable */ +@property --popup-margin { + syntax: ""; + inherits: true; + initial-value: 0px; } + +:root { + scroll-behavior: smooth; + --label-height: 1.7lh; + --header-scale: clamp(1rem, 1.333rem + -0.333vw, 1.3rem) + --popup-margin: 2vmax; + + /* regarding fonts, this is one of the clearest I found: https://modern-fluid-typography.vercel.app/ */ + &:has(body.desktop-mode) { + font-size: clamp(1rem, 1.68rem + -0.57vw, 1.4rem); + --quick-header-scale: clamp(0.8rem, 0.6rem + 0.4vw, 1.2rem); + --list-item-size: 1.2em; + } + + &:has(body.mobile-mode) { + font-size: clamp(2.5rem, 3vw + 1.7rem, 3.5rem); + --quick-header-scale: 1.3em; + --header-scale: clamp(1rem, -0.5vw + 1.25rem, 1.125rem); + --list-item-size: 1.6em; + } +} + /* Fixed missing 'import nib' stylesheet reset and extra li bullet points * https://github.com/wekan/wekan/issues/4512#issuecomment-1129347536 */ @@ -32,29 +58,26 @@ a:focus { color: unset; text-decoration: unset; } + .badge { - display: unset; - min-width: unset; - padding: unset; - font-size: unset; - font-weight: unset; - line-height: unset; - color: unset; - text-align: unset; - white-space: unset; - vertical-align: unset; - background-color: unset; - border-radius: unset; + display: flex; + gap: 0 0.3ch; + align-items: center; } + +body { + /* changed programmatically on swimlane resizes, or e.g. when un-collapsed */ + transition: height 0.2s ease-out, width 0.2s ease-out; +} + html, body, input, select, textarea, button { - font: clamp(14px, 2.5vw, 18px) Roboto, Poppins, "Helvetica Neue", Arial, Helvetica, sans-serif; - line-height: 1.4; - color: #4d4d4d; + font-family: Roboto, Poppins, "Helvetica Neue", "Liberation Sans", Arial, Helvetica, sans-serif; + color: hsl(0, 0%, 30%); /* Improve text rendering */ -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; @@ -63,58 +86,74 @@ button { user-select: text; } html { - font-size: 100%; max-height: 100%; -webkit-user-select: text; user-select: text; - -webkit-text-size-adjust: 100%; -text-size-adjust: 100%; + text-size-adjust: 100%; + overscroll-behavior: none; } body { background: #dedede; margin: 0; position: relative; - z-index: 0; + overflow-x: hidden; overflow-y: auto; display: flex; flex-direction: column; - height: 100vh; - /* iOS Safari fixes */ - -webkit-overflow-scrolling: touch; + align-items: stretch; + justify-content: start; + /* height is auto; if set to 100vh, it prevents navbar to disappear on scroll... */ + width: 100%; + /* Needs to be set on body and html. Feels ok to disable entirely as Wekan is really drag/scroll-heavy */ + overscroll-behavior: none; + min-height: 100vh; + line-height: 1.4; } -/* Mobile mode specific fixes for iOS Safari */ body.mobile-mode { - overflow-x: hidden; - position: fixed; width: 100%; - height: 100vh; - /* Prevent iOS Safari bounce scroll */ - overscroll-behavior: none; -webkit-overflow-scrolling: touch; } /* Ensure content area is scrollable in mobile mode */ body.mobile-mode #content { + width: 100%; overflow-y: auto; overflow-x: hidden; -webkit-overflow-scrolling: touch; - height: calc(100vh - 48px); } + +/* Prevent scroll through popups */ +body:has(.pop-over:hover) { + overflow: hidden; +} + +/* Some forms will need extra adjustement (removing margins, etc) +but it worth it to let browsers take care of exact placement/sizing */ +.inlined-form { + flex: 1; + display: flex; + flex-direction: column; + align-items: stretch; + justify-content: center; + gap: 0.3lh; + width: 100%; +} + #content { + display: flex; position: relative; flex: 1; overflow-x: hidden; + margin-bottom: 1vh; + min-height: 100vh; + max-width: min(100%, 100vw); } #content .sk-spinner { margin-top: 30vh; } -#content > .wrapper { - margin-top: 1vh; - padding: 2vh 2vw; -} #modal { position: absolute; top: 0; @@ -157,25 +196,6 @@ body.mobile-mode #content { #modal .modal-content-wide .modal-close-btn { display: block; float: right; - font-size: clamp(18px, 4vw, 24px); -} -h1 { - font-size: clamp(18px, 4vw, 24px); - line-height: 1.2em; - margin: 0 0 1vh; -} -h2 { - font-size: clamp(16px, 3.5vw, 20px); - line-height: 1.2em; - margin: 0 0 0.8vh; -} -h3, -h4, -h5, -h6 { - font-size: clamp(14px, 3vw, 18px); - line-height: 1.25em; - margin: 0 0 0.6vh; } .quiet, .quiet a { @@ -226,7 +246,7 @@ p { } p a { text-decoration: underline; - word-wrap: break-word; + overflow-wrap: break-word; } table, p { @@ -250,13 +270,13 @@ blockquote { padding: 0 0 0 1vw; } hr { - height: 1px; + height: 0.2ch; border: 0; border: none; width: 100%; background: #dbdbdb; color: #dbdbdb; - margin: 2vh 0; + margin: 0.2lh 0; padding: 0; } table, @@ -303,7 +323,7 @@ kbd { clear: both; } .hide { - display: none; + display: none !important; } .show { display: block; @@ -337,8 +357,11 @@ kbd { padding-bottom: 0; } .wrapper { - width: calc(100% - 2vw); - margin: 0 auto; + margin: 0; + flex: 1; + width: auto; + height: fit-content; + display: grid; } .relative { position: relative; @@ -369,8 +392,12 @@ kbd { .invisible { visibility: hidden; } +.invisible-line { + height: 1.3lh; + visibility: hidden; +} .wrapword { - word-wrap: break-word; + overflow-wrap: break-word; } .grab { cursor: grab; @@ -445,8 +472,39 @@ a:not(.disabled).is-active i.fa { } .viewer { min-height: 2.5vh; - display: block; - word-wrap: break-word; + display: flex; + flex-direction: column; + align-items: start; + justify-content: center; + /* a tentative to get layout less dependant of content, + especially for small elements e.g. labels: the goal is that + content will be cut with `...` if too large (but will be fully + rendered in dedicated interfaces) + + the classic technique is to use flex-basis, but it depends + on the parent not overflowing to get the right size; also, + specifying in terms of lines makes the browser act clever, by + fitting the available space and cutting after N lines, whatever + is the text's length */ + min-width: 0; + p, ul { + margin: 0; + padding: 0; + text-overflow: ellipsis; + overflow: hidden; + + /* See https: //css-tricks.com/line-clampin/, + it is widely supported and waiting standardization https: //caniuse.com/?search=-webkit-line-clamp */ + display: -webkit-box !important; + /* 0 has no effect; ensures will not interfere unless asked */ + -webkit-line-clamp: var(--overflow-lines, 0); + -webkit-box-orient: vertical; + -webkit-align-items: center; + /* grid properties apply */ + align-content: center; + word-break: break-word; + white-space: normal; + } } .viewer table { word-wrap: normal; @@ -481,6 +539,12 @@ a:not(.disabled).is-active i.fa { padding: 0; padding-top: 15px; } + +.basicTabs-container .tabs-list .tab-item { + /* where does templates_tabs.css come from? visible in + devtools but not in sources */ + font-size: unset !important; +} .no-scrollbars { scrollbar-width: none; } @@ -495,133 +559,30 @@ a:not(.disabled).is-active i.fa { @media screen and (max-width: 800px), screen and (max-device-width: 932px) and (-webkit-min-device-pixel-ratio: 3) and (orientation: landscape), screen and (max-device-width: 932px) and (-webkit-min-device-pixel-ratio: 3) and (orientation: portrait) { - #content { - margin: 1px 0px 0px 0px; - height: calc(100% - 0px); - /* Improve touch scrolling */ - -webkit-overflow-scrolling: touch; - } - #content > .wrapper { - margin-top: 0px; - padding: 8px; - } - .wrapper { - height: calc(100% - 31px); - margin: 0px; - padding: 8px; - } + .panel-default { width: 95vw; max-width: 95vw; margin: 0 auto; } - + /* Improve touch targets */ button, .btn, .js-toggle, .js-color-choice, .js-reaction, .close { min-height: 44px; min-width: 44px; padding: 12px 16px; - font-size: 16px; /* Prevent zoom on iOS */ + /* Prevent zoom on iOS */ touch-action: manipulation; } - + /* Form elements */ input, select, textarea { - font-size: 16px; /* Prevent zoom on iOS */ + /* Prevent zoom on iOS */ padding: 12px; min-height: 44px; touch-action: manipulation; } - - /* Cards and lists */ - .minicard { - min-height: 48px; - padding: 12px; - margin-bottom: 8px; - touch-action: manipulation; - } - - .list { - margin: 0 8px; - min-width: 280px; - } - - /* Board canvas */ - .board-canvas { - padding: 0 8px 8px 0; - overflow-x: auto; - -webkit-overflow-scrolling: touch; - } - - /* Header mobile layout */ - #header { - padding: 8px; - /* Keep top bar on a single row on small screens */ - flex-wrap: nowrap; - align-items: center; - gap: 8px; - } - - #header-quick-access { - /* Keep quick-access items in one row */ - display: flex; - flex-direction: row; - align-items: center; - gap: 8px; - width: 100%; - } - /* Hide elements that should move to the hamburger menu on mobile */ - #header-quick-access .header-quick-access-list, - #header-quick-access #header-help { - display: none !important; - } - - /* Show only the home icon (hide the trailing text) on mobile */ - #header-quick-access .home-icon a { - display: inline-flex; - align-items: center; - max-width: 28px; /* enough to display the icon */ - overflow: hidden; - white-space: nowrap; - } - - /* Hide text in home icon on mobile, show only icon */ - #header-quick-access .home-icon a span:not(.fa) { - display: none !important; - } - - /* Ensure proper spacing for mobile header elements */ - #header-quick-access .zoom-controls { - margin-left: auto; - margin-right: 8px; - } - - .mobile-mode-toggle { - margin-right: 8px; - } - - #header-user-bar { - margin-left: auto; - } - - /* Ensure header elements don't wrap on very small screens */ - #header-quick-access { - min-width: 0; /* Allow flexbox to shrink */ - } - - /* Make sure logo doesn't take too much space on mobile */ - #header-quick-access img { - max-height: 24px; - max-width: 120px; - } - - /* Ensure zoom controls are compact on mobile */ - .zoom-controls .zoom-level { - padding: 4px 8px; - font-size: 12px; - } - /* Modal mobile optimization */ #modal .modal-content, #modal .modal-content-wide { @@ -632,29 +593,28 @@ a:not(.disabled).is-active i.fa { max-height: 90vh; overflow-y: auto; } - + /* Table mobile optimization */ table { - font-size: 14px; + width: 100%; display: block; overflow-x: auto; white-space: nowrap; -webkit-overflow-scrolling: touch; } - + /* Admin panel mobile optimization */ .setting-content .content-body { flex-direction: column; gap: 16px; padding: 8px; } - + .setting-content .content-body .side-menu { width: 100%; - order: 2; } - + .setting-content .content-body .main-body { order: 1; min-height: 60vh; @@ -663,139 +623,175 @@ a:not(.disabled).is-active i.fa { } } +<<<<<<< HEAD /* Tablet devices (768px - 1024px) */ @media screen and (min-width: 768px) and (max-width: 1024px) { #content > .wrapper { padding: 12px; } - + .wrapper { padding: 12px; } - + .panel-default { width: 90vw; max-width: 90vw; } - + /* Touch-friendly but more compact */ button, .btn, .js-toggle, .js-color-choice, .js-reaction, .close { min-height: 48px; min-width: 48px; padding: 10px 14px; } - + .minicard { min-height: 40px; padding: 10px; } - + .list { margin: 0 12px; min-width: 300px; } - + .board-canvas { padding: 0 12px 12px 0; } - + #header { padding: 12px 16px; } - + #modal .modal-content { width: 80vw; max-width: 600px; } - + #modal .modal-content-wide { width: 90vw; max-width: 800px; } - + .setting-content .content-body { gap: 20px; } - + .setting-content .content-body .side-menu { width: 250px; } - + /* Responsive handling for quick-access description on tablets */ #header-quick-access ul.header-quick-access-list li.current.empty { max-width: 300px; } } +||||||| parent of 2e0149f79 (🚧 Remove zoom/mobile option, rework header/misc layout to be more responsive) +/* Tablet devices (768px - 1024px) */ +@media screen and (min-width: 768px) and (max-width: 1024px) { + #content > .wrapper { + padding: 12px; + } + + .wrapper { + padding: 12px; + } + + .panel-default { + width: 90vw; + max-width: 90vw; + } + + /* Touch-friendly but more compact */ + button, .btn, .js-toggle, .js-color-choice, .js-reaction, .close { + min-height: 48px; + min-width: 48px; + padding: 10px 14px; + } + + .minicard { + min-height: 40px; + padding: 10px; + } + + .list { + margin: 0 12px; + min-width: 300px; + } + + .board-canvas { + padding: 0 12px 12px 0; + } + + #header { + padding: 12px 16px; + } + + #modal .modal-content { + width: 80vw; + max-width: 600px; + } + + #modal .modal-content-wide { + width: 90vw; + max-width: 800px; + } + + .setting-content .content-body { + gap: 20px; + } + + .setting-content .content-body .side-menu { + width: 250px; + } +} +======= +>>>>>>> 2e0149f79 (🚧 Remove zoom/mobile option, rework header/misc layout to be more responsive) /* Large displays and digital signage (1920px+) */ @media screen and (min-width: 1920px) { - body { - font-size: 18px; - } - - button, .btn, .js-toggle, .js-color-choice, .js-reaction, .close { - min-height: 56px; - min-width: 56px; - padding: 16px 20px; - font-size: 18px; - } - - .minicard { - min-height: 56px; - padding: 16px; - font-size: 18px; - } - - .list { - margin: 0 8px; - min-width: 360px; - } - .board-canvas { padding: 0; } - + #header { padding: 0 8px; } - + #content > .wrapper { padding: 0; } - + #modal .modal-content { width: 600px; } - + #modal .modal-content-wide { width: 1000px; } - + .setting-content .content-body { gap: 32px; } - + .setting-content .content-body .side-menu { width: 320px; } } -.inline-input { - height: 37px; - margin: 8px 10px 0 0; - width: 100px; + +.ui-sortable-handle { + cursor: grab !important; } + .select-authentication { width: 100%; } -.textBelowCustomLoginLogo, -.auth-layout { +#rescue-card-description { display: flex; - flex-direction: column; - align-items: center; - justify-content: center; -} -.auth-layout .auth-dialog { - margin: 0 !important; + flex: 1 0 auto; + align-self: center; + margin: 0 0.2lh; } .loadingText { text-align: center; @@ -882,8 +878,18 @@ a:not(.disabled).is-active i.fa { text-decoration: underline; text-decoration-color: #17683a; } +/* +Prevents popups to compute real size, trying to comment .at-pwd-form, .at-sep, .at-oauth { display: none; +}*/ + +#at-pwd-form { + display: flex; + flex-direction: column; + justify-content: space-evenly; + align-items: stretch; + gap: 0.3lh; } @-moz-keyframes fadeIn { from { @@ -928,31 +934,19 @@ a:not(.disabled).is-active i.fa { /* iOS Safari Mobile Mode Fixes */ @media screen and (max-width: 800px) { - /* Prevent scrolling issues on iOS Safari when card popup is open */ - body.mobile-mode { - overflow: hidden; - position: fixed; - width: 100%; - height: 100vh; - } - /* Fix z-index stacking for mobile Safari */ body.mobile-mode .board-wrapper { z-index: 1; } - - body.mobile-mode .board-wrapper .board-canvas .board-overlay { - z-index: 17 !important; - } - + body.mobile-mode .card-details { z-index: 100 !important; } - + body.mobile-mode .pop-over { z-index: 999; } - + /* Ensure smooth scrolling on iOS */ body.mobile-mode .card-details, body.mobile-mode .pop-over .content-wrapper { diff --git a/client/components/main/layouts.jade b/client/components/main/layouts.jade index 7bd257fbd..2589f6d70 100644 --- a/client/components/main/layouts.jade +++ b/client/components/main/layouts.jade @@ -23,61 +23,56 @@ template(name="main") //link(rel="stylesheet" type="text/css" class="__meteor-css__" href="css/html5-default-theme.css") template(name="userFormsLayout") - section.auth-layout - if currentSetting.hideLogo - h1.at-form-landing-logo - br - br - unless currentSetting.hideLogo - h1.at-form-landing-logo - if currentSetting.customLoginLogoImageUrl - if currentSetting.customLoginLogoLinkUrl - a(href="{{currentSetting.customLoginLogoLinkUrl}}") - img(src="{{currentSetting.customLoginLogoImageUrl}}" width="300" height="auto") + .auth-container + section.auth-layout.auth-logo + if currentSetting.hideLogo + h1.at-form-landing-logo + unless currentSetting.hideLogo + if currentSetting.customLoginLogoImageUrl + if currentSetting.customLoginLogoLinkUrl + a(href="{{currentSetting.customLoginLogoLinkUrl}}") + img(src="{{currentSetting.customLoginLogoImageUrl}}") + unless currentSetting.customLoginLogoLinkUrl + a + img(src="{{currentSetting.customLoginLogoImageUrl}}") + else + a + img(src="{{pathFor '/wekan-logo.svg'}}" alt="") br - unless currentSetting.customLoginLogoLinkUrl - img(src="{{currentSetting.customLoginLogoImageUrl}}" width="300" height="auto") - br - else - img(src="{{pathFor '/wekan-logo.svg'}}" alt="" width="300" height="auto") - br - if currentSetting.textBelowCustomLoginLogo - hr - section.textBelowCustomLoginLogo - +viewer - | {{currentSetting.textBelowCustomLoginLogo}} - hr - section.auth-layout - section.auth-dialog - if isLoading - +loader - else - // ARIA live region for error messages - div#login-error-message(role="alert" aria-live="assertive" style="color: #d32f2f; margin-bottom: 1em;") - +Template.dynamic(template=content) - if currentSetting.displayAuthenticationMethod - +connectionMethod(authenticationMethod=currentSetting.defaultAuthenticationMethod) - if isLegalNoticeLinkExist - div#legalNoticeDiv - span#legalNoticeSpan {{_ 'acceptance_of_our_legalNotice'}} - a#legalNoticeAtLink.at-link(href="{{currentSetting.legalNotice}}", target="_blank", rel="noopener noreferrer") - | {{_ 'legalNotice'}} - if getLegalNoticeWithWritTraduction - div - div.at-form-lang - label(for="userform-set-language-select") {{_ 'changeLanguagePopup-title'}} - select.select-lang.js-userform-set-language#userform-set-language-select(aria-label="{{_ 'changeLanguagePopup-title'}}") - each languages - if isCurrentLanguage - if rtl - option(value="{{tag}}" selected="selected") {{name}} (RTL) + section.auth-custom-text + if currentSetting.textBelowCustomLoginLogo + section.textBelowCustomLoginLogo + +viewer + | {{currentSetting.textBelowCustomLoginLogo}} + section.auth-layout.auth-form + section.auth-dialog + if isLoading + +loader + else + // ARIA live region for error messages + div#login-error-message(role="alert" aria-live="assertive" style="color: #d32f2f;") + +Template.dynamic(template=content) + if currentSetting.displayAuthenticationMethod + +connectionMethod(authenticationMethod=currentSetting.defaultAuthenticationMethod) + if isLegalNoticeLinkExist + div#legalNoticeDiv + span#legalNoticeSpan {{_ 'acceptance_of_our_legalNotice'}} + a#legalNoticeAtLink.at-link(href="{{currentSetting.legalNotice}}", target="_blank", rel="noopener noreferrer") + | {{_ 'legalNotice'}} + div.at-form-lang + label(for="userform-set-language-select") {{_ 'changeLanguagePopup-title'}} + select.select-lang.js-userform-set-language#userform-set-language-select(aria-label="{{_ 'changeLanguagePopup-title'}}") + each languages + if isCurrentLanguage + if rtl + option(value="{{tag}}" selected="selected") {{name}} (RTL) + else + option(value="{{tag}}" selected="selected") {{name}} else - option(value="{{tag}}" selected="selected") {{name}} - else - if rtl - option(value="{{tag}}") {{name}} (RTL) - else - option(value="{{tag}}") {{name}} + if rtl + option(value="{{tag}}") {{name}} (RTL) + else + option(value="{{tag}}") {{name}} template(name="defaultLayout") +header diff --git a/client/components/main/myCards.css b/client/components/main/myCards.css index 4b83555fa..c97f0c9d3 100644 --- a/client/components/main/myCards.css +++ b/client/components/main/myCards.css @@ -1,22 +1,18 @@ -.my-cards-board-wrapper { - border-radius: 0 0 0.5vw 0.5vw; - min-width: min(400px, 52vw); - margin-bottom: 2.5vh; - margin-right: auto; - margin-left: auto; - border-width: 0.3vw; - border-style: solid; - border-color: #a2a2a2; +body.mobile-mode { + .my-cards-board-wrapper { + width: 100vw; + } + .my-cards-swimlane-body { + grid-auto-flow: row; + } } -.my-cards-board-title { - font-size: clamp(1.2rem, 3vw, 1.6rem); - font-weight: bold; - padding: 0.7vh 0.7vw; - background-color: #808080; - color: #fff; +.my-cards-swimlane-body { + display: grid; + grid-auto-flow: column; + gap: 1ch; } .my-cards-swimlane-title { - font-size: clamp(1rem, 2.5vw, 1.3rem); + font-size: clamp(1em, 2.5vw, 1.3rem); font-weight: bold; padding: 0.7vh 0.7vw; padding-bottom: 0.5vh; @@ -27,48 +23,12 @@ .swimlane-default-color { background-color: #d3d3d3; } -.my-cards-list-title { - font-weight: bold; - font-size: clamp(1rem, 2.5vw, 1.3rem); - text-align: center; - margin-bottom: 0.9vh; -} .my-cards-list-wrapper { - margin: 1.3vh 1.3vw; - border-radius: 0.7vw; - display: inline-grid; - min-width: min(250px, 32vw); - max-width: min(350px, 45vw); + display: flex; + flex-direction: column; + max-width: clamp(300px, 20vw, 30vw); } -.my-cards-card-wrapper { - margin-top: 0; - margin-bottom: 1.3vh; -} -.my-cards-dueat-list-wrapper { - max-width: min(500px, 65vw); - margin-right: auto; - margin-left: auto; -} -.my-cards-board-table thead { - border-bottom: 3px solid #4d4d4d; - background-color: transparent; -} -.my-cards-board-table th, -.my-cards-board-table td { - border: 0; -} -.my-cards-board-table tr { - border-bottom: 2px solid #a2a2a2; -} -.my-cards-card-title-table { - font-weight: bold; - padding-left: 2px; - max-width: 243px; -} -.my-cards-board-badge { - width: 36px; - height: 24px; - float: left; - border-radius: 5px; - margin-right: 5px; + +body.mobile-mode .my-cards-list-wrapper { + max-width: unset; } diff --git a/client/components/main/myCards.jade b/client/components/main/myCards.jade index 33c8afa01..98e7010f0 100644 --- a/client/components/main/myCards.jade +++ b/client/components/main/myCards.jade @@ -39,15 +39,16 @@ template(name="myCards") .my-cards-swimlane-title(class="{{#if swimlane.colorClass}}{{ swimlane.colorClass }}{{else}}swimlane-default-color{{/if}}") +viewer = swimlane.title - each list in swimlane.myLists - .my-cards-list-wrapper - .my-cards-list-title(class=list.colorClass) - +viewer - = list.title - each card in list.myCards - .my-cards-card-wrapper - a.minicard-wrapper(href=card.originRelativeUrl) - +minicard(card) + .my-cards-swimlane-body + each list in swimlane.myLists + .my-cards-list-wrapper + .my-cards-list-title(class=list.colorClass) + +viewer + = list.title + each card in list.myCards + .my-cards-card-wrapper + a.minicard-wrapper(href=card.originRelativeUrl) + +minicard(card) if $eq myCardsView 'table' .wrapper table.my-cards-board-table diff --git a/client/components/main/popup.css b/client/components/main/popup.css index 8c0a50a42..39cbd49df 100644 --- a/client/components/main/popup.css +++ b/client/components/main/popup.css @@ -1,91 +1,121 @@ .pop-over { - background: #fff; - border-radius: 0.4vw; - border: 1px solid #dbdbdb; + background: #ededed; border-bottom-color: #c2c2c2; - box-shadow: 0 0.2vh 0.8vh rgba(0,0,0,0.3); - position: absolute; - /* Wider default to fit full color palette */ - width: min(380px, 55vw); - z-index: 99999; - margin-top: 0.7vh; + box-shadow: 0 0.2vh 0.8vh rgba(0, 0, 0, 0.3); + /* so they can easily travel with mouse */ + position: fixed; + overflow-x: hidden; + overflow-y: auto; + display: flex; + flex-direction: column; + align-items: stretch; + resize: both; + pointer-events: all; + max-height: 100vh; + + .content-wrapper { + width: auto; + height: auto; + position: relative; + overflow-y: auto; + } + + .content-wrapper >* { + /* low specificity so that it can be transparently overriden, + but could have side effects if no display is explicitely specific in inner content */ + display: flex; + flex: 1; + flex-direction: column; + width: auto; + height: auto; + } +} + +.pop-over a:has(.fa-plus)+ :not(*) { + min-height: 1.5lh; + aspect-ratio: 1/1; + display: flex; + justify-content: center; + margin-top: 0.2lh; } .pop-over hr { - margin: 0.5vh 0px; + margin: 0.3lh 0; + /* below everything in the same stacking context when + after, child or explicit z-index */ + z-index: 0; } -.pop-over p, -.pop-over textarea, -.pop-over input[type="text"], -.pop-over input[type="email"], -.pop-over input[type="password"], -.pop-over input[type="file"] { - width: 100%; +.pop-over { + /* feels like it's too ad-hod */ + input, a:not(.js-board-template, .member, .edit-avatar) { + display: inline-flex; + align-items: center; + gap: 1ch; + min-height: 1.5lh; + } } -.pop-over select { - width: 100%; - margin-bottom: 1.8vh; -} -.pop-over textarea { - height: 9vh; -} -.pop-over form a span { - padding: 0 0.7vw; +.pop-over .sub-name { + max-width: clamp(30vw, 500px, 80%); } .pop-over .header { - height: 4.5vh; - position: relative; - margin-bottom: 1vh; + display: flex; + justify-content: space-between; + gap: 1ch; + align-items: center; + padding: 0 1ch; background: #f7f7f7; border-bottom: 1px solid #dcdcdc; color: #666; + min-height: 2lh; } .pop-over .header .header-title { - display: block; - line-height: 4vh; - padding-top: 0.5vh; - margin: 0 1.3vw; + display: flex; font-weight: bold; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; + font-size: 1.2em; + flex: 1; + cursor: grab !important; } -.pop-over .header .back-btn { +.pop-over .back-btn { float: left; overflow: hidden; - width: 4vw; transition: width 0.2s; } -.pop-over .header .back-btn i.fa { - margin: 1.3vw; - margin-top: 1.5vh; -} -.pop-over .header .back-btn.is-hidden { +.pop-over .back-btn.is-hidden { width: 0; } -.pop-over .header .close-btn { - padding: 1.3vh 1.3vw 1.3vh 0.5vw; - position: absolute; - top: 0; - right: 0; -} + .pop-over.no-title .header { background: none; } -.pop-over .content-wrapper { - width: 100%; - max-height: calc(70vh + 20px); - overflow-y: auto; - overflow-x: hidden; + +.pop-over { + .content-wrapper, .header { + display: flex; + align-items: center; + } } -/* Allow dynamic max-height to override default constraint */ -.pop-over[style*="max-height"] .content-wrapper { - max-height: inherit; +.pop-over:has(.header) .content { + /* inner content has full width available, + so it is also responsive for margins, sizes, etc */ + overflow-y: auto; } + +.popup-placeholder { + /* This gives relative coordinates but height/width cannot fit the parent's + without it having position: relative; we need to get them programmatically */ + position: absolute; + /* Take all size of parent so it can be useful in computations */ + visibility: hidden; + display: none; +} + .pop-over .content-container { - width: 100%; - max-height: calc(70vh + 20px); - transition: transform 0.2s; + display: flex; + align-items: stretch; + flex: 1; } /* Allow dynamic max-height to override default constraint for content-container */ @@ -93,270 +123,42 @@ max-height: inherit; } -/* Fix overflow in the Member Settings (member menu) popup: - the popup itself gets a max-height inline style, but the header consumes space. - Make the header overlay the scrollable area so the list can't spill out. */ -.pop-over[data-popup="memberMenuPopup"] { - overflow: hidden; -} -.pop-over[data-popup="memberMenuPopup"] > .header { - position: absolute; - top: 0; - left: 0; - right: 0; - margin-bottom: 0; - z-index: 1; -} -.pop-over[data-popup="memberMenuPopup"] > .content-wrapper { - padding-top: calc(4.5vh + 1vh); - box-sizing: border-box; +.pop-over .popup-drag-handle { + cursor: move; } -/* Admin edit popups: use full height */ -.pop-over[data-popup="editUserPopup"], -.pop-over[data-popup="editOrgPopup"], -.pop-over[data-popup="editTeamPopup"] { - height: calc(100vh - 20px) !important; - max-height: calc(100vh - 20px) !important; +body.mobile-mode { + .popup-drag-handle, .close-btn { + font-size: 1.4em; + align-self: center; + } + .pop-over:has(.pop-over-list) { + min-width: 70vw; + } } -.pop-over[data-popup="editUserPopup"] .content-wrapper, -.pop-over[data-popup="editOrgPopup"] .content-wrapper, -.pop-over[data-popup="editTeamPopup"] .content-wrapper { - max-height: calc(100vh - 80px) !important; /* Subtract header height */ - height: calc(100vh - 80px) !important; - overflow-y: auto !important; +.pop-over .header-controls { + display: flex; + gap: 1ch; } - -.pop-over[data-popup="editUserPopup"] .content-container, -.pop-over[data-popup="editOrgPopup"] .content-container, -.pop-over[data-popup="editTeamPopup"] .content-container { - max-height: calc(100vh - 80px) !important; /* Subtract header height */ - height: calc(100vh - 80px) !important; -} - -/* Ensure language popup list can scroll properly */ .pop-over .pop-over-list { - max-height: none; - overflow: visible; -} - -/* Specific styling for language popup list */ -.pop-over[data-popup="changeLanguagePopup"] .pop-over-list { - max-height: none; - overflow: visible; - height: auto; - flex: 1; -} - -/* Ensure content div in language popup contains all items */ -.pop-over[data-popup="changeLanguagePopup"] .content { - height: auto; - /* Remove forced min-height to avoid top gap */ display: flex; flex-direction: column; + flex: 1; + font-size: 1.1rem; + padding: 0 1ch; + >li>a { + display: grid; + grid-auto-flow: column; + grid-auto-columns: fit-content; + justify-content: start; + padding: 0 0.5ch; + column-gap: 1ch; + .sub-name { + text-align: end; + } + } } - -/* Ensure hidden stack pages truly take no space */ -.pop-over[data-popup="changeLanguagePopup"] .content.no-height { - min-height: 0 !important; - height: 0 !important; - padding: 0 !important; - margin: 0 !important; - visibility: hidden !important; -} - -/* Make language popup extend to bottom of browser window */ -.pop-over[data-popup="changeLanguagePopup"] { - position: fixed !important; - bottom: 0 !important; - top: auto !important; - left: auto !important; - right: 20px !important; - width: auto !important; - max-width: 450px !important; - height: 100vh !important; - max-height: 100vh !important; - min-height: 300px !important; - display: flex !important; - flex-direction: column !important; - margin: 0 !important; -} - -/* Allow dynamic height for Change Language popup */ -.pop-over[data-popup="changeLanguagePopup"] .header { - flex-shrink: 0 !important; - height: auto !important; -} - -.pop-over[data-popup="changeLanguagePopup"] .content-wrapper { - flex: 1 !important; - overflow-y: auto !important; - overflow-x: hidden !important; - min-height: 0 !important; - max-height: none !important; - height: auto !important; - width: 100% !important; -} - -.pop-over[data-popup="changeLanguagePopup"] .content-container { - height: auto !important; - max-height: none !important; - flex: 1 !important; - display: flex !important; - flex-direction: column !important; - width: 100% !important; -} - -.pop-over[data-popup="changeLanguagePopup"] .content { - height: auto !important; - max-height: none !important; - padding-bottom: 50px !important; - width: 100% !important; -} - -/* Date popup sizing for native HTML inputs */ -.pop-over[data-popup="editCardReceivedDatePopup"], -.pop-over[data-popup="editCardStartDatePopup"], -.pop-over[data-popup="editCardDueDatePopup"], -.pop-over[data-popup="editCardEndDatePopup"], -.pop-over[data-popup*="Date"] { - width: min(400px, 90vw) !important; /* Smaller width for native inputs */ - min-width: 350px !important; - max-height: 80vh !important; -} - -.pop-over[data-popup="editCardReceivedDatePopup"] .content-wrapper, -.pop-over[data-popup="editCardStartDatePopup"] .content-wrapper, -.pop-over[data-popup="editCardDueDatePopup"] .content-wrapper, -.pop-over[data-popup="editCardEndDatePopup"] .content-wrapper, -.pop-over[data-popup*="Date"] .content-wrapper { - max-height: 60vh !important; - overflow-y: auto !important; -} - -.pop-over[data-popup="editCardReceivedDatePopup"] .content-container, -.pop-over[data-popup="editCardStartDatePopup"] .content-container, -.pop-over[data-popup="editCardDueDatePopup"] .content-container, -.pop-over[data-popup="editCardEndDatePopup"] .content-container, -.pop-over[data-popup*="Date"] .content-container { - max-height: 60vh !important; -} - -/* Native HTML input styling */ -.pop-over[data-popup*="Date"] .datepicker-container { - width: 100% !important; - padding: 15px !important; -} - -.pop-over[data-popup*="Date"] .datepicker-container .fields { - display: flex !important; - gap: 15px !important; - margin-bottom: 15px !important; -} - -.pop-over[data-popup*="Date"] .datepicker-container .fields .left, -.pop-over[data-popup*="Date"] .datepicker-container .fields .right { - flex: 1 !important; - width: auto !important; -} - -.pop-over[data-popup*="Date"] .datepicker-container label { - display: block !important; - margin-bottom: 5px !important; - font-weight: bold !important; -} - -.pop-over[data-popup*="Date"] .datepicker-container input[type="date"], -.pop-over[data-popup*="Date"] .datepicker-container input[type="time"] { - width: 100% !important; - padding: 8px !important; - border: 1px solid #ccc !important; - border-radius: 4px !important; - font-size: 14px !important; - box-sizing: border-box !important; -} - -.pop-over[data-popup*="Date"] .datepicker-container input[type="date"]:focus, -.pop-over[data-popup*="Date"] .datepicker-container input[type="time"]:focus { - outline: none !important; - border-color: #007cba !important; - box-shadow: 0 0 0 2px rgba(0, 124, 186, 0.2) !important; -} - -/* Ensure date popup buttons stay within popup boundaries */ -.pop-over[data-popup="editCardReceivedDatePopup"] .content, -.pop-over[data-popup="editCardStartDatePopup"] .content, -.pop-over[data-popup="editCardDueDatePopup"] .content, -.pop-over[data-popup="editCardEndDatePopup"] .content, -.pop-over[data-popup*="Date"] .content { - max-height: 60vh !important; /* Leave space for buttons */ - overflow-y: auto !important; - padding-bottom: 100px !important; /* More space for buttons */ - margin-bottom: 0 !important; -} - -.pop-over[data-popup="editCardReceivedDatePopup"] .datepicker-container, -.pop-over[data-popup="editCardStartDatePopup"] .datepicker-container, -.pop-over[data-popup="editCardDueDatePopup"] .datepicker-container, -.pop-over[data-popup="editCardEndDatePopup"] .datepicker-container, -.pop-over[data-popup*="Date"] .datepicker-container { - max-height: 50vh !important; /* Limit calendar height */ - overflow-y: auto !important; - margin-bottom: 20px !important; /* Space before buttons */ -} - -/* Ensure buttons are properly positioned */ -.pop-over[data-popup="editCardReceivedDatePopup"] .edit-date, -.pop-over[data-popup="editCardStartDatePopup"] .edit-date, -.pop-over[data-popup="editCardDueDatePopup"] .edit-date, -.pop-over[data-popup="editCardEndDatePopup"] .edit-date, -.pop-over[data-popup*="Date"] .edit-date { - display: flex !important; - flex-direction: column !important; - height: 100% !important; -} - -.pop-over[data-popup="editCardReceivedDatePopup"] .edit-date .fields, -.pop-over[data-popup="editCardStartDatePopup"] .edit-date .fields, -.pop-over[data-popup="editCardDueDatePopup"] .edit-date .fields, -.pop-over[data-popup="editCardEndDatePopup"] .edit-date .fields, -.pop-over[data-popup*="Date"] .edit-date .fields { - flex-shrink: 0 !important; - margin-bottom: 15px !important; -} - -.pop-over[data-popup="editCardReceivedDatePopup"] .edit-date .js-datepicker, -.pop-over[data-popup="editCardStartDatePopup"] .edit-date .js-datepicker, -.pop-over[data-popup="editCardDueDatePopup"] .edit-date .js-datepicker, -.pop-over[data-popup="editCardEndDatePopup"] .edit-date .js-datepicker, -.pop-over[data-popup*="Date"] .edit-date .js-datepicker { - flex: 1 !important; - overflow-y: auto !important; -} - - - -.pop-over[data-popup="editCardReceivedDatePopup"] .edit-date button, -.pop-over[data-popup="editCardStartDatePopup"] .edit-date button, -.pop-over[data-popup="editCardDueDatePopup"] .edit-date button, -.pop-over[data-popup="editCardEndDatePopup"] .edit-date button, -.pop-over[data-popup*="Date"] .edit-date button { - flex-shrink: 0 !important; - margin-top: 15px !important; - position: relative !important; - z-index: 10 !important; -} -.pop-over .content-container .content { - /* Match wider popover, leave padding */ - width: 100%; - padding: 0 1.3vw 1.3vh; - box-sizing: border-box; - /* Ensure content is not shifted left */ - margin-left: 0 !important; - transform: none !important; -} - /* Utility: remove left gutter inside specific popups */ .pop-over .content .flush-left { margin-left: 0; @@ -378,58 +180,15 @@ .pop-over .content form.create-label .palette-colors { margin-left: 0; padding-left: 0; - width: 100%; + display: grid; + grid-template-columns: repeat(5, 1fr); } /* Color palette items: ensure proper positioning */ .pop-over .content .palette-colors .palette-color { - margin-left: 0; - margin-right: 2px; - margin-bottom: 2px; -} - -/* Global fix for all popup content to prevent left shifting */ -.pop-over .content * { - margin-left: 0 !important; - transform: none !important; -} - -/* Override any potential left shifting for specific elements */ -.pop-over .content form, -.pop-over .content .palette-colors, -.pop-over .content .pop-over-list, -.pop-over .content .flush-left { - margin-left: 0 !important; - padding-left: 0 !important; - transform: none !important; -} - -/* Fix popup depth containers that cause left shifting */ -.pop-over .popup-container-depth-1, -.pop-over .popup-container-depth-2, -.pop-over .popup-container-depth-3, -.pop-over .popup-container-depth-4, -.pop-over .popup-container-depth-5, -.pop-over .popup-container-depth-6 { - transform: none !important; - margin-left: 0 !important; - padding-left: 0 !important; -} - -/* Ensure buttons don’t reserve left space; align to flow */ -.pop-over .content form.swimlane-color-popup .primary.confirm, -.pop-over .content form.swimlane-color-popup .negate.wide.right, -.pop-over .content .swimlane-height-popup .primary.confirm, -.pop-over .content .swimlane-height-popup .negate.wide.right { - float: none; - margin-left: 0; -} -.pop-over .content-container .content.no-height { - height: 0; - overflow: hidden; - padding: 0; margin: 0; - visibility: hidden; + border-radius: 0; + outline: 0.1ch solid black; } .pop-over.search-over { background: #f0f0f0; @@ -456,24 +215,6 @@ .pop-over .sk-spinner { margin: 40px auto; } -.pop-over .popup-container-depth-1 { - transform: translateX(-300px); -} -.pop-over .popup-container-depth-2 { - transform: translateX(-600px); -} -.pop-over .popup-container-depth-3 { - transform: translateX(-900px); -} -.pop-over .popup-container-depth-4 { - transform: translateX(-1200px); -} -.pop-over .popup-container-depth-5 { - transform: translateX(-1500px); -} -.pop-over .popup-container-depth-6 { - transform: translateX(-1800px); -} .select-members-list, .select-avatars-list { margin-bottom: 8px; @@ -487,15 +228,12 @@ cursor: pointer; display: block; font-weight: 700; - padding: 1.5px 10px; + padding-inline: 2vmin 10vmin; position: relative; margin: 0; text-decoration: none; overflow: hidden; - line-height: 33px; display:flex; -/* flex-wrap:wrap;*/ - gap:5px; align-items: center; color: #000 !important; } @@ -506,7 +244,6 @@ .pop-over-list li > a .item-name { display: block; width: auto; - padding-right: 22px; } .pop-over-list li > a:not(.disabled):hover { background-color: #005377; @@ -522,9 +259,9 @@ .pop-over-list li > a .sub-name { color: #8c8c8c; display: block; - font-size: 12px; + font-size: 0.8em; font-weight: 400; - line-height: 15px; + line-height: 1.2em; } .pop-over-list li > a.current { background-color: #e2e6e9; @@ -570,156 +307,21 @@ body.grey-icons-enabled .pop-over-list .pop-over-list.checkable .fa-check { color: #7a7a7a; } -.pop-over.miniprofile .header { - border-bottom-color: transparent; - height: 30px; - position: absolute; - right: 0; - top: 0; - width: 60px; - z-index: 1; -} -.pop-over.miniprofile .header-title { - display: none; -} -.pop-over.miniprofile .pop-over-list { - padding-top: 8px; -} -.pop-over.miniprofile .miniprofile-header { - margin-top: 8px; - min-height: 56px; - position: relative; -} -.pop-over.miniprofile .miniprofile-header .member, -.pop-over.miniprofile .miniprofile-header .avatar { - position: absolute; - top: 2px; - left: 2px; - height: 50px; - width: 50px; -} -.pop-over.miniprofile .miniprofile-header .info { - margin: 0 0 0 64px; - word-wrap: break-word; -} -.pop-over.miniprofile .miniprofile-header .info h3 a { - text-decoration: none; -} -.pop-over.miniprofile .miniprofile-header .info h3 a:hover { - text-decoration: underline; -} -@media screen and (max-width: 800px) { - .pop-over { - width: 100%; - height: 100%; - overflow: hidden; - margin-top: 0px; - border: 0px solid #dbdbdb; - /* Ensure popups appear above card details on mobile */ - z-index: 999999 !important; - /* iOS Safari scrolling fix */ - -webkit-overflow-scrolling: touch; - } - .pop-over .header { - color: #fff; - background: #2980b9; - height: 48px; - padding: 0px 0px; - border: 0px; - margin: 0px 0px; - width: 100%; - position: absolute; - top: 0px; - } - .pop-over .header .header-title { - font-size: 20px; - font-weight: normal; - padding-top: 8px; - } - .pop-over .header .back-btn { - width: 30px; - padding: 8px 12px 8px 12px; - } - .pop-over .header .back-btn i.fa { - color: #fff; - } - .pop-over .header .close-btn { - padding: 10px 12px; - } - .pop-over .header .close-btn i.fa { - font-size: 24px; - color: #fff; - } - .pop-over .content-wrapper { - width: 100%; - height: calc(100% - 48px); - overflow-y: scroll; - overflow-x: hidden; - margin: 48px 0px 0px 0px; - } - .pop-over .content-container { - width: 100%; - height: 100%; - max-height: 100%; - } - .pop-over .content-container .content { - width: calc(100% - 20px); - height: calc(100% - 20px); - padding: 10px; - } - .pop-over .content-container .content form { - margin: 10px 10px; - width: calc(100% - 20px); - } - .pop-over .content-container .content p, - .pop-over .content-container .content textarea, - .pop-over .content-container .content input[type="text"], - .pop-over .content-container .content input[type="email"], - .pop-over .content-container .content input[type="password"], - .pop-over .content-container .content input[type="file"] { - width: 100%; - box-sizing: border-box; - } - .pop-over .pop-over-list li > a { - width: calc(100% - 20px); - margin: 0px 0px; - } - .pop-over .popup-container-depth-1 { - transform: none !important; - } - .pop-over .popup-container-depth-2 { - transform: none !important; - } - .pop-over .popup-container-depth-3 { - transform: none !important; - } - .pop-over .popup-container-depth-4 { - transform: none !important; - } - .pop-over .popup-container-depth-5 { - transform: none !important; - } - .pop-over .popup-container-depth-6 { - transform: none !important; - } + +.pop-over .content > form { + padding: 0 1ch; + gap: 0.2lh; + display: flex; + max-width: clamp(20vw, 400px, 50vw); } -/* Force full-screen popups in mobile mode regardless of screen width */ -body.mobile-mode .pop-over { - position: fixed !important; - top: 0 !important; - left: 0 !important; - right: 0 !important; - bottom: 0 !important; - width: 100vw !important; - height: 100vh !important; - max-width: 100vw !important; - max-height: 100vh !important; -} -body.mobile-mode .pop-over .content-wrapper { - width: 100% !important; - height: calc(100vh - 48px) !important; - max-height: calc(100vh - 48px) !important; - overflow-y: auto !important; - overflow-x: hidden !important; +body.mobile-mode .pop-over .content>form { + max-width: 100%; } + +.pop-over .board-subtask-settings { + >h3 { + display: flex; + flex-direction: column; + } +} \ No newline at end of file diff --git a/client/components/main/popup.js b/client/components/main/popup.js index ba20a6d3c..4c17c50b5 100644 --- a/client/components/main/popup.js +++ b/client/components/main/popup.js @@ -1,39 +1,696 @@ -Popup.template.events({ - 'click .js-back-view'() { - Popup.back(); - }, - 'click .js-close-pop-over'() { - Popup.close(); - }, - 'click .js-confirm'() { - this.__afterConfirmAction.call(this); - }, - // This handler intends to solve a pretty tricky bug with our popup - // transition. The transition is implemented using a large container - // (.content-container) that is moved on the x-axis (from 0 to n*PopupSize) - // inside a wrapper (.container-wrapper) with a hidden overflow. The problem - // is that sometimes the wrapper is scrolled -- even if there are no - // scrollbars. This happen for instance when the newly opened popup has some - // focused field, the browser will automatically scroll the wrapper, resulting - // in moving the whole popup container outside of the popup wrapper. To - // disable this behavior we have to manually reset the scrollLeft position - // whenever it is modified. - 'scroll .content-wrapper'(evt) { - evt.currentTarget.scrollLeft = 0; - }, -}); +import { BlazeComponent } from 'meteor/peerlibrary:blaze-components'; +import { Template } from 'meteor/templating'; -// When a popup content is removed (ie, when the user press the "back" button), -// we need to wait for the container translation to end before removing the -// actual DOM element. For that purpose we use the undocumented `_uihooks` API. -Popup.template.onRendered(() => { - const container = this.find('.content-container'); - container._uihooks = { - removeElement(node) { - $(node).addClass('no-height'); - $(container).one(CSSEvents.transitionend, () => { - node.parentNode.removeChild(node); +const PopupBias = { + Before: Symbol("S"), + Overlap: Symbol("M"), + After: Symbol("A"), + Fullscreen: Symbol("F"), + includes(e) { + return Object.values(this).includes(e); + } +} + +// this class is a bit cumbersome and could probably be done simpler. +// it manages two things : initial placement and sizing given an opener element, +// and then movement and resizing. one difficulty was to be able, as a popup +// which can be resized from the "outside" (CSS4) and move from the inside (inner +// component), which also grows and shrinks frequently, to adapt. +// I tried many approach and failed to get the perfect fit; I feel that there is +// always something indeterminate at some point. so the only drawback is that +// if a popup contains another resizable component (e.g. card details), and if +// it has been resized (with CSS handle), it will lose its dimensions when dragging +// it next time. +class PopupDetachedComponent extends BlazeComponent { + onCreated() { + // Set by parent/caller (usually PopupComponent) + ({ nonPlaceholderOpener: this.nonPlaceholderOpener, closeDOMs: this.closeDOMs = [], followDOM: this.followDOM } = this.data()); + + + if (typeof(this.closeDOMs) === "string") { + // helper for passing arg in JADE template + this.closeDOMs = this.closeDOMs.split(';'); + } + + // The popup's own header, if it exists + this.closeDOMs.push("click .js-close-detached-popup"); + } + + // Main intent of this component is to have a modular popup with defaults: + // - sticks to its opener while being a child of body (thus in the same stacking context, no z-index issue) + // - is responsive on shrink while keeping position absolute + // - can grow back to initial position step by step + // - exposes various sizes as CSS variables so each rendered popup can use them to adapt defaults + // * issue is that it is done by hand, with heurisitic/simple algorithm from my thoughts, not sure it covers edge cases + // * however it works well so far and maybe more "fixed" element should be popups + onRendered() { + // Remember initial ratio between initial dimensions and viewport + const viewportHeight = window.innerHeight; + const viewportWidth = window.innerWidth; + + this.popup = this.firstNode(); + this.popupOpener = this.data().openerElement; + + const popupStyle = window.getComputedStyle(this.firstNode()); + // margin may be in a relative unit, not computable in JS, but we get the actual pixels here + this.popupMargin = parseFloat(popupStyle.getPropertyValue("--popup-margin"), 10) || Math.min(window.innerWidth / 50, window.innerHeight / 50); + + this.dims(this.computeMaxDims()); + + this.initialPopupWidth = this.popupDims.width; + this.initialPopupHeight = this.popupDims.height; + this.initialHeightRatio = this.initialPopupHeight / viewportHeight; + this.initialWidthRatio = this.initialPopupWidth / viewportWidth; + + this.dims(this.computePopupDims()); + + + if (this.followDOM) { + this.innerElement = this.find(this.followDOM) ?? document.querySelector(this.followDOM); + } + + this.follow(); + this.toFront(); + + // #FIXME the idea of keeping the initial ratio on resize is quite bad. remove that part. + // there is a reactive variable for window resize in Utils, but the interface is too slow + // with all reactive stuff, use events when possible and when not really bypassing logic + $(window).on('resize', () => { + // #FIXME there is a bug when window grows; popup outer container + // will grow beyond the size of content and it's not easy to fix for me (and I feel tired of this popup) + this.dims(this.computePopupDims()); + }); + } + + margin() { + return this.popupMargin; + } + + ensureDimsLimit(dims) { + // boilerplate to make sure that popup visually fits + let { left, top, width, height } = dims; + let overflowBottom = top + height + 2 * this.margin() - window.innerHeight; + let overflowRight = left + width + 2 * this.margin() - window.innerWidth; + if (overflowRight > 0) { + width = Math.max(20 * this.margin(), Math.min(width - overflowRight, window.innerWidth - 2 * this.margin())); + } + if (overflowBottom > 0) { + height = Math.max(10 * this.margin(), Math.min(height - overflowBottom, window.innerHeight - 2 * this.margin())); + } + left = Math.max(left, this.margin()); + top = Math.max(top, this.margin()); + return { left, top, width, height } + } + + dims(newDims) { + if (!this.popupDims) { + this.popupDims = {}; + } + if (newDims) { + newDims = this.ensureDimsLimit(newDims); + for (const e of Object.keys(newDims)) { + let value = parseFloat(newDims[e]); + if (!isNaN(value)) { + $(this.popup).css(e, `${value}px`); + this.popupDims[e] = value; + } + } + } + return this.popupDims; + } + + isFullscreen() { + return this.fullscreen; + } + + maximize() { + this.fullscreen = true; + this.dims(this.computePopupDims()); + if (this.innerElement) { + $(this.innerElement).css('width', ''); + $(this.innerElement).css('height', '') + } + } + + minimize() { + this.fullscreen = false; + this.dims(this.computePopupDims()); + } + + follow() { + const adaptChild = new ResizeObserver((_) => { + if (this.fullscreen) {return} + const width = this.innerElement?.scrollWidth || this.popup.scrollWidth; + const height = this.innerElement?.scrollHeight || this.popup.scrollHeight; + // we don't want to run this during something that we have caused, eg. dragging + if (!this.mouseDown) { + // extra-"future-proof" stuff: if somebody adds a margin to the popup, it would trigger a loop + if (Math.abs(this.dims().width - width) < 20 && Math.abs(this.dims().height - height) < 20) { return } + + // if inner shrinks, follow + if (width < this.dims().width || height < this.dims().height) { + this.dims({ width, height }); + } + // otherwise it may be complicated to find a generic situation, but we have the + // classic positionning procedure which works, so use it and ignore positionning + else { + const newDims = this.computePopupDims(); + // a bit twisted/ad-hoc for card details, in the edge case where they are opened when collapsed then uncollapsed, + // not sure to understand why the sizing works differently that starting uncollapsed then doing the same sequence + this.dims(this.ensureDimsLimit({ + top: this.dims().top, + left: this.dims().left, + width: Math.max(newDims.width, width), + height: Math.max(newDims.height, height) + })); + } + } + else { + const { width, height } = this.popup.getBoundingClientRect(); + // only case when we bypass .dims(), to avoid loop + this.popupDims.width = width; + this.popupDims.height = height; + } + }); + + if (this.innerElement) { + adaptChild.observe(this.innerElement); + } else { + adaptChild.observe(this.popup); + } + } + + currentZ(z = undefined) { + // relative, add a constant to be above root elements + if (z !== undefined) { + this.firstNode().style.zIndex = parseInt(z) + 10; + } + return parseInt(this.firstNode().style.zIndex) - 10; + } + + // a bit complex... + toFront() { + this.currentZ(Math.max(...PopupComponent.stack.map(p => BlazeComponent.getComponentForElement(p.outerView.firstNode()).currentZ())) || 0 + 1); + + } + + toBack() { + this.currentZ(Math.min(...PopupComponent.stack.map(p => BlazeComponent.getComponentForElement(p.outerView.firstNode()).currentZ())) || 1 - 1); + } + + events() { + // needs to be done at this level; "parent" is not a parent in DOM + let closeEvents = {}; + + this.closeDOMs?.forEach((e) => { + closeEvents[e] = (_) => { + this.parentComponent().destroy(); + } + }) + + const miscEvents = { + 'click .js-confirm'() { + this.data().afterConfirm?.call(this); + }, + // bad heuristic but only for best-effort UI + 'pointerdown .pop-over'() { + this.mouseDown = true; + }, + 'pointerup .pop-over'() { + this.mouseDown = false; + } + }; + + const movePopup = (event) => { + event.preventDefault(); + $(event.target).addClass('is-active'); + const deltaHandleX = this.dims().left - event.clientX; + const deltaHandleY = this.dims().top - event.clientY; + + const onPointerMove = (e) => { + this.dims(this.ensureDimsLimit({ left: e.clientX + deltaHandleX, top: e.clientY + deltaHandleY, width: this.dims().width, height: this.dims().height })); + + if (this.popup.scrollY) { + this.popup.scrollTo(0, 0); + } + }; + + const onPointerUp = (event) => { + $(document).off('pointermove', onPointerMove); + $(document).off('pointerup', onPointerUp); + $(event.target).removeClass('is-active'); + }; + + if (Utils.shouldIgnorePointer(event)) { + onPointerUp(event); + return; + } + + $(document).on('pointermove', onPointerMove); + $(document).on('pointerup', onPointerUp); + }; + + // We do not manage dragging without our own header + const handleDOM = this.data().handleDOM; + if (this.data().showHeader) { + const handleSelector = Utils.isMiniScreen() ? '.js-popup-drag-handle' : '.header-title'; + miscEvents[`pointerdown ${handleSelector}`] = (e) => movePopup(e); + } + if (handleDOM) { + miscEvents[`pointerdown ${handleDOM}`] = (e) => movePopup(e); + } + return super.events().concat(closeEvents).concat(miscEvents); + } + + computeMaxDims() { + // Get size of inner content, even if it overflows + const content = this.find('.content'); + let popupHeight = content.scrollHeight; + let popupWidth = content.scrollWidth; + if (this.data().showHeader) { + const headerRect = this.find('.header'); + popupHeight += headerRect.scrollHeight; + popupWidth = Math.max(popupWidth, headerRect.scrollWidth) + } + return { width: Math.max(popupWidth, $(this.popup).width()), height: Math.max(popupHeight, $(this.popup).height()) }; + + } + + placeOnSingleDimension(elementLength, openerPos, openerLength, maxLength, biases, n) { + // avoid too much recursion if no solution + if (!n) { + n = 0; + } + if (n >= 5) { + // if we exhausted a bias, remove it + n = 0; + biases.pop(); + if (biases.length === 0) { + return -1; + } + } else { + n += 1; + } + + if (!biases?.length) { + const cut = maxLength / 3; + + if (openerPos < cut) { + // Corresponds to the default ordering: if element is close to the axe's start, + // try to put the popup after it; then to overlap; and give up otherwise. + biases = [PopupBias.After, PopupBias.Overlap] + } + else if (openerPos > 2 * cut) { + // Same idea if popup is close to the end + biases = [PopupBias.Before, PopupBias.Overlap] + } + else { + // If in the middle, try to overlap: choosing between start or end, even for + // default, is too arbitrary; a custom order can be passed in argument. + biases = [PopupBias.Overlap] + } + } + // Remove the first element and get it + const bias = biases.splice(0, 1)[0]; + + let factor; + const openerRef = openerPos + openerLength / 2; + if (bias === PopupBias.Before) { + factor = 1; + } + else if (bias === PopupBias.Overlap) { + factor = openerRef / maxLength; + } + else { + factor = 0; + } + + let candidatePos = openerRef - elementLength * factor; + const deltaMax = candidatePos + elementLength - maxLength; + if (candidatePos < 0 || deltaMax > 0) { + if (deltaMax <= 2 * this.margin()) { + // if this is just a matter of margin, try again + // useful for (literal) corner cases + biases = [bias].concat(biases); + openerPos -= 5; + } + if (biases.length === 0) { + // we could have returned candidate position even if the size is too large, so + // that the caller can choose, but it means more computations and edge cases... + // any negative means fullscreen overall as the caller will take the maximum between + // margin and candidate. + return -1; + } + return this.placeOnSingleDimension(elementLength, openerPos, openerLength, maxLength, biases, n); + } + return candidatePos; + } + + computePopupDims() { + if (!this.isRendered?.()) { + return; + } + + // Coordinates of opener related to viewport + let { x: parentX, y: parentY } = this.nonPlaceholderOpener.getBoundingClientRect(); + let { height: parentHeight, width: parentWidth } = this.nonPlaceholderOpener.getBoundingClientRect(); + + // Initial dimensions scaled to the viewport, if it has changed + let popupHeight = window.innerHeight * this.initialHeightRatio; + let popupWidth = window.innerWidth * this.initialWidthRatio; + + if (this.fullscreen || Utils.isMiniScreen() && popupWidth >= 4 * window.innerWidth / 5 && popupHeight >= 4 * window.innerHeight / 5) { + // Go fullscreen! + popupWidth = window.innerWidth; + // Avoid address bar, let a bit of margin to scroll + popupHeight = 4 * window.innerHeight / 5; + return ({ + width: window.innerWidth, + height: window.innerHeight, + left: 0, + top: 0, }); - }, - }; -}); + } else { + // Current viewport dimensions + let maxHeight = window.innerHeight - this.margin() * 2; + let maxWidth = window.innerWidth - this.margin() * 2; + let biasX, biasY; + if (Utils.isMiniScreen()) { + // On mobile I found that being able to close a popup really close from where it has been clicked + // is comfortable; so given that the close button is top-right, we prefer the position of + // popup being right-bottom, when possible. We then try every position, rather than choosing + // relatively to the relative position of opener in viewport + biasX = [PopupBias.Before, PopupBias.Overlap, PopupBias.After]; + biasY = [PopupBias.After, PopupBias.Overlap, PopupBias.Before]; + } + + const candidateX = this.placeOnSingleDimension(popupWidth, parentX, parentWidth, maxWidth, biasX); + const candidateY = this.placeOnSingleDimension(popupHeight, parentY, parentHeight, maxHeight, biasY); + + // Reasonable defaults that can be overriden by CSS later: popups are tall, try to fit the reste + // of the screen starting from parent element, or full screen if element if not fitting + return ({ + width: popupWidth, + height: popupHeight, + left: candidateX, + top: candidateY, + }); + } + } +} + +class PopupComponent extends BlazeComponent { + static stack = []; + // good enough as long as few occurences of such cases + static multipleBlacklist = ["cardDetails"]; + + // to provide compatibility with Popup.open(). + static open(args) { + const openerView = Blaze.getView(args.openerElement); + if (!openerView) { + console.warn(`no parent found for popup ${args.name}, attaching to body: this should not happen`); + } + + + // render ourselves; everything is automatically managed from that moment, we just added + // a level of indirection but this will not interfere with data + const popup = new PopupComponent(); + Blaze.renderWithData( + popup.renderComponent(BlazeComponent.currentComponent()), + args, + args.openerElement, + null, + openerView + ); + return popup; + } + + static destroy() { + PopupComponent.stack.at(-1)?.destroy(); + } + + static findParentPopup(element) { + return BlazeComponent.getComponentForElement($(element).closest('.pop-over')[0]); + } + + static toFront(event) { + const popup = PopupComponent.findParentPopup(event.target) + popup?.toFront(); + return popup; + } + + static toBack(event) { + const popup = PopupComponent.findParentPopup(event.target); + popup?.toBack(); + return popup; + } + + static maximize(event) { + const popup = PopupComponent.findParentPopup(event.target); + popup?.toFront(); + popup?.maximize(); + return popup; + } + + static minimize(event) { + const popup = PopupComponent.findParentPopup(event.target); + popup?.minimize(); + return popup; + } + + + getOpenerElement(view) { + // Look for the first parent view whose first DOM element is not virtually us + const firstNode = $(view.firstNode()); + + // The goal is to have the best chances to get the element whose size and pos + // are relevant; e.g. when clicking on a date on a minicard, we don't wan't + // the opener to be set to the minicard. + // In order to work in general, we need to take special situations into account, + // e.g. the placeholder is isolated, or does not have previous node, and so on. + // In general we prefer previous node, then next, then any displayed sibling, + // then the parent, and so on. + let candidates = []; + if (!firstNode.hasClass(this.popupPlaceholderClass())) { + candidates.push(firstNode); + } + candidates = candidates.concat([firstNode.prev(), firstNode.next()]); + const otherSiblings = Array.from(firstNode.siblings()).filter(e => !candidates.includes(e)); + + for (const cand of candidates.concat(otherSiblings)) { + const displayCSS = cand?.css("display"); + if (displayCSS && displayCSS !== "none") { + return cand[0]; + } + } + return this.getOpenerElement(view.parentView); + } + + getParentData(view) {; + let data; + // ⚠️ node can be a text node + while (view.firstNode?.()?.classList?.contains(this.popupPlaceholderClass())) { + view = view.parentView; + data = Blaze.getData(view); + } + // This is VERY IMPORTANT to get data like this and not with templateInstance.data, + // because this form is reactive. So all inner popups have reactive data, which is nice + return data; + } + + onCreated() { + // #FIXME prevent secondary popups to open + // Special "magic number" case: never render, for any reason, the same card + // const maybeID = this.parentComponent?.()?.data?.()?._id; + // if (maybeID && PopupComponent.stack.find(e => e.parentComponent().data?.()?._id === maybeID)) { + // this.destroy(); + // return; + // } + // do not render a template multiple times + const existing = PopupComponent.stack.find((e) => (e.name == this.data().name)); + if (existing && PopupComponent.multipleBlacklist.indexOf(this.data().name)) { + // ⚠️ is there a default better than another? I feel that closing existing + // popup is not bad in general because having the same button for open and close + // is common + if (PopupComponent.multipleBlacklist.includes(existing.name)) { + existing.destroy(); + } + // but is could also be re-rendering, eg + // existing.render(); + return; + } + + // All of this, except name, is optional. The rest is provided "just in case", for convenience (hopefully) + // + // - name is the name of a template to render inside the popup (to the detriment of its size) or the contrary + // - showHeader can be turned off if the inner content always have a header with buttons and so on + // - title is shown when header is shown + // - miscOptions is for compatibility + // - closeVar is an optional string representing a Session variable: if set, the popup reactively closes when the variable changes and set the variable to null on close + // - closeDOMs can be used alternatively; it is an array of " " to listen that closes the popup. + // if header is shown, closing the popup is already managed. selector is relative to the inner template (same as its event map) + // - followDOM is an element whose dimension will serve as reference so that popup can react to inner changes; works only with inline styles (otherwise we probably would need IntersectionObserver-like stuff, async etc) + // - handleDOM is an element who can be clicked to move popup + // it is useful when the content can be redimensionned/moved by code or user; we still manage events, resizes etc + // but allow inner elements or handles to do it (and we adapt). + const data = this.data(); + this.popupArgs = { + name: data.name, + showHeader: data.showHeader ?? true, + title: data.title, + openerElement: data.openerElement, + closeDOMs: data.closeDOMs, + followDOM: data.followDOM, + handleDOM: data.handleDOM, + forceData: data.miscOptions?.dataContextIfCurrentDataIsUndefined, + afterConfirm: data.miscOptions?.afterConfirm, + } + this.name = this.data().name; + + this.innerTemplate = Template[this.name]; + this.innerComponent = BlazeComponent.getComponent(this.name); + + this.outerComponent = BlazeComponent.getComponent('popupDetached'); + if (!(this.innerComponent || this.innerTemplate)) { + throw new Error(`template and/or component ${this.name} not found`); + } + + // If arg is not set, must be closed manually by calling destroy() + if (this.popupArgs.closeVar) { + this.closeInitialValue = Session.get(this.data().closeVar); + if (!this.closeInitialValue === undefined) { + this.autorun(() => { + if (Session.get(this.data().closeVar) !== this.closeInitialValue) { + this.onDestroyed(); + } + }); + } + } + } + + popupPlaceholderClass() { + return "popup-placeholder"; + } + + render() { + const oldOuterView = this.outerView; + // see below for comments + this.outerView = Blaze.renderWithData( + // data is passed through the parent relationship + // we need to render it again to keep events in sync with inner popup + this.outerComponent.renderComponent(this.component()), + this.popupArgs, + document.body, + null, + this.openerView + ); + this.innerView = Blaze.renderWithData( + // the template to render: either the content is a BlazeComponent or a regular template + // if a BlazeComponent, render it as a template first + this.innerComponent?.renderComponent?.(this.component()) || this.innerTemplate, + // dataContext used for rendering: each time we go find data, because it is non-reactive + () => (this.popupArgs.forceData || this.getParentData(this.currentView)), + // DOM parent: ask to the detached popup, will be inserted at the last child + this.outerView.firstNode()?.getElementsByClassName('content')?.[0] || document.body, + // "stop" DOM element; we don't use + null, + // important: this is the Blaze.View object which will be set as `parentView` of + // the rendered view. we set it as the parent view, so that the detached popup + // can interact with its "parent" without being a child of it, and without + // manipulating DOM directly. + this.openerView + ); + if (oldOuterView) { + Blaze.remove(oldOuterView); + } + } + + onRendered() { + if (this.detached) {return} + // Use plain Blaze stuff to be able to render all templates, but use components when available/relevant + this.currentView = Blaze.currentView || Blaze.getView(this.component().firstNode()); + + // Placement will be related to the opener (usually clicked element) + // But template data and view related to the opener are not the same: + // - view is probably outer, as is was already rendered on click + // - template data could be found with Template.parentData(n), but `n` can + // vary depending on context: using those methods feels more reliable for this use case + this.popupArgs.openerElement ??= this.getOpenerElement(this.currentView); + this.openerView = Blaze.getView(this.popupArgs.openerElement); + // With programmatic/click opening, we get the "real" opener; with dynamic + // templating we get the placeholder and need to go up to get a glimpse of + // the "real" opener size. It is quite imprecise in that case (maybe the + // interesting opener is a sibling, not an ancestor), but seems to do the job + // for now. + // Also it feels sane that inner content does not have a reference to + // a virtual placeholder. + const opener = this.popupArgs.openerElement; + let sizedOpener = opener; + if (opener.classList?.contains?.(this.popupPlaceholderClass())) { + sizedOpener = opener.parentNode; + } + this.popupArgs.nonPlaceholderOpener = sizedOpener; + + PopupComponent.stack.push(this); + + try { + this.render(); + // Render above other popups by default + } catch(e) { + // If something went wrong during rendering, do not create + // "zombie" popups + console.error(`cannot render popup ${this.name}: ${e}`); + this.destroy(); + } + } + + destroy() { + this.detached = true; + if (!PopupComponent.stack.includes(this)) { + // Avoid loop destroy + return; + } + // Maybe overkill but may help to avoid leaking memory + // as programmatic rendering is less usual + for (const view of [this.innerView, this.currentView, this.outerView]) { + try { + Blaze.remove(view); + } catch { + console.warn(`A view failed to be removed: ${view}`) + } + } + this.innerComponent?.removeComponent?.(); + this.outerComponent?.removeComponent?.(); + this.removeComponent(); + + // not necesserly removed in order, e.g. multiple cards + PopupComponent.stack = PopupComponent.stack.filter(e => e !== this); + } + + + closeWithPlaceholder(parentElement) { + // adapted from https://stackoverflow.com/questions/52834774/dom-event-when-element-is-removed + // strangely, when opener is removed because of a reactive change, this component + // do not get any lifecycle hook called, so we need to bridge the gap. Simply + // "close" popup when placeholder is off-DOM. + while (parentElement.nodeType === Node.TEXT_NODE) { + parentElement = parentElement.parentElement; + } + const placeholder = parentElement.getElementsByClassName(this.popupPlaceholderClass()); + if (!placeholder.length) { + return; + } + const observer = new MutationObserver(() => { + // DOM element being suppressed is reflected in array + if (placeholder.length === 0) { + this.destroy(); + } + }); + observer.observe(parentElement, {childList: true}); + } +} + +PopupComponent.register("popup"); +PopupDetachedComponent.register('popupDetached'); + +export default PopupComponent; \ No newline at end of file diff --git a/client/components/main/popup.tpl.jade b/client/components/main/popup.tpl.jade deleted file mode 100644 index 463b2a5d0..000000000 --- a/client/components/main/popup.tpl.jade +++ /dev/null @@ -1,24 +0,0 @@ -.pop-over.js-pop-over( - class="{{#unless title}}miniprofile{{/unless}}" - class=currentBoard.colorClass - class="{{#unless title}}no-title{{/unless}}" - data-popup="{{popupName}}" - 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 - the "window" by translating .content-container inside .content-wrapper. - .content-container(class="popup-container-depth-{{depth}}") - each stack - //- - XXX We need a better way to express the "is the last element" condition. - Hopefully the @last helper will come soon (or at least @index) - .content(class="{{#unless $eq popupName ../popupName}}no-height{{/unless}}") - +Template.dynamic(template=popupName data=dataContext) - .clearfix diff --git a/client/components/main/spinner_wave.css b/client/components/main/spinner_wave.css index 2855ffbb0..1ec019ed6 100644 --- a/client/components/main/spinner_wave.css +++ b/client/components/main/spinner_wave.css @@ -3,7 +3,7 @@ height: 50px; margin: auto; text-align: center; - font-size: 10px; + } .sk-spinner-wave div { background-color: #333; diff --git a/client/components/notifications/notifications.css b/client/components/notifications/notifications.css index 1fddb553d..39b05c245 100644 --- a/client/components/notifications/notifications.css +++ b/client/components/notifications/notifications.css @@ -1,17 +1,40 @@ -#notifications { - position: relative; -} -#notifications .notifications-drawer-toggle { - display: block; - line-height: 28px; - color: #f2f2f2; - margin: 0 10px; - width: 28px; - height: 28px; - text-align: center; - border: 0; - padding: 0; +.notifications-container { + /* absolute to render close to emoji and render on top, + "naturally" on top because no parent stacking context */ + position: absolute; + right: 0; + top: 1.5lh; + background-color: #fafafa; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.15); + border-radius: 2px; + color: #000; + z-index: 1; } + #notifications .notifications-drawer-toggle.alert { background-color: #eb4646; } + +#notifications { + /* to position popup */ + position: relative; + overflow: visible; +} + +#notifications-drawer { + position: relative; + min-height: min-content; + height: fit-content; + max-height: 100vh; + z-index: 300; + width: max-content; + .fa { + color: #bcbcbc !important; + } +} + +body.mobile-mode { + #notifications-drawer .header { + flex-direction: column; + } +} \ No newline at end of file diff --git a/client/components/notifications/notifications.jade b/client/components/notifications/notifications.jade index b2209a72c..ac426f46d 100644 --- a/client/components/notifications/notifications.jade +++ b/client/components/notifications/notifications.jade @@ -1,6 +1,7 @@ template(name='notifications') #notifications.board-header-btns.right + .notifications-container + if $.Session.get 'showNotificationsDrawer' + +notificationsDrawer(unreadNotifications=unreadNotifications) a.notifications-drawer-toggle(class="{{#if $gt unreadNotifications 0}}alert{{/if}}" title="{{_ 'notifications'}}") i.fa.fa-bell - if $.Session.get 'showNotificationsDrawer' - +notificationsDrawer(unreadNotifications=unreadNotifications) diff --git a/client/components/notifications/notificationsDrawer.css b/client/components/notifications/notificationsDrawer.css index fac7b9574..531ff7c77 100644 --- a/client/components/notifications/notificationsDrawer.css +++ b/client/components/notifications/notificationsDrawer.css @@ -1,38 +1,16 @@ -section#notifications-drawer { - position: fixed; - top: 48px; - right: 0; - width: 400px; - background-color: #fafafa; - box-shadow: 0 1px 2px rgba(0,0,0,0.15); - border-radius: 2px; - max-height: calc(100vh - 28px - 36px); - color: #000; - padding-top: 36px; -} section#notifications-drawer a:hover { color: #2980b9 !important; } -section#notifications-drawer .header { - position: fixed; - top: 48px; - right: 0; - width: calc(400px - 32px); - padding: 8px 16px; +section#notifications-drawer .header { + display: flex; + justify-content: space-between; + padding: 0.5lh 2ch; + gap: 0.5lh; + align-items: center; background: #ededed; border-bottom: 1px solid #dbdbdb; - z-index: 2; } -section#notifications-drawer .header .notification-menu-toggle { - position: absolute; - left: 16px; - top: calc(50% - 12px); - font-size: 20px; - cursor: pointer; - color: #333; - line-height: 24px; -} -section#notifications-drawer .header .notification-menu-toggle:hover { +section#notifications-drawer .header .toggle-read { color: #2980b9; } section#notifications-drawer .header .notification-menu { @@ -88,19 +66,13 @@ section#notifications-drawer .header h5 { margin: 0; } section#notifications-drawer .header .close { - position: absolute; - top: calc(50% - 12px); - right: 12px; - font-size: 24px; - height: 24px; - line-height: 24px; + display: flex; opacity: 1; } section#notifications-drawer ul.notifications { - display: block; - padding: 0px 16px 0px 16px; margin: 0; - height: calc(100vh - 122px); - overflow-y: scroll; + height: fit-content; + display: flex; + flex-direction: column; } diff --git a/client/components/notifications/notificationsDrawer.jade b/client/components/notifications/notificationsDrawer.jade index 0c6070459..206c8d502 100644 --- a/client/components/notifications/notificationsDrawer.jade +++ b/client/components/notifications/notificationsDrawer.jade @@ -3,6 +3,7 @@ template(name='notificationsDrawer') .header a.notification-menu-toggle i.fa.fa-bars + //- #FIXME could be replaced by a popup to help placement ? .notification-menu(class="{{#if $.Session.get 'showNotificationMenu'}}is-open{{/if}}") .menu-section a.menu-item(class="{{#unless $.Session.get 'showReadNotifications'}}selected{{/unless}}") @@ -44,9 +45,10 @@ template(name='notificationsDrawer') span.menu-icon i.fa.fa-trash span {{_ 'delete-all-notifications'}} - h5 {{_ 'notifications'}} - if($gt unreadNotifications 0) - |(#{unreadNotifications}) + if($gt unreadNotifications 0) + |(#{unreadNotifications}) {{_ 'notifications'}} + else + |0 {{_ 'notifications'}} a.close i.fa.fa-times-thin ul.notifications diff --git a/client/components/rules/actions/cardActions.jade b/client/components/rules/actions/cardActions.jade index aa31ca6da..235b0adbe 100644 --- a/client/components/rules/actions/cardActions.jade +++ b/client/components/rules/actions/cardActions.jade @@ -85,4 +85,5 @@ template(name="setCardActionsColorPopup") 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'}} + .form-buttons + button.primary.confirm.js-submit {{_ 'save'}} diff --git a/client/components/rules/rules.css b/client/components/rules/rules.css index 6305f64a7..02a674a4b 100644 --- a/client/components/rules/rules.css +++ b/client/components/rules/rules.css @@ -80,7 +80,7 @@ .triggers-content .triggers-body .triggers-side-menu { background-color: #f7f7f7; border: 1px solid #f0f0f0; - border-radius: 4px; + border-radius: 0.4ch; height: intrinsic; box-shadow: inset -1px -1px 3px rgba(0,0,0,0.05); } @@ -89,7 +89,7 @@ width: 50px; height: 50px; text-align: center; - font-size: 25px; + position: relative; } .triggers-content .triggers-body .triggers-side-menu ul li i { @@ -112,7 +112,7 @@ width: 95%; } .triggers-content .triggers-body .triggers-side-menu ul li a span { - font-size: 13px; + } .triggers-content .triggers-body .triggers-main-body { padding: 0.1em 1em; @@ -134,15 +134,15 @@ left: 10px; } .triggers-content .triggers-body .triggers-main-body .trigger-item .trigger-content .trigger-text { - font-size: 16px; + display: inline-block; } .triggers-content .triggers-body .triggers-main-body .trigger-item .trigger-content .trigger-inline-button { - font-size: 16px; + display: inline; padding: 6px; border: 1px solid #eee; - border-radius: 4px; + border-radius: 0.4ch; box-shadow: inset -1px -1px 3px rgba(0,0,0,0.05); } .triggers-content .triggers-body .triggers-main-body .trigger-item .trigger-content .trigger-inline-button:hover, @@ -179,10 +179,10 @@ width: 30px; height: 30px; border: 1px solid #eee; - border-radius: 4px; + border-radius: 0.4ch; box-shadow: inset -1px -1px 3px rgba(0,0,0,0.05); text-align: center; - font-size: 20px; + right: 10px; } .triggers-content .triggers-body .triggers-main-body .trigger-item .trigger-button i { @@ -206,7 +206,7 @@ top: unset; position: unset; transform: unset; - font-size: 16px; + width: auto; padding-left: 10px; padding-right: 10px; diff --git a/client/components/settings/cronSettings.css b/client/components/settings/cronSettings.css index 0213157b3..e0980d3ee 100644 --- a/client/components/settings/cronSettings.css +++ b/client/components/settings/cronSettings.css @@ -19,7 +19,7 @@ .migration-header h2 { margin: 0; color: #333; - font-size: 24px; + font-weight: 600; } @@ -35,8 +35,8 @@ .migration-controls .btn { padding: 8px 16px; - font-size: 14px; - border-radius: 4px; + + border-radius: 0.4ch; border: none; cursor: pointer; transition: all 0.3s ease; @@ -72,7 +72,7 @@ .migration-progress { background: #f8f9fa; padding: 20px; - border-radius: 8px; + border-radius: 0.8ch; margin-bottom: 30px; border-left: 4px solid #667eea; } @@ -128,20 +128,20 @@ text-align: center; font-weight: 700; color: #667eea; - font-size: 18px; + } .progress-label { text-align: center; color: #666; - font-size: 14px; + margin-top: 4px; } .current-step { text-align: center; color: #333; - font-size: 16px; + font-weight: 500; margin-bottom: 16px; } @@ -154,7 +154,7 @@ .migration-status { text-align: center; color: #333; - font-size: 16px; + background-color: #e3f2fd; padding: 12px 16px; border-radius: 6px; @@ -173,7 +173,7 @@ .migration-steps h3 { margin: 0 0 20px 0; color: #333; - font-size: 20px; + font-weight: 600; } @@ -181,7 +181,7 @@ max-height: 400px; overflow-y: auto; border: 1px solid #e0e0e0; - border-radius: 8px; + border-radius: 0.8ch; } .migration-step { @@ -210,7 +210,7 @@ box-shadow: 0 0 0 0 rgba(102, 126, 234, 0.4); } 70% { - box-shadow: 0 0 0 10px rgba(102, 126, 234, 0); + box-shadow: 0 0 0 0.5rem rgba(102, 126, 234, 0); } 100% { box-shadow: 0 0 0 0 rgba(102, 126, 234, 0); @@ -225,7 +225,7 @@ .step-icon { margin-right: 12px; - font-size: 18px; + width: 24px; text-align: center; } @@ -249,13 +249,13 @@ .step-name { font-weight: 600; color: #333; - font-size: 14px; + margin-bottom: 2px; } .step-description { color: #666; - font-size: 12px; + line-height: 1.3; } @@ -265,7 +265,7 @@ } .step-progress .progress-text { - font-size: 12px; + font-weight: 600; } @@ -302,7 +302,7 @@ .jobs-header h2 { margin: 0; color: #333; - font-size: 24px; + font-weight: 600; } @@ -313,8 +313,8 @@ .jobs-controls .btn { padding: 8px 16px; - font-size: 14px; - border-radius: 4px; + + border-radius: 0.4ch; border: none; cursor: pointer; transition: all 0.3s ease; @@ -337,7 +337,7 @@ width: 100%; border-collapse: collapse; background: white; - border-radius: 8px; + border-radius: 0.8ch; overflow: hidden; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); } @@ -356,18 +356,18 @@ .table th { font-weight: 600; color: #333; - font-size: 14px; + } .table td { - font-size: 14px; + color: #666; } .status-badge { padding: 4px 8px; - border-radius: 4px; - font-size: 12px; + border-radius: 0.4ch; + font-weight: 600; text-transform: uppercase; } @@ -404,7 +404,7 @@ .btn-group .btn { padding: 4px 8px; - font-size: 12px; + border-radius: 3px; border: none; cursor: pointer; @@ -452,7 +452,7 @@ .add-job-header h2 { margin: 0; color: #333; - font-size: 24px; + font-weight: 600; } @@ -474,15 +474,15 @@ margin-bottom: 8px; font-weight: 600; color: #333; - font-size: 14px; + } .form-control { width: 100%; padding: 10px 12px; border: 1px solid #ddd; - border-radius: 4px; - font-size: 14px; + border-radius: 0.4ch; + transition: border-color 0.3s ease; } @@ -504,8 +504,8 @@ .form-actions .btn { padding: 10px 20px; - font-size: 14px; - border-radius: 4px; + + border-radius: 0.4ch; border: none; cursor: pointer; transition: all 0.3s ease; @@ -546,7 +546,7 @@ .board-operations-header h2 { margin: 0; color: #333; - font-size: 24px; + font-weight: 600; } @@ -562,8 +562,8 @@ .board-operations-controls .btn { padding: 8px 16px; - font-size: 14px; - border-radius: 4px; + + border-radius: 0.4ch; border: none; cursor: pointer; transition: all 0.3s ease; @@ -590,7 +590,7 @@ .board-operations-stats { background: #f8f9fa; padding: 20px; - border-radius: 8px; + border-radius: 0.8ch; margin-bottom: 30px; border-left: 4px solid #667eea; } @@ -606,14 +606,14 @@ } .stat-value { - font-size: 32px; + font-weight: 700; color: #667eea; margin-bottom: 4px; } .stat-label { - font-size: 14px; + color: #666; text-transform: uppercase; letter-spacing: 0.5px; @@ -622,7 +622,7 @@ .system-resources { background: #f8f9fa; padding: 20px; - border-radius: 8px; + border-radius: 0.8ch; margin-bottom: 30px; border-left: 4px solid #28a745; } @@ -641,7 +641,7 @@ min-width: 120px; font-weight: 600; color: #333; - font-size: 14px; + } .resource-bar { @@ -674,7 +674,7 @@ text-align: right; font-weight: 600; color: #333; - font-size: 14px; + } .board-operations-search { @@ -683,7 +683,7 @@ .search-box { position: relative; - max-width: 400px; + max-width: 50vw; } .search-box .form-control { @@ -696,12 +696,12 @@ top: 50%; transform: translateY(-50%); color: #999; - font-size: 16px; + } .board-operations-list { background: white; - border-radius: 8px; + border-radius: 0.8ch; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); overflow: hidden; } @@ -718,13 +718,13 @@ .operations-header h3 { margin: 0; color: #333; - font-size: 18px; + font-weight: 600; } .pagination-info { color: #666; - font-size: 14px; + } .operations-table { @@ -751,11 +751,11 @@ .board-id { font-family: monospace; - font-size: 12px; + color: #666; background: #f8f9fa; padding: 4px 8px; - border-radius: 4px; + border-radius: 0.4ch; display: inline-block; } @@ -776,19 +776,19 @@ flex: 1; height: 8px; background-color: #e0e0e0; - border-radius: 4px; + border-radius: 0.4ch; overflow: hidden; } .progress-container .progress-fill { height: 100%; background: linear-gradient(90deg, #667eea, #764ba2); - border-radius: 4px; + border-radius: 0.4ch; transition: width 0.3s ease; } .progress-container .progress-text { - font-size: 12px; + font-weight: 600; color: #667eea; min-width: 35px; @@ -806,8 +806,8 @@ .pagination .btn { padding: 6px 12px; - font-size: 12px; - border-radius: 4px; + + border-radius: 0.4ch; border: 1px solid #ddd; background: white; color: #333; @@ -827,7 +827,7 @@ .page-info { color: #666; - font-size: 14px; + } /* Responsive design */ @@ -838,26 +838,26 @@ align-items: flex-start; gap: 15px; } - + .migration-controls, .jobs-controls { width: 100%; justify-content: center; } - + .table { - font-size: 12px; + } - + .table th, .table td { padding: 8px 12px; } - + .btn-group { flex-direction: column; } - + .add-job-form { max-width: 100%; } @@ -878,7 +878,7 @@ #cron-setting .progress { height: 30px; background-color: #e9ecef; - border-radius: 4px; + border-radius: 0.4ch; overflow: visible; margin-bottom: 5px; max-width: calc(100% - 40px); @@ -893,7 +893,7 @@ font-size: 14px; text-align: center; transition: width 0.3s ease; - border-radius: 4px; + border-radius: 0.4ch; } #cron-setting .progress-text { diff --git a/client/components/settings/migrationProgress.css b/client/components/settings/migrationProgress.css index 2077cc524..1e4ce7f94 100644 --- a/client/components/settings/migrationProgress.css +++ b/client/components/settings/migrationProgress.css @@ -15,7 +15,7 @@ .migration-progress-modal { background: white; - border-radius: 8px; + border-radius: 0.8ch; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3); max-width: 500px; width: 90%; @@ -46,13 +46,13 @@ .migration-progress-title { margin: 0; - font-size: 18px; + font-weight: 600; } .migration-progress-close { cursor: pointer; - font-size: 16px; + opacity: 0.8; transition: opacity 0.2s ease; } @@ -73,7 +73,7 @@ font-weight: 600; color: #333; margin-bottom: 8px; - font-size: 14px; + } .migration-progress-overall-bar { @@ -110,7 +110,7 @@ .migration-progress-overall-percentage { text-align: right; - font-size: 12px; + color: #666; font-weight: 600; } @@ -123,12 +123,12 @@ font-weight: 600; color: #333; margin-bottom: 8px; - font-size: 14px; + } .migration-progress-step-bar { background: #e9ecef; - border-radius: 8px; + border-radius: 0.8ch; height: 8px; overflow: hidden; margin-bottom: 5px; @@ -137,13 +137,13 @@ .migration-progress-step-fill { background: linear-gradient(90deg, #007bff, #0056b3); height: 100%; - border-radius: 8px; + border-radius: 0.8ch; transition: width 0.3s ease; } .migration-progress-step-percentage { text-align: right; - font-size: 12px; + color: #666; font-weight: 600; } @@ -160,12 +160,12 @@ font-weight: 600; color: #333; margin-bottom: 5px; - font-size: 13px; + } .migration-progress-status-text { color: #555; - font-size: 14px; + line-height: 1.4; } @@ -181,12 +181,12 @@ font-weight: 600; color: #1976d2; margin-bottom: 5px; - font-size: 13px; + } .migration-progress-details-text { color: #1565c0; - font-size: 13px; + line-height: 1.4; } @@ -199,7 +199,7 @@ .migration-progress-note { text-align: center; color: #666; - font-size: 13px; + font-style: italic; } @@ -209,17 +209,17 @@ width: 95%; margin: 20px; } - + .migration-progress-content { padding: 20px; } - + .migration-progress-header { padding: 15px; } - + .migration-progress-title { - font-size: 16px; + } } @@ -229,40 +229,40 @@ background: #2d3748; color: #e2e8f0; } - + .migration-progress-overall-label, .migration-progress-step-label, .migration-progress-status-label { color: #e2e8f0; } - + .migration-progress-status { background: #4a5568; border-left-color: #63b3ed; } - + .migration-progress-status-text { color: #cbd5e0; } - + .migration-progress-details { background: #2b6cb0; border-left-color: #4299e1; } - + .migration-progress-details-label { color: #bee3f8; } - + .migration-progress-details-text { color: #90cdf4; } - + .migration-progress-footer { background: #4a5568; border-top-color: #718096; } - + .migration-progress-note { color: #a0aec0; } @@ -285,7 +285,7 @@ align-items: center; justify-content: center; z-index: 10; - border-radius: 4px; + border-radius: 0.4ch; } .migration-spinner { diff --git a/client/components/settings/peopleBody.css b/client/components/settings/peopleBody.css index bb529b2d2..c58252ccd 100644 --- a/client/components/settings/peopleBody.css +++ b/client/components/settings/peopleBody.css @@ -39,9 +39,6 @@ table tr:nth-child(even) { .ext-box button { min-width: 90px; } -.content-wrapper { - margin-top: 10px; -} .buttonsContainer { display: flex; } @@ -164,7 +161,7 @@ table td:first-child { background-color: #27ae60; color: white; padding: 10px 20px; - border-radius: 4px; + border-radius: 0.4ch; z-index: 9999; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2); animation: fadeOut 3s ease-in forwards; diff --git a/client/components/settings/settingBody.css b/client/components/settings/settingBody.css index b69914713..352c0e30d 100644 --- a/client/components/settings/settingBody.css +++ b/client/components/settings/settingBody.css @@ -9,19 +9,32 @@ display: flex; height: 100%; } + +.setting-detail { + display: flex; + flex-direction: column; + flex: 1; + justify-content: stretch; + align-items: stretch; + +} .setting-content { color: #727479; background: #dedede; - width: 100%; - height: 100%; - position: absolute; + overflow-y: scroll; } + +.setting-content .wekan-form-control:not([type="radio"]) { + display: flex; + width: 100%; +} + .setting-content .content-title { - font-size: clamp(16px, 3.5vw, 22px); + font-size: 1.3em; + padding: 0.5lh 1ch; } .setting-content .content-body { display: flex; - padding-top: 2vh; height: 100%; gap: 1.3vw; } @@ -29,8 +42,15 @@ background-color: #f7f7f7; border: 1px solid #f0f0f0; border-radius: 0.5vw; - width: min(250px, 32vw); + min-width: fit-content; box-shadow: inset -0.2vh -0.2vh 0.4vh rgba(0,0,0,0.05); + display: flex; + flex-direction: column; + padding-right: 2ch; + overflow-y: scroll; + min-height: 20vh; + flex-grow: 1; + } .setting-content .content-body .side-menu ul li { margin: 0.2vh 0.3vw; @@ -47,12 +67,10 @@ padding: 1.3vh 0 1.3vh 1.3vw; width: 95%; } -.setting-content .content-body .side-menu ul li a span { - font-size: 13px; -} .setting-content .content-body .side-menu ul li a i { margin-right: 20px; } + .setting-content .content-body .main-body { -webkit-user-select: text; -moz-user-select: text; @@ -62,9 +80,9 @@ overflow-x: scroll !important; overflow-y: scroll !important; scrollbar-gutter: stable; - /* Force horizontal scrollbar to always be visible */ - min-width: 100%; - width: 100%; + flex-grow: 5; + padding-right: 2ch; + padding-bottom: 1lh; } /* Ensure scrollbars are always visible with proper styling for all admin pages */ @@ -126,7 +144,6 @@ .setting-content .content-body .main-body::after { content: ''; display: block; - width: 100vw; height: 1px; position: absolute; bottom: 0; @@ -137,7 +154,7 @@ padding: 0.5rem 0.5rem; } .setting-content .content-body .main-body ul li a .is-checked { - border-bottom: 2px solid #3cb500; + border-bottom: 0.2ch solid #3cb500; border-right: 2px solid #3cb500; } /* Grey checkmarks when grey icons setting is enabled */ diff --git a/client/components/settings/settingHeader.css b/client/components/settings/settingHeader.css index 5b880b9f2..5eb091822 100644 --- a/client/components/settings/settingHeader.css +++ b/client/components/settings/settingHeader.css @@ -4,7 +4,7 @@ margin-left: 20px; padding-right: 10px; height: 28px; - font-size: 13px; + float: left; overflow: hidden; line-height: 28px; @@ -26,3 +26,12 @@ margin-top: 1px; margin-right: 10px; } + + +.setting-header-btns { + display: flex; + align-items: center; + gap: 1ch; + padding: 0 1ch; + flex-wrap: wrap; +} \ No newline at end of file diff --git a/client/components/settings/translationBody.css b/client/components/settings/translationBody.css index 856b1967a..cf817d2dc 100644 --- a/client/components/settings/translationBody.css +++ b/client/components/settings/translationBody.css @@ -32,9 +32,6 @@ table tr:nth-child(even) { .ext-box button { min-width: 90px; } -.content-wrapper { - margin-top: 10px; -} .buttonsContainer { display: flex; } diff --git a/client/components/sidebar/sidebar.css b/client/components/sidebar/sidebar.css index 5b0ad44cf..df59fa8cb 100644 --- a/client/components/sidebar/sidebar.css +++ b/client/components/sidebar/sidebar.css @@ -13,7 +13,7 @@ position: absolute; right: 0px; top: 0px; - font-size: 25px; + padding: 10px; } .sidebar-xmark:hover { @@ -27,7 +27,21 @@ padding: 10px 10px 0px 10px; } .sidebar .sidebar-content { - padding: 0 12px; + padding: 0 1ch; + >ul { + display: flex; + } + .fa:not(.fa-plus) { + padding-right: 0.5ch; + align-self: center; + } + *:has(>.fa-plus) { + /* as long as container as a min height, + we can accomodate it while staying symetric */ + aspect-ratio: 1/1; + height: var(--label-height); + min-width: 0; + } } .sidebar .sidebar-content .hide-btn { display: none; @@ -38,15 +52,13 @@ margin-bottom: 10px; font-weight: bold; } -.sidebar .sidebar-content h3 i.fa { - margin-right: 3px; -} .sidebar .sidebar-content hr { margin: 13px 0; } .sidebar .sidebar-content ul.sidebar-list { display: flex; flex-direction: column; + gap: 0.1lh; } /* Use checklist-style green checkboxes for all sidebar checkboxes */ @@ -60,7 +72,7 @@ margin-right: 6px !important; border-top: 2px solid transparent !important; border-left: 2px solid transparent !important; - border-bottom: 2px solid #3cb500 !important; + border-bottom: 0.2ch solid #3cb500 !important; border-right: 2px solid #3cb500 !important; transform: rotate(40deg) !important; -webkit-backface-visibility: hidden !important; @@ -105,16 +117,17 @@ body.grey-icons-enabled .boardSubtaskSettingsPopup .materialCheckBox.is-checked .card-settings-column h4 { margin: 0; - font-size: 12px; + font-weight: bold; text-align: center; } .sidebar .sidebar-content ul.sidebar-list li > a { display: flex; - height: 30px; margin: 0; padding: 4px; border-radius: 3px; + max-height: 2lh; + overflow: hidden; align-items: center; } .sidebar .sidebar-content ul.sidebar-list li > a:hover, @@ -132,10 +145,6 @@ body.grey-icons-enabled .boardSubtaskSettingsPopup .materialCheckBox.is-checked padding: 8px; border-radius: 3px; } -.sidebar .sidebar-content ul.sidebar-list li > a .sidebar-list-item-description { - flex: 1; - overflow: ellipsis; -} .sidebar .sidebar-content ul.sidebar-list li > a .fa.fa-check { margin: 0 4px; color: #3cb500; @@ -144,9 +153,6 @@ body.grey-icons-enabled .boardSubtaskSettingsPopup .materialCheckBox.is-checked body.grey-icons-enabled .sidebar .sidebar-content ul.sidebar-list li > a .fa.fa-check { color: #7a7a7a; } -.sidebar .sidebar-content ul.sidebar-list li .minicard { - padding: 6px 8px 4px; -} .sidebar .sidebar-content ul.sidebar-list li .minicard .minicard-edit-button { float: right; padding: 4px; @@ -183,13 +189,28 @@ body.grey-icons-enabled .sidebar .sidebar-content ul.sidebar-list li > a .fa.fa- } .board-sidebar { display: none; - width: 30vw; - z-index: 100; + width: fit-content; + height: fit-content; + max-width: min(50ch, 50vw); + max-height: 100vh; + overflow: auto; + z-index: 10; transition: top 0.1s, right 0.1s, width 0.1s; } + +body.mobile-mode .board-sidebar { + max-width: 100vw; +} .board-sidebar.is-open { display: block; } +.board-widget-content { + display: flex; + flex-wrap: wrap; + gap: 0.2lh; + min-height: 1.5lh; + align-items: stretch; +} .board-widget h4 { margin: 5px 0; } @@ -212,7 +233,7 @@ body.grey-icons-enabled .sidebar .sidebar-content ul.sidebar-list li > a .fa.fa- } .sidebar-tongue i.fa { padding: 3px 9px; - font-size: 24px; + transition: transform 0.5s; } .sidebar-accessibility { @@ -283,7 +304,7 @@ body.grey-icons-enabled .sidebar .sidebar-content ul.sidebar-list li > a .fa.fa- } .board-sidebar .sidebar-content .hide-btn i.fa { padding: 8px 16px; - font-size: 24px; + font-weight: bold; } .sidebar-tongue { diff --git a/client/components/sidebar/sidebar.jade b/client/components/sidebar/sidebar.jade index e3772a9a3..9b489d03a 100644 --- a/client/components/sidebar/sidebar.jade +++ b/client/components/sidebar/sidebar.jade @@ -48,8 +48,9 @@ template(name='homeSidebar') hr if currentUser.isBoardAdmin h3.activity-title - i.fa.fa-comment-o - | {{_ 'activities'}} + span + i.fa.fa-comment-o + span {{_ 'activities'}} a.flex.js-toggle-show-activities(title="{{_ 'show-activities'}}") i.fa(class="{{#if showActivities}}fa-check{{else}}fa-square-o{{/if}}") @@ -60,7 +61,7 @@ template(name="membersWidget") unless currentUser.isCommentOnly unless currentUser.isWorker h3 - a.board-header-btn.js-open-board-menu(title="{{_ 'boardMenuPopup-title'}}") + a.js-open-board-menu(title="{{_ 'boardMenuPopup-title'}}") i.fa.fa-cog | {{_ 'boardMenuPopup-title'}} hr @@ -161,7 +162,7 @@ template(name="boardChangeBackgroundImagePopup") form label | {{_ 'board-background-image-url'}} - input.js-board-background-image-url(type="text" value="{{backgroundImageURL}}" autofocus) + input.js-board-background-image-url(type="text" value="{{backgroundImageURL}}" ) div.buttonsContainer input.primary.wide(type="submit" value="{{_ 'save'}}") br @@ -307,7 +308,7 @@ template(name="boardCardSettingsPopup") .card-settings-column span i.fa.fa-user - | ➕ + i.fa.fa-plus | {{_ 'requested-by'}} .card-settings-row .card-settings-column @@ -635,6 +636,10 @@ template(name="boardMenuPopup") a.js-archive-board i.fa.fa-archive | {{_ 'archive-board'}} + //- this popup is the only one to not open + //- with correct size; related to issue linked above ? + //- artificially add a bit a space + div.invisible-line template(name="exportBoard") ul.pop-over-list diff --git a/client/components/sidebar/sidebar.js b/client/components/sidebar/sidebar.js index f09f09c3f..ee1e01620 100644 --- a/client/components/sidebar/sidebar.js +++ b/client/components/sidebar/sidebar.js @@ -41,16 +41,15 @@ BlazeComponent.extendComponent({ }, open() { - if (!this._isOpen.get()) { - this._isOpen.set(true); - EscapeActions.executeUpTo('detailsPane'); - } + // setting a ReactiveVar is idempotent; + // do not try to get(), because it will + // react to changes... + this._isOpen.set(true); + EscapeActions.executeUpTo('detailsPane'); }, hide() { - if (this._isOpen.get()) { - this._isOpen.set(false); - } + this._isOpen.set(false); }, toggle() { @@ -154,7 +153,7 @@ BlazeComponent.extendComponent({ ReactiveCache.getCurrentUser().toggleVerticalScrollbars(); }, 'click .js-show-week-of-year-toggle'() { - ReactiveCache.getCurrentUser().toggleShowWeekOfYear(); + Meteor.call('toggleShowWeekOfYear'); }, 'click .sidebar-accessibility'() { FlowRouter.go('accessibility'); @@ -291,10 +290,10 @@ Template.boardMenuPopup.events({ 'click .js-delete-duplicate-lists': Popup.afterConfirm('deleteDuplicateLists', function() { const currentBoard = Utils.getCurrentBoard(); if (!currentBoard) return; - + // Get all lists in the current board const allLists = ReactiveCache.getLists({ boardId: currentBoard._id, archived: false }); - + // Group lists by title to find duplicates const listsByTitle = {}; allLists.forEach(list => { @@ -303,7 +302,7 @@ Template.boardMenuPopup.events({ } listsByTitle[list.title].push(list); }); - + // Find and delete duplicate lists that have no cards let deletedCount = 0; Object.keys(listsByTitle).forEach(title => { @@ -313,7 +312,7 @@ Template.boardMenuPopup.events({ for (let i = 1; i < listsWithSameTitle.length; i++) { const list = listsWithSameTitle[i]; const cardsInList = ReactiveCache.getCards({ listId: list._id, archived: false }); - + if (cardsInList.length === 0) { Lists.remove(list._id); deletedCount++; @@ -321,7 +320,7 @@ Template.boardMenuPopup.events({ } } }); - + // Show notification if (deletedCount > 0) { // You could add a toast notification here if available @@ -402,7 +401,7 @@ Template.memberPopup.events({ FlowRouter.go('home'); }); }), - + }); Template.removeMemberPopup.helpers({ @@ -934,7 +933,7 @@ BlazeComponent.extendComponent({ // Get the current board reactively using board ID from Session const boardId = Session.get('currentBoard'); const currentBoard = ReactiveCache.getBoard(boardId); - + let result = currentBoard ? currentBoard.presentParentTask : null; if (result === null || result === undefined) { result = 'no-parent'; @@ -947,7 +946,7 @@ BlazeComponent.extendComponent({ { 'click .js-field-has-subtasks'(evt) { evt.preventDefault(); - const newValue = !this.currentBoard.allowsSubtasks; + const newValue = !this.allowsSubtasks(); Boards.update(this.currentBoard._id, { $set: { allowsSubtasks: newValue } }); $('.js-field-deposit-board').prop( 'disabled', @@ -970,7 +969,7 @@ BlazeComponent.extendComponent({ // Get the ID from the anchor element, not the span const anchorElement = $(evt.target).closest('.js-field-show-parent-in-minicard')[0]; const value = anchorElement ? anchorElement.id : null; - + if (value) { Boards.update(this.currentBoard._id, { $set: { presentParentTask: value } }); } @@ -986,171 +985,6 @@ BlazeComponent.extendComponent({ this.currentBoard = Utils.getCurrentBoard(); }, - allowsReceivedDate() { - const boardId = Session.get('currentBoard'); - const currentBoard = ReactiveCache.getBoard(boardId); - return currentBoard ? currentBoard.allowsReceivedDate : false; - }, - - allowsStartDate() { - const boardId = Session.get('currentBoard'); - const currentBoard = ReactiveCache.getBoard(boardId); - return currentBoard ? currentBoard.allowsStartDate : false; - }, - - allowsDueDate() { - const boardId = Session.get('currentBoard'); - const currentBoard = ReactiveCache.getBoard(boardId); - return currentBoard ? currentBoard.allowsDueDate : false; - }, - - allowsEndDate() { - const boardId = Session.get('currentBoard'); - const currentBoard = ReactiveCache.getBoard(boardId); - return currentBoard ? currentBoard.allowsEndDate : false; - }, - - allowsSubtasks() { - const boardId = Session.get('currentBoard'); - const currentBoard = ReactiveCache.getBoard(boardId); - return currentBoard ? currentBoard.allowsSubtasks : false; - }, - - allowsCreator() { - const boardId = Session.get('currentBoard'); - const currentBoard = ReactiveCache.getBoard(boardId); - return currentBoard ? (currentBoard.allowsCreator ?? false) : false; - }, - - allowsCreatorOnMinicard() { - const boardId = Session.get('currentBoard'); - const currentBoard = ReactiveCache.getBoard(boardId); - return currentBoard ? (currentBoard.allowsCreatorOnMinicard ?? false) : false; - }, - - allowsMembers() { - const boardId = Session.get('currentBoard'); - const currentBoard = ReactiveCache.getBoard(boardId); - return currentBoard ? currentBoard.allowsMembers : false; - }, - - allowsAssignee() { - const boardId = Session.get('currentBoard'); - const currentBoard = ReactiveCache.getBoard(boardId); - return currentBoard ? currentBoard.allowsAssignee : false; - }, - - allowsAssignedBy() { - const boardId = Session.get('currentBoard'); - const currentBoard = ReactiveCache.getBoard(boardId); - return currentBoard ? currentBoard.allowsAssignedBy : false; - }, - - allowsRequestedBy() { - const boardId = Session.get('currentBoard'); - const currentBoard = ReactiveCache.getBoard(boardId); - return currentBoard ? currentBoard.allowsRequestedBy : false; - }, - - allowsCardSortingByNumber() { - const boardId = Session.get('currentBoard'); - const currentBoard = ReactiveCache.getBoard(boardId); - return currentBoard ? currentBoard.allowsCardSortingByNumber : false; - }, - - allowsShowLists() { - const boardId = Session.get('currentBoard'); - const currentBoard = ReactiveCache.getBoard(boardId); - return currentBoard ? currentBoard.allowsShowLists : false; - }, - - allowsLabels() { - const boardId = Session.get('currentBoard'); - const currentBoard = ReactiveCache.getBoard(boardId); - return currentBoard ? currentBoard.allowsLabels : false; - }, - - allowsShowListsOnMinicard() { - const boardId = Session.get('currentBoard'); - const currentBoard = ReactiveCache.getBoard(boardId); - return currentBoard ? currentBoard.allowsShowListsOnMinicard : false; - }, - - allowsChecklists() { - const boardId = Session.get('currentBoard'); - const currentBoard = ReactiveCache.getBoard(boardId); - return currentBoard ? currentBoard.allowsChecklists : false; - }, - - allowsAttachments() { - const boardId = Session.get('currentBoard'); - const currentBoard = ReactiveCache.getBoard(boardId); - return currentBoard ? currentBoard.allowsAttachments : false; - }, - - allowsComments() { - const boardId = Session.get('currentBoard'); - const currentBoard = ReactiveCache.getBoard(boardId); - return currentBoard ? currentBoard.allowsComments : false; - }, - - allowsCardNumber() { - const boardId = Session.get('currentBoard'); - const currentBoard = ReactiveCache.getBoard(boardId); - return currentBoard ? currentBoard.allowsCardNumber : false; - }, - - allowsDescriptionTitle() { - const boardId = Session.get('currentBoard'); - const currentBoard = ReactiveCache.getBoard(boardId); - return currentBoard ? currentBoard.allowsDescriptionTitle : false; - }, - - allowsDescriptionText() { - const boardId = Session.get('currentBoard'); - const currentBoard = ReactiveCache.getBoard(boardId); - return currentBoard ? currentBoard.allowsDescriptionText : false; - }, - - isBoardSelected() { - const boardId = Session.get('currentBoard'); - const currentBoard = ReactiveCache.getBoard(boardId); - return currentBoard ? currentBoard.dateSettingsDefaultBoardID : false; - }, - - isNullBoardSelected() { - const boardId = Session.get('currentBoard'); - const currentBoard = ReactiveCache.getBoard(boardId); - return currentBoard ? ( - currentBoard.dateSettingsDefaultBoardId === null || - currentBoard.dateSettingsDefaultBoardId === undefined - ) : true; - }, - - allowsDescriptionTextOnMinicard() { - const boardId = Session.get('currentBoard'); - const currentBoard = ReactiveCache.getBoard(boardId); - return currentBoard ? currentBoard.allowsDescriptionTextOnMinicard : false; - }, - - allowsCoverAttachmentOnMinicard() { - const boardId = Session.get('currentBoard'); - const currentBoard = ReactiveCache.getBoard(boardId); - return currentBoard ? currentBoard.allowsCoverAttachmentOnMinicard : false; - }, - - allowsBadgeAttachmentOnMinicard() { - const boardId = Session.get('currentBoard'); - const currentBoard = ReactiveCache.getBoard(boardId); - return currentBoard ? currentBoard.allowsBadgeAttachmentOnMinicard : false; - }, - - allowsCardSortingByNumberOnMinicard() { - const boardId = Session.get('currentBoard'); - const currentBoard = ReactiveCache.getBoard(boardId); - return currentBoard ? currentBoard.allowsCardSortingByNumberOnMinicard : false; - }, - boards() { const ret = ReactiveCache.getBoards( { @@ -1191,261 +1025,228 @@ BlazeComponent.extendComponent({ { 'click .js-field-has-receiveddate'(evt) { evt.preventDefault(); - const newValue = !this.currentBoard.allowsReceivedDate; - Boards.update(this.currentBoard._id, { $set: { allowsReceivedDate: newValue } }); + const newValue = !Utils.allowsReceivedDate(); + this.currentBoard.setAllowsReceivedDate(newValue); }, 'click .js-field-has-startdate'(evt) { evt.preventDefault(); - const newValue = !this.currentBoard.allowsStartDate; - Boards.update(this.currentBoard._id, { $set: { allowsStartDate: newValue } }); + const newValue = !Utils.allowsStartDate(); + this.currentBoard.setAllowsStartDate(newValue); }, 'click .js-field-has-enddate'(evt) { evt.preventDefault(); - const newValue = !this.currentBoard.allowsEndDate; - Boards.update(this.currentBoard._id, { $set: { allowsEndDate: newValue } }); + const newValue = !Utils.allowsEndDate(); + this.currentBoard.setAllowsEndDate(newValue); }, 'click .js-field-has-duedate'(evt) { evt.preventDefault(); - const newValue = !this.currentBoard.allowsDueDate; - Boards.update(this.currentBoard._id, { $set: { allowsDueDate: newValue } }); + const newValue = !Utils.allowsDueDate(); + this.currentBoard.setAllowsDueDate(newValue); }, 'click .js-field-has-subtasks'(evt) { evt.preventDefault(); - const newValue = !this.currentBoard.allowsSubtasks; - Boards.update(this.currentBoard._id, { $set: { allowsSubtasks: newValue } }); + const newValue = !Utils.allowsSubtasks(); + this.currentBoard.setAllowsSubtasks(newValue); }, 'click .js-field-has-creator'(evt) { evt.preventDefault(); - const newValue = !this.currentBoard.allowsCreator; - Boards.update(this.currentBoard._id, { $set: { allowsCreator: newValue } }); + const newValue = !Utils.allowsCreator(); + this.currentBoard.setAllowsCreator(newValue); }, 'click .js-field-has-creator-on-minicard'(evt) { evt.preventDefault(); - const newValue = !this.currentBoard.allowsCreatorOnMinicard; - Boards.update(this.currentBoard._id, { $set: { allowsCreatorOnMinicard: newValue } }); + const newValue = !Utils.allowsCreatorOnMinicard(); + this.currentBoard.setAllowsCreatorOnMinicard(newValue); }, 'click .js-field-has-members'(evt) { evt.preventDefault(); - const newValue = !this.currentBoard.allowsMembers; - Boards.update(this.currentBoard._id, { $set: { allowsMembers: newValue } }); + const newValue = !Utils.allowsMembers(); + this.currentBoard.setAllowsMembers(newValue); }, 'click .js-field-has-assignee'(evt) { evt.preventDefault(); - const newValue = !this.currentBoard.allowsAssignee; - Boards.update(this.currentBoard._id, { $set: { allowsAssignee: newValue } }); + const newValue = !Utils.allowsAssignee(); + this.currentBoard.setAllowsAssignee(newValue); }, 'click .js-field-has-assigned-by'(evt) { evt.preventDefault(); - const newValue = !this.currentBoard.allowsAssignedBy; - Boards.update(this.currentBoard._id, { $set: { allowsAssignedBy: newValue } }); + const newValue = !Utils.allowsAssignedBy(); + this.currentBoard.setAllowsAssignedBy(newValue); }, 'click .js-field-has-requested-by'(evt) { evt.preventDefault(); - const newValue = !this.currentBoard.allowsRequestedBy; - Boards.update(this.currentBoard._id, { $set: { allowsRequestedBy: newValue } }); + const newValue = !Utils.allowsRequestedBy(); + this.currentBoard.setAllowsRequestedBy(newValue); }, 'click .js-field-has-card-sorting-by-number'(evt) { evt.preventDefault(); - const newValue = !this.currentBoard.allowsCardSortingByNumber; - Boards.update(this.currentBoard._id, { $set: { allowsCardSortingByNumber: newValue } }); + const newValue = !Utils.allowsCardSortingByNumber(); + this.currentBoard.setAllowsCardSortingByNumber(newValue); }, 'click .js-field-has-card-show-lists'(evt) { evt.preventDefault(); - const newValue = !this.currentBoard.allowsShowLists; - Boards.update(this.currentBoard._id, { $set: { allowsShowLists: newValue } }); + const newValue = !Utils.allowsShowLists(); + this.currentBoard.setAllowsShowLists(newValue); }, 'click .js-field-has-labels'(evt) { evt.preventDefault(); - const newValue = !this.currentBoard.allowsLabels; - Boards.update(this.currentBoard._id, { $set: { allowsLabels: newValue } }); + const newValue = !Utils.allowsLabels(); + this.currentBoard.setAllowsLabels(newValue); }, 'click .js-field-has-card-show-lists-on-minicard'(evt) { evt.preventDefault(); - this.currentBoard.allowsShowListsOnMinicard = !this.currentBoard - .allowsShowListsOnMinicard; - this.currentBoard.setAllowsShowListsOnMinicard( - this.currentBoard.allowsShowListsOnMinicard, - ); + const newValue = !Utils.allowsShowListsOnMinicard(); + this.currentBoard.setAllowsShowListsOnMinicard(newValue); $(`.js-field-has-card-show-lists-on-minicard ${MCB}`).toggleClass( CKCLS, - this.currentBoard.allowsShowListsOnMinicard, + Utils.allowsShowListsOnMinicard(), ); $('.js-field-has-card-show-lists-on-minicard').toggleClass( CKCLS, - this.currentBoard.allowsShowListsOnMinicard, + Utils.allowsShowListsOnMinicard(), ); }, 'click .js-field-has-description-title'(evt) { evt.preventDefault(); - this.currentBoard.allowsDescriptionTitle = !this.currentBoard - .allowsDescriptionTitle; - this.currentBoard.setAllowsDescriptionTitle( - this.currentBoard.allowsDescriptionTitle, - ); + const newValue = !Utils.allowsDescriptionTitle(); + this.currentBoard.setAllowsDescriptionTitle(newValue); $(`.js-field-has-description-title ${MCB}`).toggleClass( CKCLS, - this.currentBoard.allowsDescriptionTitle, + Utils.allowsDescriptionTitle(), ); $('.js-field-has-description-title').toggleClass( CKCLS, - this.currentBoard.allowsDescriptionTitle, + Utils.allowsDescriptionTitle(), ); }, 'click .js-field-has-card-number'(evt) { evt.preventDefault(); - this.currentBoard.allowsCardNumber = !this.currentBoard - .allowsCardNumber; - this.currentBoard.setAllowsCardNumber( - this.currentBoard.allowsCardNumber, - ); + const newValue = !Utils.allowsCardNumber(); + this.currentBoard.setAllowsCardNumber(newValue); $(`.js-field-has-card-number ${MCB}`).toggleClass( CKCLS, - this.currentBoard.allowsCardNumber, + Utils.allowsCardNumber(), ); $('.js-field-has-card-number').toggleClass( CKCLS, - this.currentBoard.allowsCardNumber, + Utils.allowsCardNumber(), ); }, 'click .js-field-has-description-text-on-minicard'(evt) { evt.preventDefault(); - this.currentBoard.allowsDescriptionTextOnMinicard = !this.currentBoard - .allowsDescriptionTextOnMinicard; - this.currentBoard.setallowsDescriptionTextOnMinicard( - this.currentBoard.allowsDescriptionTextOnMinicard, - ); + const newValue = !Utils.allowsDescriptionTextOnMinicard(); + this.currentBoard.setAllowsDescriptionTextOnMinicard(newValue); $(`.js-field-has-description-text-on-minicard ${MCB}`).toggleClass( CKCLS, - this.currentBoard.allowsDescriptionTextOnMinicard, + Utils.allowsDescriptionTextOnMinicard(), ); $('.js-field-has-description-text-on-minicard').toggleClass( CKCLS, - this.currentBoard.allowsDescriptionTextOnMinicard, + Utils.allowsDescriptionTextOnMinicard(), ); }, 'click .js-field-has-description-text'(evt) { evt.preventDefault(); - this.currentBoard.allowsDescriptionText = !this.currentBoard - .allowsDescriptionText; - this.currentBoard.setAllowsDescriptionText( - this.currentBoard.allowsDescriptionText, - ); + const newValue = !Utils.allowsDescriptionText(); + this.currentBoard.setAllowsDescriptionText(newValue); $(`.js-field-has-description-text ${MCB}`).toggleClass( CKCLS, - this.currentBoard.allowsDescriptionText, + Utils.allowsDescriptionText(), ); $('.js-field-has-description-text').toggleClass( CKCLS, - this.currentBoard.allowsDescriptionText, + Utils.allowsDescriptionText(), ); }, 'click .js-field-has-checklists'(evt) { evt.preventDefault(); - this.currentBoard.allowsChecklists = !this.currentBoard - .allowsChecklists; - this.currentBoard.setAllowsChecklists( - this.currentBoard.allowsChecklists, - ); + const newValue = !Utils.allowsChecklists(); + this.currentBoard.setAllowsChecklists(newValue); $(`.js-field-has-checklists ${MCB}`).toggleClass( CKCLS, - this.currentBoard.allowsChecklists, + Utils.allowsChecklists(), ); $('.js-field-has-checklists').toggleClass( CKCLS, - this.currentBoard.allowsChecklists, + Utils.allowsChecklists(), ); }, 'click .js-field-has-attachments'(evt) { evt.preventDefault(); - this.currentBoard.allowsAttachments = !this.currentBoard - .allowsAttachments; - this.currentBoard.setAllowsAttachments( - this.currentBoard.allowsAttachments, - ); + const newValue = !Utils.allowsAttachments(); + this.currentBoard.setAllowsAttachments(newValue); $(`.js-field-has-attachments ${MCB}`).toggleClass( CKCLS, - this.currentBoard.allowsAttachments, + Utils.allowsAttachments(), ); $('.js-field-has-attachments').toggleClass( CKCLS, - this.currentBoard.allowsAttachments, + Utils.allowsAttachments(), ); }, 'click .js-field-has-comments'(evt) { evt.preventDefault(); - this.currentBoard.allowsComments = !this.currentBoard.allowsComments; - this.currentBoard.setAllowsComments(this.currentBoard.allowsComments); + const newValue = !Utils.allowsComments(); + this.currentBoard.setAllowsComments(newValue); $(`.js-field-has-comments ${MCB}`).toggleClass( CKCLS, - this.currentBoard.allowsComments, + Utils.allowsComments(), ); $('.js-field-has-comments').toggleClass( CKCLS, - this.currentBoard.allowsComments, + Utils.allowsComments(), ); }, 'click .js-field-has-activities'(evt) { evt.preventDefault(); - this.currentBoard.allowsActivities = !this.currentBoard - .allowsActivities; - this.currentBoard.setAllowsActivities( - this.currentBoard.allowsActivities, - ); + const newValue = !Utils.allowsActivities(); + this.currentBoard.setAllowsActivities(newValue); $(`.js-field-has-activities ${MCB}`).toggleClass( CKCLS, - this.currentBoard.allowsActivities, + Utils.allowsActivities(), ); $('.js-field-has-activities').toggleClass( CKCLS, - this.currentBoard.allowsActivities, + Utils.allowsActivities(), ); }, 'click .js-field-has-cover-attachment-on-minicard'(evt) { evt.preventDefault(); - this.currentBoard.allowsCoverAttachmentOnMinicard = !this.currentBoard - .allowsCoverAttachmentOnMinicard; - this.currentBoard.setallowsCoverAttachmentOnMinicard( - this.currentBoard.allowsCoverAttachmentOnMinicard, - ); + const newValue = !Utils.allowsCoverAttachmentOnMinicard(); + this.currentBoard.setAllowsCoverAttachmentOnMinicard(newValue); $(`.js-field-has-cover-attachment-on-minicard ${MCB}`).toggleClass( CKCLS, - this.currentBoard.allowsCoverAttachmentOnMinicard, + Utils.allowsCoverAttachmentOnMinicard(), ); $('.js-field-has-cover-attachment-on-minicard').toggleClass( CKCLS, - this.currentBoard.allowsCoverAttachmentOnMinicard, + Utils.allowsCoverAttachmentOnMinicard(), ); }, 'click .js-field-has-badge-attachment-on-minicard'(evt) { evt.preventDefault(); - this.currentBoard.allowsBadgeAttachmentOnMinicard = !this.currentBoard - .allowsBadgeAttachmentOnMinicard; - this.currentBoard.setallowsBadgeAttachmentOnMinicard( - this.currentBoard.allowsBadgeAttachmentOnMinicard, - ); + const newValue = !Utils.allowsBadgeAttachmentOnMinicard(); + this.currentBoard.setAllowsBadgeAttachmentOnMinicard(newValue); $(`.js-field-has-badge-attachment-on-minicard ${MCB}`).toggleClass( CKCLS, - this.currentBoard.allowsBadgeAttachmentOnMinicard, + Utils.allowsBadgeAttachmentOnMinicard(), ); $('.js-field-has-badge-attachment-on-minicard').toggleClass( CKCLS, - this.currentBoard.allowsBadgeAttachmentOnMinicard, + Utils.allowsBadgeAttachmentOnMinicard(), ); }, 'click .js-field-has-card-sorting-by-number-on-minicard'(evt) { evt.preventDefault(); - this.currentBoard.allowsCardSortingByNumberOnMinicard = !this.currentBoard - .allowsCardSortingByNumberOnMinicard; - this.currentBoard.setallowsCardSortingByNumberOnMinicard( - this.currentBoard.allowsCardSortingByNumberOnMinicard, - ); + const newValue = !Utils.allowsCardSortingByNumberOnMinicard(); + this.currentBoard.setAllowsCardSortingByNumberOnMinicard(newValue); $(`.js-field-has-card-sorting-by-number-on-minicard ${MCB}`).toggleClass( CKCLS, - this.currentBoard.allowsCardSortingByNumberOnMinicard, + Utils.allowsCardSortingByNumberOnMinicard(), ); $('.js-field-has-card-sorting-by-number-on-minicard').toggleClass( CKCLS, - this.currentBoard.allowsCardSortingByNumberOnMinicard, + Utils.allowsCardSortingByNumberOnMinicard(), ); }, }, @@ -1541,12 +1342,13 @@ BlazeComponent.extendComponent({ 'keyup .js-search-member-input'(event) { Session.set('addMemberPopup.error', ''); const query = event.target.value.trim(); - + this.searchQuery.set(query); + // Clear previous timeout if (this.searchTimeout) { clearTimeout(this.searchTimeout); } - + // Debounce search this.searchTimeout = setTimeout(() => { this.performSearch(query); @@ -2061,4 +1863,3 @@ Template.changePermissionsPopup.helpers({ ); }, }); - diff --git a/client/components/sidebar/sidebarSearches.css b/client/components/sidebar/sidebarSearches.css index a3c900ef6..e69de29bb 100644 --- a/client/components/sidebar/sidebarSearches.css +++ b/client/components/sidebar/sidebarSearches.css @@ -1,3 +0,0 @@ -input { - max-width: 100%; -} diff --git a/client/components/sidebar/sidebarSearches.js b/client/components/sidebar/sidebarSearches.js index a6e649ffb..7baf06179 100644 --- a/client/components/sidebar/sidebarSearches.js +++ b/client/components/sidebar/sidebarSearches.js @@ -14,11 +14,8 @@ BlazeComponent.extendComponent({ }, clickOnMiniCard(evt) { - if (Utils.isMiniScreen()) { - evt.preventDefault(); - Session.set('popupCardId', this.currentData()._id); - this.cardDetailsPopup(evt); - } + evt.preventDefault(); + Session.set('popupCardId', this.currentData()._id); }, cardDetailsPopup(event) { diff --git a/client/components/swimlanes/swimlaneHeader.jade b/client/components/swimlanes/swimlaneHeader.jade index 3f62749bc..c88747980 100644 --- a/client/components/swimlanes/swimlaneHeader.jade +++ b/client/components/swimlanes/swimlaneHeader.jade @@ -9,41 +9,37 @@ template(name="swimlaneHeader") +swimlaneFixedHeader(this) template(name="swimlaneFixedHeader") - .swimlane-header( - class="{{#if currentUser.isBoardMember}}js-open-inlined-form is-editable{{/if}}") - if $eq title 'Card Templates' - | {{_ 'card-templates-swimlane'}} - else if $eq title 'List Templates' - | {{_ 'list-templates-swimlane'}} - else if $eq title 'Board Templates' - | {{_ 'board-templates-swimlane'}} - else if $eq title 'Default' - | {{_ 'defaultdefault'}} - else - +viewer - | {{isTitleDefault title}} - .swimlane-header-menu + .swimlane-header-menu-left if currentUser unless currentUser.isCommentOnly - unless currentUser.isReadOnly - unless currentUser.isReadAssignedOnly - unless currentUser.isWorker - a.swimlane-collapse-indicator.js-collapse-swimlane.swimlane-header-collapse(title="{{_ 'collapse'}}") - if collapseSwimlane - i.fa.fa-caret-right - else - i.fa.fa-caret-down - a.js-open-swimlane-menu(title="{{_ 'swimlaneActionPopup-title'}}") - i.fa.fa-bars - a.js-open-add-swimlane-menu.swimlane-header-plus-icon(title="{{_ 'add-swimlane'}}") - i.fa.fa-plus - 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 - i.fa.fa-arrows + unless currentUser.isWorker + a.swimlane-collapse-indicator.js-collapse-swimlane.swimlane-header-collapse(title="{{_ 'collapse'}}") + if collapseSwimlane + i.fa.fa-caret-right + else + i.fa.fa-caret-down + .swimlane-header( + class="{{#if currentUser.isBoardMember}}js-open-inlined-form is-editable{{/if}}") + if $eq title 'Card Templates' + | {{_ 'card-templates-swimlane'}} + else if $eq title 'List Templates' + | {{_ 'list-templates-swimlane'}} + else if $eq title 'Board Templates' + | {{_ 'board-templates-swimlane'}} + else if $eq title 'Default' + | {{_ 'defaultdefault'}} + else + +viewer + | {{isTitleDefault title}} + .swimlane-header-menu-right + if currentUser + unless currentUser.isCommentOnly + unless currentUser.isWorker + a.js-open-swimlane-menu(title="{{_ 'swimlaneActionPopup-title'}}") + i.fa.fa-bars + if isMiniScreen + a.swimlane-header-miniscreen-handle.handle.js-swimlane-header-handle + i.fa.fa-arrows template(name="editSwimlaneTitleForm") .list-composer @@ -59,23 +55,23 @@ template(name="swimlaneActionPopup") unless currentUser.isReadOnly unless currentUser.isReadAssignedOnly ul.pop-over-list - li: a.js-add-swimlane - i.fa.fa-plus - span {{_ 'add-swimlane'}} + 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'}} + 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 + 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 @@ -117,8 +113,7 @@ template(name="setSwimlaneColorPopup") span.card-label.palette-color.js-palette-color(class="card-details-{{color}}") if(isSelected color) i.fa.fa-check - // Buttons aligned left too - .flush-left + .form-buttons button.primary.confirm.js-submit(style="margin-left:0") {{_ 'save'}} button.js-remove-color.negate.wide.right(style="margin-left:8px") {{_ 'unset-color'}} diff --git a/client/components/swimlanes/swimlaneHeader.js b/client/components/swimlanes/swimlaneHeader.js index 08993dbf9..4511dbc64 100644 --- a/client/components/swimlanes/swimlaneHeader.js +++ b/client/components/swimlanes/swimlaneHeader.js @@ -86,7 +86,7 @@ Template.editSwimlaneTitleForm.helpers({ // When that happens, try use translation "defaultdefault" that has same content of default, or return text "Default". // This can happen, if swimlane does not have name. // Yes, this is fixing the symptom (Swimlane title does not have title) - // instead of fixing the problem (Add Swimlane title when creating swimlane) + // instead of fixing the problem (Add Swimlane title when creating swimlane) // because there could be thousands of swimlanes, adding name Default to all of them // would be very slow. if (title.startsWith("key 'default") && title.endsWith('returned an object instead of string.')) { diff --git a/client/components/swimlanes/swimlanes.css b/client/components/swimlanes/swimlanes.css index 4c35b3580..86e82db30 100644 --- a/client/components/swimlanes/swimlanes.css +++ b/client/components/swimlanes/swimlanes.css @@ -1,39 +1,29 @@ -[class=swimlane] { - position: sticky; - left: 0; -} -.swimlane { +.swimlane.js-lists{ background: #dedede; display: flex; - flex-direction: row; overflow: auto; - max-height: 100%; - position: relative; + flex-direction: row; + box-sizing: border-box; + height: var(--swimlane-height, auto); + min-height: var(--swimlane-min-height, 200px); } -.swimlane.js-lists.js-swimlane { - min-height: 150px; + +body.mobile-mode .swimlane { + display: flex; + flex-direction: column; + width: 100%; + .swimlane-header { + font-size: var(--header-scale); + } } -.swimlane-header-menu .swimlane-header-collapse-down { - font-size: 50%; - color: #a6a6a6; - position: absolute; - top: 0.7vh; - left: 13vw; -} -.swimlane-header-menu .swimlane-header-collapse-up { - font-size: 50%; - color: #a6a6a6; - position: absolute; - bottom: 0.7vh; - left: 13vw; -} -.swimlane-header-menu .swimlane-header-uncollapse-up { - font-size: 50%; - color: #a6a6a6; -} -.swimlane-header-menu .swimlane-header-uncollapse-down { - font-size: 50%; - color: #a6a6a6; + +.swimlane-container { + background-color: #ccc; + display: flex; + flex: 1; + flex-direction: column; + /* default to the same as lists to avoid contrast with the handle */ + background: #dedede; } .swimlane.placeholder { background-color: rgba(0,0,0,0.2); @@ -50,30 +40,28 @@ cursor: grabbing; } .swimlane .swimlane-header-wrap { + overflow: hidden; display: flex; - flex-direction: row; - flex: 1 0 100%; + flex: 1; + align-items: center; + justify-content: space-between; + height: max-content; + padding: 0.5lh 1ch; background-color: #ccc; - width: 100%; - min-width: 100%; - position: relative; - overflow: visible; - min-height: 33px; - padding: 0; - margin: 0; + + position: sticky; + left: 0; + p { + margin: 0; + } } + .swimlane .swimlane-header-wrap .swimlane-header { - font-size: 14px; - padding: 0; font-weight: bold; - min-height: 33px; - width: 100%; overflow: hidden; -o-text-overflow: ellipsis; text-overflow: ellipsis; - word-wrap: break-word; - text-align: center; - position: relative; + overflow-wrap: break-word; z-index: 10; pointer-events: auto; display: flex; @@ -81,87 +69,30 @@ justify-content: center; line-height: 1.2; } -.swimlane .swimlane-header-wrap .swimlane-header-menu { - position: absolute; - top: 0; - left: 0; - padding: 0; - margin: 0; - font-size: 22px; - line-height: 1; - z-index: 20; - pointer-events: auto; -} -.swimlane .swimlane-header-wrap .swimlane-header-menu .js-open-swimlane-menu { - top: calc(50% + 6px); - padding: 5px; - display: inline-block; - margin-left: 30px; - color: #a6a6a6; - vertical-align: middle; - line-height: 1.2; + +.swimlane { + .swimlane-header-menu-right, .swimlane-header-menu-left { + display: inline-flex; + align-content: center; + gap: 2ch; + } + /* can't resize beyond that point, but resizing screen causes + overflow, which is great because lists would shrink too much otherwise */ + max-width: 100vw; } + @media print { - .swimlane .swimlane-header-wrap .swimlane-header-menu { + .swimlane .swimlane-header-wrap .swimlane-header-menu-right { display: none; } } -.swimlane .swimlane-header-wrap .swimlane-header-plus-icon { - top: calc(50% + 6px); - padding: 5px; - margin-left: 20px; - font-size: 22px; - color: #a6a6a6; -} -.swimlane .swimlane-header-wrap .swimlane-header-menu-icon { - top: calc(50% + 6px); - padding-left: 5px; - font-size: 22px; -} -.swimlane .swimlane-header-wrap .swimlane-header-handle { - position: relative; - top: calc(50% + 2px); - padding: 2px 5px; - font-size: clamp(16px, 3vw, 20px); - display: inline-block; - vertical-align: middle; - margin-left: 30px; - cursor: move; - pointer-events: auto; - color: #a6a6a6; - line-height: 1.2; -} -.swimlane .swimlane-header-wrap .swimlane-header-miniscreen-handle { - position: relative; - padding: 2px 5px; - top: calc(50% + 2px); - font-size: 24px; - display: inline-block; - vertical-align: middle; - margin-left: 30px; - cursor: move; - pointer-events: auto; - color: #a6a6a6; -} -/* Swimlane collapse button styling - matches list collapse button */ -.swimlane .swimlane-header-wrap .swimlane-header-menu .swimlane-collapse-indicator { +.swimlane .swimlane-header-wrap .swimlane-header-handle { + cursor: move; + pointer-events: auto; color: #a6a6a6; - display: inline-block; - vertical-align: middle; - padding: 5px; - border: none; - border-radius: 0; - background-color: transparent; - cursor: pointer; - font-size: 18px; - line-height: 1.2; - text-align: center; - text-decoration: none; - margin: 0; - flex-shrink: 0; } -.swimlane .swimlane-header-wrap .swimlane-header-menu .swimlane-collapse-indicator:hover { +.swimlane .swimlane-header-wrap .swimlane-header-menu-right .swimlane-collapse-indicator:hover { background-color: transparent; color: #333; } @@ -290,105 +221,75 @@ color: #fff !important; } +body.mobile-mode { + .swimlane-resize-handle { + height: 2ch; + :active { + background: rgba(0, 123, 255, 0.4) !important; + } + } +} +body.mobile-mode { + .swimlane-resize-handle { + height: 1lh; + } +} /* Swimlane resize handle */ .swimlane-resize-handle { - position: absolute; - bottom: 0; - left: 0; - right: 0; - height: 8px; - background: transparent; + height: max(0.7ch, 0.3lh); cursor: row-resize; - z-index: 20; border-top: 2px solid transparent; transition: all 0.2s ease; border-radius: 2px; /* Ensure the handle is clickable */ pointer-events: auto; -} - -/* Show resize handle only on hover */ -.swimlane:hover .swimlane-resize-handle { + /* Prevent scrolling behaviour on click */ + touch-action: none; background: rgba(0, 0, 0, 0.1); - border-top-color: rgba(0, 0, 0, 0.2); -} - -/* Add a subtle resize indicator line at the bottom of swimlane on hover */ -.swimlane:hover .swimlane-resize-handle::after { - content: ''; - position: absolute; - bottom: 0; - left: 0; - right: 0; - height: 2px; - background: rgba(0, 123, 255, 0.3); - z-index: 21; - transition: all 0.2s ease; - border-radius: 1px; -} - -/* Make the indicator line more prominent when hovering over the resize handle */ -.swimlane-resize-handle:hover::after { - background: rgba(0, 123, 255, 0.6) !important; - height: 3px !important; - box-shadow: 0 0 4px rgba(0, 123, 255, 0.2); -} - -.swimlane-resize-handle:hover { - background: rgba(0, 123, 255, 0.4) !important; - border-top-color: #0079bf !important; - box-shadow: 0 0 4px rgba(0, 123, 255, 0.3); -} - -.swimlane-resize-handle:active { - background: rgba(0, 123, 255, 0.6) !important; - border-top-color: #0079bf !important; - box-shadow: 0 0 6px rgba(0, 123, 255, 0.4); + box-sizing: border-box; } /* Add a subtle indicator line */ .swimlane-resize-handle::before { content: ''; position: absolute; - left: 50%; - top: 50%; - transform: translate(-50%, -50%); + left: 50vw; width: 20px; - height: 2px; - background: rgba(0, 123, 255, 0.6); - border-radius: 1px; + height: 1px; + background: rgba(0, 0, 0, 0.2); + border-radius: 5px; opacity: 0; transition: opacity 0.2s ease; } -.swimlane-resize-handle:hover::before { - opacity: 1; +.swimlane.swimlane-resizing + .swimlane-resize-handle:hover::before, .swimlane-resize-handle:hover::before { + opacity:1; } -/* Visual feedback during resize */ -.swimlane.swimlane-resizing { - transition: none !important; - box-shadow: 0 0 10px rgba(0, 123, 255, 0.3); - /* Ensure the swimlane maintains its new height during resize */ - flex: none !important; - flex-basis: auto !important; - flex-grow: 0 !important; - flex-shrink: 0 !important; - /* Override any conflicting layout properties */ - display: flex !important; - position: relative !important; - /* Force height to be respected */ - height: var(--swimlane-height, auto) !important; - min-height: var(--swimlane-height, auto) !important; - max-height: var(--swimlane-height, auto) !important; - /* Ensure the height is applied immediately */ - overflow: visible !important; +.swimlane:not(.cannot-resize) { + /* Add a subtle resize indicator line at the bottom of swimlane on hover */ + &:hover + .swimlane-resize-handle, + .swimlane-resize-handle:hover { + border-top: 1px solid rgba(0, 123, 255, 0.5); + background: rgba(0, 123, 255, 0.2); + border-radius: 0; + } +} + +.swimlane.swimlane-resizing + .swimlane-resize-handle { + background: rgba(0, 123, 255, 0.4) !important; +} + +.swimlane.cannot-resize + .swimlane-resize-handle { + background: rgba(227, 64, 83, 0.5) !important; + border-radius: 0; } body.swimlane-resizing-active { cursor: row-resize !important; + user-select: none !important; } body.swimlane-resizing-active * { cursor: row-resize !important; + user-select: none !important; } diff --git a/client/components/swimlanes/swimlanes.jade b/client/components/swimlanes/swimlanes.jade index 4f3ae4ed6..5eb152b24 100644 --- a/client/components/swimlanes/swimlanes.jade +++ b/client/components/swimlanes/swimlanes.jade @@ -1,43 +1,38 @@ template(name="swimlane") - .swimlane.nodragscroll - +swimlaneHeader - unless collapseSwimlane - .swimlane.js-lists.js-swimlane.dragscroll(id="swimlane-{{_id}}" - style="height:{{swimlaneHeight}};") - .swimlane-resize-handle.js-swimlane-resize-handle.nodragscroll - if isMiniScreen - if currentListIsInThisSwimlane _id - +list(currentList) - unless currentList + .swimlane-container + .swimlane.nodragscroll + +swimlaneHeader + unless collapseSwimlane + .swimlane.js-lists.js-swimlane.dragscroll(id="swimlane-{{_id}}") + if isMiniScreen + each lists + +miniList(this) + if currentUser.isBoardMember + unless currentUser.isCommentOnly + +addListForm + 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) - if currentCardIsInThisList _id ../_id - +cardDetails(currentCard) + if visible this + +list(this) + //- allow resizing in mobile mode + .swimlane-resize-handle.js-swimlane-resize-handle.nodragscroll template(name="listsGroup") .swimlane.list-group.js-lists.dragscroll if isMiniScreen - if currentList - +list(currentList) - else - each lists - +miniList(this) + each lists + +miniList(this) + if currentUser.isBoardMember + unless currentUser.isCommentOnly + +addListForm else each lists if visible this +list(this) - if currentCardIsInThisList _id null - +cardDetails(currentCard) + .swimlane-resize-handle.js-swimlane-resize-handle.nodragscroll template(name="addListForm") unless currentUser.isWorker @@ -45,27 +40,27 @@ template(name="addListForm") unless currentUser.isReadOnly unless currentUser.isReadAssignedOnly .list.list-composer.js-list-composer(class="{{#if isMiniScreen}}mini-list{{/if}}") - .list-header-add - +inlinedForm(autoclose=false) - input.list-name-input.full-line(type="text" placeholder="{{_ 'add-list'}}" - autocomplete="off" autofocus) - if currentBoard.getLastList - | {{_ 'add-after-list'}} - select.list-position-input.full-line - each currentBoard.lists - option(value="{{_id}}" selected=currentBoard.getLastList.title) {{title}} - .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 - | {{_ 'or'}} - a.js-list-template {{_ 'template'}} - else - a.open-list-composer.js-open-inlined-form(title="{{_ 'add-list'}}") - i.fa.fa-plus + .list-header-add + +inlinedForm(autoclose=false) + input.list-name-input.full-line(type="text" placeholder="{{_ 'add-list'}}" + autocomplete="off" autofocus) + if lists + | {{_ 'add-after-list'}} + select.list-position-input.full-line + each lists + option(value="{{_id}}" selected=currentBoard.getLastList.title) {{title}} + .edit-controls.clearfix + button.primary.confirm(type="submit") {{_ 'save'}} + a.js-close-inlined-form + i.fa.fa-times-thin + unless currentBoard.isTemplatesBoard + unless currentBoard.isTemplateBoard + span.quiet + | {{_ 'or'}} + a.js-list-template {{_ 'template'}} + else + a.open-list-composer.list-header.js-open-inlined-form(title="{{_ 'add-list'}}") + i.fa.fa-plus template(name="moveSwimlanePopup") if currentUser diff --git a/client/components/swimlanes/swimlanes.js b/client/components/swimlanes/swimlanes.js index a210a27a0..990ed1eab 100644 --- a/client/components/swimlanes/swimlanes.js +++ b/client/components/swimlanes/swimlanes.js @@ -2,6 +2,12 @@ import { ReactiveCache } from '/imports/reactiveCache'; import dragscroll from '@wekanteam/dragscroll'; const { calculateIndex } = Utils; +function getBoardComponent() { + // as list can be rendered from multiple inner elements, feels like a reliable + // way to get the components having rendered the board + return BlazeComponent.getComponentForElement(document.getElementsByClassName('board-canvas')[0]); +} + function saveSorting(ui) { // To attribute the new index number, we need to get the DOM element // of the previous and the following list -- if any. @@ -152,6 +158,12 @@ function currentListIsInThisSwimlane(swimlaneId) { ); } +function currentList(listId, swimlaneId) { + const list = Utils.getCurrentList(); + return list && list._id == listId && (list.swimlaneId === swimlaneId || list.swimlaneId === ''); +} + + function currentCardIsInThisList(listId, swimlaneId) { const currentCard = Utils.getCurrentCard(); //const currentUser = ReactiveCache.getCurrentUser(); @@ -227,122 +239,63 @@ function syncListOrderFromStorage(boardId) { } }; -function initSortable(boardComponent, $listsDom) { - // Safety check: ensure we have valid DOM elements - if (!$listsDom || $listsDom.length === 0) { - console.error('initSortable: No valid DOM elements provided'); - return; - } - - // Check if sortable is already initialized - if ($listsDom.data('uiSortable') || $listsDom.data('sortable')) { - $listsDom.sortable('destroy'); - } - - // We want to animate the card details window closing. We rely on CSS - // transition for the actual animation. - $listsDom._uihooks = { - removeElement(node) { - const removeNode = _.once(() => { - node.parentNode.removeChild(node); - }); - if ($(node).hasClass('js-card-details')) { - $(node).css({ - flexBasis: 0, - padding: 0, - }); - $listsDom.one(CSSEvents.transitionend, removeNode); - } else { - removeNode(); - } - }, - }; - - - // Add click debugging for drag handles - $listsDom.on('mousedown', '.js-list-handle', function(e) { - e.stopPropagation(); - }); - - $listsDom.on('mousedown', '.js-list-header', function(e) { - }); - - // Add debugging for any mousedown on lists - $listsDom.on('mousedown', '.js-list', function(e) { - }); - - // Add debugging for sortable events - $listsDom.on('sortstart', function(e, ui) { - }); - - $listsDom.on('sortbeforestop', function(e, ui) { - }); - - $listsDom.on('sortstop', function(e, ui) { - }); - - try { - $listsDom.sortable({ - connectWith: '.js-swimlane, .js-lists', - tolerance: 'pointer', - appendTo: '.board-canvas', - helper(evt, item) { - const helper = item.clone(); - helper.css('z-index', 1000); - return helper; - }, - items: '.js-list:not(.js-list-composer)', - placeholder: 'list placeholder', - distance: 3, - forcePlaceholderSize: true, - cursor: 'move', - start(evt, ui) { - ui.helper.css('z-index', 1000); - ui.placeholder.height(ui.helper.height()); - ui.placeholder.width(ui.helper.width()); - EscapeActions.executeUpTo('popup-close'); - boardComponent.setIsDragging(true); - - // Add visual feedback for list being dragged - ui.item.addClass('ui-sortable-helper'); - - // Disable dragscroll during list dragging to prevent interference - try { - dragscroll.reset(); - } catch (e) { - } - - // Also disable dragscroll on all swimlanes during list dragging - $('.js-swimlane').each(function() { - $(this).removeClass('dragscroll'); - }); - }, - beforeStop(evt, ui) { - // Clean up visual feedback - ui.item.removeClass('ui-sortable-helper'); - }, - stop(evt, ui) { - saveSorting(ui); - } - }); - } catch (error) { - console.error('Error initializing list sortable:', error); - return; - } - - - // Check if drag handles exist - const dragHandles = $listsDom.find('.js-list-handle'); - - // Check if lists exist - const lists = $listsDom.find('.js-list'); - - // Skip the complex autorun and options for now -} BlazeComponent.extendComponent({ + + initializeSortableLists() { + let boardComponent = getBoardComponent(); + + // needs to be run again on uncollapsed + const handleSelector = Utils.isMiniScreen() + ? '.js-list-handle' + : '.list-header-name-container'; + const $lists = this.$('.js-list'); + const $parent = $lists.parent(); + + if ($lists.length > 0) { + + // Check for drag handles + const $handles = $parent.find(handleSelector); + + // Test if drag handles are clickable + $handles.on('click', function (e) { + e.preventDefault(); + e.stopPropagation(); + }); + + $parent.sortable({ + connectWith: '.js-swimlane, .js-lists', + tolerance: 'pointer', + appendTo: '.board-canvas', + helper: 'clone', + items: '.js-list', + placeholder: 'list placeholder', + distance: 7, + handle: handleSelector, + disabled: !Utils.canModifyBoard(), + start(evt, ui) { + ui.helper.css('z-index', 1000); + width = ui.helper.width(); + height = ui.helper.height(); + ui.placeholder.height(height); + ui.placeholder.width(width); + ui.placeholder[0].setAttribute('style', `width: ${width}px !important; height: ${height}px !important;`); + EscapeActions.executeUpTo('popup-close'); + boardComponent.setIsDragging(true); + }, + stop(evt, ui) { + boardComponent.setIsDragging(false); + saveSorting(ui); + }, + sort(event, ui) { + Utils.scrollIfNeeded(event); + }, + }); + } + }, + onRendered() { - const boardComponent = this.parentComponent(); + // can be rendered from either swimlane or board; check with DOM class heuristic, const $listsDom = this.$('.js-lists'); // Sync list order from localStorage on board load const boardId = Session.get('currentBoard'); @@ -353,68 +306,18 @@ BlazeComponent.extendComponent({ }, 500); } - - if (!Utils.getCurrentCardId()) { - boardComponent.scrollLeft(); - } - // Try a simpler approach - initialize sortable directly like cards do this.initializeSwimlaneResize(); // Wait for DOM to be ready - setTimeout(() => { - const handleSelector = Utils.isTouchScreenOrShowDesktopDragHandles() - ? '.js-list-handle' - : '.js-list-header'; - const $lists = this.$('.js-list'); + setTimeout(this.initializeSortableLists, 100); - const $parent = $lists.parent(); - - if ($lists.length > 0) { - - // Check for drag handles - const $handles = $parent.find('.js-list-handle'); - - // Test if drag handles are clickable - $handles.on('click', function(e) { - e.preventDefault(); - e.stopPropagation(); - }); - - $parent.sortable({ - connectWith: '.js-swimlane, .js-lists', - tolerance: 'pointer', - appendTo: '.board-canvas', - helper: 'clone', - items: '.js-list:not(.js-list-composer)', - placeholder: 'list placeholder', - distance: 7, - handle: handleSelector, - disabled: !Utils.canModifyBoard(), - start(evt, ui) { - ui.helper.css('z-index', 1000); - ui.placeholder.height(ui.helper.height()); - ui.placeholder.width(ui.helper.width()); - EscapeActions.executeUpTo('popup-close'); - boardComponent.setIsDragging(true); - }, - stop(evt, ui) { - boardComponent.setIsDragging(false); - saveSorting(ui); - } - }); - // Reactively update handle when user toggles desktop drag handles - this.autorun(() => { - const newHandle = Utils.isTouchScreenOrShowDesktopDragHandles() - ? '.js-list-handle' - : '.js-list-header'; - if ($parent.data('uiSortable') || $parent.data('sortable')) { - try { $parent.sortable('option', 'handle', newHandle); } catch (e) {} - } - }); - } else { + // React to uncollapse (data is always reactive) + this.autorun(() => { + if (!this.currentData().isCollapsed()) { + this.initializeSortableLists(); } - }, 100); + }); }, onCreated() { this.draggingActive = new ReactiveVar(false); @@ -465,7 +368,7 @@ BlazeComponent.extendComponent({ // his mouse. const noDragInside = ['a', 'input', 'textarea', 'p'].concat( - Utils.isTouchScreenOrShowDesktopDragHandles() + Utils.isMiniScreen() ? ['.js-list-handle', '.js-swimlane-header-handle'] : ['.js-list-header'], ).concat([ @@ -477,7 +380,7 @@ BlazeComponent.extendComponent({ const isInNoDragArea = $(evt.target).closest(noDragInside.join(',')).length > 0; if (isResizeHandle) { - return; + //return; } if ( @@ -512,6 +415,11 @@ BlazeComponent.extendComponent({ }, swimlaneHeight() { + // Using previous size with so much collasped/vertical logic will probably + // be worst that letting layout takes needed space given the opened list each time + if (Utils.isMiniScreen()) { + return; + } const user = ReactiveCache.getCurrentUser(); const swimlane = Template.currentData(); @@ -552,7 +460,7 @@ BlazeComponent.extendComponent({ const swimlane = Template.currentData(); const $swimlane = $(`#swimlane-${swimlane._id}`); - const $resizeHandle = $swimlane.find('.js-swimlane-resize-handle'); + const $resizeHandle = $swimlane.siblings('.js-swimlane-resize-handle'); // Check if elements exist if (!$swimlane.length || !$resizeHandle.length) { @@ -570,76 +478,190 @@ BlazeComponent.extendComponent({ return; } + const isTouchScreen = Utils.isTouchScreen(); let isResizing = false; - let startY = 0; - let startHeight = 0; - const minHeight = 100; - const maxHeight = 2000; + const minHeight = Utils.isMiniScreen() ? 200 : 50; + const absoluteMaxHeight = 2000; + let computingHeight; + let frame; + + let fullHeight, maxHeight; + let pageY, screenY, deltaY; + + // how to do cleaner? + const flexContainer = document.getElementsByClassName('swim-flex')[0]; + // only for cosmetic + let maxHeightWithTolerance; + const tolerance = 30; + let previousLimit = false; + + $swimlane[0].style.setProperty('--swimlane-min-height', `${minHeight}px`); + // avoid jump effect and ensure height stays consistent + // ⚠️ here, I propose to ignore saved height if it is not filled by content. + // having large portions of blank lists makes the layout strange and hard to + // navigate; also, the height changes a lot between different views, so it + // feels ok to use the size as a hint, not as an absolute (as a user also) + const unconstraignedHeight = $swimlane[0].getBoundingClientRect().height; + const userHeight = parseFloat(this.swimlaneHeight(), 10); + const preferredHeight = Math.min(userHeight, absoluteMaxHeight, unconstraignedHeight); + $swimlane[0].style.setProperty('--swimlane-height', `${preferredHeight}px`); const startResize = (e) => { - isResizing = true; - startY = e.pageY || e.originalEvent.touches[0].pageY; - startHeight = parseInt($swimlane.css('height')) || 300; + // gain access to modern attributes e.g. isPrimary + e = e.originalEvent; - - $swimlane.addClass('swimlane-resizing'); - $('body').addClass('swimlane-resizing-active'); - $('body').css('user-select', 'none'); - - - e.preventDefault(); - e.stopPropagation(); - }; - - const doResize = (e) => { - if (!isResizing) { + if (isResizing || !(e.isPrimary && (e.pointerType !== 'mouse' || e.button === 0))) { return; } - const currentY = e.pageY || e.originalEvent.touches[0].pageY; - const deltaY = currentY - startY; - const newHeight = Math.max(minHeight, Math.min(maxHeight, startHeight + deltaY)); + waitHeight(e, startResizeKnowingHeight); + }; + // unsure about this one; this is a way to compute what would be a "fit-content" height, + // so that user cannot drag the swimlane too far. to do so, we clone the swimlane add + // add it to the body, taking care of catching the frame just before it would be rendered. + // it is well supported by browsers and adds extra-computation only once, when start dragging, + // but still it feels odd. + // the reason we cannot use initial, computed height is because it could have changed because + // on new cards, thus constraining dragging too much. it is simple for list, add "real" unconstrained + // width do not update on adding cards. + const waitHeight = (e, callback) => { + const computeSwimlaneHeight = (_) => { + if (!computingHeight) { + computingHeight = $swimlane[0].cloneNode(true); + computingHeight.id = "clonedSwimlane"; + $(computingHeight).attr('style', 'height: auto !important; position: absolute'); + frame = requestAnimationFrame(computeSwimlaneHeight); + document.body.appendChild(computingHeight); + return; + } + catchBeforeRender = document.getElementById('clonedSwimlane'); + if (catchBeforeRender) { + fullHeight = catchBeforeRender.offsetHeight; + if (fullHeight > 0) { + cancelAnimationFrame(frame); + document.body.removeChild(computingHeight); + computingHeight = undefined; + frame = undefined; + callback(e, fullHeight); + return; + } + } + frame = requestAnimationFrame(computeSwimlaneHeight); + } + computeSwimlaneHeight(); + } - // Apply the new height immediately for real-time feedback - $swimlane[0].style.setProperty('--swimlane-height', `${newHeight}px`); - $swimlane[0].style.setProperty('height', `${newHeight}px`); - $swimlane[0].style.setProperty('min-height', `${newHeight}px`); - $swimlane[0].style.setProperty('max-height', `${newHeight}px`); - $swimlane[0].style.setProperty('flex', 'none'); - $swimlane[0].style.setProperty('flex-basis', 'auto'); - $swimlane[0].style.setProperty('flex-grow', '0'); - $swimlane[0].style.setProperty('flex-shrink', '0'); + const startResizeKnowingHeight = (e, height) => { + document.addEventListener('pointermove', doResize); + // e.g. debugger can cancel event without pointerup being fired + // document.addEventListener('pointercancel', stopResize); + document.addEventListener('pointerup', stopResize); + // unavailable on e.g. Safari but mostly for smoothness + document.addEventListener('wheel', doResize); + // --swimlane-height can be either a stored size or "auto"; get actual computed size + currentHeight = $swimlane[0].offsetHeight; + $swimlane.addClass('swimlane-resizing'); + $('body').addClass('swimlane-resizing-active'); - e.preventDefault(); - e.stopPropagation(); + // not being able to resize can be frustrating, give a little more room + maxHeight = Math.max(height, absoluteMaxHeight); + maxHeightWithTolerance = maxHeight + tolerance; + + $swimlane[0].style.setProperty('--swimlane-max-height', `${maxHeightWithTolerance}px`); + + pageY = e.pageY; + + isResizing = true; + previousLimit = false; + deltaY = null; + } + + const doResize = (e) => { + if (!isResizing || !(e.isPrimary || e instanceof WheelEvent)) { + return; + } + const { y: handleY, height: handleHeight } = $resizeHandle[0].getBoundingClientRect(); + const containerHeight = flexContainer.offsetHeight; + const isBlocked = $swimlane[0].classList.contains('cannot-resize'); + + // deltaY of WheelEvent is unreliable, do with a simple actual delta with handle and pointer + deltaY = e.clientY - handleY; + + const candidateHeight = currentHeight + deltaY; + const oldHeight = currentHeight; + let stepHeight = Math.max(minHeight, Math.min(maxHeightWithTolerance, candidateHeight)); + + const reachingMax = (maxHeightWithTolerance - stepHeight - 20) <= 0; + const reachingMin = (stepHeight - 20 - minHeight) <= 0; + if (!previousLimit && (reachingMax && deltaY > 0 || reachingMin && deltaY < 0)) { + $swimlane[0].classList.add('cannot-resize'); + previousLimit = true; + if (reachingMax) { + stepHeight = maxHeightWithTolerance; + } else { + stepHeight = minHeight; + } + } else if (previousLimit && !reachingMax && !reachingMin) { + // we want to re-init only below handle if min-size, above if max-size, + // so computed values are accurate + if ((deltaY > 0 && pageY >= handleY + handleHeight) + || (deltaY < 0 && pageY <= handleY)) { + $swimlane[0].classList.remove('cannot-resize'); + // considered as a new move, changing direction is certain + previousLimit = false; + } + } + + if (!isBlocked) { + // Ensure container grows and shrinks with swimlanes, so you guess a sense of scrolling something + if (e.pageY > (containerHeight - window.innerHeight)) { + document.body.style.height = `${containerHeight + window.innerHeight / 4}px`; + } + // helps to scroll at the beginning/end of the page + let gapToLeave = window.innerHeight / 10; + const factor = isTouchScreen ? 6 : 7; + if (e.clientY > factor * gapToLeave) { + //correct but too laggy + window.scrollBy({ top: gapToLeave, behavior: "smooth" }); + } + // special case where scrolling down while + // swimlane is stuck; feels weird + else if (e.clientY < (10 - factor) * gapToLeave) { + window.scrollBy({ top: -gapToLeave , behavior: "smooth"}); + } + } + + if (oldHeight !== stepHeight && !isBlocked) { + // Apply the new height immediately for real-time feedback + $swimlane[0].style.setProperty('--swimlane-height', `${stepHeight}px`); + currentHeight = stepHeight; + } }; const stopResize = (e) => { - if (!isResizing) return; + if(!isResizing) { + return; + } + if (previousLimit) { + $swimlane[0].classList.remove('cannot-resize'); + } + + // hopefully be gentler on cpu + document.removeEventListener('pointermove', doResize); + document.removeEventListener('pointercancel', stopResize); + document.removeEventListener('pointerup', stopResize); + document.removeEventListener('wheel', doResize); isResizing = false; - // Calculate final height - const currentY = e.pageY || e.originalEvent.touches[0].pageY; - const deltaY = currentY - startY; - const finalHeight = Math.max(minHeight, Math.min(maxHeight, startHeight + deltaY)); - - // Ensure the final height is applied + let finalHeight = Math.min(parseInt($swimlane[0].style.getPropertyValue('--swimlane-height'), 10), maxHeight); $swimlane[0].style.setProperty('--swimlane-height', `${finalHeight}px`); - $swimlane[0].style.setProperty('height', `${finalHeight}px`); - $swimlane[0].style.setProperty('min-height', `${finalHeight}px`); - $swimlane[0].style.setProperty('max-height', `${finalHeight}px`); - $swimlane[0].style.setProperty('flex', 'none'); - $swimlane[0].style.setProperty('flex-basis', 'auto'); - $swimlane[0].style.setProperty('flex-grow', '0'); - $swimlane[0].style.setProperty('flex-shrink', '0'); // Remove visual feedback but keep the height $swimlane.removeClass('swimlane-resizing'); $('body').removeClass('swimlane-resizing-active'); - $('body').css('user-select', ''); // Save the new height using the existing system const boardId = swimlane.boardId; @@ -678,30 +700,15 @@ BlazeComponent.extendComponent({ console.warn('Error saving swimlane height to localStorage:', e); } } - - e.preventDefault(); }; - - // Mouse events - $resizeHandle.on('mousedown', startResize); - $(document).on('mousemove', doResize); - $(document).on('mouseup', stopResize); - - // Touch events for mobile - $resizeHandle.on('touchstart', startResize, { passive: false }); - $(document).on('touchmove', doResize, { passive: false }); - $(document).on('touchend', stopResize, { passive: false }); - - - // Prevent dragscroll interference - $resizeHandle.on('mousedown', (e) => { - e.stopPropagation(); - }); - + // handle both pointer and touch + $resizeHandle.on("pointerdown", startResize); }, }).register('swimlane'); + + BlazeComponent.extendComponent({ onCreated() { this.currentBoard = Utils.getCurrentBoard(); @@ -709,6 +716,8 @@ BlazeComponent.extendComponent({ this.currentBoard.isTemplatesBoard() && this.currentData().isListTemplatesSwimlane(); this.currentSwimlane = this.currentData(); + // so that lists can be filtered from Board methods + this.currentBoard.swimlane = this.currentSwimlane; }, // Proxy @@ -765,6 +774,13 @@ BlazeComponent.extendComponent({ }, }).register('addListForm'); + +Template.addListForm.helpers({ + lists() { + return this.myLists(); + } +}); + Template.swimlane.helpers({ canSeeAddList() { return ReactiveCache.getCurrentUser().isBoardAdmin(); @@ -777,16 +793,14 @@ Template.swimlane.helpers({ collapseSwimlane() { return Utils.getSwimlaneCollapseState(this); - } + }, }); // Initialize sortable on DOM elements setTimeout(() => { const $listsGroupElements = $('.list-group'); - const computeHandle = () => ( - Utils.isTouchScreenOrShowDesktopDragHandles() ? '.js-list-handle' : '.js-list-header' - ); + const computeHandle = () => Utils.isMiniScreen() ? '.js-list-handle' : '.list-header-name-container'; // Initialize sortable on ALL listsGroup elements (even empty ones) $listsGroupElements.each(function(index) { @@ -800,7 +814,7 @@ setTimeout(() => { tolerance: 'pointer', appendTo: '.board-canvas', helper: 'clone', - items: '.js-list:not(.js-list-composer)', + items: '.js-list', placeholder: 'list placeholder', distance: 7, handle: computeHandle(), @@ -820,29 +834,10 @@ setTimeout(() => { // Silent fail } }, + sort(event, ui) { + Utils.scrollIfNeeded(event); + }, stop(evt, ui) { - // To attribute the new index number, we need to get the DOM element - // of the previous and the following list -- if any. - const prevListDom = ui.item.prev('.js-list').get(0); - const nextListDom = ui.item.next('.js-list').get(0); - const sortIndex = calculateIndex(prevListDom, nextListDom, 1); - - const listDomElement = ui.item.get(0); - if (!listDomElement) { - return; - } - - let list; - try { - list = Blaze.getData(listDomElement); - } catch (error) { - return; - } - - if (!list) { - return; - } - // Detect if the list was dropped in a different swimlane const targetSwimlaneDom = ui.item.closest('.js-swimlane'); let targetSwimlaneId = null; @@ -949,18 +944,6 @@ setTimeout(() => { } catch (e) { // Silent fail } - - // Re-enable dragscroll after list dragging is complete - try { - dragscroll.reset(); - } catch (e) { - // Silent fail - } - - // Re-enable dragscroll on all swimlanes - $('.js-swimlane').each(function() { - $(this).addClass('dragscroll'); - }); } }); // Reactively adjust handle when setting changes @@ -980,6 +963,7 @@ BlazeComponent.extendComponent({ currentCardIsInThisList(listId, swimlaneId) { return currentCardIsInThisList(listId, swimlaneId); }, + visible(list) { if (list.archived) { // Show archived list only when filter archive is on @@ -1003,7 +987,7 @@ BlazeComponent.extendComponent({ return true; }, onRendered() { - const boardComponent = this.parentComponent(); + let boardComponent = getBoardComponent(); const $listsDom = this.$('.js-lists'); @@ -1015,25 +999,24 @@ BlazeComponent.extendComponent({ // Wait for DOM to be ready setTimeout(() => { - const handleSelector = Utils.isTouchScreenOrShowDesktopDragHandles() + const handleSelector = Utils.isMiniScreen() ? '.js-list-handle' - : '.js-list-header'; + : '.list-header-name-container'; const $lists = this.$('.js-list'); - - const $parent = $lists.parent(); + const parent = $lists.parent(); if ($lists.length > 0) { // Check for drag handles - const $handles = $parent.find('.js-list-handle'); + const handles = $(parent).find(handleSelector); // Test if drag handles are clickable - $handles.on('click', function(e) { + handles.on('click', function(e) { e.preventDefault(); e.stopPropagation(); }); - $parent.sortable({ + parent.sortable({ connectWith: '.js-swimlane, .js-lists', tolerance: 'pointer', appendTo: '.board-canvas', @@ -1045,18 +1028,25 @@ BlazeComponent.extendComponent({ disabled: !Utils.canModifyBoard(), start(evt, ui) { ui.helper.css('z-index', 1000); - ui.placeholder.height(ui.helper.height()); - ui.placeholder.width(ui.helper.width()); + width = ui.helper.width(); + height = ui.helper.height(); + ui.placeholder.height(height); + ui.placeholder.width(width); + ui.placeholder[0].setAttribute('style', `width: ${width}px !important; height: ${height}px !important;`); EscapeActions.executeUpTo('popup-close'); boardComponent.setIsDragging(true); }, stop(evt, ui) { boardComponent.setIsDragging(false); - } + saveSorting(ui); + }, + sort(event, ui) { + Utils.scrollIfNeeded(event); + }, }); // Reactively update handle when user toggles desktop drag handles this.autorun(() => { - const newHandle = Utils.isTouchScreenOrShowDesktopDragHandles() + const newHandle = Utils.isMiniScreen() ? '.js-list-handle' : '.js-list-header'; if ($parent.data('uiSortable') || $parent.data('sortable')) { diff --git a/client/components/users/userAvatar.css b/client/components/users/userAvatar.css index 27d8993b7..a97fd469e 100644 --- a/client/components/users/userAvatar.css +++ b/client/components/users/userAvatar.css @@ -1,47 +1,40 @@ .member { - border-radius: 3px; - display: block; - position: relative; - float: left; - height: clamp(24px, 3.5vw, 36px); - width: clamp(24px, 3.5vw, 36px); - margin: .3vh; - cursor: pointer; - user-select: none; - z-index: 1; - text-decoration: none; - border-radius: 50%; -} -.member .avatar { - overflow: hidden; - border-radius: 50%; -} -.member .avatar.avatar-initials { - height: 70%; - width: 70%; - padding: 15%; + display: flex; background-color: #dbdbdb; - color: #444; - position: absolute; + aspect-ratio: 1 / 1; + border-radius: 50%; + padding: 0.2em; + font-size: 0.9em; + height: var(--label-height); + align-items: center; + justify-content: center; + align-self: flex-start; + color: #111; + margin: 0 0.2ch; +} + +.js-select-initials { + justify-content: start; + p { + margin: 0; + } display: flex; align-items: center; justify-content: center; } + .member .avatar.avatar-image { object-fit: cover; object-position: center; - height: 100%; - width: 100%; } .member .member-presence-status { background-color: #b3b3b3; border: 1px solid #fff; border-radius: 50%; - height: 7px; - width: 7px; + height: 1.2ch; + width: 1.2ch; position: absolute; - right: -1px; - bottom: -1px; + transform: translate(1.6ch, 1.6ch); border: 1px solid #fff; z-index: 15; } @@ -61,18 +54,6 @@ background: #e44242; border-color: #f1dada; } -.member .edit-avatar { - position: absolute; - top: 0; - height: 100%; - width: 100%; - border-radius: 50%; - background: #000; - display: flex; - align-items: center; - justify-content: center; - opacity: 0; -} .member .edit-avatar:hover { opacity: 0.6; } @@ -112,9 +93,4 @@ } .mini-profile-info .info p { padding-top: 0; -} -.mini-profile-info .member { - width: clamp(40px, 5vw, 60px); - height: clamp(40px, 5vw, 60px); - margin-right: 10px; -} +} \ No newline at end of file diff --git a/client/components/users/userAvatar.jade b/client/components/users/userAvatar.jade index 1905e4c79..18face53a 100644 --- a/client/components/users/userAvatar.jade +++ b/client/components/users/userAvatar.jade @@ -19,8 +19,8 @@ template(name="userAvatar") i.fa.fa-pencil-square-o template(name="userAvatarInitials") - svg.avatar.avatar-initials(viewBox="0 0 {{viewPortWidth}} 15") - text(x="50%" y="11" text-anchor="middle" dominant-baseline="middle" font-size="16")= initials + .avatar-initials + = initials template(name="orgAvatar") a.member.orgOrTeamMember(class="js-member" title="{{orgData.orgDisplayName}}") diff --git a/client/components/users/userForm.css b/client/components/users/userForm.css index be5e0522d..e115aa279 100644 --- a/client/components/users/userForm.css +++ b/client/components/users/userForm.css @@ -1,109 +1,106 @@ -.auth-layout .at-form-landing-logo { - width: min(249px, 32vw); - margin: auto; - margin-top: 6vh; - margin-bottom: 2.5vh; +.auth-container { + display: grid; + align-content: stretch; + align-items: stretch; + justify-items: stretch; + justify-content: center; + padding: 2lh 0; + /* i.e. center horizontally */ + margin-inline: auto;; + /* parent container has relative positionning */ + grid-template-columns: 100%; + grid-template-rows: minmax(20vh, 300px) min-content 1fr; + position: relative; } + +body.mobile-mode:has(.auth-container) { + .auth-container { + grid-template-columns: 90vw; + min-height: 100%; + } +} + +.auth-logo { + &, &>a:not(img), > img { + display: flex; + flex: 1; + justify-content: center; + } +} + +.auth-container { + flex: 1; + max-width: max(30vw, 600px); + gap: 1lh; + margin-bottom: 1lh; + max-height: 80vh; + position: relative; +} + + .auth-layout .auth-dialog { - width: min(275px, 36vw); - padding: 3vh 3vw; - margin: auto; - margin-bottom: 2.5vh; background: #fff; + font-size: 1.1em; border-radius: 0.4vw; border: 1px solid #dbdbdb; border-bottom-color: #c2c2c2; box-shadow: 0 0.2vh 0.8vh rgba(0,0,0,0.3); + padding: 0 2ch 0.5lh 2ch; + white-space: wrap; + /* try to override properties of non-flex forms + without referring too much to classes and ids, as forms + are dynamic */ + &, div:not(#legalNoticeDiv, .lds-roller, .password-input-container, :empty), form { + display: flex; + flex-direction: column; + gap: 1lh; + >:not(.at-input) { + gap: 0.4lh; + } + .at-input { + gap: 0; + } + } + + *:not(div) { + width: 100%; + margin: 0; + } } + .auth-layout .auth-dialog .at-form .at-link { color: #17683a; } -.auth-layout .auth-dialog .at-form label { - margin-bottom: 0.4vh; -} -.auth-layout .auth-dialog .at-form input { - width: 100%; -} + .password-input-container { - position: relative; - display: flex; - align-items: center; + display: grid; + align-self: stretch; + grid-template-columns: 1fr 6ch; } -.password-input-container input { - flex: 1; - padding-right: 55px; /* More room for the bigger button */ - box-sizing: border-box; -} -.password-toggle-btn { - position: absolute; - right: 5px; /* Adjusted for larger button */ - 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 6px 8px 12px; /* 2x bigger padding, 6px less on right */ - font-size: 16px; /* 2x bigger font size */ - width: auto !important; - height: auto !important; - line-height: 1; - display: flex !important; - align-items: center; - justify-content: center; - z-index: 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; - line-height: 1; - filter: grayscale(100%); - -webkit-filter: grayscale(100%); - opacity: 0.8; -} -.eye-slash-line { - position: absolute; - top: 10px; - left: 10px; - width: 20px; - height: 20px; - pointer-events: none; - stroke: #000; - stroke-width: 2; - fill: none; -} -.password-toggle-btn:hover .eye-text { - color: #000 !important; - filter: grayscale(100%); - -webkit-filter: grayscale(100%); - opacity: 0.8; + +body.mobile-mode { + .auth-layout { + max-height: unset; + } + .password-input-container { + grid-auto-flow: row; + } } .auth-layout .auth-dialog .at-form button { - width: 100%; background: #216694; color: #fff; + min-height: 2lh; } .auth-layout .auth-dialog .at-form .at-title { - background: #f7f7f7; - margin: -3vh -3vw; - padding: 2vh 3vw 0.7vh; - margin-bottom: 2.5vh; border-bottom: 1px solid #dcdcdc; color: #4d4d4d; font-weight: bold; + text-align: center; } .auth-layout .auth-dialog .at-form .at-signup-link, .auth-layout .auth-dialog .at-form .at-signin-link, .auth-layout .auth-dialog .at-form .at-forgotPwd { font-size: 0.9em; - margin-top: 2vh; color: #4d4d4d; } .auth-layout .auth-dialog .at-form .at-signup-link .at-signUp, @@ -113,43 +110,4 @@ .auth-layout .auth-dialog .at-form .at-signin-link .at-signIn, .auth-layout .auth-dialog .at-form .at-forgotPwd .at-signIn { font-weight: bold; -} -.auth-layout .auth-dialog .at-form-lang { - margin-top: 0px; -} -.auth-layout .auth-dialog .at-form-lang .select-lang { - width: 100%; - margin-top: 10px; -} -@media screen and (max-width: 800px) { - .auth-layout { - width: 100%; - height: 100%; - margin: 0px; - padding: 0px; - } - .auth-layout .at-form-landing-logo { - width: 125px; - position: absolute; - top: 0px; - right: 20px; - margin-top: 5px; - margin-bottom: 5px; - } - .auth-layout .at-form-landing-logo img { - width: 125px; - } - .auth-layout .auth-dialog { - width: calc(100% - 50px); - height: calc(100% - 50px); - padding: 25px; - min-height: 380px; - margin: 0px; - margin-bottom: 0px; - border: 0px; - } - .auth-layout .auth-dialog .at-form .at-title h3 { - width: calc(100% - 125px); - overflow-x: hidden; - } -} +} \ No newline at end of file diff --git a/client/components/users/userHeader.jade b/client/components/users/userHeader.jade index c095db48a..a59305715 100644 --- a/client/components/users/userHeader.jade +++ b/client/components/users/userHeader.jade @@ -5,106 +5,126 @@ template(name="headerUserBar") +userAvatar(userId=currentUser._id) unless isMiniScreen unless isSandstorm - if currentUser.profile.fullname - = currentUser.profile.fullname - else - = currentUser.username + .avatar-user-fullname + if currentUser.profile.fullname + = currentUser.profile.fullname + else + = currentUser.username template(name="memberMenuPopup") ul.pop-over-list with currentUser li a.js-toggle-grey-icons(href="#") - i.fa.fa-paint-brush - | {{_ 'grey-icons'}} + span + i.fa.fa-paint-brush + | {{_ 'grey-icons'}} if currentUser.profile if currentUser.profile.GreyIcons i.fa.fa-check li a.js-my-cards(href="{{pathFor 'my-cards'}}") - i.fa.fa-list - | {{_ 'my-cards'}} + span + i.fa.fa-list + | {{_ 'my-cards'}} li a.js-due-cards(href="{{pathFor 'due-cards'}}") - i.fa.fa-calendar - | {{_ 'dueCards-title'}} + span + i.fa.fa-calendar + | {{_ 'dueCards-title'}} li a.js-global-search(href="{{pathFor 'global-search'}}") - i.fa.fa-search - | {{_ 'globalSearch-title'}} + span + i.fa.fa-search + | {{_ 'globalSearch-title'}} li a(href="{{pathFor 'home'}}") - i.fa.fa-home - | {{_ 'all-boards'}} + span + i.fa.fa-home + | {{_ 'all-boards'}} li a(href="{{pathFor 'public'}}") - i.fa.fa-globe - | {{_ 'public'}} + span + i.fa.fa-globe + | {{_ 'public'}} li - a.board-header-btn.js-open-archived-board - i.fa.fa-archive - span {{_ 'archives'}} + a.js-open-archived-board + span + i.fa.fa-archive + | {{_ 'archives'}} li a.js-notifications-drawer-toggle - i.fa.fa-bell - | {{_ 'notifications'}} + span + 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'}} + span + 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'}} + span + i.fa.fa-list + | {{_ 'templates'}} if currentUser.isAdmin li a.js-go-setting(href="{{pathFor 'setting'}}") - i.fa.fa-lock - | {{_ 'admin-panel'}} + span + i.fa.fa-lock + | {{_ 'admin-panel'}} hr if isSameDomainNameSettingValue li a.js-invite-people - i.fa.fa-envelope - | {{_ 'invite-people'}} + span + i.fa.fa-envelope + | {{_ 'invite-people'}} if isNotOAuth2AuthenticationMethod li a.js-edit-profile - i.fa.fa-user - | {{_ 'edit-profile'}} + span + i.fa.fa-user + | {{_ 'edit-profile'}} li a.js-change-settings - i.fa.fa-cog - | {{_ 'change-settings'}} + span + i.fa.fa-cog + | {{_ 'change-settings'}} li a.js-change-avatar - i.fa.fa-picture-o - | {{_ 'edit-avatar'}} + span + i.fa.fa-picture-o + | {{_ 'edit-avatar'}} unless isSandstorm if isNotOAuth2AuthenticationMethod li a.js-change-password - i.fa.fa-key - | {{_ 'changePasswordPopup-title'}} + span + i.fa.fa-key + | {{_ 'changePasswordPopup-title'}} li a.js-change-language - i.fa.fa-flag - | {{_ 'changeLanguagePopup-title'}} + span + i.fa.fa-flag + | {{_ 'changeLanguagePopup-title'}} if isSupportPageEnabled li a(href="{{pathFor 'support'}}") - i.fa.fa-question-circle - | {{_ 'support'}} + span + i.fa.fa-question-circle + | {{_ 'support'}} unless isSandstorm - hr ul.pop-over-list + hr li a.js-logout - i.fa.fa-sign-out - | {{_ 'log-out'}} + span + i.fa.fa-sign-out + | {{_ 'log-out'}} template(name="invitePeoplePopup") ul#registration-setting.setting-detail @@ -134,7 +154,7 @@ template(name="editProfilePopup") form label | {{_ 'fullname'}} - input.js-profile-fullname(type="text" value=profile.fullname autofocus) + input.js-profile-fullname(type="text" value=profile.fullname ) label | {{_ 'username'}} span.error.hide.username-taken diff --git a/client/components/users/userHeader.js b/client/components/users/userHeader.js index 8c892e747..4d8071917 100644 --- a/client/components/users/userHeader.js +++ b/client/components/users/userHeader.js @@ -342,6 +342,7 @@ Template.changeLanguagePopup.events({ }, }); TAPi18n.setLanguage(this.tag); + Popup.close(); event.preventDefault(); }, }); diff --git a/client/lib/boardConverter.js b/client/lib/boardConverter.js index 71bbe5622..68b8c7d72 100644 --- a/client/lib/boardConverter.js +++ b/client/lib/boardConverter.js @@ -113,7 +113,7 @@ class BoardConverter { } conversionStatus.set(`Converting ${listsToConvert.length} lists...`); - + const startTime = Date.now(); const totalLists = listsToConvert.length; let convertedLists = 0; @@ -122,20 +122,20 @@ class BoardConverter { const batchSize = 10; for (let i = 0; i < listsToConvert.length; i += batchSize) { const batch = listsToConvert.slice(i, i + batchSize); - + // Process batch await this.processBatch(batch, defaultSwimlane._id); - + convertedLists += batch.length; const progress = Math.round((convertedLists / totalLists) * 100); conversionProgress.set(progress); - + // Calculate estimated time remaining const elapsed = Date.now() - startTime; const rate = convertedLists / elapsed; // lists per millisecond const remaining = totalLists - convertedLists; const estimatedMs = remaining / rate; - + conversionStatus.set(`Converting list ${convertedLists} of ${totalLists}...`); conversionEstimatedTime.set(this.formatTime(estimatedMs)); @@ -146,11 +146,11 @@ class BoardConverter { // Mark as converted this.conversionCache.set(boardId, true); globalConvertedBoards.add(boardId); // Mark board as converted - + conversionStatus.set('Board conversion completed!'); conversionProgress.set(100); console.log(`Board ${boardId} conversion completed and marked as converted`); - + // Clear status after a delay setTimeout(() => { isConverting.set(false); diff --git a/client/lib/dialogWithBoardSwimlaneList.js b/client/lib/dialogWithBoardSwimlaneList.js index 888601a56..31c14b334 100644 --- a/client/lib/dialogWithBoardSwimlaneList.js +++ b/client/lib/dialogWithBoardSwimlaneList.js @@ -20,9 +20,9 @@ export class DialogWithBoardSwimlaneList extends BlazeComponent { */ getDefaultOption(boardId) { const ret = { - 'boardId' : "", - 'swimlaneId' : "", - 'listId' : "", + 'boardId' : this.data().boardId, + 'swimlaneId' : this.data().swimlaneId, + 'listId' : this.data().listId, } return ret; } @@ -44,21 +44,20 @@ export class DialogWithBoardSwimlaneList extends BlazeComponent { let currentOptions = this.getDialogOptions(); if (currentOptions && boardId && currentOptions[boardId]) { this.cardOption = currentOptions[boardId]; - if (this.cardOption.boardId && - this.cardOption.swimlaneId && - this.cardOption.listId - ) - { - this.selectedBoardId.set(this.cardOption.boardId) - this.selectedSwimlaneId.set(this.cardOption.swimlaneId); - this.selectedListId.set(this.cardOption.listId); - } + } + if (this.cardOption.boardId && + this.cardOption.swimlaneId && + this.cardOption.listId + ) { + this.selectedBoardId.set(this.cardOption.boardId) + this.selectedSwimlaneId.set(this.cardOption.swimlaneId); + this.selectedListId.set(this.cardOption.listId); } this.getBoardData(this.selectedBoardId.get()); - if (!this.selectedSwimlaneId.get() || !ReactiveCache.getSwimlane({_id: this.selectedSwimlaneId.get(), boardId: this.selectedBoardId.get()})) { + if (this.selectedSwimlaneId.get() || ReactiveCache.getSwimlane({_id: this.selectedSwimlaneId.get(), boardId: this.selectedBoardId.get()})) { this.setFirstSwimlaneId(); } - if (!this.selectedListId.get() || !ReactiveCache.getList({_id: this.selectedListId.get(), boardId: this.selectedBoardId.get()})) { + if (this.selectedListId.get() || ReactiveCache.getList({_id: this.selectedListId.get(), boardId: this.selectedBoardId.get()})) { this.setFirstListId(); } } @@ -74,7 +73,7 @@ export class DialogWithBoardSwimlaneList extends BlazeComponent { setFirstListId() { try { const board = ReactiveCache.getBoard(this.selectedBoardId.get()); - const listId = board.lists()[0]._id; + const listId = board.listsInSwimlane(this.selectedSwimlaneId.get())[0]._id; this.selectedListId.set(listId); } catch (e) {} } @@ -131,7 +130,7 @@ export class DialogWithBoardSwimlaneList extends BlazeComponent { /** returns all available lists of the current board */ lists() { const board = ReactiveCache.getBoard(this.selectedBoardId.get()); - const ret = board.lists(); + const ret = board.listsInSwimlane(this.selectedSwimlaneId.get()); return ret; } @@ -219,4 +218,3 @@ export class DialogWithBoardSwimlaneList extends BlazeComponent { ]; } } - diff --git a/client/lib/dialogWithBoardSwimlaneListCard.js b/client/lib/dialogWithBoardSwimlaneListCard.js index 10421c3c1..6ab5aa663 100644 --- a/client/lib/dialogWithBoardSwimlaneListCard.js +++ b/client/lib/dialogWithBoardSwimlaneListCard.js @@ -27,7 +27,7 @@ export class DialogWithBoardSwimlaneListCard extends DialogWithBoardSwimlaneList */ setOption(boardId) { super.setOption(boardId); - + // Also set cardId if available if (this.cardOption && this.cardOption.cardId) { this.selectedCardId.set(this.cardOption.cardId); @@ -69,7 +69,7 @@ export class DialogWithBoardSwimlaneListCard extends DialogWithBoardSwimlaneList // reset list id self.setFirstListId(); - + // reset card id self.selectedCardId.set(''); } diff --git a/client/lib/escapeActions.js b/client/lib/escapeActions.js index e76221074..75a4625cb 100644 --- a/client/lib/escapeActions.js +++ b/client/lib/escapeActions.js @@ -128,10 +128,24 @@ hotkeys('escape', () => { Sidebar.hide(); }); +let currentMouseDown; + +// Avoid the common issue of dragging an element a bit fast and releasing +// out of the element; in that case e.g. popup closes, which is not pleasant. +// Only execute actions if mousedown and mouseup are on the same element (the +// initial issue is that a long drag is still a click event) +$(document).on('pointerdown', evt => { + currentMouseDown = evt.target; +}); // On a left click on the document, we try to exectute one escape action (eg, // close the popup). We don't execute any action if the user has clicked on a // link or a button. -$(document).on('click', evt => { +$(document).on('pointerup', evt => { + const currentMouseUp = evt.target; + if (currentMouseDown !== currentMouseUp) { + // console.debug(`not executing escape actions on ${currentMouseUp} because click started on ${currentMouseDown}`); + return; + } if ( evt.button === 0 && $(evt.target).closest('a,button,.is-editable').length === 0 diff --git a/client/lib/inlinedform.js b/client/lib/inlinedform.js index 62da01993..643c2cb97 100644 --- a/client/lib/inlinedform.js +++ b/client/lib/inlinedform.js @@ -77,8 +77,28 @@ InlinedForm = BlazeComponent.extendComponent({ return [ { 'click .js-close-inlined-form': this.close, - 'click .js-open-inlined-form': this.open, - + 'pointerdown .js-open-inlined-form'(e) { + if (Utils.shouldIgnorePointer(e)) { + return; + } + // to measure the click duration + $(e.target).data("clickStart", new Date()); + }, + 'pointerup .js-open-inlined-form'(e) { + if(Utils.shouldIgnorePointer(e)) { + return; + } + const start = $(e.target).data("clickStart",); + if (!start) { + return; + } + const end = new Date(); + // 500ms feels reasonable for a simple click + if (end - start < 500) { + this.open(e); + } + $(e.target).data("clickStart", null); + }, // Pressing Ctrl+Enter should submit the form 'keydown form textarea'(evt) { if (evt.keyCode === 13 && (evt.metaKey || evt.ctrlKey)) { diff --git a/client/lib/keyboard.js b/client/lib/keyboard.js index 7a72df472..c77eac7f3 100644 --- a/client/lib/keyboard.js +++ b/client/lib/keyboard.js @@ -174,6 +174,7 @@ hotkeys(nums, (event, handler) => { return; } const board = ReactiveCache.getBoard(currentBoardId); + if (!board) {return} const labels = board.labels; if (MultiSelection.isActive() && ReactiveCache.getCurrentUser().isBoardMember()) { const cardIds = MultiSelection.getSelectedCardIds(); diff --git a/client/lib/modal.js b/client/lib/modal.js index 08e1b380e..bf7d8e7f8 100644 --- a/client/lib/modal.js +++ b/client/lib/modal.js @@ -1,6 +1,5 @@ const closedValue = null; import { FlowRouter } from 'meteor/ostrio:flow-router-extra'; - window.Modal = new (class { constructor() { this._currentModal = new ReactiveVar(closedValue); diff --git a/client/lib/popup.js b/client/lib/popup.js index 4a8b481ac..5db8f56b5 100644 --- a/client/lib/popup.js +++ b/client/lib/popup.js @@ -1,121 +1,25 @@ +import PopupComponent from '/client/components/main/popup'; import { TAPi18n } from '/imports/i18n'; window.Popup = new (class { - constructor() { - // The template we use to render popups - this.template = Template.popup; - - // We only want to display one popup at a time and we keep the view object - // in this `Popup.current` variable. If there is no popup currently opened - // the value is `null`. - this.current = null; - - // It's possible to open a sub-popup B from a popup A. In that case we keep - // the data of popup A so we can return back to it. Every time we open a new - // popup the stack grows, every time we go back the stack decrease, and if - // we close the popup the stack is reseted to the empty stack []. - this._stack = []; - - // We invalidate this internal dependency every time the top of the stack - // has changed and we want to re-render a popup with the new top-stack data. - this._dep = new Tracker.Dependency(); - } - /// This function returns a callback that can be used in an event map: /// Template.tplName.events({ /// 'click .elementClass': Popup.open("popupName"), /// }); /// The popup inherit the data context of its parent. - open(name) { + open(name, args) { const self = this; - const popupName = `${name}Popup`; - function clickFromPopup(evt) { - return $(evt.target).closest('.js-pop-over').length !== 0; - } - /** opens the popup - * @param evt the current event - * @param options options (dataContextIfCurrentDataIsUndefined use this dataContext if this.currentData() is undefined) - */ return function(evt, options) { - // If a popup is already opened, clicking again on the opener element - // should close it -- and interrupt the current `open` function. - if (self.isOpen()) { - const previousOpenerElement = self._getTopStack().openerElement; - if (previousOpenerElement === evt.currentTarget) { - self.close(); - return; - } else { - $(previousOpenerElement).removeClass('is-active'); - // Clean up previous popup content to prevent mixing - self._cleanupPreviousPopupContent(); - } + const popupName = `${name}Popup`; + const openerElement = evt.target; + let classicArgs = { openerElement: openerElement, name: popupName, title: self._getTitle(popupName), miscOptions: options }; + if (typeof(args) === "object") { + classicArgs = Object.assign(classicArgs, args); } - - // We determine the `openerElement` (the DOM element that is being clicked - // and the one we take in reference to position the popup) from the event - // if the popup has no parent, or from the parent `openerElement` if it - // has one. This allows us to position a sub-popup exactly at the same - // position than its parent. - let openerElement; - if (clickFromPopup(evt) && self._getTopStack()) { - openerElement = self._getTopStack().openerElement; - } else { - // For Member Settings sub-popups, always start fresh to avoid content mixing - if (popupName.includes('changeLanguage') || popupName.includes('changeAvatar') || - popupName.includes('editProfile') || popupName.includes('changePassword') || - popupName.includes('invitePeople') || popupName.includes('support')) { - self._stack = []; - } - openerElement = evt.currentTarget; - } - $(openerElement).addClass('is-active'); + PopupComponent.open(classicArgs); evt.preventDefault(); - - // We push our popup data to the stack. The top of the stack is always - // used as the data source for our current popup. - self._stack.push({ - popupName, - openerElement, - hasPopupParent: clickFromPopup(evt), - title: self._getTitle(popupName), - depth: self._stack.length, - offset: self._getOffset(openerElement), - dataContext: (this && this.currentData && this.currentData()) || (options && options.dataContextIfCurrentDataIsUndefined) || this, - }); - - const $contentWrapper = $('.content-wrapper') - if ($contentWrapper.length > 0) { - const contentWrapper = $contentWrapper[0]; - self._getTopStack().scrollTop = contentWrapper.scrollTop; - // scroll from e.g. delete comment to the top (where the confirm button is) - $contentWrapper.scrollTop(0); - } - - // If there are no popup currently opened we use the Blaze API to render - // one into the DOM. We use a reactive function as the data parameter that - // return the complete along with its top element and depends on our - // internal dependency that is being invalidated every time the top - // element of the stack has changed and we want to update the popup. - // - // Otherwise if there is already a popup open we just need to invalidate - // our internal dependency, and since we just changed the top element of - // our internal stack, the popup will be updated with the new data. - if (!self.isOpen()) { - if (!Template[popupName]) { - console.error('Template not found:', popupName); - return; - } - self.current = Blaze.renderWithData( - self.template, - () => { - self._dep.depend(); - return { ...self._getTopStack(), stack: self._stack }; - }, - document.body, - ); - } else { - self._dep.changed(); - } + // important so that one click does not opens multiple, stacked popups + evt.stopPropagation(); }; } @@ -127,149 +31,40 @@ window.Popup = new (class { /// }); afterConfirm(name, action) { const self = this; - return function(evt, tpl) { - const context = (this.currentData && this.currentData()) || this; - context.__afterConfirmAction = action; - self.open(name).call(context, evt, tpl); + tpl ??= {}; + tpl.afterConfirm = action; + // Just a wrapper of open which will call `action` on some events + // see PopupDetachedComponent; for now this is hardcoded + self.open(name)(evt, tpl); + evt.preventDefault(); }; } - /// The public reactive state of the popup. - isOpen() { - this._dep.changed(); - return Boolean(this.current); - } - /// In case the popup was opened from a parent popup we can get back to it /// with this `Popup.back()` function. You can go back several steps at once /// by providing a number to this function, e.g. `Popup.back(2)`. In this case /// intermediate popup won't even be rendered on the DOM. If the number of /// steps back is greater than the popup stack size, the popup will be closed. back(n = 1) { - if (this._stack.length > n) { - const $contentWrapper = $('.content-wrapper') - if ($contentWrapper.length > 0) { - const contentWrapper = $contentWrapper[0]; - const stack = this._stack[this._stack.length - n]; - // scrollTopMax and scrollLeftMax only available at Firefox (https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollTopMax) - const scrollTopMax = contentWrapper.scrollTopMax || contentWrapper.scrollHeight - contentWrapper.clientHeight; - if (scrollTopMax && stack.scrollTop > scrollTopMax) { - // sometimes scrollTopMax is lower than scrollTop, so i need this dirty hack - setTimeout(() => { - $contentWrapper.scrollTop(stack.scrollTop); - }, 6); - } - // restore the old popup scroll position - $contentWrapper.scrollTop(stack.scrollTop); - } - _.times(n, () => this._stack.pop()); - this._dep.changed(); - } else { - this.close(); - } + _.times(n, () => PopupComponent.destroy()); } /// Close the current opened popup. close() { - if (this.isOpen()) { - Blaze.remove(this.current); - this.current = null; - - const openerElement = this._getTopStack().openerElement; - $(openerElement).removeClass('is-active'); - - this._stack = []; - // Clean up popup content when closing - this._cleanupPreviousPopupContent(); - } + this.back(); } + closeAll() { + this.back(PopupComponent.stack.length) + } + + getOpenerComponent(n=4) { const { openerElement } = Template.parentData(n); return BlazeComponent.getComponentForElement(openerElement); } - // An utility function that returns the top element of the internal stack - _getTopStack() { - return this._stack[this._stack.length - 1]; - } - - _cleanupPreviousPopupContent() { - // Force a re-render to ensure proper cleanup - if (this._dep) { - this._dep.changed(); - } - } - - // We automatically calculate the popup offset from the reference element - // position and dimensions. We also reactively use the window dimensions to - // ensure that the popup is always visible on the screen. - _getOffset(element) { - const $element = $(element); - return () => { - Utils.windowResizeDep.depend(); - - if (Utils.isMiniScreen()) return { left: 0, top: 0 }; - - // If the opener element is missing (e.g., programmatic open), fallback to viewport origin - if (!$element || $element.length === 0) { - return { left: 10, top: 10, maxHeight: $(window).height() - 20 }; - } - - const offset = $element.offset(); - // Calculate actual popup width based on CSS: min(380px, 55vw) - const viewportWidth = $(window).width(); - const viewportHeight = $(window).height(); - const popupWidth = Math.min(380, viewportWidth * 0.55) + 15; // Add 15px for margin - - // Check if this is an admin panel edit popup - const isAdminEditPopup = $element.hasClass('edit-user') || - $element.hasClass('edit-org') || - $element.hasClass('edit-team'); - - if (isAdminEditPopup) { - // Center the popup horizontally and use full height - const centeredLeft = (viewportWidth - popupWidth) / 2; - - return { - left: Math.max(10, centeredLeft), // Ensure popup doesn't go off screen - top: 10, // Start from top with small margin - maxHeight: viewportHeight - 20, // Use full height minus small margins - }; - } - - // Calculate available height for popup - const popupTop = offset.top + $element.outerHeight(); - - // For language popup, don't use dynamic height to avoid overlapping board - const isLanguagePopup = $element.hasClass('js-change-language'); - let availableHeight, maxPopupHeight; - - if (isLanguagePopup) { - // For language popup, position content area below right vertical scrollbar - const availableHeight = viewportHeight - popupTop - 20; // 20px margin from bottom (near scrollbar) - const calculatedHeight = Math.min(availableHeight, viewportHeight * 0.5); // Max 50% of viewport - - return { - left: Math.min(offset.left, viewportWidth - popupWidth), - top: popupTop, - maxHeight: Math.max(calculatedHeight, 200), // Minimum 200px height - }; - } else { - // For other popups, use the dynamic height calculation - availableHeight = viewportHeight - popupTop - 20; // 20px margin from bottom - maxPopupHeight = Math.min(availableHeight, viewportHeight * 0.8); // Max 80% of viewport - - return { - left: Math.min(offset.left, viewportWidth - popupWidth), - top: popupTop, - maxHeight: Math.max(maxPopupHeight, 200), // Minimum 200px height - }; - } - }; - } - // We get the title from the translation files. Instead of returning the // result, we return a function that compute the result and since `TAPi18n.__` // is a reactive data source, the title will be changed reactively. @@ -297,10 +92,11 @@ escapeActions.forEach(actionName => { EscapeActions.register( `popup-${actionName}`, () => Popup[actionName](), - () => Popup.isOpen(), + () => PopupComponent.stack.length > 0, { - noClickEscapeOn: '.js-pop-over,.js-open-card-title-popup,.js-open-inlined-form,.textcomplete-dropdown', + // will maybe need something more robust, but for now it enables multiple cards opened without closing each other when clicking on common UI elements + noClickEscapeOn: '.js-pop-over,.js-open-card-title-popup,.js-open-inlined-form,.textcomplete-dropdown,.js-card-details,.board-sidebar,#header,.add-comment-reaction', enabledOnClick: actionName === 'close', }, ); -}); +}); \ No newline at end of file diff --git a/client/lib/utils.js b/client/lib/utils.js index 735e23025..09ae2f0ad 100644 --- a/client/lib/utils.js +++ b/client/lib/utils.js @@ -24,7 +24,7 @@ Utils = { } return ret; }, - getCurrentCardId(ignorePopupCard) { + getCurrentCardId(ignorePopupCard = false) { let ret = Session.get('currentCard'); if (!ret && !ignorePopupCard) { ret = Utils.getPopupCardId(); @@ -47,70 +47,62 @@ Utils = { const ret = ReactiveCache.getBoard(boardId); return ret; }, - getCurrentCard(ignorePopupCard) { + getCurrentCard(ignorePopupCard = false) { const cardId = Utils.getCurrentCardId(ignorePopupCard); const ret = ReactiveCache.getCard(cardId); return ret; }, - // Zoom and mobile mode utilities - getZoomLevel() { - const user = ReactiveCache.getCurrentUser(); - if (user && user.profile && user.profile.zoomLevel !== undefined) { - return user.profile.zoomLevel; - } - // For non-logged-in users, check localStorage - const stored = localStorage.getItem('wekan-zoom-level'); - return stored ? parseFloat(stored) : 1.0; + // in fact, what we really care is screen size + // large mobile device like iPad or android Pad has a big screen, it should also behave like a desktop + // in a small window (even on desktop), Wekan run in compact mode. + // we can easily debug with a small window of desktop browser. :-) + isMiniScreen() { + this.windowResizeDep.depend(); + // Also depend on mobile mode changes to make this reactive + + // innerWidth can be over screen width in some case; rely on physical pixels + // we get what we want, i.e real width, no need for orientation + const width = Math.min(window.innerWidth, window.screen.width); + const isMobilePhone = /iPhone|iPad|Mobile|Android|iPhone|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) && !/iPad/i.test(navigator.userAgent); + const isTouch = this.isTouchScreen(); + + return (isTouch || isMobilePhone || width < 800); }, - setZoomLevel(level) { - const user = ReactiveCache.getCurrentUser(); - if (user) { - // Update user profile - user.setZoomLevel(level); + isTouchScreen() { + // NEW TOUCH DEVICE DETECTION: + // https://developer.mozilla.org/en-US/docs/Web/HTTP/Browser_detection_using_the_user_agent + var hasTouchScreen = false; + if ("maxTouchPoints" in navigator) { + hasTouchScreen = navigator.maxTouchPoints > 0; + } else if ("msMaxTouchPoints" in navigator) { + hasTouchScreen = navigator.msMaxTouchPoints > 0; } else { - // Store in localStorage for non-logged-in users - localStorage.setItem('wekan-zoom-level', level.toString()); + var mQ = window.matchMedia && matchMedia("(pointer:coarse)"); + if (mQ && mQ.media === "(pointer:coarse)") { + hasTouchScreen = !!mQ.matches; + } else if ('orientation' in window) { + hasTouchScreen = true; // deprecated, but good fallback + } else { + // Only as a last resort, fall back to user agent sniffing + var UA = navigator.userAgent; + hasTouchScreen = ( + /\b(BlackBerry|webOS|iPhone|IEMobile)\b/i.test(UA) || + /\b(Android|Windows Phone|iPad|iPod)\b/i.test(UA) + ); + } } - Utils.applyZoomLevel(level); - - // Trigger reactive updates for UI components - Session.set('wekan-zoom-level', level); + return hasTouchScreen; }, getMobileMode() { - // Check localStorage first - user's explicit preference takes priority - const stored = localStorage.getItem('wekan-mobile-mode'); - if (stored !== null) { - return stored === 'true'; - } - - // Then check user profile - const user = ReactiveCache.getCurrentUser(); - if (user && user.profile && user.profile.mobileMode !== undefined) { - return user.profile.mobileMode; - } - - // Default to mobile mode for iPhone/iPod - const isIPhone = /iPhone|iPod/i.test(navigator.userAgent); - return isIPhone; + return this.isMiniScreen(); }, setMobileMode(enabled) { - const user = ReactiveCache.getCurrentUser(); - if (user) { - // Update user profile - user.setMobileMode(enabled); - } - // Always store in localStorage for persistence across sessions - localStorage.setItem('wekan-mobile-mode', enabled.toString()); - Utils.applyMobileMode(enabled); - // Trigger reactive updates for UI components Session.set('wekan-mobile-mode', enabled); - // Re-apply zoom level to ensure proper rendering - const zoomLevel = Utils.getZoomLevel(); - Utils.applyZoomLevel(zoomLevel); + Utils.applyMobileMode(enabled); }, getCardZoom() { @@ -139,77 +131,6 @@ Utils = { } }, - applyZoomLevel(level) { - const boardWrapper = document.querySelector('.board-wrapper'); - const body = document.body; - const isMobileMode = body.classList.contains('mobile-mode'); - - if (boardWrapper) { - if (isMobileMode) { - // On mobile mode, only apply zoom to text and icons, not the entire layout - // Remove any existing transform from board-wrapper - boardWrapper.style.transform = ''; - boardWrapper.style.transformOrigin = ''; - - // Apply zoom to text and icon elements instead - const textElements = boardWrapper.querySelectorAll('h1, h2, h3, h4, h5, h6, p, span, div, .minicard, .list-header-name, .board-header-btn, .fa, .icon'); - textElements.forEach(element => { - element.style.transform = `scale(${level})`; - element.style.transformOrigin = 'center'; - }); - - // Reset board-canvas height - const boardCanvas = document.querySelector('.board-canvas'); - if (boardCanvas) { - boardCanvas.style.height = ''; - } - } else { - // Desktop mode: apply zoom to entire board-wrapper as before - boardWrapper.style.transform = `scale(${level})`; - boardWrapper.style.transformOrigin = 'top left'; - - // If zoom is 50% or lower, make board wrapper full width like content - if (level <= 0.5) { - boardWrapper.style.width = '100%'; - boardWrapper.style.maxWidth = '100%'; - boardWrapper.style.margin = '0'; - } else { - // Reset to normal width for higher zoom levels - boardWrapper.style.width = ''; - boardWrapper.style.maxWidth = ''; - boardWrapper.style.margin = ''; - } - - // Adjust container height to prevent scroll issues - const boardCanvas = document.querySelector('.board-canvas'); - if (boardCanvas) { - boardCanvas.style.height = `${100 / level}%`; - - // For high zoom levels (200%+), enable both horizontal and vertical scrolling - if (level >= 2.0) { - boardCanvas.style.overflowX = 'auto'; - boardCanvas.style.overflowY = 'auto'; - // Ensure the content area can scroll both horizontally and vertically - const content = document.querySelector('#content'); - if (content) { - content.style.overflowX = 'auto'; - content.style.overflowY = 'auto'; - } - } else { - // Reset overflow for normal zoom levels - boardCanvas.style.overflowX = ''; - boardCanvas.style.overflowY = ''; - const content = document.querySelector('#content'); - if (content) { - content.style.overflowX = ''; - content.style.overflowY = ''; - } - } - } - } - } - }, - applyMobileMode(enabled) { const body = document.body; if (enabled) { @@ -223,9 +144,7 @@ Utils = { initializeUserSettings() { // Apply saved settings on page load - const zoomLevel = Utils.getZoomLevel(); const mobileMode = Utils.getMobileMode(); - Utils.applyZoomLevel(zoomLevel); Utils.applyMobileMode(mobileMode); }, getCurrentList() { @@ -284,11 +203,11 @@ Utils = { }, setBoardView(view) { const currentUser = ReactiveCache.getCurrentUser(); - + if (currentUser) { // Update localStorage first window.localStorage.setItem('boardView', view); - + // Update user profile via Meteor method Meteor.call('setBoardView', view, (error) => { if (error) { @@ -575,82 +494,6 @@ Utils = { }, windowResizeDep: new Tracker.Dependency(), - // in fact, what we really care is screen size - // large mobile device like iPad or android Pad has a big screen, it should also behave like a desktop - // in a small window (even on desktop), Wekan run in compact mode. - // we can easily debug with a small window of desktop browser. :-) - isMiniScreen() { - this.windowResizeDep.depend(); - // Also depend on mobile mode changes to make this reactive - Session.get('wekan-mobile-mode'); - - // Show mobile view when: - // 1. Screen width is 800px or less (matches CSS media queries) - // 2. Mobile phones in portrait mode - // 3. iPad in very small screens (≤ 600px) - // 4. All iPhone models by default (including largest models), but respect user preference - const isSmallScreen = window.innerWidth <= 800; - const isVerySmallScreen = window.innerWidth <= 600; - const isPortrait = window.innerWidth < window.innerHeight || window.matchMedia("(orientation: portrait)").matches; - const isMobilePhone = /Mobile|Android|iPhone|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) && !/iPad/i.test(navigator.userAgent); - const isIPhone = /iPhone|iPod/i.test(navigator.userAgent); - const isIPad = /iPad/i.test(navigator.userAgent); - const isUbuntuTouch = /Ubuntu/i.test(navigator.userAgent); - - // Check if user has explicitly set mobile mode preference - const userMobileMode = this.getMobileMode(); - - // For iPhone: default to mobile view, but respect user's mobile mode toggle preference - // This ensures all iPhone models (including iPhone 15 Pro Max, 14 Pro Max, etc.) start with mobile view - // but users can still switch to desktop mode if they prefer - if (isIPhone) { - // If user has explicitly set a preference, respect it - if (userMobileMode !== null && userMobileMode !== undefined) { - return userMobileMode; - } - // Otherwise, default to mobile view for iPhones - return true; - } else if (isMobilePhone) { - return isPortrait; // Other mobile phones: portrait = mobile, landscape = desktop - } else if (isIPad) { - return isVerySmallScreen; // iPad: only very small screens get mobile view - } else if (isUbuntuTouch) { - // Ubuntu Touch: smartphones (≤ 600px) behave like mobile phones, tablets (> 600px) like iPad - if (isVerySmallScreen) { - return isPortrait; // Ubuntu Touch smartphone: portrait = mobile, landscape = desktop - } else { - return isVerySmallScreen; // Ubuntu Touch tablet: only very small screens get mobile view - } - } else { - return isSmallScreen; // Desktop: based on 800px screen width - } - }, - - isTouchScreen() { - // NEW TOUCH DEVICE DETECTION: - // https://developer.mozilla.org/en-US/docs/Web/HTTP/Browser_detection_using_the_user_agent - var hasTouchScreen = false; - if ("maxTouchPoints" in navigator) { - hasTouchScreen = navigator.maxTouchPoints > 0; - } else if ("msMaxTouchPoints" in navigator) { - hasTouchScreen = navigator.msMaxTouchPoints > 0; - } else { - var mQ = window.matchMedia && matchMedia("(pointer:coarse)"); - if (mQ && mQ.media === "(pointer:coarse)") { - hasTouchScreen = !!mQ.matches; - } else if ('orientation' in window) { - hasTouchScreen = true; // deprecated, but good fallback - } else { - // Only as a last resort, fall back to user agent sniffing - var UA = navigator.userAgent; - hasTouchScreen = ( - /\b(BlackBerry|webOS|iPhone|IEMobile)\b/i.test(UA) || - /\b(Android|Windows Phone|iPad|iPod)\b/i.test(UA) - ); - } - } - return hasTouchScreen; - }, // returns if desktop drag handles are enabled isShowDesktopDragHandles() { @@ -894,17 +737,249 @@ Utils = { showCopied(promise, $tooltip) { if (promise) { promise.then(() => { - $tooltip.show(100); - setTimeout(() => $tooltip.hide(100), 1000); + $tooltip.removeClass("copied-tooltip-hidden").addClass("copied-tooltip-visible"); + setTimeout(() => $tooltip.removeClass("copied-tooltip-visible").addClass("copied-tooltip-hidden"), 1000); }, (err) => { console.error("error: ", err); }); } }, + coalesceSearch(root, queries, fallbackSel) { + // a little helper to chain jQuery lookups + // use with arg like [{func: "closest", sels: [".whatever"...]}...] + root = $(root); + for ({func, sels} of queries) { + for (sel of sels) { + res = root[func](sel); + if (res.length) { + return res; + } + } + } + return $(fallbackSel); + }, + + scrollIfNeeded(event) { + // helper used when dragging either cards or lists + const xFactor = 5; + const yFactor = Utils.isMiniScreen() ? 5 : 10; + const limitX = window.innerWidth / xFactor; + const limitY = window.innerHeight / yFactor; + const componentScrollX = this.coalesceSearch(event.target, [{ + func: "closest", + sels: [".swimlane-container", ".swimlane.js-lists", ".board-canvas"] + } + ], ".board-canvas"); + let scrollX = 0; + let scrollY = 0; + if (event.clientX < limitX) { + scrollX = -limitX; + } else if (event.clientX > (xFactor - 1) * limitX) { + scrollX = limitX; + } + if (event.clientY < limitY) { + scrollY = -limitY; + } else if (event.clientY > (yFactor - 1) * limitY) { + scrollY = limitY; + } + window.scrollBy({ top: scrollY, behavior: "smooth" }); + componentScrollX[0].scrollBy({ left: scrollX, behavior: "smooth" }); + }, + + shouldIgnorePointer(event) { + // handle jQuery and native events + if (event.originalEvent) { + event = event.originalEvent; + } + return !(event.isPrimary && (event.pointerType !== 'mouse' || event.button === 0)); + }, + allowsReceivedDate() { + const boardId = Session.get('currentBoard'); + const currentBoard = ReactiveCache.getBoard(boardId); + return currentBoard ? currentBoard.allowsReceivedDate : false; + }, + + allowsStartDate() { + const boardId = Session.get('currentBoard'); + const currentBoard = ReactiveCache.getBoard(boardId); + return currentBoard ? currentBoard.allowsStartDate : false; + }, + + allowsDueDate() { + const boardId = Session.get('currentBoard'); + const currentBoard = ReactiveCache.getBoard(boardId); + return currentBoard ? currentBoard.allowsDueDate : false; + }, + + allowsEndDate() { + const boardId = Session.get('currentBoard'); + const currentBoard = ReactiveCache.getBoard(boardId); + return currentBoard ? currentBoard.allowsEndDate : false; + }, + + allowsSubtasks() { + const boardId = Session.get('currentBoard'); + const currentBoard = ReactiveCache.getBoard(boardId); + return currentBoard ? currentBoard.allowsSubtasks : false; + }, + + allowsCreator() { + const boardId = Session.get('currentBoard'); + const currentBoard = ReactiveCache.getBoard(boardId); + return currentBoard ? (currentBoard.allowsCreator ?? false) : false; + }, + + allowsCreatorOnMinicard() { + const boardId = Session.get('currentBoard'); + const currentBoard = ReactiveCache.getBoard(boardId); + return currentBoard ? (currentBoard.allowsCreatorOnMinicard ?? false) : false; + }, + + allowsMembers() { + const boardId = Session.get('currentBoard'); + const currentBoard = ReactiveCache.getBoard(boardId); + return currentBoard ? currentBoard.allowsMembers : false; + }, + + allowsAssignee() { + const boardId = Session.get('currentBoard'); + const currentBoard = ReactiveCache.getBoard(boardId); + return currentBoard ? currentBoard.allowsAssignee : false; + }, + + allowsAssignedBy() { + const boardId = Session.get('currentBoard'); + const currentBoard = ReactiveCache.getBoard(boardId); + return currentBoard ? currentBoard.allowsAssignedBy : false; + }, + + allowsRequestedBy() { + const boardId = Session.get('currentBoard'); + const currentBoard = ReactiveCache.getBoard(boardId); + return currentBoard ? currentBoard.allowsRequestedBy : false; + }, + + allowsCardSortingByNumber() { + const boardId = Session.get('currentBoard'); + const currentBoard = ReactiveCache.getBoard(boardId); + return currentBoard ? currentBoard.allowsCardSortingByNumber : false; + }, + + allowsShowLists() { + const boardId = Session.get('currentBoard'); + const currentBoard = ReactiveCache.getBoard(boardId); + return currentBoard ? currentBoard.allowsShowLists : false; + }, + + allowsLabels() { + const boardId = Session.get('currentBoard'); + const currentBoard = ReactiveCache.getBoard(boardId); + return currentBoard ? currentBoard.allowsLabels : false; + }, + + allowsShowListsOnMinicard() { + const boardId = Session.get('currentBoard'); + const currentBoard = ReactiveCache.getBoard(boardId); + return currentBoard ? currentBoard.allowsShowListsOnMinicard : false; + }, + + allowsChecklists() { + const boardId = Session.get('currentBoard'); + const currentBoard = ReactiveCache.getBoard(boardId); + return currentBoard ? currentBoard.allowsChecklists : false; + }, + + allowsAttachments() { + const boardId = Session.get('currentBoard'); + const currentBoard = ReactiveCache.getBoard(boardId); + return currentBoard ? currentBoard.allowsAttachments : false; + }, + + allowsComments() { + const boardId = Session.get('currentBoard'); + const currentBoard = ReactiveCache.getBoard(boardId); + return currentBoard ? currentBoard.allowsComments : false; + }, + + allowsCardNumber() { + const boardId = Session.get('currentBoard'); + const currentBoard = ReactiveCache.getBoard(boardId); + return currentBoard ? currentBoard.allowsCardNumber : false; + }, + + allowsDescriptionTitle() { + const boardId = Session.get('currentBoard'); + const currentBoard = ReactiveCache.getBoard(boardId); + return currentBoard ? currentBoard.allowsDescriptionTitle : false; + }, + + allowsDescriptionText() { + const boardId = Session.get('currentBoard'); + const currentBoard = ReactiveCache.getBoard(boardId); + return currentBoard ? currentBoard.allowsDescriptionText : false; + }, + + isBoardSelected() { + const boardId = Session.get('currentBoard'); + const currentBoard = ReactiveCache.getBoard(boardId); + return currentBoard ? currentBoard.dateSettingsDefaultBoardID : false; + }, + + isNullBoardSelected() { + const boardId = Session.get('currentBoard'); + const currentBoard = ReactiveCache.getBoard(boardId); + return currentBoard ? ( + currentBoard.dateSettingsDefaultBoardId === null || + currentBoard.dateSettingsDefaultBoardId === undefined + ) : true; + }, + + allowsDescriptionTextOnMinicard() { + const boardId = Session.get('currentBoard'); + const currentBoard = ReactiveCache.getBoard(boardId); + return currentBoard ? currentBoard.allowsDescriptionTextOnMinicard : false; + }, + + allowsActivities() { + const boardId = Session.get('currentBoard'); + const currentBoard = ReactiveCache.getBoard(boardId); + return currentBoard ? currentBoard.allowsActivities : false; + }, + + allowsCoverAttachmentOnMinicard() { + const boardId = Session.get('currentBoard'); + const currentBoard = ReactiveCache.getBoard(boardId); + return currentBoard ? currentBoard.allowsCoverAttachmentOnMinicard : false; + }, + + allowsBadgeAttachmentOnMinicard() { + const boardId = Session.get('currentBoard'); + const currentBoard = ReactiveCache.getBoard(boardId); + return currentBoard ? currentBoard.allowsBadgeAttachmentOnMinicard : false; + }, + + allowsCardSortingByNumberOnMinicard() { + const boardId = Session.get('currentBoard'); + const currentBoard = ReactiveCache.getBoard(boardId); + return currentBoard ? currentBoard.allowsCardSortingByNumberOnMinicard : false; + }, }; -// A simple tracker dependency that we invalidate every time the window is -// resized. This is used to reactively re-calculate the popup position in case -// of a window resize. This is the equivalent of a "Signal" in some other -// programming environments (eg, elm). -$(window).on('resize', () => Utils.windowResizeDep.changed()); + +$(window).on('resize', () => { + // A simple tracker dependency that we invalidate every time the window is + // resized. This is used to reactively re-calculate the popup position in case + // of a window resize. This is the equivalent of a "Signal" in some other + // programming environments (eg, elm). + Utils.windowResizeDep.changed(); + // Simple, generic switch based exclusively on the new detection algorithm + // Hope it will centralize decision and reduce edge cases + Utils.setMobileMode(Utils.isMiniScreen()); +}); + +$(() => { + const settingsHelpers = ["allowsReceivedDate", "allowsStartDate", "allowsDueDate", "allowsEndDate", "allowsSubtasks", "allowsCreator", "allowsCreatorOnMinicard", "allowsMembers", "allowsAssignee", "allowsAssignedBy", "allowsRequestedBy", "allowsCardSortingByNumber", "allowsShowLists", "allowsLabels", "allowsShowListsOnMinicard", "allowsChecklists", "allowsAttachments", "allowsComments", "allowsCardNumber", "allowsDescriptionTitle", "allowsDescriptionText", "allowsDescriptionTextOnMinicard", "allowsActivities", "allowsCoverAttachmentOnMinicard", "allowsBadgeAttachmentOnMinicard", "allowsCardSortingByNumberOnMinicard"] + for (f of settingsHelpers) { + Template.registerHelper(f, Utils[f]); + } +}); \ No newline at end of file diff --git a/config/router.js b/config/router.js index 85a6d0353..6b1ab3ea9 100644 --- a/config/router.js +++ b/config/router.js @@ -136,8 +136,6 @@ FlowRouter.route('/public', { FlowRouter.route('/b/:boardId/:slug/:cardId', { name: 'card', action(params) { - EscapeActions.executeUpTo('inlinedForm'); - Session.set('currentBoard', params.boardId); Session.set('currentCard', params.cardId); Session.set('popupCardId', null); @@ -163,6 +161,7 @@ FlowRouter.route('/b/:boardId/:slug/:cardId', { }, }); + FlowRouter.route('/b/:id/:slug', { name: 'board', action(params) { diff --git a/imports/i18n/data/ace.i18n.json b/imports/i18n/data/ace.i18n.json index dc0066e8b..53ceb3ee1 100644 --- a/imports/i18n/data/ace.i18n.json +++ b/imports/i18n/data/ace.i18n.json @@ -195,8 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", "zoom-in": "Zoom In", "zoom-out": "Zoom Out", "click-to-change-zoom": "Click to change zoom level", @@ -385,7 +383,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1505,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1515,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/af.i18n.json b/imports/i18n/data/af.i18n.json index dc0066e8b..54394bc96 100644 --- a/imports/i18n/data/af.i18n.json +++ b/imports/i18n/data/af.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/af_ZA.i18n.json b/imports/i18n/data/af_ZA.i18n.json index 49454d207..cd5ba1fac 100644 --- a/imports/i18n/data/af_ZA.i18n.json +++ b/imports/i18n/data/af_ZA.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/ar-DZ.i18n.json b/imports/i18n/data/ar-DZ.i18n.json index d70fa6514..d8eda67ee 100644 --- a/imports/i18n/data/ar-DZ.i18n.json +++ b/imports/i18n/data/ar-DZ.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/ar-EG.i18n.json b/imports/i18n/data/ar-EG.i18n.json index d70fa6514..d8eda67ee 100644 --- a/imports/i18n/data/ar-EG.i18n.json +++ b/imports/i18n/data/ar-EG.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/ar.i18n.json b/imports/i18n/data/ar.i18n.json index 1d374208a..d32239c74 100644 --- a/imports/i18n/data/ar.i18n.json +++ b/imports/i18n/data/ar.i18n.json @@ -195,13 +195,6 @@ "boards": "لوحات", "board-view": "عرض اللوحات", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "التقويم", "board-view-swimlanes": "خطوط السباحة", "board-view-collapse": "انهيار", @@ -385,7 +378,7 @@ "date": "تاريخ", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "صورة شخصية افتراضية", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/ary.i18n.json b/imports/i18n/data/ary.i18n.json index d70fa6514..d8eda67ee 100644 --- a/imports/i18n/data/ary.i18n.json +++ b/imports/i18n/data/ary.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/ast-ES.i18n.json b/imports/i18n/data/ast-ES.i18n.json index d70fa6514..d8eda67ee 100644 --- a/imports/i18n/data/ast-ES.i18n.json +++ b/imports/i18n/data/ast-ES.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/az-AZ.i18n.json b/imports/i18n/data/az-AZ.i18n.json index d70fa6514..d8eda67ee 100644 --- a/imports/i18n/data/az-AZ.i18n.json +++ b/imports/i18n/data/az-AZ.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/az-LA.i18n.json b/imports/i18n/data/az-LA.i18n.json index d70fa6514..d8eda67ee 100644 --- a/imports/i18n/data/az-LA.i18n.json +++ b/imports/i18n/data/az-LA.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/az.i18n.json b/imports/i18n/data/az.i18n.json index d70fa6514..d8eda67ee 100644 --- a/imports/i18n/data/az.i18n.json +++ b/imports/i18n/data/az.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/bg.i18n.json b/imports/i18n/data/bg.i18n.json index 01d582576..7df2af061 100644 --- a/imports/i18n/data/bg.i18n.json +++ b/imports/i18n/data/bg.i18n.json @@ -195,13 +195,6 @@ "boards": "Табла", "board-view": "Изглед на таблото", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Календар", "board-view-swimlanes": "Коридори", "board-view-collapse": "Събери", @@ -385,7 +378,7 @@ "date": "Дата", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Отказ", "default-avatar": "Основен аватар", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/br.i18n.json b/imports/i18n/data/br.i18n.json index 1022fd606..21d6f4097 100644 --- a/imports/i18n/data/br.i18n.json +++ b/imports/i18n/data/br.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/ca.i18n.json b/imports/i18n/data/ca.i18n.json index cbae9d47f..ddfa5edea 100644 --- a/imports/i18n/data/ca.i18n.json +++ b/imports/i18n/data/ca.i18n.json @@ -195,13 +195,6 @@ "boards": "Taulers", "board-view": "Visió del tauler", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendari", "board-view-swimlanes": "Carrils", "board-view-collapse": "Contraure", @@ -385,7 +378,7 @@ "date": "Dades", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Declina", "default-avatar": "Avatar per defecte", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/ca@valencia.i18n.json b/imports/i18n/data/ca@valencia.i18n.json index dab1b8c59..46e3e7ca0 100644 --- a/imports/i18n/data/ca@valencia.i18n.json +++ b/imports/i18n/data/ca@valencia.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/ca_ES.i18n.json b/imports/i18n/data/ca_ES.i18n.json index 2ad8f85f6..64c69a4f1 100644 --- a/imports/i18n/data/ca_ES.i18n.json +++ b/imports/i18n/data/ca_ES.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/cmn.i18n.json b/imports/i18n/data/cmn.i18n.json index 9c4bf0e49..69bb99e81 100644 --- a/imports/i18n/data/cmn.i18n.json +++ b/imports/i18n/data/cmn.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/cs-CZ.i18n.json b/imports/i18n/data/cs-CZ.i18n.json index 42f43682d..9969973a9 100644 --- a/imports/i18n/data/cs-CZ.i18n.json +++ b/imports/i18n/data/cs-CZ.i18n.json @@ -195,13 +195,6 @@ "boards": "Tabla", "board-view": "Náhled tabla", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Kalendář", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Sbalit", @@ -385,7 +378,7 @@ "date": "Datum", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Zamítnout", "default-avatar": "Výchozí avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/cs.i18n.json b/imports/i18n/data/cs.i18n.json index 68120a255..4fb45c08b 100644 --- a/imports/i18n/data/cs.i18n.json +++ b/imports/i18n/data/cs.i18n.json @@ -195,13 +195,6 @@ "boards": "Tabla", "board-view": "Náhled tabla", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Kalendář", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Sbalit", @@ -385,7 +378,7 @@ "date": "Datum", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Zamítnout", "default-avatar": "Výchozí avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/cy-GB.i18n.json b/imports/i18n/data/cy-GB.i18n.json index d70fa6514..d8eda67ee 100644 --- a/imports/i18n/data/cy-GB.i18n.json +++ b/imports/i18n/data/cy-GB.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/cy.i18n.json b/imports/i18n/data/cy.i18n.json index d70fa6514..d8eda67ee 100644 --- a/imports/i18n/data/cy.i18n.json +++ b/imports/i18n/data/cy.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/da.i18n.json b/imports/i18n/data/da.i18n.json index 7a3c9024c..ffc6b0797 100644 --- a/imports/i18n/data/da.i18n.json +++ b/imports/i18n/data/da.i18n.json @@ -195,13 +195,6 @@ "boards": "Tavler", "board-view": "Tavlevisning", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Kalender", "board-view-swimlanes": "Svømmebaner", "board-view-collapse": "Sammenfold", @@ -385,7 +378,7 @@ "date": "Dato", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Afslå", "default-avatar": "Standard-avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/de-AT.i18n.json b/imports/i18n/data/de-AT.i18n.json index bbe3b2047..8dab587b9 100644 --- a/imports/i18n/data/de-AT.i18n.json +++ b/imports/i18n/data/de-AT.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Boardansicht", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Kalender", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Einklappen", @@ -385,7 +378,7 @@ "date": "Datum", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Ablehnen", "default-avatar": "Standard Profilbild", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/de-CH.i18n.json b/imports/i18n/data/de-CH.i18n.json index c0a964876..9000353f3 100644 --- a/imports/i18n/data/de-CH.i18n.json +++ b/imports/i18n/data/de-CH.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Boardansicht", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Kalender", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Einklappen", @@ -385,7 +378,7 @@ "date": "Datum", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Ablehnen", "default-avatar": "Standard Profilbild", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/de.i18n.json b/imports/i18n/data/de.i18n.json index 4a8e95a50..0db824225 100644 --- a/imports/i18n/data/de.i18n.json +++ b/imports/i18n/data/de.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Boardansicht", "desktop-mode": "Desktop Modus", - "mobile-mode": "Mobil Modus", - "mobile-desktop-toggle": "Wechseln zwischen Mobil und Desktop Modus", - "zoom-in": "Zoom vergrößern", - "zoom-out": "Zoom verkleinern", - "click-to-change-zoom": "Klicken um die Zoom Stufe zu ändern", - "zoom-level": "Zoom Stufe", - "enter-zoom-level": "Eingabe Zoom Stufe (50-300%):", "board-view-cal": "Kalender", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Einklappen", @@ -385,7 +378,7 @@ "date": "Datum", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Ablehnen", "default-avatar": "Standard Profilbild", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/de_DE.i18n.json b/imports/i18n/data/de_DE.i18n.json index 4032e9a9f..897a715b1 100644 --- a/imports/i18n/data/de_DE.i18n.json +++ b/imports/i18n/data/de_DE.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Boardansicht", "desktop-mode": "Desktop-Modus", - "mobile-mode": "Handy-Modus", - "mobile-desktop-toggle": "Umschalten zwischen Mobil und Desktop Ansicht", - "zoom-in": "Vergrößern", - "zoom-out": "Verkleinern", - "click-to-change-zoom": "Klicken um die Zoom Stufe zu ändern", - "zoom-level": "Zoomstufe", - "enter-zoom-level": "Eingabe Zoom Stufe (50-300%):", "board-view-cal": "Kalender", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Einklappen", @@ -385,7 +378,7 @@ "date": "Datum", "date-format": "Datumsformat", "date-format-yyyy-mm-dd": "JJJJ-MM-TT hh:mm", - "date-format-dd-mm-yyyy": "TT-MM-JJJJ", + "date-format-dd-mm-yyyy": "TT-MM-JJJJ", "date-format-mm-dd-yyyy": "MM-TT-JJJJ", "decline": "Ablehnen", "default-avatar": "Standard Profilbild", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Gesamtfortschritt", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/el-GR.i18n.json b/imports/i18n/data/el-GR.i18n.json index bff8e2f5b..f67233384 100644 --- a/imports/i18n/data/el-GR.i18n.json +++ b/imports/i18n/data/el-GR.i18n.json @@ -195,13 +195,6 @@ "boards": "Πίνακες", "board-view": "Προβολή Πίνακα", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Ημερολόγιο", "board-view-swimlanes": "Λωρίδες", "board-view-collapse": "Σύμπτυξη", @@ -385,7 +378,7 @@ "date": "Ημερομηνία", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Απόρριψη", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/el.i18n.json b/imports/i18n/data/el.i18n.json index 15f36f608..1eddd9d43 100644 --- a/imports/i18n/data/el.i18n.json +++ b/imports/i18n/data/el.i18n.json @@ -195,13 +195,6 @@ "boards": "Πίνακες", "board-view": "Προβολή Πίνακα", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Ημερολόγιο", "board-view-swimlanes": "Λωρίδες", "board-view-collapse": "Σύμπτυξη", @@ -385,7 +378,7 @@ "date": "Ημερομηνία", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Απόρριψη", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/en-BR.i18n.json b/imports/i18n/data/en-BR.i18n.json index d70fa6514..d8eda67ee 100644 --- a/imports/i18n/data/en-BR.i18n.json +++ b/imports/i18n/data/en-BR.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/en-DE.i18n.json b/imports/i18n/data/en-DE.i18n.json index e13545217..47180210c 100644 --- a/imports/i18n/data/en-DE.i18n.json +++ b/imports/i18n/data/en-DE.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/en-GB.i18n.json b/imports/i18n/data/en-GB.i18n.json index dc0066e8b..54394bc96 100644 --- a/imports/i18n/data/en-GB.i18n.json +++ b/imports/i18n/data/en-GB.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/en-IT.i18n.json b/imports/i18n/data/en-IT.i18n.json index d70fa6514..d8eda67ee 100644 --- a/imports/i18n/data/en-IT.i18n.json +++ b/imports/i18n/data/en-IT.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/en-MY.i18n.json b/imports/i18n/data/en-MY.i18n.json index d70fa6514..d8eda67ee 100644 --- a/imports/i18n/data/en-MY.i18n.json +++ b/imports/i18n/data/en-MY.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/en-YS.i18n.json b/imports/i18n/data/en-YS.i18n.json index d70fa6514..d8eda67ee 100644 --- a/imports/i18n/data/en-YS.i18n.json +++ b/imports/i18n/data/en-YS.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/en.i18n.json b/imports/i18n/data/en.i18n.json index dc0066e8b..54394bc96 100644 --- a/imports/i18n/data/en.i18n.json +++ b/imports/i18n/data/en.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/en_AU.i18n.json b/imports/i18n/data/en_AU.i18n.json index dc0066e8b..54394bc96 100644 --- a/imports/i18n/data/en_AU.i18n.json +++ b/imports/i18n/data/en_AU.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/en_ID.i18n.json b/imports/i18n/data/en_ID.i18n.json index dc0066e8b..54394bc96 100644 --- a/imports/i18n/data/en_ID.i18n.json +++ b/imports/i18n/data/en_ID.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/en_SG.i18n.json b/imports/i18n/data/en_SG.i18n.json index dc0066e8b..54394bc96 100644 --- a/imports/i18n/data/en_SG.i18n.json +++ b/imports/i18n/data/en_SG.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/en_TR.i18n.json b/imports/i18n/data/en_TR.i18n.json index dc0066e8b..54394bc96 100644 --- a/imports/i18n/data/en_TR.i18n.json +++ b/imports/i18n/data/en_TR.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/en_ZA.i18n.json b/imports/i18n/data/en_ZA.i18n.json index dc0066e8b..54394bc96 100644 --- a/imports/i18n/data/en_ZA.i18n.json +++ b/imports/i18n/data/en_ZA.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/eo.i18n.json b/imports/i18n/data/eo.i18n.json index b4c5f8864..0aef127ab 100644 --- a/imports/i18n/data/eo.i18n.json +++ b/imports/i18n/data/eo.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Dato", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/es-AR.i18n.json b/imports/i18n/data/es-AR.i18n.json index dc1a5dec2..358b62842 100644 --- a/imports/i18n/data/es-AR.i18n.json +++ b/imports/i18n/data/es-AR.i18n.json @@ -195,13 +195,6 @@ "boards": "Tableros", "board-view": "Vista de Tablero", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendario", "board-view-swimlanes": "Calles", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Fecha", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Rechazar", "default-avatar": "Avatar por defecto", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/es-CL.i18n.json b/imports/i18n/data/es-CL.i18n.json index eb845683e..d8fcb1966 100644 --- a/imports/i18n/data/es-CL.i18n.json +++ b/imports/i18n/data/es-CL.i18n.json @@ -195,13 +195,6 @@ "boards": "Tableros", "board-view": "Vista del tablero", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendario", "board-view-swimlanes": "Carriles", "board-view-collapse": "Contraer", @@ -385,7 +378,7 @@ "date": "Fecha", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Declinar", "default-avatar": "Avatar por defecto", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/es-LA.i18n.json b/imports/i18n/data/es-LA.i18n.json index dc0066e8b..54394bc96 100644 --- a/imports/i18n/data/es-LA.i18n.json +++ b/imports/i18n/data/es-LA.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/es-MX.i18n.json b/imports/i18n/data/es-MX.i18n.json index 79f1c4f48..f8112803f 100644 --- a/imports/i18n/data/es-MX.i18n.json +++ b/imports/i18n/data/es-MX.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/es-PE.i18n.json b/imports/i18n/data/es-PE.i18n.json index 21da0955d..ef6a03c39 100644 --- a/imports/i18n/data/es-PE.i18n.json +++ b/imports/i18n/data/es-PE.i18n.json @@ -195,13 +195,6 @@ "boards": "Tableros", "board-view": "Vista del tablero", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendario", "board-view-swimlanes": "Carriles", "board-view-collapse": "Contraer", @@ -385,7 +378,7 @@ "date": "Fecha", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Declinar", "default-avatar": "Avatar por defecto", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/es-PY.i18n.json b/imports/i18n/data/es-PY.i18n.json index dc0066e8b..54394bc96 100644 --- a/imports/i18n/data/es-PY.i18n.json +++ b/imports/i18n/data/es-PY.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/es.i18n.json b/imports/i18n/data/es.i18n.json index 1eae20bfd..d618aa5b7 100644 --- a/imports/i18n/data/es.i18n.json +++ b/imports/i18n/data/es.i18n.json @@ -195,13 +195,6 @@ "boards": "Tableros", "board-view": "Vista del tablero", "desktop-mode": "Modo de Escritorio", - "mobile-mode": "Modo Móvil", - "mobile-desktop-toggle": "Alterna entre el Modo Móvil y el Modo de Escritorio", - "zoom-in": "Acercar", - "zoom-out": "Alejar", - "click-to-change-zoom": "Haz clic para cambiar el nivel de zoom", - "zoom-level": "Nivel de zoom", - "enter-zoom-level": "Introduzca el nivel de zoom (50-300%):", "board-view-cal": "Calendario", "board-view-swimlanes": "Carriles", "board-view-collapse": "Contraer", @@ -385,7 +378,7 @@ "date": "Fecha", "date-format": "Formato de fecha", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Declinar", "default-avatar": "Avatar por defecto", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/es_CO.i18n.json b/imports/i18n/data/es_CO.i18n.json index dc0066e8b..54394bc96 100644 --- a/imports/i18n/data/es_CO.i18n.json +++ b/imports/i18n/data/es_CO.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/et-EE.i18n.json b/imports/i18n/data/et-EE.i18n.json index 2f7e4668c..99b8af756 100644 --- a/imports/i18n/data/et-EE.i18n.json +++ b/imports/i18n/data/et-EE.i18n.json @@ -195,13 +195,6 @@ "boards": "Lauad", "board-view": "Juhatuse vaade", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Kalender", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Kokkupõrge", @@ -385,7 +378,7 @@ "date": "Kuupäev", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Langus", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/eu.i18n.json b/imports/i18n/data/eu.i18n.json index 954c000a8..d7c993fc8 100644 --- a/imports/i18n/data/eu.i18n.json +++ b/imports/i18n/data/eu.i18n.json @@ -195,13 +195,6 @@ "boards": "Arbelak", "board-view": "Arbela ikuspegia", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Egutegia", "board-view-swimlanes": "Errailak", "board-view-collapse": "Tolestu", @@ -385,7 +378,7 @@ "date": "Data", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Ukatu", "default-avatar": "Lehenetsitako avatarra", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/fa-IR.i18n.json b/imports/i18n/data/fa-IR.i18n.json index 003632d91..01939aef8 100644 --- a/imports/i18n/data/fa-IR.i18n.json +++ b/imports/i18n/data/fa-IR.i18n.json @@ -195,13 +195,6 @@ "boards": "بردها", "board-view": "نمایش برد", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "تقویم", "board-view-swimlanes": "مسیرها", "board-view-collapse": "جمع کردن", @@ -385,7 +378,7 @@ "date": "تاریخ", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "رد", "default-avatar": "آواتار پیش‌فرض", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/fa.i18n.json b/imports/i18n/data/fa.i18n.json index 61f596944..1db7681c2 100644 --- a/imports/i18n/data/fa.i18n.json +++ b/imports/i18n/data/fa.i18n.json @@ -195,13 +195,6 @@ "boards": "بردها", "board-view": "نمایش برد", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "تقویم", "board-view-swimlanes": "مسیرها", "board-view-collapse": "جمع کردن", @@ -385,7 +378,7 @@ "date": "تاریخ", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "رد", "default-avatar": "آواتار پیش‌فرض", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/fi.i18n.json b/imports/i18n/data/fi.i18n.json index 7aa692804..9eeb34666 100644 --- a/imports/i18n/data/fi.i18n.json +++ b/imports/i18n/data/fi.i18n.json @@ -197,11 +197,6 @@ "desktop-mode": "Työpöytätila", "mobile-mode": "Mobiilitila", "mobile-desktop-toggle": "Vaihda mobiili- ja työpöytätilan välillä", - "zoom-in": "Lähennä", - "zoom-out": "Loitonna", - "click-to-change-zoom": "Napsauta muuttaaksesi zoomaustasoa", - "zoom-level": "Zoomaus taso", - "enter-zoom-level": "Kirjoita zoomaus taso (50-300%):", "board-view-cal": "Kalenteri", "board-view-swimlanes": "Uimaradat", "board-view-collapse": "Pienennä", @@ -385,7 +380,7 @@ "date": "Päivämäärä", "date-format": "Päivämäärämuoto", "date-format-yyyy-mm-dd": "VVVV-KK-PP", - "date-format-dd-mm-yyyy": "PP-KK-VVVV", + "date-format-dd-mm-yyyy": "PP-KK-VVVV", "date-format-mm-dd-yyyy": "KK-PP-VVVV", "decline": "Kieltäydy", "default-avatar": "Oletusprofiilikuva", @@ -1507,7 +1502,7 @@ "run-fix-avatar-urls-migration-confirm": "Tämä päivittää taulun jäsenten avatar-URL-osoitteet käyttämään oikeaa tallennustilaa. Jatketaanko?", "run-fix-all-file-urls-migration-confirm": "Tämä päivittää kaikkien tällä taululla olevien tiedostoliitteiden URL-osoitteet käyttämään oikeaa tallennuspalvelinta. Jatketaanko?", "restore-lost-cards-nothing-to-restore": "Ei kadonneita uintikaistoja, listoja tai kortteja palautettavaksi", - + "migration-progress-title": "Taulu siirto meneillään", "migration-progress-overall": "Kokonaisedistyminen", "migration-progress-current-step": "Nykyinen vaihe", @@ -1517,7 +1512,7 @@ "steps": "askelta", "view": "Näkymä", "has-swimlanes": "Sisältää uimaratoja", - + "step-analyze-board-structure": "Analysoi taulun rakennetta", "step-fix-orphaned-cards": "Korjaa orvot kortit", "step-convert-shared-lists": "Muunna jaetut listat", diff --git a/imports/i18n/data/fr-CH.i18n.json b/imports/i18n/data/fr-CH.i18n.json index 454aa4a90..848514280 100644 --- a/imports/i18n/data/fr-CH.i18n.json +++ b/imports/i18n/data/fr-CH.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/fr-FR.i18n.json b/imports/i18n/data/fr-FR.i18n.json index 70ec90162..f04e582f4 100644 --- a/imports/i18n/data/fr-FR.i18n.json +++ b/imports/i18n/data/fr-FR.i18n.json @@ -195,13 +195,6 @@ "boards": "Tableaux", "board-view": "Vue du tableau", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendrier", "board-view-swimlanes": "Couloirs", "board-view-collapse": "Réduire", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Refuser", "default-avatar": "Avatar par défaut", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/fr.i18n.json b/imports/i18n/data/fr.i18n.json index cc77ce895..d79c7836e 100644 --- a/imports/i18n/data/fr.i18n.json +++ b/imports/i18n/data/fr.i18n.json @@ -195,13 +195,6 @@ "boards": "Tableaux", "board-view": "Vue du tableau", "desktop-mode": "Mode bureau", - "mobile-mode": "Mode mobile", - "mobile-desktop-toggle": "Basculer entre le mode mobile et le mode bureau", - "zoom-in": "Agrandir", - "zoom-out": "Réduire", - "click-to-change-zoom": "Cliquer pour changer le niveau d'agrandissement", - "zoom-level": "Niveau d'agrandissement", - "enter-zoom-level": "Entrer le niveau d'agrandissement (50-300%) :", "board-view-cal": "Calendrier", "board-view-swimlanes": "Couloirs", "board-view-collapse": "Réduire", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Format de la date", "date-format-yyyy-mm-dd": "AAAA-MM-JJ", - "date-format-dd-mm-yyyy": "JJ-MM-AAAA", + "date-format-dd-mm-yyyy": "JJ-MM-AAAA", "date-format-mm-dd-yyyy": "MM-JJ-AAAA", "decline": "Refuser", "default-avatar": "Avatar par défaut", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Migration du tableau en cours", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Étape courante", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Corriger les cartes orphelines", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/fy-NL.i18n.json b/imports/i18n/data/fy-NL.i18n.json index dc0066e8b..54394bc96 100644 --- a/imports/i18n/data/fy-NL.i18n.json +++ b/imports/i18n/data/fy-NL.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/fy.i18n.json b/imports/i18n/data/fy.i18n.json index dc0066e8b..54394bc96 100644 --- a/imports/i18n/data/fy.i18n.json +++ b/imports/i18n/data/fy.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/gl-ES.i18n.json b/imports/i18n/data/gl-ES.i18n.json index 888699e20..028171256 100644 --- a/imports/i18n/data/gl-ES.i18n.json +++ b/imports/i18n/data/gl-ES.i18n.json @@ -195,13 +195,6 @@ "boards": "Taboleiros", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Data", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Rexeitar", "default-avatar": "Avatar predeterminado", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/gl.i18n.json b/imports/i18n/data/gl.i18n.json index 466fac3d3..f4dd8dff0 100644 --- a/imports/i18n/data/gl.i18n.json +++ b/imports/i18n/data/gl.i18n.json @@ -195,13 +195,6 @@ "boards": "Taboleiros", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Data", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Rexeitar", "default-avatar": "Avatar predeterminado", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/gu-IN.i18n.json b/imports/i18n/data/gu-IN.i18n.json index d70fa6514..d8eda67ee 100644 --- a/imports/i18n/data/gu-IN.i18n.json +++ b/imports/i18n/data/gu-IN.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/he-IL.i18n.json b/imports/i18n/data/he-IL.i18n.json index 28bd8f363..b933d8de0 100644 --- a/imports/i18n/data/he-IL.i18n.json +++ b/imports/i18n/data/he-IL.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/he.i18n.json b/imports/i18n/data/he.i18n.json index 8a5f41059..7c6ca570e 100644 --- a/imports/i18n/data/he.i18n.json +++ b/imports/i18n/data/he.i18n.json @@ -195,13 +195,6 @@ "boards": "לוחות", "board-view": "תצוגת לוח", "desktop-mode": "מצב שולחן עבודה", - "mobile-mode": "מצב נייד", - "mobile-desktop-toggle": "החלפה בין מצב לניידים לבין מצב לשולחן עבודה", - "zoom-in": "התקרבות", - "zoom-out": "התרחקות", - "click-to-change-zoom": "לחיצה תשנה את רמת התקריב", - "zoom-level": "מרחק מתצוגה", - "enter-zoom-level": "נא למלא רמת מרחק מתצוגה (50-300%):", "board-view-cal": "לוח שנה", "board-view-swimlanes": "מסלולים", "board-view-collapse": "צמצום", @@ -385,7 +378,7 @@ "date": "תאריך", "date-format": "תבנית תאריך", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "סירוב", "default-avatar": "תמונת משתמש כבררת מחדל", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "סך כל ההתקדמות", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/hi-IN.i18n.json b/imports/i18n/data/hi-IN.i18n.json index 8efeec742..859bf4162 100644 --- a/imports/i18n/data/hi-IN.i18n.json +++ b/imports/i18n/data/hi-IN.i18n.json @@ -195,13 +195,6 @@ "boards": "बोर्डों", "board-view": "बोर्ड दृष्टिकोण", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "तिथि-पत्र", "board-view-swimlanes": "तैरना", "board-view-collapse": "संक्षिप्त करें", @@ -385,7 +378,7 @@ "date": "दिनांक", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/hi.i18n.json b/imports/i18n/data/hi.i18n.json index e4622dea0..d2119385c 100644 --- a/imports/i18n/data/hi.i18n.json +++ b/imports/i18n/data/hi.i18n.json @@ -195,13 +195,6 @@ "boards": "बोर्डों", "board-view": "बोर्ड दृष्टिकोण", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "तिथि-पत्र", "board-view-swimlanes": "तैरना", "board-view-collapse": "संक्षिप्त करें", @@ -385,7 +378,7 @@ "date": "दिनांक", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/hr.i18n.json b/imports/i18n/data/hr.i18n.json index 399e0e8d1..0501d3114 100644 --- a/imports/i18n/data/hr.i18n.json +++ b/imports/i18n/data/hr.i18n.json @@ -195,13 +195,6 @@ "boards": "Ploče", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Kalendar", "board-view-swimlanes": "Trake", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Datum", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Odustani", "default-avatar": "Zadani avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/hu.i18n.json b/imports/i18n/data/hu.i18n.json index 21498ad82..6ca0d7789 100644 --- a/imports/i18n/data/hu.i18n.json +++ b/imports/i18n/data/hu.i18n.json @@ -195,13 +195,6 @@ "boards": "Táblák", "board-view": "Tábla nézet", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Naptár", "board-view-swimlanes": "Úszósávok", "board-view-collapse": "Összecsukás", @@ -385,7 +378,7 @@ "date": "Dátum", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Elutasítás", "default-avatar": "Alapértelmezett avatár", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/hy.i18n.json b/imports/i18n/data/hy.i18n.json index 45c802721..4aad01f56 100644 --- a/imports/i18n/data/hy.i18n.json +++ b/imports/i18n/data/hy.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/id.i18n.json b/imports/i18n/data/id.i18n.json index 491d8b2f4..55b440929 100644 --- a/imports/i18n/data/id.i18n.json +++ b/imports/i18n/data/id.i18n.json @@ -195,13 +195,6 @@ "boards": "Panel", "board-view": "Tampilan Papan", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Kalender", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Ciutkan", @@ -385,7 +378,7 @@ "date": "Tanggal", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Tolak", "default-avatar": "Avatar standar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/ig.i18n.json b/imports/i18n/data/ig.i18n.json index 34ae87cd0..5dad80b71 100644 --- a/imports/i18n/data/ig.i18n.json +++ b/imports/i18n/data/ig.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/it.i18n.json b/imports/i18n/data/it.i18n.json index 2b8b8fc11..27ebc7b87 100644 --- a/imports/i18n/data/it.i18n.json +++ b/imports/i18n/data/it.i18n.json @@ -195,13 +195,6 @@ "boards": "Bacheche", "board-view": "Vista bacheca", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendario", "board-view-swimlanes": "Swimlane", "board-view-collapse": "Comprimi", @@ -385,7 +378,7 @@ "date": "Data", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Rifiuta", "default-avatar": "Avatar predefinito", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/ja-HI.i18n.json b/imports/i18n/data/ja-HI.i18n.json index 529162200..5b23bb90f 100644 --- a/imports/i18n/data/ja-HI.i18n.json +++ b/imports/i18n/data/ja-HI.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "デスクトップモード", - "mobile-mode": "モバイルモード", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "拡大", - "zoom-out": "縮小", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "拡大率(50-300%)", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/ja.i18n.json b/imports/i18n/data/ja.i18n.json index 323f0d4c7..fb47cb5a0 100644 --- a/imports/i18n/data/ja.i18n.json +++ b/imports/i18n/data/ja.i18n.json @@ -195,13 +195,6 @@ "boards": "ボード", "board-view": "ボード表示", "desktop-mode": "デスクトップモード", - "mobile-mode": "モバイルモード", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "拡大", - "zoom-out": "縮小", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "拡大率(50-300%)", "board-view-cal": "カレンダー", "board-view-swimlanes": "スイムレーン", "board-view-collapse": "折りたたむ", @@ -385,7 +378,7 @@ "date": "日付", "date-format": "日付形式", "date-format-yyyy-mm-dd": "年-月-日", - "date-format-dd-mm-yyyy": "日-月-年", + "date-format-dd-mm-yyyy": "日-月-年", "date-format-mm-dd-yyyy": "月-日-年", "decline": "拒否", "default-avatar": "デフォルトのアバター", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "手順", "view": "ビュー", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/ka.i18n.json b/imports/i18n/data/ka.i18n.json index f3869eb80..9ae5ef8d4 100644 --- a/imports/i18n/data/ka.i18n.json +++ b/imports/i18n/data/ka.i18n.json @@ -195,13 +195,6 @@ "boards": "დაფები", "board-view": "დაფის ნახვა", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "კალენდარი", "board-view-swimlanes": "ბილიკები", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "თარიღი", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "უარყოფა", "default-avatar": "სტანდარტული ავატარი", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/km.i18n.json b/imports/i18n/data/km.i18n.json index 123f4dd76..535a1be15 100644 --- a/imports/i18n/data/km.i18n.json +++ b/imports/i18n/data/km.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/km_KH.i18n.json b/imports/i18n/data/km_KH.i18n.json index dc0066e8b..54394bc96 100644 --- a/imports/i18n/data/km_KH.i18n.json +++ b/imports/i18n/data/km_KH.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/ko-KR.i18n.json b/imports/i18n/data/ko-KR.i18n.json index 2caf70336..a658b7087 100644 --- a/imports/i18n/data/ko-KR.i18n.json +++ b/imports/i18n/data/ko-KR.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/ko.i18n.json b/imports/i18n/data/ko.i18n.json index ce2f58dc5..51228cb77 100644 --- a/imports/i18n/data/ko.i18n.json +++ b/imports/i18n/data/ko.i18n.json @@ -195,13 +195,6 @@ "boards": "보드", "board-view": "보드 화면", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "달력", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "접기", @@ -385,7 +378,7 @@ "date": "날짜", "date-format": "날짜 형식", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "쇠퇴", "default-avatar": "기본 아바타", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/lt.i18n.json b/imports/i18n/data/lt.i18n.json index d70fa6514..d8eda67ee 100644 --- a/imports/i18n/data/lt.i18n.json +++ b/imports/i18n/data/lt.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/lv.i18n.json b/imports/i18n/data/lv.i18n.json index 35fab48cc..bb283f487 100644 --- a/imports/i18n/data/lv.i18n.json +++ b/imports/i18n/data/lv.i18n.json @@ -195,13 +195,6 @@ "boards": "Dēļi", "board-view": "Dēļa skats", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Kalendārs", "board-view-swimlanes": "Joslas", "board-view-collapse": "Sakļaut", @@ -385,7 +378,7 @@ "date": "Datums", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Noraidīt", "default-avatar": "Noklusētais attēls", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/mk.i18n.json b/imports/i18n/data/mk.i18n.json index bc7530eba..a2e2edaf9 100644 --- a/imports/i18n/data/mk.i18n.json +++ b/imports/i18n/data/mk.i18n.json @@ -195,13 +195,6 @@ "boards": "Табли", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Календар", "board-view-swimlanes": "Коридори", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Дата", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Откажи", "default-avatar": "Основен аватар", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/mn.i18n.json b/imports/i18n/data/mn.i18n.json index de5e066c6..843c422c2 100644 --- a/imports/i18n/data/mn.i18n.json +++ b/imports/i18n/data/mn.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/ms-MY.i18n.json b/imports/i18n/data/ms-MY.i18n.json index 0603d4e67..39490faf4 100644 --- a/imports/i18n/data/ms-MY.i18n.json +++ b/imports/i18n/data/ms-MY.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Mod Desktop", - "mobile-mode": "Mod Mudah Alih", - "mobile-desktop-toggle": "Tukar antara mod mudah alih dan desktop", - "zoom-in": "Zum masuk", - "zoom-out": "Zum keluar", - "click-to-change-zoom": "Klik untuk ubah aras zum", - "zoom-level": "Aras zum", - "enter-zoom-level": "Masukkan aras zum (50-300%)", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Format Tarikh", "date-format-yyyy-mm-dd": "TTTT-BB-HH", - "date-format-dd-mm-yyyy": "HH-BB-TTTT", + "date-format-dd-mm-yyyy": "HH-BB-TTTT", "date-format-mm-dd-yyyy": "BB-HH-TTTT", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/ms.i18n.json b/imports/i18n/data/ms.i18n.json index 27e2b2bc4..43f1c4dfd 100644 --- a/imports/i18n/data/ms.i18n.json +++ b/imports/i18n/data/ms.i18n.json @@ -195,13 +195,6 @@ "boards": "Papan", "board-view": "Paparan Papan", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Kalendar", "board-view-swimlanes": "Aliran Renang", "board-view-collapse": "Buka", @@ -385,7 +378,7 @@ "date": "Tarikh", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Ditolak", "default-avatar": "Avatar Lalai", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/nb.i18n.json b/imports/i18n/data/nb.i18n.json index 05152f3d5..bd7a9c219 100644 --- a/imports/i18n/data/nb.i18n.json +++ b/imports/i18n/data/nb.i18n.json @@ -195,13 +195,6 @@ "boards": "Tavler", "board-view": "Tavlevisning", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Kalender", "board-view-swimlanes": "Svømmebaner", "board-view-collapse": "Slå sammen", @@ -385,7 +378,7 @@ "date": "Dato", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Avvis", "default-avatar": "Standard avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/nl-NL.i18n.json b/imports/i18n/data/nl-NL.i18n.json index 06ff85a4d..dff0c7bde 100644 --- a/imports/i18n/data/nl-NL.i18n.json +++ b/imports/i18n/data/nl-NL.i18n.json @@ -195,13 +195,6 @@ "boards": "Borden", "board-view": "Bord overzicht", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Kalender", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Klap in", @@ -385,7 +378,7 @@ "date": "Datum", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Weigeren", "default-avatar": "Standaard avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/nl.i18n.json b/imports/i18n/data/nl.i18n.json index a21f4fa05..439848c94 100644 --- a/imports/i18n/data/nl.i18n.json +++ b/imports/i18n/data/nl.i18n.json @@ -195,13 +195,6 @@ "boards": "Borden", "board-view": "Bord overzicht", "desktop-mode": "Desktop Modus", - "mobile-mode": "Telefoon Modus", - "mobile-desktop-toggle": "Schakel tussen Telefoon en Desktop Modus", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Uit", - "click-to-change-zoom": "Klik om zoom niveau te wijzigen", - "zoom-level": "Zoom Niveau", - "enter-zoom-level": "Voer zoom niveau in (50-300%)", "board-view-cal": "Kalender", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Inklappen", @@ -385,7 +378,7 @@ "date": "Datum", "date-format": "Datumformaat", "date-format-yyyy-mm-dd": "JJJJ-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-JJJJ", + "date-format-dd-mm-yyyy": "DD-MM-JJJJ", "date-format-mm-dd-yyyy": "MM-DD-JJJJ", "decline": "Weigeren", "default-avatar": "Standaard avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "Dit werkt alle avatar URL's van de bord-leden bij naar de juiste opslagmethode. Doorgaan?", "run-fix-all-file-urls-migration-confirm": "dit werkt alle bestandsbijlagen URL's bij naar de juiste opslagmethode. Doorgaan?", "restore-lost-cards-nothing-to-restore": "Geen verloren swinmlanes, lijsten of kaarten om te herstellen", - + "migration-progress-title": "Bord Migratie in Uitvoering", "migration-progress-overall": "Algehele Voortgang", "migration-progress-current-step": "Huidige Stap", @@ -1517,7 +1510,7 @@ "steps": "stappen", "view": "Toon", "has-swimlanes": "Heeft Swimlanes", - + "step-analyze-board-structure": "Bordstructuur Analyseren", "step-fix-orphaned-cards": "Repareer Verweesde Kaarten", "step-convert-shared-lists": "Converteer Gedeelde Lijsten", diff --git a/imports/i18n/data/oc.i18n.json b/imports/i18n/data/oc.i18n.json index a94e74905..8bef344b4 100644 --- a/imports/i18n/data/oc.i18n.json +++ b/imports/i18n/data/oc.i18n.json @@ -195,13 +195,6 @@ "boards": "Tablèus", "board-view": "Presentacion del tablèu", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendièr", "board-view-swimlanes": "Corredor", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Data", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Refusar", "default-avatar": "Fòto per defaut", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/or_IN.i18n.json b/imports/i18n/data/or_IN.i18n.json index dc0066e8b..54394bc96 100644 --- a/imports/i18n/data/or_IN.i18n.json +++ b/imports/i18n/data/or_IN.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/pa.i18n.json b/imports/i18n/data/pa.i18n.json index d70fa6514..d8eda67ee 100644 --- a/imports/i18n/data/pa.i18n.json +++ b/imports/i18n/data/pa.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/pl-PL.i18n.json b/imports/i18n/data/pl-PL.i18n.json index 1b66b6394..cb4e78f2f 100644 --- a/imports/i18n/data/pl-PL.i18n.json +++ b/imports/i18n/data/pl-PL.i18n.json @@ -195,13 +195,6 @@ "boards": "Tablice", "board-view": "Widok tablicy", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Kalendarz", "board-view-swimlanes": "Ścieżki", "board-view-collapse": "Zwiń", @@ -385,7 +378,7 @@ "date": "Data", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Odrzuć", "default-avatar": "Domyślny avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/pl.i18n.json b/imports/i18n/data/pl.i18n.json index a6bb1ee68..fe97c133a 100644 --- a/imports/i18n/data/pl.i18n.json +++ b/imports/i18n/data/pl.i18n.json @@ -195,13 +195,6 @@ "boards": "Tablice", "board-view": "Widok tablicy", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Kalendarz", "board-view-swimlanes": "Ścieżki", "board-view-collapse": "Zwiń", @@ -385,7 +378,7 @@ "date": "Data", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Odrzuć", "default-avatar": "Domyślny avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/pt-BR.i18n.json b/imports/i18n/data/pt-BR.i18n.json index d5951bbbf..3534e919d 100644 --- a/imports/i18n/data/pt-BR.i18n.json +++ b/imports/i18n/data/pt-BR.i18n.json @@ -195,13 +195,6 @@ "boards": "Quadros", "board-view": "Visão de quadro", "desktop-mode": "Modo Desktop", - "mobile-mode": "Modo Celular", - "mobile-desktop-toggle": "Alternar entre modo Celular e Desktop", - "zoom-in": "Aumentar Zoom", - "zoom-out": "Diminuir Zoom", - "click-to-change-zoom": "Clique para mudar nível de zoom", - "zoom-level": "Nível de Zoom", - "enter-zoom-level": "Definir nível de zoom (50-300%):", "board-view-cal": "Calendário", "board-view-swimlanes": "Raias", "board-view-collapse": "Expandir", @@ -385,7 +378,7 @@ "date": "Data", "date-format": "Formato da Data", "date-format-yyyy-mm-dd": "AAAA-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-AAAA", + "date-format-dd-mm-yyyy": "DD-MM-AAAA", "date-format-mm-dd-yyyy": "MM-DD-AAAA", "decline": "Rejeitar", "default-avatar": "Avatar padrão", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "Isso atualizará as URLs dos avatares dos membros do quadro para usar o backend de armazenamento correto. Continuar?", "run-fix-all-file-urls-migration-confirm": "Isso atualizará todas URLs de arquivos de anexos neste quadro para usar o servidor de armazenamento correto. Continuar?", "restore-lost-cards-nothing-to-restore": "Sem raias, listas ou cartões perdidos para restaurar.", - + "migration-progress-title": "Migração do Quadro em Andamento", "migration-progress-overall": "Progresso Geral", "migration-progress-current-step": "Etapa Atual", @@ -1517,7 +1510,7 @@ "steps": "etapas", "view": "Visão", "has-swimlanes": "Possui Raias", - + "step-analyze-board-structure": "Analisar a Estrutura do Quadro", "step-fix-orphaned-cards": "Corrigir Cartões Órfãos", "step-convert-shared-lists": "Converter Listas Compartilhadas", diff --git a/imports/i18n/data/pt.i18n.json b/imports/i18n/data/pt.i18n.json index c6b9678b4..0e69a3be2 100644 --- a/imports/i18n/data/pt.i18n.json +++ b/imports/i18n/data/pt.i18n.json @@ -195,13 +195,6 @@ "boards": "Quadros", "board-view": "Visão do Quadro", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendário", "board-view-swimlanes": "Pistas", "board-view-collapse": "Colapsar", @@ -385,7 +378,7 @@ "date": "Data", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Rejeitar", "default-avatar": "Avatar por omissão", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/pt_PT.i18n.json b/imports/i18n/data/pt_PT.i18n.json index 495da29e4..c6212aa1b 100644 --- a/imports/i18n/data/pt_PT.i18n.json +++ b/imports/i18n/data/pt_PT.i18n.json @@ -195,13 +195,6 @@ "boards": "Quadros", "board-view": "Visão do Quadro", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendário", "board-view-swimlanes": "Pistas", "board-view-collapse": "Colapsar", @@ -385,7 +378,7 @@ "date": "Data", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Rejeitar", "default-avatar": "Avatar por omissão", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/ro-RO.i18n.json b/imports/i18n/data/ro-RO.i18n.json index 63d499f5b..499e3a544 100644 --- a/imports/i18n/data/ro-RO.i18n.json +++ b/imports/i18n/data/ro-RO.i18n.json @@ -195,13 +195,6 @@ "boards": "Table", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/ro.i18n.json b/imports/i18n/data/ro.i18n.json index b81ceb824..fe4992212 100644 --- a/imports/i18n/data/ro.i18n.json +++ b/imports/i18n/data/ro.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/ru-UA.i18n.json b/imports/i18n/data/ru-UA.i18n.json index e8cccb025..2eb097d6c 100644 --- a/imports/i18n/data/ru-UA.i18n.json +++ b/imports/i18n/data/ru-UA.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/ru.i18n.json b/imports/i18n/data/ru.i18n.json index fed7f266f..20837cd2d 100644 --- a/imports/i18n/data/ru.i18n.json +++ b/imports/i18n/data/ru.i18n.json @@ -195,13 +195,6 @@ "boards": "Доски", "board-view": "Вид доски", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Календарь", "board-view-swimlanes": "Дорожки", "board-view-collapse": "Свернуть", @@ -385,7 +378,7 @@ "date": "Дата", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Отклонить", "default-avatar": "Аватар по умолчанию", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/ru_RU.i18n.json b/imports/i18n/data/ru_RU.i18n.json index dc0066e8b..54394bc96 100644 --- a/imports/i18n/data/ru_RU.i18n.json +++ b/imports/i18n/data/ru_RU.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/sk.i18n.json b/imports/i18n/data/sk.i18n.json index 058cb102b..936828095 100644 --- a/imports/i18n/data/sk.i18n.json +++ b/imports/i18n/data/sk.i18n.json @@ -195,13 +195,6 @@ "boards": "Tabule", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Dátum", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/sl.i18n.json b/imports/i18n/data/sl.i18n.json index f38109cf0..d9bb2d97b 100644 --- a/imports/i18n/data/sl.i18n.json +++ b/imports/i18n/data/sl.i18n.json @@ -195,13 +195,6 @@ "boards": "Table", "board-view": "Pogled table", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Koledar", "board-view-swimlanes": "Plavalne steze", "board-view-collapse": "Skrči", @@ -385,7 +378,7 @@ "date": "Datum", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Zavrni", "default-avatar": "Privzeti avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/sl_SI.i18n.json b/imports/i18n/data/sl_SI.i18n.json index f38109cf0..491d1167c 100644 --- a/imports/i18n/data/sl_SI.i18n.json +++ b/imports/i18n/data/sl_SI.i18n.json @@ -195,8 +195,6 @@ "boards": "Table", "board-view": "Pogled table", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", "zoom-in": "Zoom In", "zoom-out": "Zoom Out", "click-to-change-zoom": "Click to change zoom level", @@ -385,7 +383,7 @@ "date": "Datum", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Zavrni", "default-avatar": "Privzeti avatar", @@ -1507,7 +1505,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1515,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/sr.i18n.json b/imports/i18n/data/sr.i18n.json index 8f6ec5fc3..a4f0b02a1 100644 --- a/imports/i18n/data/sr.i18n.json +++ b/imports/i18n/data/sr.i18n.json @@ -197,11 +197,6 @@ "desktop-mode": "Приказ прилагођен за екран рачунара", "mobile-mode": "Приказ прилагођен за екран мобилног уређаја", "mobile-desktop-toggle": "Замени приказ прилагођен за рачунар/мобилни", - "zoom-in": "Приближи", - "zoom-out": "Одаљи", - "click-to-change-zoom": "Лупа", - "zoom-level": "Ниво", - "enter-zoom-level": "Задајте ниво (50-300%):", "board-view-cal": "Календар", "board-view-swimlanes": "Врсте поступака", "board-view-collapse": "Скупи", @@ -385,7 +380,7 @@ "date": "Датум", "date-format": "Запис", "date-format-yyyy-mm-dd": "година-месец-дан", - "date-format-dd-mm-yyyy": "дан-месец-година", + "date-format-dd-mm-yyyy": "дан-месец-година", "date-format-mm-dd-yyyy": "месец-дан-година", "decline": "Одбијам", "default-avatar": "иницијали уместо слике", @@ -1507,7 +1502,7 @@ "run-fix-avatar-urls-migration-confirm": "Овим се исправља веза до складишта са сликама сарадника из ових списа. Да ли сте сагласни?", "run-fix-all-file-urls-migration-confirm": "Овим ће бити исправљене све везе у списима да упућују на стварно складиште предметне грађе. Да ли сте сагласни?", "restore-lost-cards-nothing-to-restore": "Нема нити загубљених поступака нити предмета за опоравак", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Укупни напредак", "migration-progress-current-step": "Current Step", @@ -1517,7 +1512,6 @@ "steps": "кораци", "view": "Поглед", "has-swimlanes": "има више поступака", - "step-analyze-board-structure": "Изучавам везе у списима", "step-fix-orphaned-cards": "Поправљам одбачене предмете", "step-convert-shared-lists": "Претварам дељене делове поступка", diff --git a/imports/i18n/data/sv.i18n.json b/imports/i18n/data/sv.i18n.json index 61b1acae3..8aa7a329b 100644 --- a/imports/i18n/data/sv.i18n.json +++ b/imports/i18n/data/sv.i18n.json @@ -195,13 +195,6 @@ "boards": "Tavlor", "board-view": "Tavelvy", "desktop-mode": " Skrivbordsläge", - "mobile-mode": " Mobilläge", - "mobile-desktop-toggle": " Växla mellan mobilläge och skrivbordsläge", - "zoom-in": "Zooma in", - "zoom-out": "Zooma ut", - "click-to-change-zoom": " Klicka för att ändra zoomnivå", - "zoom-level": " Zoomnivå", - "enter-zoom-level": " Ange zoomnivå (50-300%):", "board-view-cal": "Kalender", "board-view-swimlanes": "Simbanor", "board-view-collapse": "Fäll ihop", @@ -385,7 +378,7 @@ "date": "Datum", "date-format": "Datumformat", "date-format-yyyy-mm-dd": "ÅÅÅÅ-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-ÅÅÅÅ", + "date-format-dd-mm-yyyy": "DD-MM-ÅÅÅÅ", "date-format-mm-dd-yyyy": "MM-DD-ÅÅÅÅ", "decline": "Neka", "default-avatar": "Standard avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "Detta kommer att uppdatera avatar-URL:er för tavlans medlemmar till att använda rätt lagrings-backend. Fortsätt?", "run-fix-all-file-urls-migration-confirm": "Detta kommer att uppdatera alla URL:er för filbilagor på denna tavla till att använda rätt lagrings-backend. Fortsätt?", "restore-lost-cards-nothing-to-restore": "Inga förlorade simbanor, listor eller kort att återställa", - + "migration-progress-title": "Tavlans migrering pågår", "migration-progress-overall": "Övergripande förlopp", "migration-progress-current-step": "Nuvarande steg", @@ -1517,7 +1510,7 @@ "steps": "steg", "view": "Visa", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analysera tavlans struktur", "step-fix-orphaned-cards": "Fixa övergivna kort", "step-convert-shared-lists": "Konvertera delade listor", diff --git a/imports/i18n/data/sw.i18n.json b/imports/i18n/data/sw.i18n.json index f4c046c2d..31e20927c 100644 --- a/imports/i18n/data/sw.i18n.json +++ b/imports/i18n/data/sw.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/ta.i18n.json b/imports/i18n/data/ta.i18n.json index 9c9cb9c42..bcdc051ac 100644 --- a/imports/i18n/data/ta.i18n.json +++ b/imports/i18n/data/ta.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "நாள்கட்டி", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "நாள்", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/te-IN.i18n.json b/imports/i18n/data/te-IN.i18n.json index dc0066e8b..54394bc96 100644 --- a/imports/i18n/data/te-IN.i18n.json +++ b/imports/i18n/data/te-IN.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/th.i18n.json b/imports/i18n/data/th.i18n.json index 0a7caedb1..888cd1e78 100644 --- a/imports/i18n/data/th.i18n.json +++ b/imports/i18n/data/th.i18n.json @@ -195,13 +195,6 @@ "boards": "บอร์ด", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "วันที่", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "ปฎิเสธ", "default-avatar": "ภาพเริ่มต้น", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/tk_TM.i18n.json b/imports/i18n/data/tk_TM.i18n.json index dc0066e8b..54394bc96 100644 --- a/imports/i18n/data/tk_TM.i18n.json +++ b/imports/i18n/data/tk_TM.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/tlh.i18n.json b/imports/i18n/data/tlh.i18n.json index dc0066e8b..54394bc96 100644 --- a/imports/i18n/data/tlh.i18n.json +++ b/imports/i18n/data/tlh.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/tr.i18n.json b/imports/i18n/data/tr.i18n.json index 0dd984f34..b9949a679 100644 --- a/imports/i18n/data/tr.i18n.json +++ b/imports/i18n/data/tr.i18n.json @@ -195,13 +195,6 @@ "boards": "Panolar", "board-view": "Pano Görünümü", "desktop-mode": "Masaüstü Modu", - "mobile-mode": "Mobil Modu", - "mobile-desktop-toggle": "Mobil ve Masaüstü Modu arasında geçiş yapın", - "zoom-in": "Yakınlaştır", - "zoom-out": "Uzaklaştır", - "click-to-change-zoom": "Yakınlaştırma düzeyini değiştirmek için tıklayın", - "zoom-level": "Yakınlaştırma düzeyi", - "enter-zoom-level": "Yakınlaştırma düzeyini girin (50-300%):", "board-view-cal": "Takvim", "board-view-swimlanes": "Kulvarlar", "board-view-collapse": "Katla", @@ -385,7 +378,7 @@ "date": "Tarih", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Reddet", "default-avatar": "Varsayılan avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/ug.i18n.json b/imports/i18n/data/ug.i18n.json index dc0066e8b..54394bc96 100644 --- a/imports/i18n/data/ug.i18n.json +++ b/imports/i18n/data/ug.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/uk-UA.i18n.json b/imports/i18n/data/uk-UA.i18n.json index 327f98c24..5c98600ec 100644 --- a/imports/i18n/data/uk-UA.i18n.json +++ b/imports/i18n/data/uk-UA.i18n.json @@ -195,13 +195,6 @@ "boards": "Дошки", "board-view": "Вид дошки", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Календар", "board-view-swimlanes": "Свімлейни", "board-view-collapse": "Згорнути", @@ -385,7 +378,7 @@ "date": "Дата", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Відхилити", "default-avatar": "Аватар за замовчуванням", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/uk.i18n.json b/imports/i18n/data/uk.i18n.json index 2ab6e051a..907b436dc 100644 --- a/imports/i18n/data/uk.i18n.json +++ b/imports/i18n/data/uk.i18n.json @@ -195,13 +195,6 @@ "boards": "Дошки", "board-view": "Вид дошки", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Календар", "board-view-swimlanes": "Свімлейни", "board-view-collapse": "Згорнути", @@ -385,7 +378,7 @@ "date": "Дата", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Відхилити", "default-avatar": "Аватар за замовчуванням", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/uz-AR.i18n.json b/imports/i18n/data/uz-AR.i18n.json index dc0066e8b..54394bc96 100644 --- a/imports/i18n/data/uz-AR.i18n.json +++ b/imports/i18n/data/uz-AR.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/uz-LA.i18n.json b/imports/i18n/data/uz-LA.i18n.json index dc0066e8b..54394bc96 100644 --- a/imports/i18n/data/uz-LA.i18n.json +++ b/imports/i18n/data/uz-LA.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/uz-UZ.i18n.json b/imports/i18n/data/uz-UZ.i18n.json index dc0066e8b..54394bc96 100644 --- a/imports/i18n/data/uz-UZ.i18n.json +++ b/imports/i18n/data/uz-UZ.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/uz.i18n.json b/imports/i18n/data/uz.i18n.json index dc0066e8b..54394bc96 100644 --- a/imports/i18n/data/uz.i18n.json +++ b/imports/i18n/data/uz.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/ve-CC.i18n.json b/imports/i18n/data/ve-CC.i18n.json index dc0066e8b..54394bc96 100644 --- a/imports/i18n/data/ve-CC.i18n.json +++ b/imports/i18n/data/ve-CC.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/ve-PP.i18n.json b/imports/i18n/data/ve-PP.i18n.json index dc0066e8b..54394bc96 100644 --- a/imports/i18n/data/ve-PP.i18n.json +++ b/imports/i18n/data/ve-PP.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/ve.i18n.json b/imports/i18n/data/ve.i18n.json index dc0066e8b..54394bc96 100644 --- a/imports/i18n/data/ve.i18n.json +++ b/imports/i18n/data/ve.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/vi-VN.i18n.json b/imports/i18n/data/vi-VN.i18n.json index 86580529d..c3e13d5ad 100644 --- a/imports/i18n/data/vi-VN.i18n.json +++ b/imports/i18n/data/vi-VN.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/vi.i18n.json b/imports/i18n/data/vi.i18n.json index 78b98de72..6e1ef737c 100644 --- a/imports/i18n/data/vi.i18n.json +++ b/imports/i18n/data/vi.i18n.json @@ -195,13 +195,6 @@ "boards": "Bảng", "board-view": "Kiểu xem Bảng", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Lịch", "board-view-swimlanes": "Làn ngang", "board-view-collapse": "Thu gọn", @@ -385,7 +378,7 @@ "date": "Ngày", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Từ chối", "default-avatar": "Hình đại diện mặc định", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/vl-SS.i18n.json b/imports/i18n/data/vl-SS.i18n.json index dc0066e8b..54394bc96 100644 --- a/imports/i18n/data/vl-SS.i18n.json +++ b/imports/i18n/data/vl-SS.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/vo.i18n.json b/imports/i18n/data/vo.i18n.json index dc0066e8b..54394bc96 100644 --- a/imports/i18n/data/vo.i18n.json +++ b/imports/i18n/data/vo.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/wa-RR.i18n.json b/imports/i18n/data/wa-RR.i18n.json index dc0066e8b..54394bc96 100644 --- a/imports/i18n/data/wa-RR.i18n.json +++ b/imports/i18n/data/wa-RR.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/wa.i18n.json b/imports/i18n/data/wa.i18n.json index dc0066e8b..54394bc96 100644 --- a/imports/i18n/data/wa.i18n.json +++ b/imports/i18n/data/wa.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/wo.i18n.json b/imports/i18n/data/wo.i18n.json index dc0066e8b..54394bc96 100644 --- a/imports/i18n/data/wo.i18n.json +++ b/imports/i18n/data/wo.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/wuu-Hans.i18n.json b/imports/i18n/data/wuu-Hans.i18n.json index dc0066e8b..54394bc96 100644 --- a/imports/i18n/data/wuu-Hans.i18n.json +++ b/imports/i18n/data/wuu-Hans.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/xh.i18n.json b/imports/i18n/data/xh.i18n.json index dc0066e8b..54394bc96 100644 --- a/imports/i18n/data/xh.i18n.json +++ b/imports/i18n/data/xh.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/yi.i18n.json b/imports/i18n/data/yi.i18n.json index dc0066e8b..54394bc96 100644 --- a/imports/i18n/data/yi.i18n.json +++ b/imports/i18n/data/yi.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/yo.i18n.json b/imports/i18n/data/yo.i18n.json index dc0066e8b..54394bc96 100644 --- a/imports/i18n/data/yo.i18n.json +++ b/imports/i18n/data/yo.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/yue_CN.i18n.json b/imports/i18n/data/yue_CN.i18n.json index dc0066e8b..54394bc96 100644 --- a/imports/i18n/data/yue_CN.i18n.json +++ b/imports/i18n/data/yue_CN.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/zgh.i18n.json b/imports/i18n/data/zgh.i18n.json index dc0066e8b..54394bc96 100644 --- a/imports/i18n/data/zgh.i18n.json +++ b/imports/i18n/data/zgh.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/zh-CN.i18n.json b/imports/i18n/data/zh-CN.i18n.json index 2f6f2ec63..5edce2d7b 100644 --- a/imports/i18n/data/zh-CN.i18n.json +++ b/imports/i18n/data/zh-CN.i18n.json @@ -195,13 +195,6 @@ "boards": "看板", "board-view": "看板视图", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "日历", "board-view-swimlanes": "泳道图", "board-view-collapse": "崩溃", @@ -385,7 +378,7 @@ "date": "日期", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "拒绝", "default-avatar": "默认头像", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/zh-GB.i18n.json b/imports/i18n/data/zh-GB.i18n.json index 2021f27d5..93e5ed691 100644 --- a/imports/i18n/data/zh-GB.i18n.json +++ b/imports/i18n/data/zh-GB.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/zh-HK.i18n.json b/imports/i18n/data/zh-HK.i18n.json index ac9a21d55..57c873aed 100644 --- a/imports/i18n/data/zh-HK.i18n.json +++ b/imports/i18n/data/zh-HK.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/zh-Hans.i18n.json b/imports/i18n/data/zh-Hans.i18n.json index f4de050da..fda492018 100644 --- a/imports/i18n/data/zh-Hans.i18n.json +++ b/imports/i18n/data/zh-Hans.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/zh-Hant.i18n.json b/imports/i18n/data/zh-Hant.i18n.json index 262c10b65..ab783b1b2 100644 --- a/imports/i18n/data/zh-Hant.i18n.json +++ b/imports/i18n/data/zh-Hant.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/zh-TW.i18n.json b/imports/i18n/data/zh-TW.i18n.json index 73c61a8b6..e3071a54c 100644 --- a/imports/i18n/data/zh-TW.i18n.json +++ b/imports/i18n/data/zh-TW.i18n.json @@ -195,13 +195,6 @@ "boards": "看板", "board-view": "看板檢視", "desktop-mode": "桌面模式", - "mobile-mode": "行動裝置模式", - "mobile-desktop-toggle": "在行動裝置與桌面模式間切換", - "zoom-in": "放大", - "zoom-out": "縮小", - "click-to-change-zoom": "點選以變更縮放層級", - "zoom-level": "縮放層級", - "enter-zoom-level": "輸入縮放層級 (50-300%):", "board-view-cal": "日曆", "board-view-swimlanes": "泳道", "board-view-collapse": "折疊", @@ -385,7 +378,7 @@ "date": "日期", "date-format": "日期格式", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "拒絕", "default-avatar": "預設大頭照", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "這將會更新看板成員的大頭照 URL 以使用正確的儲存空間後端。要繼續嗎?", "run-fix-all-file-urls-migration-confirm": "這將會更新此看板上的所有檔案附件 URL 以使用正確的儲存空間後端。要繼續嗎?", "restore-lost-cards-nothing-to-restore": "沒有需要還原的遺失泳道、清單或卡片", - + "migration-progress-title": "正在進行看板遷移", "migration-progress-overall": "整體進度", "migration-progress-current-step": "目前步驟", @@ -1517,7 +1510,7 @@ "steps": "步進", "view": "檢視", "has-swimlanes": "有泳道", - + "step-analyze-board-structure": "分析看板結構", "step-fix-orphaned-cards": "修復孤立卡片", "step-convert-shared-lists": "轉換共享清單", diff --git a/imports/i18n/data/zh.i18n.json b/imports/i18n/data/zh.i18n.json index 8e191222b..0d10e541c 100644 --- a/imports/i18n/data/zh.i18n.json +++ b/imports/i18n/data/zh.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/zh_SG.i18n.json b/imports/i18n/data/zh_SG.i18n.json index dc0066e8b..54394bc96 100644 --- a/imports/i18n/data/zh_SG.i18n.json +++ b/imports/i18n/data/zh_SG.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/zu-ZA.i18n.json b/imports/i18n/data/zu-ZA.i18n.json index dc0066e8b..54394bc96 100644 --- a/imports/i18n/data/zu-ZA.i18n.json +++ b/imports/i18n/data/zu-ZA.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/imports/i18n/data/zu.i18n.json b/imports/i18n/data/zu.i18n.json index dc0066e8b..54394bc96 100644 --- a/imports/i18n/data/zu.i18n.json +++ b/imports/i18n/data/zu.i18n.json @@ -195,13 +195,6 @@ "boards": "Boards", "board-view": "Board View", "desktop-mode": "Desktop Mode", - "mobile-mode": "Mobile Mode", - "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", - "zoom-in": "Zoom In", - "zoom-out": "Zoom Out", - "click-to-change-zoom": "Click to change zoom level", - "zoom-level": "Zoom Level", - "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", @@ -385,7 +378,7 @@ "date": "Date", "date-format": "Date Format", "date-format-yyyy-mm-dd": "YYYY-MM-DD", - "date-format-dd-mm-yyyy": "DD-MM-YYYY", + "date-format-dd-mm-yyyy": "DD-MM-YYYY", "date-format-mm-dd-yyyy": "MM-DD-YYYY", "decline": "Decline", "default-avatar": "Default avatar", @@ -1507,7 +1500,7 @@ "run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?", "run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?", "restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore", - + "migration-progress-title": "Board Migration in Progress", "migration-progress-overall": "Overall Progress", "migration-progress-current-step": "Current Step", @@ -1517,7 +1510,7 @@ "steps": "steps", "view": "View", "has-swimlanes": "Has Swimlanes", - + "step-analyze-board-structure": "Analyze Board Structure", "step-fix-orphaned-cards": "Fix Orphaned Cards", "step-convert-shared-lists": "Convert Shared Lists", diff --git a/models/boards.js b/models/boards.js index 479b2530e..f5d8d61d6 100644 --- a/models/boards.js +++ b/models/boards.js @@ -857,12 +857,22 @@ Boards.helpers({ ); }, + listsInSwimlane(swimlaneId) { + return this.lists().filter(e => e.swimlaneId === swimlaneId); + }, + /** returns the last list * @returns Document the last list */ getLastList() { - const ret = ReactiveCache.getList({ boardId: this._id }, { sort: { sort: 'desc' } }); - return ret; + req = { boardId: this._id }; + if (this.swimlane && this.swimlane._id != this._id) { + req.swimlaneId = this.swimlane._id; + } + return ReactiveCache.getList( + req, + { sort: { sort: 'desc' } + }); }, nullSortLists() { @@ -949,12 +959,12 @@ Boards.helpers({ const user = ReactiveCache.getUser(member.userId); return user !== undefined; }); - + // Sort by role priority first (admin, normal, normal-assigned, no-comments, comment-only, comment-assigned, worker, read-only, read-assigned), then by fullname return _.sortBy(filteredMembers, member => { const user = ReactiveCache.getUser(member.userId); let rolePriority = 8; // Default for normal - + if (member.isAdmin) rolePriority = 0; else if (member.isReadAssignedOnly) rolePriority = 8; else if (member.isReadOnly) rolePriority = 7; @@ -964,7 +974,7 @@ Boards.helpers({ else if (member.isNoComments) rolePriority = 3; else if (member.isNormalAssignedOnly) rolePriority = 2; else rolePriority = 1; // Normal - + const fullname = user ? user.profile.fullname : ''; return rolePriority + '-' + fullname; }); @@ -1144,10 +1154,7 @@ Boards.helpers({ searchBoards(term) { check(term, Match.OneOf(String, null, undefined)); - const query = { boardId: this._id }; - query.type = 'cardType-linkedBoard'; - query.archived = false; - + const query = { type: 'template-container', archived: false }; const projection = { limit: 10, sort: { createdAt: -1 } }; if (term) { @@ -1156,7 +1163,7 @@ Boards.helpers({ query.$or = [{ title: regex }, { description: regex }]; } - const ret = ReactiveCache.getCards(query, projection); + const ret = ReactiveCache.getBoards(query, projection); return ret; }, @@ -1644,19 +1651,19 @@ Boards.helpers({ return await Boards.updateAsync(this._id, { $set: { allowsDescriptionText } }); }, - async setallowsDescriptionTextOnMinicard(allowsDescriptionTextOnMinicard) { + async setAllowsDescriptionTextOnMinicard(allowsDescriptionTextOnMinicard) { return await Boards.updateAsync(this._id, { $set: { allowsDescriptionTextOnMinicard } }); }, - async setallowsCoverAttachmentOnMinicard(allowsCoverAttachmentOnMinicard) { + async setAllowsCoverAttachmentOnMinicard(allowsCoverAttachmentOnMinicard) { return await Boards.updateAsync(this._id, { $set: { allowsCoverAttachmentOnMinicard } }); }, - async setallowsBadgeAttachmentOnMinicard(allowsBadgeAttachmentOnMinicard) { + async setAllowsBadgeAttachmentOnMinicard(allowsBadgeAttachmentOnMinicard) { return await Boards.updateAsync(this._id, { $set: { allowsBadgeAttachmentOnMinicard } }); }, - async setallowsCardSortingByNumberOnMinicard(allowsCardSortingByNumberOnMinicard) { + async setAllowsCardSortingByNumberOnMinicard(allowsCardSortingByNumberOnMinicard) { return await Boards.updateAsync(this._id, { $set: { allowsCardSortingByNumberOnMinicard } }); }, @@ -1775,7 +1782,7 @@ Boards.userBoards = ( selector.archived = archived; } if (!selector.type) { - selector.type = 'board'; + selector.type = { $in: ['board', 'template-container'] }; } selector.$or = [ diff --git a/models/cardComments.js b/models/cardComments.js index fd2e8502d..0f2fdd633 100644 --- a/models/cardComments.js +++ b/models/cardComments.js @@ -106,40 +106,53 @@ CardComments.helpers({ }, reactions() { - const cardCommentReactions = ReactiveCache.getCardCommentReaction({cardCommentId: this._id}); + const reaction = this.reaction(); return !!cardCommentReactions ? cardCommentReactions.reactions : []; }, + reaction() { + return cardCommentReactions = ReactiveCache.getCardCommentReaction({ cardCommentId: this._id }); + }, + + userReactions(userId) { + const reactions = this.reactions(); + return reactions?.filter(r => r.userIds.includes(userId)); + }, + + hasUserReacted(codepoint) { + return this.userReactions(Meteor.userId()).find(e => e.reactionCodepoint === codepoint); + }, + toggleReaction(reactionCodepoint) { if (reactionCodepoint !== sanitizeText(reactionCodepoint)) { return false; } else { - const cardCommentReactions = ReactiveCache.getCardCommentReaction({cardCommentId: this._id}); - const reactions = !!cardCommentReactions ? cardCommentReactions.reactions : []; const userId = Meteor.userId(); - const reaction = reactions.find(r => r.reactionCodepoint === reactionCodepoint); + const reactionDoc = this.reaction(); + const reactions = this.reactions(); + const reactionTog = reactions.find(r => r.reactionCodepoint === reactionCodepoint); // If no reaction is set for the codepoint, add this - if (!reaction) { + if (!reactionTog) { reactions.push({ reactionCodepoint, userIds: [userId] }); } else { // toggle user reaction upon previous reaction state - const userHasReacted = reaction.userIds.includes(userId); + const userHasReacted = reactionTog.userIds.includes(userId); if (userHasReacted) { - reaction.userIds.splice(reaction.userIds.indexOf(userId), 1); - if (reaction.userIds.length === 0) { - reactions.splice(reactions.indexOf(reaction), 1); + reactionTog.userIds.splice(reactionTog.userIds.indexOf(userId), 1); + if (reactionTog.userIds.length === 0) { + reactions.splice(reactions.indexOf(reactionTog), 1); } } else { - reaction.userIds.push(userId); + reactionTog.userIds.push(userId); } } // If no reaction doc exists yet create otherwise update reaction set - if (!!cardCommentReactions) { - return CardCommentReactions.update({ _id: cardCommentReactions._id }, { $set: { reactions } }); + if (!!reactionDoc) { + return CardCommentReactions.update({ _id: reactionDoc._id }, { $set: { reactions } }); } else { return CardCommentReactions.insert({ boardId: this.boardId, diff --git a/models/cards.js b/models/cards.js index 450fb0e35..9509c0c2c 100644 --- a/models/cards.js +++ b/models/cards.js @@ -1,24 +1,24 @@ import { ReactiveCache, ReactiveMiniMongoIndex } from '/imports/reactiveCache'; import { FlowRouter } from 'meteor/ostrio:flow-router-extra'; -import { - formatDateTime, - formatDate, - formatTime, - getISOWeek, - isValidDate, - isBefore, - isAfter, - isSame, - add, - subtract, - startOf, - endOf, - format, - parseDate, - now, - createDate, - fromNow, - calendar +import { + formatDateTime, + formatDate, + formatTime, + getISOWeek, + isValidDate, + isBefore, + isAfter, + isSame, + add, + subtract, + startOf, + endOf, + format, + parseDate, + now, + createDate, + fromNow, + calendar } from '/imports/lib/dateUtils'; import { ALLOWED_COLORS, @@ -2682,16 +2682,21 @@ function cardCustomFields(userId, doc, fieldNames, modifier) { } function cardCreation(userId, doc) { + // For any reason some special cards also have + // special data, e.g. linked cards who have list/swimlane ID + // being their own ID + const list = ReactiveCache.getList(doc.listId); + const swim = ReactiveCache.getSwimlane(doc.listId); Activities.insert({ userId, activityType: 'createCard', boardId: doc.boardId, - listName: ReactiveCache.getList(doc.listId).title, - listId: doc.listId, + listName: list?.title, + listId: list ? doc.listId : undefined, cardId: doc._id, cardTitle: doc.title, - swimlaneName: ReactiveCache.getSwimlane(doc.swimlaneId).title, - swimlaneId: doc.swimlaneId, + swimlaneName: swim?.title, + swimlaneId: swim ? doc.swimlaneId : undefined, }); } @@ -4294,10 +4299,10 @@ Cards.helpers({ hasMovedFromOriginalPosition() { const history = this.getOriginalPosition(); if (!history) return false; - + const currentSwimlaneId = this.swimlaneId || null; const currentListId = this.listId || null; - + return history.originalPosition.sort !== this.sort || history.originalSwimlaneId !== currentSwimlaneId || history.originalListId !== currentListId; @@ -4309,12 +4314,12 @@ Cards.helpers({ getOriginalPositionDescription() { const history = this.getOriginalPosition(); if (!history) return 'No original position data'; - - const swimlaneInfo = history.originalSwimlaneId ? - ` in swimlane ${history.originalSwimlaneId}` : + + const swimlaneInfo = history.originalSwimlaneId ? + ` in swimlane ${history.originalSwimlaneId}` : ' in default swimlane'; - const listInfo = history.originalListId ? - ` in list ${history.originalListId}` : + const listInfo = history.originalListId ? + ` in list ${history.originalListId}` : ''; return `Original position: ${history.originalPosition.sort || 0}${swimlaneInfo}${listInfo}`; }, diff --git a/models/lib/fileStoreStrategy.js b/models/lib/fileStoreStrategy.js index 911011526..f60d88d35 100644 --- a/models/lib/fileStoreStrategy.js +++ b/models/lib/fileStoreStrategy.js @@ -103,10 +103,10 @@ export default class FileStoreStrategyFactory { if (!storage) { storage = fileObj.versions[versionName].storage; if (!storage) { - if (fileObj.meta.source == "import" || fileObj.versions[versionName].meta.gridFsFileId) { + if (fileObj.meta.source == "import" || Object.hasOwnProperty(fileObj.versions[versionName].meta, 'gridFsFileId')) { // uploaded by import, so it's in GridFS (MongoDB) storage = STORAGE_NAME_GRIDFS; - } else if (fileObj && fileObj.versions && fileObj.versions[version] && fileObj.versions[version].meta && fileObj.versions[version].meta.pipePath) { + } else if (fileObj && fileObj.versions && fileObj.versions[versionName] && fileObj.versions[versionName].meta && Object.hasOwnProperty(fileObj.versions[versionName].meta, 'pipePath')) { // DISABLED: S3 storage removed due to Node.js compatibility - fallback to filesystem storage = STORAGE_NAME_FILESYSTEM; } else { diff --git a/models/users.js b/models/users.js index 83fbeff66..75e40cc8f 100644 --- a/models/users.js +++ b/models/users.js @@ -615,15 +615,6 @@ Users.attachSchema( allowedValues: ['YYYY-MM-DD', 'DD-MM-YYYY', 'MM-DD-YYYY'], defaultValue: 'YYYY-MM-DD', }, - 'profile.zoomLevel': { - /** - * User-specified zoom level for board view (1.0 = 100%, 1.5 = 150%, etc.) - */ - type: Number, - defaultValue: 1.0, - min: 0.5, - max: 3.0, - }, 'profile.mobileMode': { /** * User-specified mobile/desktop mode toggle @@ -842,7 +833,6 @@ Users.safeFields = { 'profile.fullname': 1, 'profile.avatarUrl': 1, 'profile.initials': 1, - 'profile.zoomLevel': 1, 'profile.mobileMode': 1, 'profile.GreyIcons': 1, orgs: 1, @@ -1103,7 +1093,7 @@ Users.helpers({ if (this._id) { return this.getSwimlaneHeight(boardId, swimlaneId); } - + // For non-logged-in users, get from localStorage try { const stored = localStorage.getItem('wekan-swimlane-heights'); @@ -1116,7 +1106,7 @@ Users.helpers({ } catch (e) { console.warn('Error reading swimlane heights from localStorage:', e); } - + return -1; }, @@ -1125,17 +1115,17 @@ Users.helpers({ if (this._id) { return this.setSwimlaneHeight(boardId, swimlaneId, height); } - + // For non-logged-in users, save to localStorage try { const stored = localStorage.getItem('wekan-swimlane-heights'); let heights = stored ? JSON.parse(stored) : {}; - + if (!heights[boardId]) { heights[boardId] = {}; } heights[boardId][swimlaneId] = height; - + localStorage.setItem('wekan-swimlane-heights', JSON.stringify(heights)); return true; } catch (e) { @@ -1322,7 +1312,7 @@ Users.helpers({ if (this._id) { return this.getListWidth(boardId, listId); } - + // For non-logged-in users, get from validated localStorage if (typeof localStorage !== 'undefined' && typeof getValidatedLocalStorageData === 'function') { try { @@ -1338,7 +1328,7 @@ Users.helpers({ console.warn('Error reading list widths from localStorage:', e); } } - + return 270; // Return default width }, @@ -1347,23 +1337,23 @@ Users.helpers({ if (this._id) { return this.setListWidth(boardId, listId, width); } - + // Validate width before storing if (!validators.isValidNumber(width, 270, 1000)) { console.warn('Invalid list width:', width); return false; } - + // For non-logged-in users, save to validated localStorage if (typeof localStorage !== 'undefined' && typeof setValidatedLocalStorageData === 'function') { try { const widths = getValidatedLocalStorageData('wekan-list-widths', validators.listWidths); - + if (!widths[boardId]) { widths[boardId] = {}; } widths[boardId][listId] = width; - + return setValidatedLocalStorageData('wekan-list-widths', widths, validators.listWidths); } catch (e) { console.warn('Error saving list width to localStorage:', e); @@ -1378,7 +1368,7 @@ Users.helpers({ if (this._id) { return this.getListConstraint(boardId, listId); } - + // For non-logged-in users, get from localStorage try { const stored = localStorage.getItem('wekan-list-constraints'); @@ -1391,7 +1381,7 @@ Users.helpers({ } catch (e) { console.warn('Error reading list constraints from localStorage:', e); } - + return 550; // Return default constraint instead of -1 }, @@ -1400,17 +1390,17 @@ Users.helpers({ if (this._id) { return this.setListConstraint(boardId, listId, constraint); } - + // For non-logged-in users, save to localStorage try { const stored = localStorage.getItem('wekan-list-constraints'); let constraints = stored ? JSON.parse(stored) : {}; - + if (!constraints[boardId]) { constraints[boardId] = {}; } constraints[boardId][listId] = constraint; - + localStorage.setItem('wekan-list-constraints', JSON.stringify(constraints)); return true; } catch (e) { @@ -1424,7 +1414,7 @@ Users.helpers({ if (this._id) { return this.getSwimlaneHeight(boardId, swimlaneId); } - + // For non-logged-in users, get from localStorage try { const stored = localStorage.getItem('wekan-swimlane-heights'); @@ -1437,7 +1427,7 @@ Users.helpers({ } catch (e) { console.warn('Error reading swimlane heights from localStorage:', e); } - + return -1; // Return -1 if not found }, @@ -1446,17 +1436,17 @@ Users.helpers({ if (this._id) { return this.setSwimlaneHeight(boardId, swimlaneId, height); } - + // For non-logged-in users, save to localStorage try { const stored = localStorage.getItem('wekan-swimlane-heights'); let heights = stored ? JSON.parse(stored) : {}; - + if (!heights[boardId]) { heights[boardId] = {}; } heights[boardId][swimlaneId] = height; - + localStorage.setItem('wekan-swimlane-heights', JSON.stringify(heights)); return true; } catch (e) { @@ -1782,18 +1772,6 @@ Users.helpers({ current[boardId][swimlaneId] = !!collapsed; return await Users.updateAsync(this._id, { $set: { 'profile.collapsedSwimlanes': current } }); }, - - async setZoomLevel(level) { - return await Users.updateAsync(this._id, { $set: { 'profile.zoomLevel': level } }); - }, - - async setMobileMode(enabled) { - return await Users.updateAsync(this._id, { $set: { 'profile.mobileMode': enabled } }); - }, - - async setCardZoom(level) { - return await Users.updateAsync(this._id, { $set: { 'profile.cardZoom': level } }); - }, }); Meteor.methods({ @@ -1914,16 +1892,16 @@ Meteor.methods({ if (!user) { throw new Meteor.Error('user-not-found', 'User not found'); } - + // Check if board is already starred const starredBoards = (user.profile && user.profile.starredBoards) || []; const isStarred = starredBoards.includes(boardId); - + // Build update object - const updateObject = isStarred + const updateObject = isStarred ? { $pull: { 'profile.starredBoards': boardId } } : { $addToSet: { 'profile.starredBoards': boardId } }; - + Users.update(this.userId, updateObject); }, toggleGreyIcons(value) { @@ -1991,11 +1969,11 @@ Meteor.methods({ check(boardId, String); check(spaceId, String); if (!this.userId) throw new Meteor.Error('not-logged-in'); - + const user = Users.findOne(this.userId); const assignments = user.profile?.boardWorkspaceAssignments || {}; assignments[boardId] = spaceId; - + Users.update(this.userId, { $set: { 'profile.boardWorkspaceAssignments': assignments } }); @@ -2005,11 +1983,11 @@ Meteor.methods({ unassignBoardFromWorkspace(boardId) { check(boardId, String); if (!this.userId) throw new Meteor.Error('not-logged-in'); - + const user = Users.findOne(this.userId); const assignments = user.profile?.boardWorkspaceAssignments || {}; delete assignments[boardId]; - + Users.update(this.userId, { $set: { 'profile.boardWorkspaceAssignments': assignments } }); @@ -2023,9 +2001,11 @@ Meteor.methods({ const user = ReactiveCache.getCurrentUser(); user.toggleFieldsGrid(user.hasCustomFieldsGrid()); }, - toggleCardMaximized() { + /* #FIXME not sure about what I'm doing here, but this methods call an async method AFAIU. + not making it wait to it creates flickering and multiple renderings on client side. */ + async toggleCardMaximized() { const user = ReactiveCache.getCurrentUser(); - user.toggleCardMaximized(user.hasCardMaximized()); + await user.toggleCardMaximized(user.hasCardMaximized()); }, setCardCollapsed(value) { check(value, Boolean); @@ -2036,6 +2016,10 @@ Meteor.methods({ const user = ReactiveCache.getCurrentUser(); user.toggleLabelText(user.hasHiddenMinicardLabelText()); }, + toggleShowWeekOfYear() { + const user = ReactiveCache.getCurrentUser(); + user.toggleShowWeekOfYear(user.isShowWeekOfYear()); + }, toggleRescueCardDescription() { const user = ReactiveCache.getCurrentUser(); user.toggleRescueCardDescription(user.hasRescuedCardDescription()); @@ -2116,7 +2100,7 @@ Meteor.methods({ check(height, Number); const user = ReactiveCache.getCurrentUser(); if (user) { - user.setSwimlaneHeightToStorage(boardId, swimlaneId, height); + user.setSwimlaneHeightToStorage(boardId, swimlaneId, parseInt(height)); } // For non-logged-in users, the client-side code will handle localStorage }, @@ -2133,11 +2117,6 @@ Meteor.methods({ } // For non-logged-in users, the client-side code will handle localStorage }, - setZoomLevel(level) { - check(level, Number); - const user = ReactiveCache.getCurrentUser(); - user.setZoomLevel(level); - }, setMobileMode(enabled) { check(enabled, Boolean); const user = ReactiveCache.getCurrentUser(); @@ -3037,7 +3016,7 @@ if (Meteor.isServer) { // get all boards where the user is member of let boards = ReactiveCache.getBoards( { - type: 'board', + type: {$in: ['board', 'template-container']}, 'members.userId': req.userId, }, { @@ -3123,7 +3102,7 @@ if (Meteor.isServer) { // get all boards where the user is member of let boards = ReactiveCache.getBoards( { - type: 'board', + type: { $in: ['board', 'template-container'] }, 'members.userId': id, }, { diff --git a/packages/wekan-accounts-cas/cas_client.js b/packages/wekan-accounts-cas/cas_client.js index ca9288ae2..9790fb22a 100644 --- a/packages/wekan-accounts-cas/cas_client.js +++ b/packages/wekan-accounts-cas/cas_client.js @@ -93,6 +93,8 @@ Meteor.loginWithCas = function(options, callback) { }; var openCenteredPopup = function(url, width, height) { + // #FIXME screenX and outerWidth are often different units on mobile screen or high DPI + // see https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio var screenX = typeof window.screenX !== 'undefined' ? window.screenX : window.screenLeft; var screenY = typeof window.screenY !== 'undefined' diff --git a/packages/wekan-fullcalendar/fullcalendar/fullcalendar.css b/packages/wekan-fullcalendar/fullcalendar/fullcalendar.css index 1600d948e..055efc4f2 100644 --- a/packages/wekan-fullcalendar/fullcalendar/fullcalendar.css +++ b/packages/wekan-fullcalendar/fullcalendar/fullcalendar.css @@ -467,7 +467,7 @@ temporary rendered events). /* resizer (touch devices) */ .fc-h-event.fc-selected .fc-resizer { /* 8x8 little dot */ - border-radius: 4px; + border-radius: 0.4ch; border-width: 1px; width: 6px; height: 6px; @@ -1145,7 +1145,7 @@ be a descendant of the grid when it is being dragged. height: 8px; overflow: hidden; line-height: 8px; - font-size: 11px; + font-family: monospace; text-align: center; cursor: s-resize; } diff --git a/popup.jade b/popup.jade new file mode 100644 index 000000000..5236e0d5f --- /dev/null +++ b/popup.jade @@ -0,0 +1,21 @@ +template(name="popup") + span(class=popupPlaceholderClass) + +template(name="popupDetached") + .pop-over.js-pop-over( + class="{{#unless title}}miniprofile{{/unless}}" + class=currentBoard.colorClass + class="{{#unless title}}no-title{{/unless}}" + class="{{#unless isRendered}}invisible{{/unless}}" + data-popup=name) + if showHeader + .header + span.header-title= title + .header-controls + if isMiniScreen + span.popup-drag-handle.js-popup-drag-handle(title="Drag popup") + i.fa.fa-arrows + a.close-btn.js-close-detached-popup + i.fa.fa-times-thin + .content-wrapper + .content diff --git a/public/css/reset.css b/public/css/reset.css index 3839cb35c..a152f5e4f 100644 --- a/public/css/reset.css +++ b/public/css/reset.css @@ -46,14 +46,9 @@ article, aside, canvas, details, figcaption, display: block; } audio, canvas, video { - display inline-block; - *display inline; - *zoom 1; + display: inline-block; + zoom: 1; } audio:not([controls]),[hidden] { display: none; } - - - -