mirror of
https://github.com/wekan/wekan.git
synced 2026-11-08 21:44:59 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8f83ece2ed | ||
|
|
ac8e39daca | ||
|
|
3c07777722 | ||
|
|
0e10d24bef | ||
|
|
4a7df37459 | ||
|
|
f9b5de0e8e | ||
|
|
88f353dc1f | ||
|
|
50525f6fd1 | ||
|
|
219ee659e9 |
No files matched your search
@@ -41,6 +41,52 @@ them up next.
|
||||
[#3823](https://github.com/wekan/wekan/issues/3823), [#3138](https://github.com/wekan/wekan/issues/3138),
|
||||
[#2204](https://github.com/wekan/wekan/issues/2204) (restrict permanent delete to the Admin role).
|
||||
|
||||
# v9.73 2026-06-26 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Mobile UI still too large at All Boards / iPhone 12 mini](https://github.com/wekan/wekan/issues/6426),
|
||||
[#6426](https://github.com/wekan/wekan/issues/6426): the first revert only cleaned
|
||||
`boardsList.css`, leaving the same forced "2x/3x bigger on mobile" rules in `header.css`
|
||||
(`#header-quick-access` logo/quick-access bar) and `boardBody.css` (`#content` — which the
|
||||
All Boards list and popups render inside) and the iPhone card-details body text. Those are now
|
||||
neutralized to normal size too, and the iPhone-12-mini header blocks that had grown tall and
|
||||
wrapped (to fit the 3x text) are back to a compact single row. The #6419 mobile touch-target
|
||||
icon sizes in the card-details header are intentionally kept.
|
||||
Fixed in [219ee659e](https://github.com/wekan/wekan/commit/219ee659e).
|
||||
- Drag-to-scroll (dragscroll) not working on the Login, Register and All Boards pages: the page
|
||||
helper tagged `<body>` with the `dragscroll` class, but on phones `body.mobile-mode` is
|
||||
`position: fixed` and the real scroll container becomes `#content`, so tagging only `<body>`
|
||||
could never scroll on those pages (Login/Register have no `#content` and correctly use
|
||||
`<body>`). `enablePageDragscroll`/`disablePageDragscroll` now tag whichever element actually
|
||||
scrolls — both `<body>` and `#content` when present — so only the overflowing one scrolls (no
|
||||
double-scroll). Touch one-finger scrolling (`dragscrollTouch.js`) already picks the nearest
|
||||
scrollable `.dragscroll` ancestor, so `#content` wins over `<body>` when both are tagged.
|
||||
Fixed in [219ee659e](https://github.com/wekan/wekan/commit/219ee659e).
|
||||
- Drag-to-scroll now works on **every** whole-page layout in both mobile and desktop modes, not
|
||||
just All Boards / My Cards / Login / Register. It was wired into only those few templates, so
|
||||
Due Cards, Global Search, Public, Bookmarks, Broken Cards, Settings, People, Admin Reports,
|
||||
Attachments, Translation, Import, board Rules and the Not Found page had no page drag-scroll at
|
||||
all. The per-template enable/disable calls (which also fought each other when navigating between
|
||||
two non-board pages) were replaced by a single route-aware autorun in `defaultLayout` (the
|
||||
persistent shell that owns `#content`): every non-board route tags the real scroll container
|
||||
(`<body>` + `#content`), and the board-canvas routes (`board` / `board-short` / `card`) leave it
|
||||
off so their own `.board-canvas.dragscroll` keeps handling the drag. Login / Register keep their
|
||||
own enable/disable because they use `userFormsLayout` (no `#content`).
|
||||
Fixed in [88f353dc1](https://github.com/wekan/wekan/commit/88f353dc1).
|
||||
- Login / Register pages not scrollable on phones — the sign-up / sign-in link, legal notice and
|
||||
language selector below the form were unreachable (and hidden behind the on-screen keyboard). On
|
||||
mobile, `body.mobile-mode` pins `<body>` to `position: fixed` + `height: 100vh` (an iOS
|
||||
board-view anti-bounce fix), but the auth pages have no inner `#content` scroller and their
|
||||
`.auth-layout`/`.auth-dialog` were sized to the viewport height, so the page was trapped at
|
||||
100vh. `userFormsLayout` now tags `<body>` with `.userform-layout` while mounted, and CSS lets
|
||||
those pages scroll as a normal document on mobile (`position: static; height: auto;
|
||||
min-height: 100vh`) with the layout/dialog growing to their content. Scoped to
|
||||
`.userform-layout` so the board-view mobile lock is unchanged.
|
||||
Fixed in [4a7df3745](https://github.com/wekan/wekan/commit/4a7df3745).
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v9.72 2026-06-26 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ LABEL org.opencontainers.image.source="https://github.com/wekan/wekan"
|
||||
# TARGETARCH and TARGETVARIANT are automatically provided by Docker Buildx
|
||||
ARG TARGETARCH
|
||||
ARG TARGETVARIANT
|
||||
ARG VERSION=9.72
|
||||
ARG VERSION=9.73
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
ENV BUILD_DEPS="apt-utils gnupg wget bzip2 g++ curl libarchive-tools build-essential git ca-certificates python3 unzip"
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
appId: wekan-public/apps/77b94f60-dec9-0136-304e-16ff53095928
|
||||
appVersion: "v9.72.0"
|
||||
appVersion: "v9.73.0"
|
||||
files:
|
||||
userUploads:
|
||||
- README.md
|
||||
|
||||
@@ -107,17 +107,17 @@
|
||||
overflow-y: scroll !important;
|
||||
}
|
||||
|
||||
/* Mobile - make all text 2x bigger inside #content by default (icons stay same size) */
|
||||
/* Mobile - keep #content text at normal size (reverted #6426 oversizing) */
|
||||
@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 */
|
||||
font-size: 1em !important; /* Normal size (reverted #6426 oversizing) */
|
||||
}
|
||||
|
||||
/* Make all text elements 2x bigger */
|
||||
/* Keep all text elements at normal size */
|
||||
#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,
|
||||
@@ -186,7 +186,7 @@
|
||||
|
||||
/* Fallback for iPhone devices using JavaScript detection */
|
||||
.iphone-device #content {
|
||||
font-size: 2em !important; /* 2x bigger base font size for content area */
|
||||
font-size: 1em !important; /* Normal size (reverted #6426 oversizing) */
|
||||
}
|
||||
|
||||
.iphone-device #content h1, .iphone-device #content h2, .iphone-device #content h3, .iphone-device #content h4, .iphone-device #content h5, .iphone-device #content h6,
|
||||
@@ -231,9 +231,9 @@
|
||||
font-size: 1em !important; /* Keep original icon size */
|
||||
}
|
||||
|
||||
/* Mobile iPhone: scale card details text and icons to 2x */
|
||||
/* Mobile iPhone: keep card details text/icons at normal size (reverted #6426 oversizing) */
|
||||
body.mobile-mode.iphone-device .card-details {
|
||||
font-size: 2em !important;
|
||||
font-size: 1em !important;
|
||||
}
|
||||
body.mobile-mode.iphone-device .card-details .fa,
|
||||
body.mobile-mode.iphone-device .card-details .icon,
|
||||
|
||||
@@ -2,8 +2,6 @@ import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { TAPi18n } from '/imports/i18n';
|
||||
import { FlowRouter } from 'meteor/ostrio:flow-router-extra';
|
||||
import getSlug from 'limax';
|
||||
import '/client/lib/dragscrollTouch';
|
||||
import { enablePageDragscroll, disablePageDragscroll } from '/client/lib/pageDragscroll';
|
||||
import TableVisibilityModeSettings from '/models/tableVisibilityModeSettings';
|
||||
import { BoardMultiSelection } from '/client/lib/boardMultiSelection';
|
||||
import { EscapeActions } from '/client/lib/escapeActions';
|
||||
@@ -329,12 +327,9 @@ Template.boardList.onCreated(function () {
|
||||
});
|
||||
|
||||
Template.boardList.onRendered(function () {
|
||||
// Enable drag-to-scroll on the All Boards page the same way the board
|
||||
// canvas/swimlanes do. On desktop the page scroll container is <body>, so we
|
||||
// tag it via enablePageDragscroll(); the .board-list.dragscroll element only
|
||||
// becomes a scroll container in mobile view, where its own class handles it.
|
||||
// Finger drag-scrolling is handled by dragscrollTouch.js.
|
||||
enablePageDragscroll();
|
||||
// Drag-to-scroll on the All Boards page is handled centrally for all
|
||||
// non-board pages by defaultLayout's route-aware autorun
|
||||
// (see client/components/main/layouts.js).
|
||||
|
||||
// jQuery sortable is disabled in favor of HTML5 drag-and-drop for space management
|
||||
// The old sortable code has been removed to prevent conflicts
|
||||
@@ -380,13 +375,6 @@ Template.boardList.onRendered(function () {
|
||||
*/
|
||||
});
|
||||
|
||||
Template.boardList.onDestroyed(function () {
|
||||
// Stop tagging <body> as drag-scrollable when leaving the All Boards page so
|
||||
// other layouts (e.g. a board view, whose canvas does its own dragscroll) are
|
||||
// not affected.
|
||||
disablePageDragscroll();
|
||||
});
|
||||
|
||||
Template.boardList.helpers({
|
||||
userHasTeams() {
|
||||
if (ReactiveCache.getCurrentUser()?.teams?.length > 0) return true;
|
||||
|
||||
@@ -558,7 +558,7 @@ body:not(.board-view) #header #header-main-bar h1 {
|
||||
}
|
||||
}
|
||||
|
||||
/* Mobile - make all text and icons 2x bigger above #content by default */
|
||||
/* Mobile - keep header text/icons at normal size (reverted #6426 oversizing) */
|
||||
@media screen and (max-width: 800px),
|
||||
screen and (max-device-width: 800px),
|
||||
screen and (-webkit-min-device-pixel-ratio: 2) and (max-width: 800px),
|
||||
@@ -573,7 +573,7 @@ body:not(.board-view) #header #header-main-bar h1 {
|
||||
overflow: hidden !important; /* Prevent content overflow */
|
||||
}
|
||||
#header-quick-access {
|
||||
font-size: 2em !important; /* 2x bigger base font size */
|
||||
font-size: 1em !important; /* Normal size (reverted #6426 oversizing) */
|
||||
}
|
||||
|
||||
#header-quick-access * {
|
||||
@@ -582,7 +582,7 @@ body:not(.board-view) #header #header-main-bar h1 {
|
||||
|
||||
#header-quick-access .fa,
|
||||
#header-quick-access .icon {
|
||||
font-size: 2em !important; /* 2x bigger icons */
|
||||
font-size: 1em !important; /* Normal icon size (reverted #6426 oversizing) */
|
||||
}
|
||||
|
||||
#header-quick-access .home-icon a {
|
||||
@@ -652,7 +652,7 @@ body:not(.board-view) #header #header-main-bar h1 {
|
||||
}
|
||||
}
|
||||
|
||||
/* Mobile All Boards page - make logo row elements 2x bigger */
|
||||
/* Mobile All Boards page - keep logo row at normal size (reverted #6426 oversizing) */
|
||||
@media screen and (max-width: 800px),
|
||||
screen and (max-device-width: 800px),
|
||||
screen and (-webkit-min-device-pixel-ratio: 2) and (max-width: 800px),
|
||||
@@ -660,16 +660,16 @@ body:not(.board-view) #header #header-main-bar h1 {
|
||||
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 */
|
||||
font-size: 1em !important; /* Normal size (reverted #6426 oversizing) */
|
||||
}
|
||||
|
||||
/* iPhone 12 Mini specific - 3x bigger for All Boards page */
|
||||
/* iPhone 12 Mini specific - keep All Boards logo row at normal size (reverted #6426) */
|
||||
@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 */
|
||||
font-size: 1em !important; /* Normal size (reverted #6426 oversizing) */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -682,7 +682,7 @@ body:not(.board-view) #header #header-main-bar h1 {
|
||||
.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 */
|
||||
font-size: 1em !important; /* Normal icon size (reverted #6426 oversizing) */
|
||||
}
|
||||
|
||||
.wrapper ~ #header-quick-access .home-icon a,
|
||||
@@ -741,19 +741,19 @@ body:not(.board-view) #header #header-main-bar h1 {
|
||||
}
|
||||
}
|
||||
|
||||
/* iPhone 12 Mini specific - make header elements 3x bigger */
|
||||
/* iPhone 12 Mini specific - keep the header a normal compact single row */
|
||||
@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 */
|
||||
font-size: 1em !important; /* Normal size (reverted #6426 oversizing) */
|
||||
height: 48px !important;
|
||||
min-height: 48px !important;
|
||||
flex-wrap: nowrap !important;
|
||||
align-items: center !important;
|
||||
padding: 8px 0px !important;
|
||||
}
|
||||
|
||||
#header-quick-access * {
|
||||
@@ -762,7 +762,7 @@ body:not(.board-view) #header #header-main-bar h1 {
|
||||
|
||||
#header-quick-access .fa,
|
||||
#header-quick-access .icon {
|
||||
font-size: 3em !important; /* 3x bigger icons for iPhone 12 Mini */
|
||||
font-size: 1em !important; /* Normal icon size (reverted #6426 oversizing) */
|
||||
}
|
||||
|
||||
#header-quick-access .home-icon a {
|
||||
@@ -848,7 +848,7 @@ body:not(.board-view) #header #header-main-bar h1 {
|
||||
}
|
||||
}
|
||||
|
||||
/* iPhone 12 Mini and very small screens - make header elements much larger */
|
||||
/* iPhone 12 Mini and very small screens - header element sizing */
|
||||
@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),
|
||||
@@ -912,12 +912,12 @@ body:not(.board-view) #header #header-main-bar h1 {
|
||||
|
||||
/* 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 */
|
||||
font-size: 1em !important; /* Normal size (reverted #6426 oversizing) */
|
||||
height: 48px !important;
|
||||
min-height: 48px !important;
|
||||
flex-wrap: nowrap !important;
|
||||
align-items: center !important;
|
||||
padding: 8px 0px !important;
|
||||
}
|
||||
|
||||
.iphone-device #header-quick-access * {
|
||||
@@ -926,7 +926,7 @@ body:not(.board-view) #header #header-main-bar h1 {
|
||||
|
||||
.iphone-device #header-quick-access .fa,
|
||||
.iphone-device #header-quick-access .icon {
|
||||
font-size: 2em !important; /* 2x bigger icons */
|
||||
font-size: 1em !important; /* Normal icon size (reverted #6426 oversizing) */
|
||||
}
|
||||
|
||||
.iphone-device #header-quick-access .home-icon a {
|
||||
@@ -995,14 +995,14 @@ body:not(.board-view) #header #header-main-bar h1 {
|
||||
width: auto !important;
|
||||
}
|
||||
|
||||
/* iPhone 12 Mini specific - JavaScript detection fallback */
|
||||
/* iPhone 12 Mini specific - JavaScript detection fallback (normal compact row) */
|
||||
.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 */
|
||||
font-size: 1em !important; /* Normal size (reverted #6426 oversizing) */
|
||||
height: 48px !important;
|
||||
min-height: 48px !important;
|
||||
flex-wrap: nowrap !important;
|
||||
align-items: center !important;
|
||||
padding: 8px 0px !important;
|
||||
}
|
||||
|
||||
.iphone-device #header-quick-access * {
|
||||
@@ -1011,7 +1011,7 @@ body:not(.board-view) #header #header-main-bar h1 {
|
||||
|
||||
.iphone-device #header-quick-access .fa,
|
||||
.iphone-device #header-quick-access .icon {
|
||||
font-size: 3em !important; /* 3x bigger icons for iPhone 12 Mini */
|
||||
font-size: 1em !important; /* Normal icon size (reverted #6426 oversizing) */
|
||||
}
|
||||
|
||||
.iphone-device #header-quick-access .home-icon a {
|
||||
@@ -1096,10 +1096,10 @@ body:not(.board-view) #header #header-main-bar h1 {
|
||||
width: auto !important;
|
||||
}
|
||||
|
||||
/* iPhone 12 Mini All Boards page - make logo row elements 3x bigger */
|
||||
/* iPhone 12 Mini All Boards page - keep logo row at normal size (reverted #6426) */
|
||||
.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 */
|
||||
font-size: 1em !important; /* Normal size (reverted #6426 oversizing) */
|
||||
}
|
||||
|
||||
.iphone-device .wrapper ~ #header-quick-access *,
|
||||
@@ -1111,7 +1111,7 @@ body:not(.board-view) #header #header-main-bar h1 {
|
||||
.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 */
|
||||
font-size: 1em !important; /* Normal icon size (reverted #6426 oversizing) */
|
||||
}
|
||||
|
||||
.iphone-device .wrapper ~ #header-quick-access .home-icon a,
|
||||
|
||||
@@ -52,6 +52,13 @@ Template.userFormsLayout.onRendered(() => {
|
||||
// gesture works the same as on the board swimlanes view.
|
||||
enablePageDragscroll();
|
||||
|
||||
// Mark the auth pages so CSS can let <body> scroll as a normal document.
|
||||
// body.mobile-mode locks <body> to position:fixed/100vh (an iOS board-view
|
||||
// anti-bounce fix); without an inner #content scroller that traps these pages
|
||||
// at viewport height, hiding the sign-up link / language selector below the
|
||||
// form (and they sit behind the on-screen keyboard). See userForm.css.
|
||||
document.body.classList.add('userform-layout');
|
||||
|
||||
Meteor.call('getAuthenticationsEnabled', (_, result) => {
|
||||
let enabledAuthenticationMethods = ['password']; // we show/hide this based on isPasswordLoginEnabled
|
||||
|
||||
@@ -200,6 +207,7 @@ Template.userFormsLayout.onDestroyed(() => {
|
||||
// Stop drag-scrolling <body> after leaving login / register (e.g. once logged
|
||||
// in) so other layouts keep their normal behaviour.
|
||||
disablePageDragscroll();
|
||||
document.body.classList.remove('userform-layout');
|
||||
});
|
||||
|
||||
Template.userFormsLayout.helpers({
|
||||
@@ -314,6 +322,31 @@ Template.defaultLayout.onRendered(function () {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Drag-to-scroll for every whole-page layout rendered inside defaultLayout
|
||||
// (All Boards, My Cards, Due Cards, Global Search, Public, Bookmarks, Broken
|
||||
// Cards, Settings, People, Admin, Import, board Rules, …). These pages scroll
|
||||
// <body> on desktop and #content in mobile mode (where <body> is
|
||||
// position:fixed), so enablePageDragscroll() tags whichever element actually
|
||||
// scrolls. The board-canvas pages are the exception: their own
|
||||
// `.board-canvas.dragscroll` handles dragging, and the canvas does its own
|
||||
// vertical/horizontal scroll, so page-level tagging is turned off there to
|
||||
// avoid scrolling #content and the canvas at the same time. defaultLayout is
|
||||
// persistent (only its `content` swaps), so this single autorun covers every
|
||||
// route without per-template wiring. Login / Register use userFormsLayout and
|
||||
// keep their own enable/disable. Works the same in mobile and desktop mode.
|
||||
const boardCanvasRoutes = ['board', 'board-short', 'card'];
|
||||
this.autorun(() => {
|
||||
FlowRouter.watchPathChange();
|
||||
const onBoardCanvas = boardCanvasRoutes.includes(FlowRouter.getRouteName());
|
||||
Tracker.afterFlush(() => {
|
||||
if (onBoardCanvas) {
|
||||
disablePageDragscroll();
|
||||
} else {
|
||||
enablePageDragscroll();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
async function authentication(event, templateInstance) {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { CardSearchPaged } from '../../lib/cardSearch';
|
||||
import { Utils } from '/client/lib/utils';
|
||||
import { enablePageDragscroll, disablePageDragscroll } from '/client/lib/pageDragscroll';
|
||||
|
||||
Template.myCardsHeaderBar.helpers({
|
||||
myCardsSort() {
|
||||
@@ -41,15 +40,8 @@ Template.myCards.onCreated(function () {
|
||||
Meteor.subscribe('setting');
|
||||
});
|
||||
|
||||
Template.myCards.onRendered(function () {
|
||||
// My Cards renders into <body>'s page scroll area (.wrapper inside #content),
|
||||
// so enable drag-to-scroll on <body> like the All Boards page does.
|
||||
enablePageDragscroll();
|
||||
});
|
||||
|
||||
Template.myCards.onDestroyed(function () {
|
||||
disablePageDragscroll();
|
||||
});
|
||||
// Drag-to-scroll is handled centrally for all non-board pages by
|
||||
// defaultLayout's route-aware autorun (see client/components/main/layouts.js).
|
||||
|
||||
Template.myCards.helpers({
|
||||
userId() {
|
||||
|
||||
@@ -113,6 +113,21 @@ body.mobile-mode .auth-layout .auth-dialog .at-form .password-input-container .p
|
||||
width: 100%;
|
||||
margin-top: 10px;
|
||||
}
|
||||
/* Auth pages (login / register) must scroll as a normal document on mobile so
|
||||
the content below the form — the sign-up / sign-in link, legal notice and
|
||||
language selector — is reachable, including when the on-screen keyboard is
|
||||
open. body.mobile-mode otherwise locks <body> to position:fixed + 100vh (an
|
||||
iOS board-view anti-bounce fix); the auth layout has no inner #content
|
||||
scroller, so that lock traps the page at viewport height and the on-screen
|
||||
keyboard hides the bottom. .userform-layout is added by userFormsLayout while
|
||||
these pages are mounted (see layouts.js). */
|
||||
body.mobile-mode.userform-layout {
|
||||
position: static !important;
|
||||
height: auto !important;
|
||||
min-height: 100vh;
|
||||
overflow-y: auto !important;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 800px) {
|
||||
.auth-layout {
|
||||
width: 100%;
|
||||
@@ -120,6 +135,14 @@ body.mobile-mode .auth-layout .auth-dialog .at-form .password-input-container .p
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
/* Let the auth layout/dialog grow to their content instead of being pinned to
|
||||
the viewport height, so everything below the form scrolls into view. */
|
||||
body.userform-layout .auth-layout {
|
||||
height: auto;
|
||||
}
|
||||
body.userform-layout .auth-layout .auth-dialog {
|
||||
height: auto;
|
||||
}
|
||||
.auth-layout .at-form-landing-logo {
|
||||
width: 125px;
|
||||
position: absolute;
|
||||
|
||||
@@ -1,27 +1,45 @@
|
||||
import dragscroll from '@wekanteam/dragscroll';
|
||||
import '/client/lib/dragscrollTouch';
|
||||
|
||||
// Enable / disable mouse drag-to-scroll for whole-page layouts.
|
||||
// Enable / disable mouse drag-to-scroll for whole-page layouts (All Boards,
|
||||
// My Cards, Login, Register).
|
||||
//
|
||||
// On pages like All Boards, Login and Register the scroll container is the
|
||||
// <body> element itself (it has `overflow-y: auto; height: 100vh`), not an
|
||||
// inner board canvas or swimlane. The dragscroll library scrolls whichever
|
||||
// element carries the `dragscroll` class and has a dedicated `el ==
|
||||
// document.body` branch that also scrolls document.documentElement, so tagging
|
||||
// <body> makes dragging empty page space scroll the page — the same gesture
|
||||
// that already works on the board swimlanes view.
|
||||
// The dragscroll library scrolls whichever element carries the `dragscroll`
|
||||
// class AND is the actual scroll container. Which element that is depends on
|
||||
// the layout and on mobile vs desktop mode:
|
||||
//
|
||||
// The class is toggled per template (onRendered / onDestroyed) so it only
|
||||
// applies on those pages; dragscroll.reset() re-scans the DOM and (re)binds the
|
||||
// mouse listeners after the class is added or removed. Touch (one-finger)
|
||||
// scrolling is handled separately by client/lib/dragscrollTouch.js.
|
||||
// * Login / Register (userFormsLayout) have no `#content`; the page scroll
|
||||
// container is `<body>` in both modes (it has `overflow-y: auto` and a
|
||||
// `100vh` height).
|
||||
// * All Boards / My Cards (defaultLayout) render inside `#content`. On
|
||||
// desktop the scroll container is `<body>`; in mobile mode `<body>` becomes
|
||||
// `position: fixed` and `#content` becomes the scroller
|
||||
// (`overflow-y: auto; height: calc(100vh - 48px)`), so tagging only
|
||||
// `<body>` would never scroll on a phone.
|
||||
//
|
||||
// To cover every case we tag BOTH `<body>` and `#content` (when present). Only
|
||||
// the element that actually overflows scrolls, so there is no double-scroll:
|
||||
// on desktop `<body>` scrolls and `#content` (no vertical overflow) is a no-op;
|
||||
// in mobile mode `#content` scrolls and `<body>` (fixed, no overflow) is a
|
||||
// no-op. dragscroll has a dedicated `el == document.body` branch for the body
|
||||
// case. dragscroll.reset() re-scans the DOM and (re)binds the mouse listeners.
|
||||
// One-finger touch scrolling is handled by client/lib/dragscrollTouch.js, which
|
||||
// picks the nearest scrollable `.dragscroll` ancestor (so `#content` wins over
|
||||
// `<body>` when both are tagged).
|
||||
|
||||
function pageScrollEls() {
|
||||
const els = [document.body];
|
||||
const content = document.getElementById('content');
|
||||
if (content) els.push(content);
|
||||
return els;
|
||||
}
|
||||
|
||||
export function enablePageDragscroll() {
|
||||
document.body.classList.add('dragscroll');
|
||||
pageScrollEls().forEach(el => el.classList.add('dragscroll'));
|
||||
dragscroll.reset();
|
||||
}
|
||||
|
||||
export function disablePageDragscroll() {
|
||||
document.body.classList.remove('dragscroll');
|
||||
pageScrollEls().forEach(el => el.classList.remove('dragscroll'));
|
||||
dragscroll.reset();
|
||||
}
|
||||
@@ -10,7 +10,7 @@ This is without container (without Docker or Snap).
|
||||
|
||||
Right click and download files 1-4:
|
||||
|
||||
1. [wekan-9.72-win64.zip](https://github.com/wekan/wekan/releases/download/v9.72/wekan-9.72-win64.zip) or newest available at https://github.com/wekan/wekan/releases/
|
||||
1. [wekan-9.73-win64.zip](https://github.com/wekan/wekan/releases/download/v9.73/wekan-9.73-win64.zip) or newest available at https://github.com/wekan/wekan/releases/
|
||||
|
||||
2. [node.exe](https://nodejs.org/dist/latest-v24.x/win-x64/node.exe)
|
||||
|
||||
@@ -22,7 +22,7 @@ Right click and download files 1-4:
|
||||
|
||||
6. Double click `mongodb-windows-x86_64-7.0.34-signed.msi` . In installer, uncheck downloading MongoDB compass.
|
||||
|
||||
7. Unzip `wekan-9.72-win64.zip` , inside it is directory `bundle`, to it copy other files:
|
||||
7. Unzip `wekan-9.73-win64.zip` , inside it is directory `bundle`, to it copy other files:
|
||||
|
||||
```
|
||||
bundle (directory)
|
||||
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "wekan",
|
||||
"version": "v9.72.0",
|
||||
"version": "v9.73.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "wekan",
|
||||
"version": "v9.72.0",
|
||||
"version": "v9.73.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-s3": "^3.1071.0",
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "wekan",
|
||||
"version": "v9.72.0",
|
||||
"version": "v9.73.0",
|
||||
"description": "Open-Source kanban",
|
||||
"private": true,
|
||||
"repository": {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
<head>
|
||||
<meta charset="utf8" />
|
||||
<title>WeKan REST API v9.72</title>
|
||||
<title>WeKan REST API v9.73</title>
|
||||
<!-- needed for adaptive design -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style>
|
||||
@@ -423,7 +423,7 @@ data-styled.g139[id="sc-iIvZUO"]{content:"kAmnlO,"}/*!sc*/
|
||||
55.627 l 55.6165,55.627 -231.245496,231.24803 c -127.185,127.1864
|
||||
-231.5279,231.248 -231.873,231.248 -0.3451,0 -104.688,
|
||||
-104.0616 -231.873,-231.248 z
|
||||
" fill="currentColor"></path></g></svg></div></div><div class="sc-jtyQFi ldXCvc api-content"><div class="sc-eCQgVK jleRXN"><div class="sc-iCECmn lhRBUS"><div class="sc-hKVpXn kktglN api-info"><h1 class="sc-fuztkK sc-ctiVdb eRMVDe cBgvIi">Wekan REST API<!-- --> <span>(<!-- -->v9.72<!-- -->)</span></h1><p>Download OpenAPI specification<!-- -->:</p><div class="sc-iJSMbW sc-cBEgGa fiNpIH ewCFMV"></div><div data-role="redoc-summary" html="" class="sc-iJSMbW sc-cBEgGa fiNpIH ewCFMV"></div><div data-role="redoc-description" html="<p>The REST API allows you to control and extend Wekan with ease.</p>
|
||||
" fill="currentColor"></path></g></svg></div></div><div class="sc-jtyQFi ldXCvc api-content"><div class="sc-eCQgVK jleRXN"><div class="sc-iCECmn lhRBUS"><div class="sc-hKVpXn kktglN api-info"><h1 class="sc-fuztkK sc-ctiVdb eRMVDe cBgvIi">Wekan REST API<!-- --> <span>(<!-- -->v9.73<!-- -->)</span></h1><p>Download OpenAPI specification<!-- -->:</p><div class="sc-iJSMbW sc-cBEgGa fiNpIH ewCFMV"></div><div data-role="redoc-summary" html="" class="sc-iJSMbW sc-cBEgGa fiNpIH ewCFMV"></div><div data-role="redoc-description" html="<p>The REST API allows you to control and extend Wekan with ease.</p>
|
||||
<p>If you are an end-user and not a dev or a tester, <a href="https://github.com/wekan/wekan/issues/new">create an issue</a> to request new APIs.</p>
|
||||
<blockquote>
|
||||
<p>All API calls in the documentation are made using <code>curl</code>. However, you are free to use Java / Python / PHP / Golang / Ruby / Swift / Objective-C / Rust / Scala / C# or any other programming languages.</p>
|
||||
@@ -1983,7 +1983,7 @@ comment-only / worker members are rejected).</p>
|
||||
" class="sc-iJSMbW sc-cBEgGa sc-ciCrSJ fiNpIH dNfUH dDDioG"><p>Attachment not found</p>
|
||||
</div></button></div></div></div><div class="sc-jSppWd sc-gKkgUA fpMlmc bdQQyo"><div class="sc-fXwuWv fYxpnv"><button class="sc-jWMFtl jzaJhV"><span type="delete" class="sc-eEFuoE iINwyG http-verb delete">delete</span><span class="sc-FpjRO dsIRaZ">/api/attachment/delete/{attachmentId}</span><svg class="sc-dYjPD bQKUih" style="margin-right:-25px" version="1.1" viewBox="0 0 24 24" x="0" xmlns="http://www.w3.org/2000/svg" y="0" aria-hidden="true"><polygon points="17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 "></polygon></svg></button><div aria-hidden="true" class="sc-fmtEmb tUxhh"><div class="sc-ljIcGq bAnPPh"><div html="" class="sc-iJSMbW sc-cBEgGa fiNpIH bAoMjv"></div><div tabindex="0" role="button"><div class="sc-jlJOIR PEJyb"><span></span>/api/attachment/delete/{attachmentId}</div></div></div></div></div></div></div></div></div><div class="sc-ekVkVN bjzTxL"></div></div></div>
|
||||
<script>
|
||||
const __redoc_state = {"menu":{"activeItemIdx":-1},"spec":{"data":{"openapi":"3.0.0","info":{"title":"Wekan REST API","version":"v9.72","description":"The REST API allows you to control and extend Wekan with ease.\n\nIf you are an end-user and not a dev or a tester, [create an issue](https://github.com/wekan/wekan/issues/new) to request new APIs.\n\n> All API calls in the documentation are made using `curl`. However, you are free to use Java / Python / PHP / Golang / Ruby / Swift / Objective-C / Rust / Scala / C# or any other programming languages.\n\n# Production Security Concerns\nWhen calling a production Wekan server, ensure it is running via HTTPS and has a valid SSL Certificate. The login method requires you to post your username and password in plaintext, which is why we highly suggest only calling the REST login api over HTTPS. Also, few things to note:\n\n* Only call via HTTPS\n* Implement a timed authorization token expiration strategy\n* Ensure the calling user only has permissions for what they are calling and no more\n"},"paths":{"/users/login":{"post":{"operationId":"login","summary":"Login with REST API","tags":["Login"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["username","password"],"properties":{"username":{"description":"Your username\n","type":"string"},"password":{"description":"Your password\n","type":"string","format":"password"}}}},"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["username","password"],"properties":{"username":{"description":"Your username\n","type":"string"},"password":{"description":"Your password\n","type":"string","format":"password"}}}}},"description":"Login credentials","required":true},"responses":{"200":{"description":"Successful authentication","content":{"*/*":{"schema":{"type":"object","required":["id","token","tokenExpires"],"properties":{"id":{"type":"string","description":"User ID"},"token":{"type":"string","description":"Authentication token\n"},"tokenExpires":{"type":"string","format":"date-time","description":"Token expiration date\n"}}}}}},"400":{"description":"Error in authentication\n","content":{"*/*":{"schema":{"type":"object","properties":{"error":{"type":"string"},"reason":{"type":"string"}}}}}},"default":{"description":"Error in authentication\n"}}}},"/users/register":{"post":{"operationId":"register","summary":"Register with REST API","description":"Notes:\n - You will need to provide the token for any of the authenticated methods.\n","tags":["Login"],"requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"username":{"description":"Your username\n","type":"string"},"password":{"description":"Your password\n","type":"string","format":"password"},"email":{"description":"Your email\n","type":"string"}},"required":["username","password","email"]}}},"required":true},"responses":{"200":{"description":"Successful registration","content":{"*/*":{"schema":{"items":{"properties":{"id":{"type":"string"},"token":{"type":"string"},"tokenExpires":{"type":"string"}}}}}}},"400":{"description":"Error in registration\n","content":{"*/*":{"schema":{"items":{"properties":{"error":{"type":"number"},"reason":{"type":"string"}}}}}}},"default":{"description":"Error in registration\n"}}}},"/api/admin/attachment-settings":{"get":{"operationId":"get_attachment_settings","summary":"Get the attachment storage / upload-block settings (GlobalAdmin)","description":"Only the global admin can call this. Returns the Admin Panel >\n Attachments settings document, including `limitSettings.attachmentsUploadBlocked`\n and `limitSettings.avatarsUploadBlocked` plus the size limits. Cloud-storage\n secret keys (S3 secretAccessKey, Azure accountKey/connectionString, GCS\n credentials) are masked and never returned; a boolean `<field>Set` marker\n shows whether a value exists.\n","tags":["AttachmentStorageSettings","Settings"],"security":[{"UserSecurity":[]}],"responses":{"200":{"description":"200 response","content":{"application/json":{"schema":{"type":"Object"}}}}}},"put":{"operationId":"update_attachment_settings","summary":"Update the attachment storage / upload-block settings (GlobalAdmin)","description":"Only the global admin can call this. The request body is a\n partial settings object (for example\n `{\"limitSettings\": {\"avatarsUploadBlocked\": true}}`). It is applied through\n the same update path as the `updateAttachmentStorageSettings` Meteor method,\n so validation and `$set` semantics are identical: cloud-storage secrets left\n blank are preserved. The masked, updated settings document is returned.\n","tags":["AttachmentStorageSettings","Settings"],"security":[{"UserSecurity":[]}],"responses":{"200":{"description":"200 response","content":{"application/json":{"schema":{"type":"Object"}}}}}}},"/api/admin/domains":{"get":{"operationId":"get_admin_domains","summary":"List email domains with their user counts (GlobalAdmin)","description":"Only the gLine truncated
|
||||
const __redoc_state = {"menu":{"activeItemIdx":-1},"spec":{"data":{"openapi":"3.0.0","info":{"title":"Wekan REST API","version":"v9.73","description":"The REST API allows you to control and extend Wekan with ease.\n\nIf you are an end-user and not a dev or a tester, [create an issue](https://github.com/wekan/wekan/issues/new) to request new APIs.\n\n> All API calls in the documentation are made using `curl`. However, you are free to use Java / Python / PHP / Golang / Ruby / Swift / Objective-C / Rust / Scala / C# or any other programming languages.\n\n# Production Security Concerns\nWhen calling a production Wekan server, ensure it is running via HTTPS and has a valid SSL Certificate. The login method requires you to post your username and password in plaintext, which is why we highly suggest only calling the REST login api over HTTPS. Also, few things to note:\n\n* Only call via HTTPS\n* Implement a timed authorization token expiration strategy\n* Ensure the calling user only has permissions for what they are calling and no more\n"},"paths":{"/users/login":{"post":{"operationId":"login","summary":"Login with REST API","tags":["Login"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["username","password"],"properties":{"username":{"description":"Your username\n","type":"string"},"password":{"description":"Your password\n","type":"string","format":"password"}}}},"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["username","password"],"properties":{"username":{"description":"Your username\n","type":"string"},"password":{"description":"Your password\n","type":"string","format":"password"}}}}},"description":"Login credentials","required":true},"responses":{"200":{"description":"Successful authentication","content":{"*/*":{"schema":{"type":"object","required":["id","token","tokenExpires"],"properties":{"id":{"type":"string","description":"User ID"},"token":{"type":"string","description":"Authentication token\n"},"tokenExpires":{"type":"string","format":"date-time","description":"Token expiration date\n"}}}}}},"400":{"description":"Error in authentication\n","content":{"*/*":{"schema":{"type":"object","properties":{"error":{"type":"string"},"reason":{"type":"string"}}}}}},"default":{"description":"Error in authentication\n"}}}},"/users/register":{"post":{"operationId":"register","summary":"Register with REST API","description":"Notes:\n - You will need to provide the token for any of the authenticated methods.\n","tags":["Login"],"requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"username":{"description":"Your username\n","type":"string"},"password":{"description":"Your password\n","type":"string","format":"password"},"email":{"description":"Your email\n","type":"string"}},"required":["username","password","email"]}}},"required":true},"responses":{"200":{"description":"Successful registration","content":{"*/*":{"schema":{"items":{"properties":{"id":{"type":"string"},"token":{"type":"string"},"tokenExpires":{"type":"string"}}}}}}},"400":{"description":"Error in registration\n","content":{"*/*":{"schema":{"items":{"properties":{"error":{"type":"number"},"reason":{"type":"string"}}}}}}},"default":{"description":"Error in registration\n"}}}},"/api/admin/attachment-settings":{"get":{"operationId":"get_attachment_settings","summary":"Get the attachment storage / upload-block settings (GlobalAdmin)","description":"Only the global admin can call this. Returns the Admin Panel >\n Attachments settings document, including `limitSettings.attachmentsUploadBlocked`\n and `limitSettings.avatarsUploadBlocked` plus the size limits. Cloud-storage\n secret keys (S3 secretAccessKey, Azure accountKey/connectionString, GCS\n credentials) are masked and never returned; a boolean `<field>Set` marker\n shows whether a value exists.\n","tags":["AttachmentStorageSettings","Settings"],"security":[{"UserSecurity":[]}],"responses":{"200":{"description":"200 response","content":{"application/json":{"schema":{"type":"Object"}}}}}},"put":{"operationId":"update_attachment_settings","summary":"Update the attachment storage / upload-block settings (GlobalAdmin)","description":"Only the global admin can call this. The request body is a\n partial settings object (for example\n `{\"limitSettings\": {\"avatarsUploadBlocked\": true}}`). It is applied through\n the same update path as the `updateAttachmentStorageSettings` Meteor method,\n so validation and `$set` semantics are identical: cloud-storage secrets left\n blank are preserved. The masked, updated settings document is returned.\n","tags":["AttachmentStorageSettings","Settings"],"security":[{"UserSecurity":[]}],"responses":{"200":{"description":"200 response","content":{"application/json":{"schema":{"type":"Object"}}}}}}},"/api/admin/domains":{"get":{"operationId":"get_admin_domains","summary":"List email domains with their user counts (GlobalAdmin)","description":"Only the gLine truncated
|
||||
|
||||
var container = document.getElementById('redoc');
|
||||
Redoc.hydrate(__redoc_state, container);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
swagger: '2.0'
|
||||
info:
|
||||
title: Wekan REST API
|
||||
version: v9.72
|
||||
version: v9.73
|
||||
description: |
|
||||
The REST API allows you to control and extend Wekan with ease.
|
||||
|
||||
|
||||
@@ -22,10 +22,10 @@ const pkgdef :Spk.PackageDefinition = (
|
||||
appTitle = (defaultText = "Wekan"),
|
||||
# The name of the app as it is displayed to the user.
|
||||
|
||||
appVersion = 972,
|
||||
appVersion = 973,
|
||||
# Increment this for every release.
|
||||
|
||||
appMarketingVersion = (defaultText = "9.72~2026-06-25"),
|
||||
appMarketingVersion = (defaultText = "9.73~2026-06-26"),
|
||||
# Human-readable presentation of the app version.
|
||||
|
||||
minUpgradableAppVersion = 0,
|
||||
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
name: wekan
|
||||
version: '9.72'
|
||||
version: '9.73'
|
||||
base: core26
|
||||
build-base: devel
|
||||
confinement: strict
|
||||
@@ -194,14 +194,14 @@ parts:
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
WEKAN_ZIP="wekan-9.72-${WEKAN_ARCH}.zip"
|
||||
WEKAN_ZIP="wekan-9.73-${WEKAN_ARCH}.zip"
|
||||
NODE_TAR="node-v24.17.0-linux-${NODE_ARCH}.tar.xz"
|
||||
echo "Cleaning environment first"
|
||||
rm -rf .build
|
||||
mkdir .build
|
||||
cd .build
|
||||
#wget https://github.com/wekan/wekan/releases/download/v9.72/wekan-9.72-amd64.zip
|
||||
wget "https://github.com/wekan/wekan/releases/download/v9.72/${WEKAN_ZIP}"
|
||||
#wget https://github.com/wekan/wekan/releases/download/v9.73/wekan-9.73-amd64.zip
|
||||
wget "https://github.com/wekan/wekan/releases/download/v9.73/${WEKAN_ZIP}"
|
||||
unzip "${WEKAN_ZIP}"
|
||||
rm "${WEKAN_ZIP}"
|
||||
# Fix: bcrypt 5.0.1 (Meteor accounts-password) ships node-addon-api@3
|
||||
|
||||
Reference in new issue
Block a user