mirror of
https://github.com/wekan/wekan.git
synced 2026-11-08 21:44:59 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9bc889e274 | ||
|
|
5df924f416 | ||
|
|
5ef94b7079 | ||
|
|
dfcaaf0ae7 | ||
|
|
34e7ff532f | ||
|
|
fbdfcead50 | ||
|
|
b8bbe4431b | ||
|
|
9e31666280 | ||
|
|
5846d9c9b0 | ||
|
|
7707a5b7fc | ||
|
|
18c495940e | ||
|
|
d3155d24c6 | ||
|
|
c0661506c4 | ||
|
|
fa2b34764f | ||
|
|
7a7909b49f | ||
|
|
17d3b3088f | ||
|
|
6a78a178e2 | ||
|
|
749de39e2a | ||
|
|
cd55c0e12e | ||
|
|
d04037739e | ||
|
|
f3a97b9938 | ||
|
|
104fbef37a | ||
|
|
98b3dc71af | ||
|
|
7b28e4d589 | ||
|
|
57291dbe50 | ||
|
|
9f9eefce27 | ||
|
|
af3361b35b | ||
|
|
24d65e1e72 | ||
|
|
29922fca6a | ||
|
|
81319fc48b | ||
|
|
28b7209407 | ||
|
|
0b59f87887 | ||
|
|
b22df9e93d | ||
|
|
1fa72fd34a | ||
|
|
a2f38e7494 | ||
|
|
30a1792c92 | ||
|
|
3d70f24a78 | ||
|
|
b3d14fb5e8 | ||
|
|
59956ca720 | ||
|
|
aaf7690b9a | ||
|
|
9f549dfcd2 | ||
|
|
f191392e3a | ||
|
|
56f26418ea | ||
|
|
118e0e5d5c | ||
|
|
264dcca42b | ||
|
|
73d69f4631 | ||
|
|
485b773338 | ||
|
|
8443e3511d | ||
|
|
b2a349aec5 | ||
|
|
faf8453c6d | ||
|
|
7484c8cce3 | ||
|
|
2b02e7712e | ||
|
|
8a3a7b19aa | ||
|
|
9fa6574c80 | ||
|
|
2bad17010c | ||
|
|
4168385607 | ||
|
|
c0aa1ef375 | ||
|
|
811b79b641 | ||
|
|
dab9755dd4 | ||
|
|
6863479c09 | ||
|
|
e05eebb8b0 | ||
|
|
28ef0e6e89 |
No files matched your search
@@ -109,11 +109,14 @@ jobs:
|
||||
- name: Build WeKan bundle
|
||||
run: |
|
||||
rm -rf .build node_modules .meteor/local
|
||||
meteor npm install --no-audit
|
||||
meteor npm install --no-audit @babel/parser
|
||||
meteor npm install --no-audit underscore
|
||||
meteor npm install
|
||||
meteor build .build --directory --platforms=web.browser
|
||||
|
||||
- name: Install dependencies in bundle
|
||||
run: |
|
||||
cd .build/bundle/programs/server
|
||||
npm install
|
||||
|
||||
- name: Create amd64 zip
|
||||
run: |
|
||||
cd .build
|
||||
@@ -155,17 +158,12 @@ jobs:
|
||||
run: |
|
||||
unzip wekan-${VERSION}-amd64.zip
|
||||
cd bundle/programs/server
|
||||
npm rebuild
|
||||
cd ../../..
|
||||
rm -rf node_modules
|
||||
npm install
|
||||
cd ../..
|
||||
|
||||
- name: Clean up and create arm64 zip
|
||||
run: |
|
||||
cd bundle
|
||||
find . -type d -name '*-garbage*' -exec rm -rf {} + 2>/dev/null || true
|
||||
find . -name '*phantom*' -exec rm -rf {} + 2>/dev/null || true
|
||||
find . -name '.*.swp' -delete 2>/dev/null || true
|
||||
find . -name '*.swp' -delete 2>/dev/null || true
|
||||
cd ..
|
||||
zip -r wekan-${VERSION}-arm64.zip bundle
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
@@ -202,21 +200,16 @@ jobs:
|
||||
- name: Rebuild native modules for s390x in container
|
||||
run: |
|
||||
unzip wekan-${VERSION}-amd64.zip
|
||||
rm -rf bundle/programs/server/node_modules
|
||||
# node:22.22.2-slim s390x — same Node.js version as Meteor 3.4 bundled
|
||||
docker run --rm --platform linux/s390x \
|
||||
-v "$(pwd)/bundle:/bundle" \
|
||||
-w /bundle/programs/server \
|
||||
node:22.22.2-slim \
|
||||
sh -c "apt-get update -qq && apt-get install -y -q build-essential python3 && npm rebuild"
|
||||
sh -c "apt-get update -qq && apt-get install -y -q build-essential python3 && npm install"
|
||||
|
||||
- name: Clean up and create s390x zip
|
||||
run: |
|
||||
cd bundle
|
||||
find . -type d -name '*-garbage*' -exec rm -rf {} + 2>/dev/null || true
|
||||
find . -name '*phantom*' -exec rm -rf {} + 2>/dev/null || true
|
||||
find . -name '.*.swp' -delete 2>/dev/null || true
|
||||
find . -name '*.swp' -delete 2>/dev/null || true
|
||||
cd ..
|
||||
zip -r wekan-${VERSION}-s390x.zip bundle
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
@@ -252,21 +245,16 @@ jobs:
|
||||
- name: Rebuild native modules for ppc64le in container
|
||||
run: |
|
||||
unzip wekan-${VERSION}-amd64.zip
|
||||
rm -rf bundle/programs/server/node_modules
|
||||
# node:22.22.2-slim ppc64le — same Node.js version as Meteor 3.4 bundled
|
||||
docker run --rm --platform linux/ppc64le \
|
||||
-v "$(pwd)/bundle:/bundle" \
|
||||
-w /bundle/programs/server \
|
||||
node:22.22.2-slim \
|
||||
sh -c "apt-get update -qq && apt-get install -y -q build-essential python3 && npm rebuild"
|
||||
sh -c "apt-get update -qq && apt-get install -y -q build-essential python3 && npm install"
|
||||
|
||||
- name: Clean up and create ppc64le zip
|
||||
run: |
|
||||
cd bundle
|
||||
find . -type d -name '*-garbage*' -exec rm -rf {} + 2>/dev/null || true
|
||||
find . -name '*phantom*' -exec rm -rf {} + 2>/dev/null || true
|
||||
find . -name '.*.swp' -delete 2>/dev/null || true
|
||||
find . -name '*.swp' -delete 2>/dev/null || true
|
||||
cd ..
|
||||
zip -r wekan-${VERSION}-ppc64le.zip bundle
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
@@ -303,21 +291,16 @@ jobs:
|
||||
- name: Rebuild native modules for armhf in container
|
||||
run: |
|
||||
unzip wekan-${VERSION}-amd64.zip
|
||||
rm -rf bundle/programs/server/node_modules
|
||||
# node:22.22.2-slim arm/v7 — same Node.js version as Meteor 3.4 bundled
|
||||
docker run --rm --platform linux/arm/v7 \
|
||||
-v "$(pwd)/bundle:/bundle" \
|
||||
-w /bundle/programs/server \
|
||||
node:22.22.2-slim \
|
||||
sh -c "apt-get update -qq && apt-get install -y -q build-essential python3 && npm rebuild"
|
||||
sh -c "apt-get update -qq && apt-get install -y -q build-essential python3 && npm install"
|
||||
|
||||
- name: Clean up and create armhf zip
|
||||
run: |
|
||||
cd bundle
|
||||
find . -type d -name '*-garbage*' -exec rm -rf {} + 2>/dev/null || true
|
||||
find . -name '*phantom*' -exec rm -rf {} + 2>/dev/null || true
|
||||
find . -name '.*.swp' -delete 2>/dev/null || true
|
||||
find . -name '*.swp' -delete 2>/dev/null || true
|
||||
cd ..
|
||||
zip -r wekan-${VERSION}-armhf.zip bundle
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
@@ -355,7 +338,8 @@ jobs:
|
||||
run: |
|
||||
7z x wekan-%VERSION%-amd64.zip
|
||||
cd bundle\programs\server
|
||||
npm rebuild
|
||||
rmdir /s /q node_modules
|
||||
npm install
|
||||
cd ..\..\..
|
||||
|
||||
- name: Create win64 zip
|
||||
|
||||
@@ -124,13 +124,18 @@ jobs:
|
||||
restore-keys: |
|
||||
v1-meteor_build_cache-
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: '22.22.2'
|
||||
|
||||
- name: Setup meteor
|
||||
uses: meteorengineer/setup-meteor@v3
|
||||
with:
|
||||
meteor-release: '2.2'
|
||||
meteor-release: '3.4'
|
||||
|
||||
- name: Install NPM Dependencies
|
||||
run: meteor npm ci --no-audit
|
||||
run: meteor npm install
|
||||
|
||||
- name: Run Tests
|
||||
run: sh ./test-wekan.sh -cv
|
||||
|
||||
+194
-2
@@ -24,10 +24,202 @@ Those are fixed at WeKan 8.07 where database directory is back to /var/snap/weka
|
||||
|
||||
WeKan 8.00-8.24 used Colorful Unicode Emoji Icons, versions before and after use mostly Font Awesome 4.7 icons.
|
||||
|
||||
Upgrading to Meteor 3 progress:
|
||||
WeKan 8.43 and newer uses Meteor 3.x, Node.js 22.x and MongoDB 7.x, huge thanks to harryadel:
|
||||
|
||||
- https://harryadel.com/dev-diary-24/
|
||||
- https://harryadel.com/dev-diary-25/
|
||||
- https://harryadel.com/dev-diary-26/
|
||||
|
||||
# v8.71 2026-04-06 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Fix: Added missing null check to notification](https://github.com/wekan/wekan/commit/5df924f416083a50795443687e1c28f402dc8132).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.70 2026-04-06 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Convert upsert calls to async in authentication.js](https://github.com/wekan/wekan/commit/dfcaaf0ae719e8d8b918ac632100293a6e401371).
|
||||
Thanks to snowsky and xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.69 2026-04-06 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Try to fix Snap to start MongoDB OpLog correctly](https://github.com/wekan/wekan/commit/fbdfcead50fb599d4fafecc2f5847c46c73adf72).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.68 2026-04-06 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Try to fix Snap to start MongoDB OpLog correctly](https://github.com/wekan/wekan/commit/9e316662800fc3b5e38b1176e70a50b18d73d2a6).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.67 2026-04-05 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Try to fix GitHub Actions release bundle builds](https://github.com/wekan/wekan/commit/7707a5b7fc21f981f26c512cd3fea6171a57bd46).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.65 2026-04-05 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Fix Docker Actions Test suite](https://github.com/wekan/wekan/commit/c0661506c42ac412ae9e8fc5392d160efbc446ea).
|
||||
Thanks to xet7.
|
||||
- [Try to fix GitHub Actions release bundle builds](https://github.com/wekan/wekan/commit/d3155d24c64fe1104afe454b756d2a6324fab5c2).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.64 2026-04-05 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Try to fix GitHub Actions release bundle builds](https://github.com/wekan/wekan/commit/7a7909b49feaaa938b5dbfc2083b0c719187859d).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.63 2026-04-05 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Try to fix GitHub Actions release bundle builds](https://github.com/wekan/wekan/commit/6a78a178e2fcff9ff280ba44c123403e2792bb7b).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.62 2026-04-05 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Try to fix GitHub Actions release bundle builds](https://github.com/wekan/wekan/commit/cd55c0e12ed80ddcb07895f2d787be95c440f991).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.61 2026-04-05 WeKan ® release
|
||||
|
||||
This release adds the following updates:
|
||||
|
||||
- [Updated Docker build script to check directories and repos exist](https://github.com/wekan/wekan/commit/81319fc48bbd2a91553090428455bc11aff24fbc).
|
||||
Thanks to xet7.
|
||||
- [Updated release scripts: Delete all GitHub Actions Caches, so that old stuff does not break builds](https://github.com/wekan/wekan/commit/f3a97b993842425e4f13bb78e5939a069d64887e).
|
||||
Thanks to xet7.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Fix: Server crash during comment deletion](https://github.com/wekan/wekan/pull/6246).
|
||||
Thanks to KhaoulaMaleh.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.60 2026-04-05 WeKan ® release
|
||||
|
||||
This release adds the following updates:
|
||||
|
||||
- [Updated Docker build script](https://github.com/wekan/wekan/commit/0b59f87887c215dc34093409ccd12da9acd3ef02).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.59 2026-04-05 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Fix docker-compose.yml to use OpLog](https://github.com/wekan/wekan/commit/30a1792c92de9d485c0b9ed3970a1187ca974576).
|
||||
Thanks to xet7.
|
||||
- [Fix Snap to use OpLog](https://github.com/wekan/wekan/commit/1fa72fd34ab4547e97e7e0c201bc3d50d478ef5e).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.58 2026-04-05 WeKan ® release
|
||||
|
||||
This release adds the following updates:
|
||||
|
||||
- [Updated build docs](https://github.com/wekan/wekan/commit/b3d14fb5e87545635006958686f0340028711820).
|
||||
Thanks to xet7.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Try to fix .zip Bundle, Docker and Snap](https://github.com/wekan/wekan/commit/59956ca720d2103baaa9ecf2befff2ec76430feb).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.57 2026-04-05 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Try to fix Snap](https://github.com/wekan/wekan/commit/9f549dfcd2efa241a2ad3bdf5b0d2d942064d4e3).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.56 2026-04-05 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Try to fix Snap](https://github.com/wekan/wekan/commit/56f26418ea9d1321fc5109c4b39104ff98d65429).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.55 2026-04-05 WeKan ® release
|
||||
|
||||
This release adds the following updates:
|
||||
|
||||
- Docs: IMPORTANT: Do NOT `npm audit fix --force`, it breaks builds.
|
||||
[Part 1](https://github.com/wekan/wekan/commit/2bad17010cd445c004a228b732b17c68e18eb316),
|
||||
[Part 2](https://github.com/wekan/wekan/commit/9fa6574c80589218569dc3c49782a1a8036aa542).
|
||||
Thanks to xet7.
|
||||
- [Updated dependencies](https://github.com/wekan/wekan/commit/73d69f4631216dfe504d9f05230adadc2850c4f3).
|
||||
Thanks to developers of dependencies.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Fix Cards Reports is not working](https://github.com/wekan/wekan/commit/2b02e7712ee6a8ae8af5d416ce2d288a25386fdf).
|
||||
Thanks to titver968 and xet7.
|
||||
- [Fix Search All Boards](https://github.com/wekan/wekan/commit/faf8453c6d10613edf32a734e549961860fcdd32).
|
||||
Thanks to YosserDerbali and xet7.
|
||||
- [Try to fix Snap](https://github.com/wekan/wekan/commit/8443e3511d61d8c1bb419ed5bca2e28483c5d133).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.54 2026-04-04 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Revert v8.53 Refactor upsert calls to use async method](https://github.com/wekan/wekan/commit/811b79b641c765461f3d696ed00b5459a4747867).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.53 2026-04-04 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Refactor upsert calls to use async method](https://github.com/wekan/wekan/pull/6243).
|
||||
Thanks to snowsky.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.52 2026-04-03 WeKan ® release
|
||||
|
||||
@@ -62,7 +254,7 @@ This release adds the following updates:
|
||||
Thanks to xet7.
|
||||
- [Updated dependencies](https://github.com/wekan/wekan/commit/bf02c9a453e27edba1c08830eb4783b9dfc7bbc2).
|
||||
Thanks to developers of dependencies.
|
||||
NOTE: Do not `npm audit --force`, it downgrades @meteorjs/rspack and breaks builds.
|
||||
NOTE: Do not `npm audit fix --force`, it downgrades @meteorjs/rspack and breaks builds.
|
||||
`npm audit` shows false info, it does not recognize that elliptic is
|
||||
already updated to 6.6.1 with override at package.json like you can see with
|
||||
`npm list elliptic`.
|
||||
|
||||
+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=8.52
|
||||
ARG VERSION=8.71
|
||||
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: "v8.52.0"
|
||||
appVersion: "v8.71.0"
|
||||
files:
|
||||
userUploads:
|
||||
- README.md
|
||||
|
||||
@@ -1,7 +1,52 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
Template.resultCard.helpers({
|
||||
userId() {
|
||||
return Meteor.userId();
|
||||
},
|
||||
getBoard() {
|
||||
const card = Template.currentData();
|
||||
try {
|
||||
if (card && card.boardId) {
|
||||
const board = ReactiveCache.getBoard(card.boardId);
|
||||
return board || null;
|
||||
}
|
||||
} catch (err) {
|
||||
// Silently handle errors
|
||||
}
|
||||
return null;
|
||||
},
|
||||
getSwimlane() {
|
||||
const card = Template.currentData();
|
||||
try {
|
||||
if (card && card.swimlaneId) {
|
||||
const swimlane = ReactiveCache.getSwimlane(card.swimlaneId);
|
||||
return swimlane || null;
|
||||
}
|
||||
} catch (err) {
|
||||
// Silently handle errors
|
||||
}
|
||||
return null;
|
||||
},
|
||||
getList() {
|
||||
const card = Template.currentData();
|
||||
try {
|
||||
if (card && card.listId) {
|
||||
const list = ReactiveCache.getList(card.listId);
|
||||
return list || null;
|
||||
}
|
||||
} catch (err) {
|
||||
// Silently handle errors
|
||||
}
|
||||
return null;
|
||||
},
|
||||
originRelativeUrl() {
|
||||
const card = Template.currentData();
|
||||
if (card && card.boardId && card._id) {
|
||||
return `/board/${card.boardId}?cardId=${card._id}`;
|
||||
}
|
||||
return '#';
|
||||
},
|
||||
});
|
||||
|
||||
Template.resultCard.events({
|
||||
|
||||
@@ -84,6 +84,21 @@
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
}
|
||||
.js-new-search {
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
.board-color-belize.js-new-search {
|
||||
background-color: #216694 !important;
|
||||
color: #fff !important;
|
||||
border: none !important;
|
||||
}
|
||||
.board-color-belize.js-new-search:hover {
|
||||
background-color: #1a4d6a !important;
|
||||
}
|
||||
.board-color-belize.js-new-search:active {
|
||||
background-color: #0d334d !important;
|
||||
}
|
||||
.global-search-operator {
|
||||
font-family: Courier;
|
||||
}
|
||||
|
||||
@@ -11,68 +11,47 @@ template(name="globalSearchModalTitle")
|
||||
| {{_ 'globalSearch-title'}}
|
||||
|
||||
template(name="resultsPaged")
|
||||
if resultsHeading.get
|
||||
h1
|
||||
= resultsHeading.get
|
||||
a(title="{{_ 'link-to-search' }}" href="{{ getSearchHref }}")
|
||||
| 🔗
|
||||
each card in results.get
|
||||
if resultsHeading
|
||||
h1= resultsHeading
|
||||
each card in results
|
||||
+resultCard(card)
|
||||
table.global-search-footer
|
||||
tr
|
||||
td.global-search-previous-page
|
||||
if hasPreviousPage.get
|
||||
if hasPreviousPage
|
||||
button.js-previous-page
|
||||
| {{_ 'previous-page' }}
|
||||
td.global-search-next-page(align="right")
|
||||
if hasNextPage.get
|
||||
if hasNextPage
|
||||
button.js-next-page
|
||||
| {{_ 'next-page' }}
|
||||
|
||||
template(name="globalSearch")
|
||||
if currentUser
|
||||
.wrapper
|
||||
form.global-search-page.js-search-query-form
|
||||
.wrapper(class=boardColorClass)
|
||||
form.global-search-page.js-search-query-form(onsubmit="return false;")
|
||||
input.global-search-query-input(
|
||||
style="{# if hasResults.get #}display: inline-block;{#/if#}"
|
||||
style="display: inline-block;"
|
||||
id="global-search-input"
|
||||
type="text"
|
||||
name="searchQuery"
|
||||
placeholder="{{_ 'search-example'}}"
|
||||
value="{{ query.get }}"
|
||||
value="{{ queryValue }}"
|
||||
autofocus dir="auto"
|
||||
)
|
||||
a.js-new-search
|
||||
button.js-new-search.board-color-belize(type="button" style="background: #216694 !important; background-color: #216694 !important; color: #fff !important; border: none !important;")
|
||||
| 🧹
|
||||
if debug.get.show
|
||||
h1 Debug
|
||||
if debug.get.showSelector
|
||||
h2 Selector
|
||||
button.js-copy-debug-selector
|
||||
= 'Copy'
|
||||
pre(
|
||||
id="debug-selector"
|
||||
)
|
||||
= sessionData.selector
|
||||
if debug.get.showProjection
|
||||
h2 Projection
|
||||
button.js-copy-debug-projection
|
||||
= 'Copy'
|
||||
pre(
|
||||
id="debug-projection"
|
||||
)
|
||||
= sessionData.projection
|
||||
if searching.get
|
||||
if searching
|
||||
+spinner
|
||||
else if hasResults.get
|
||||
else if hasResults
|
||||
.global-search-results-list-wrapper
|
||||
if hasQueryErrors.get
|
||||
if hasQueryErrors
|
||||
ul
|
||||
each msg in errorMessages
|
||||
li.global-search-error-messages
|
||||
= msg
|
||||
+resultsPaged(this)
|
||||
else if serverError.get
|
||||
+resultsPaged getSearchData
|
||||
else if serverError
|
||||
.global-search-page
|
||||
.global-search-help
|
||||
h1 {{_ 'server-error' }}
|
||||
@@ -83,22 +62,22 @@ template(name="globalSearch")
|
||||
.global-search-help
|
||||
h2 {{_ 'boards' }}
|
||||
.lists-wrapper
|
||||
each title in myBoardNames.get
|
||||
each title in myBoardNames
|
||||
span.card-label.list-title.js-board-title
|
||||
= title
|
||||
h2 {{_ 'lists' }}
|
||||
.lists-wrapper
|
||||
each title in myLists.get
|
||||
each title in myLists
|
||||
span.card-label.list-title.js-list-title
|
||||
= title
|
||||
h2 {{_ 'label-colors' }}
|
||||
.palette-colors: each label in labelColors
|
||||
span.card-label.palette-color.js-label-color(class="card-label-{{label.color}}")
|
||||
= label.name
|
||||
if myLabelNames.get.length
|
||||
if myLabelNames
|
||||
h2 {{_ 'label-names' }}
|
||||
.lists-wrapper
|
||||
each name in myLabelNames.get
|
||||
each name in myLabelNames
|
||||
span.card-label.list-title.js-label-name
|
||||
= name
|
||||
.global-search-instructions
|
||||
|
||||
@@ -2,6 +2,7 @@ import { TAPi18n } from '/imports/i18n';
|
||||
import { CardSearchPaged } from '../../lib/cardSearch';
|
||||
import { LABEL_COLORS } from '/models/metadata/colors';
|
||||
import { Query, QueryErrors } from '../../../config/query-classes';
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
// const subManager = new SubsManager();
|
||||
|
||||
@@ -98,36 +99,45 @@ Template.globalSearch.helpers({
|
||||
return Meteor.userId();
|
||||
},
|
||||
|
||||
// Return ReactiveVars so jade can use .get pattern
|
||||
// Return ReactiveVar values so Blaze can use them
|
||||
searching() {
|
||||
return Template.instance().search.searching;
|
||||
const val = Template.instance().search.searching.get();
|
||||
return val;
|
||||
},
|
||||
hasResults() {
|
||||
return Template.instance().search.hasResults;
|
||||
const val = Template.instance().search.hasResults.get();
|
||||
return val;
|
||||
},
|
||||
hasQueryErrors() {
|
||||
return Template.instance().search.hasQueryErrors;
|
||||
const val = Template.instance().search.hasQueryErrors.get();
|
||||
return val;
|
||||
},
|
||||
serverError() {
|
||||
return Template.instance().search.serverError;
|
||||
const val = Template.instance().search.serverError.get();
|
||||
return val;
|
||||
},
|
||||
query() {
|
||||
return Template.instance().search.query;
|
||||
},
|
||||
debug() {
|
||||
return Template.instance().search.debug;
|
||||
const val = Template.instance().search.debug.get();
|
||||
return val;
|
||||
},
|
||||
resultsHeading() {
|
||||
return Template.instance().search.resultsHeading;
|
||||
const rv = Template.instance().search.resultsHeading;
|
||||
return rv ? rv.get() : '';
|
||||
},
|
||||
results() {
|
||||
return Template.instance().search.results;
|
||||
const rv = Template.instance().search.results;
|
||||
return rv ? rv.get() : [];
|
||||
},
|
||||
hasNextPage() {
|
||||
return Template.instance().search.hasNextPage;
|
||||
const rv = Template.instance().search.hasNextPage;
|
||||
return rv ? rv.get() : false;
|
||||
},
|
||||
hasPreviousPage() {
|
||||
return Template.instance().search.hasPreviousPage;
|
||||
const rv = Template.instance().search.hasPreviousPage;
|
||||
return rv ? rv.get() : false;
|
||||
},
|
||||
sessionData() {
|
||||
return Template.instance().search.sessionData;
|
||||
@@ -137,124 +147,170 @@ Template.globalSearch.helpers({
|
||||
},
|
||||
|
||||
myLists() {
|
||||
return Template.instance().myLists;
|
||||
const rv = Template.instance().myLists;
|
||||
return rv ? rv.get() : [];
|
||||
},
|
||||
myLabelNames() {
|
||||
return Template.instance().myLabelNames;
|
||||
const rv = Template.instance().myLabelNames;
|
||||
return rv ? rv.get() : [];
|
||||
},
|
||||
myBoardNames() {
|
||||
return Template.instance().myBoardNames;
|
||||
const rv = Template.instance().myBoardNames;
|
||||
return rv ? rv.get() : [];
|
||||
},
|
||||
|
||||
errorMessages() {
|
||||
return errorMessages(Template.instance());
|
||||
},
|
||||
|
||||
searchInstructions() {
|
||||
const tags = {
|
||||
operator_board: TAPi18n.__('operator-board'),
|
||||
operator_list: TAPi18n.__('operator-list'),
|
||||
operator_swimlane: TAPi18n.__('operator-swimlane'),
|
||||
operator_comment: TAPi18n.__('operator-comment'),
|
||||
operator_label: TAPi18n.__('operator-label'),
|
||||
operator_label_abbrev: TAPi18n.__('operator-label-abbrev'),
|
||||
operator_user: TAPi18n.__('operator-user'),
|
||||
operator_user_abbrev: TAPi18n.__('operator-user-abbrev'),
|
||||
operator_member: TAPi18n.__('operator-member'),
|
||||
operator_member_abbrev: TAPi18n.__('operator-member-abbrev'),
|
||||
operator_assignee: TAPi18n.__('operator-assignee'),
|
||||
operator_assignee_abbrev: TAPi18n.__('operator-assignee-abbrev'),
|
||||
operator_creator: TAPi18n.__('operator-creator'),
|
||||
operator_due: TAPi18n.__('operator-due'),
|
||||
operator_created: TAPi18n.__('operator-created'),
|
||||
operator_modified: TAPi18n.__('operator-modified'),
|
||||
operator_status: TAPi18n.__('operator-status'),
|
||||
operator_has: TAPi18n.__('operator-has'),
|
||||
operator_sort: TAPi18n.__('operator-sort'),
|
||||
operator_limit: TAPi18n.__('operator-limit'),
|
||||
operator_debug: TAPi18n.__('operator-debug'),
|
||||
operator_org: TAPi18n.__('operator-org'),
|
||||
operator_team: TAPi18n.__('operator-team'),
|
||||
predicate_overdue: TAPi18n.__('predicate-overdue'),
|
||||
predicate_archived: TAPi18n.__('predicate-archived'),
|
||||
predicate_all: TAPi18n.__('predicate-all'),
|
||||
predicate_ended: TAPi18n.__('predicate-ended'),
|
||||
predicate_week: TAPi18n.__('predicate-week'),
|
||||
predicate_month: TAPi18n.__('predicate-month'),
|
||||
predicate_quarter: TAPi18n.__('predicate-quarter'),
|
||||
predicate_year: TAPi18n.__('predicate-year'),
|
||||
predicate_attachment: TAPi18n.__('predicate-attachment'),
|
||||
predicate_description: TAPi18n.__('predicate-description'),
|
||||
predicate_checklist: TAPi18n.__('predicate-checklist'),
|
||||
predicate_public: TAPi18n.__('predicate-public'),
|
||||
predicate_private: TAPi18n.__('predicate-private'),
|
||||
predicate_due: TAPi18n.__('predicate-due'),
|
||||
predicate_created: TAPi18n.__('predicate-created'),
|
||||
predicate_modified: TAPi18n.__('predicate-modified'),
|
||||
predicate_start: TAPi18n.__('predicate-start'),
|
||||
predicate_end: TAPi18n.__('predicate-end'),
|
||||
predicate_assignee: TAPi18n.__('predicate-assignee'),
|
||||
predicate_member: TAPi18n.__('predicate-member'),
|
||||
predicate_selector: TAPi18n.__('predicate-selector'),
|
||||
predicate_projection: TAPi18n.__('predicate-projection'),
|
||||
};
|
||||
getSearchData() {
|
||||
return Template.instance().search;
|
||||
},
|
||||
|
||||
let text = '';
|
||||
[
|
||||
['# ', 'globalSearch-instructions-heading'],
|
||||
['\n', 'globalSearch-instructions-description'],
|
||||
['\n\n', 'globalSearch-instructions-operators'],
|
||||
['\n- ', 'globalSearch-instructions-operator-board'],
|
||||
['\n- ', 'globalSearch-instructions-operator-list'],
|
||||
['\n- ', 'globalSearch-instructions-operator-swimlane'],
|
||||
['\n- ', 'globalSearch-instructions-operator-comment'],
|
||||
['\n- ', 'globalSearch-instructions-operator-label'],
|
||||
['\n- ', 'globalSearch-instructions-operator-hash'],
|
||||
['\n- ', 'globalSearch-instructions-operator-user'],
|
||||
['\n- ', 'globalSearch-instructions-operator-at'],
|
||||
['\n- ', 'globalSearch-instructions-operator-member'],
|
||||
['\n- ', 'globalSearch-instructions-operator-assignee'],
|
||||
['\n- ', 'globalSearch-instructions-operator-creator'],
|
||||
['\n- ', 'globalSearch-instructions-operator-org'],
|
||||
['\n- ', 'globalSearch-instructions-operator-team'],
|
||||
['\n- ', 'globalSearch-instructions-operator-due'],
|
||||
['\n- ', 'globalSearch-instructions-operator-created'],
|
||||
['\n- ', 'globalSearch-instructions-operator-modified'],
|
||||
['\n- ', 'globalSearch-instructions-operator-status'],
|
||||
['\n - ', 'globalSearch-instructions-status-archived'],
|
||||
['\n - ', 'globalSearch-instructions-status-public'],
|
||||
['\n - ', 'globalSearch-instructions-status-private'],
|
||||
['\n - ', 'globalSearch-instructions-status-all'],
|
||||
['\n - ', 'globalSearch-instructions-status-ended'],
|
||||
['\n- ', 'globalSearch-instructions-operator-has'],
|
||||
['\n- ', 'globalSearch-instructions-operator-sort'],
|
||||
['\n- ', 'globalSearch-instructions-operator-limit'],
|
||||
['\n## ', 'heading-notes'],
|
||||
['\n- ', 'globalSearch-instructions-notes-1'],
|
||||
['\n- ', 'globalSearch-instructions-notes-2'],
|
||||
['\n- ', 'globalSearch-instructions-notes-3'],
|
||||
['\n- ', 'globalSearch-instructions-notes-3-2'],
|
||||
['\n- ', 'globalSearch-instructions-notes-4'],
|
||||
['\n- ', 'globalSearch-instructions-notes-5'],
|
||||
].forEach(([prefix, instruction]) => {
|
||||
text += `${prefix}${TAPi18n.__(instruction, tags)}`
|
||||
// Replace *<text>* with `<text>` so markdown shows correctly
|
||||
.replace(/\*\</, '`<')
|
||||
.replace(/\>\*/, '\>\`')
|
||||
});
|
||||
return text;
|
||||
boardColorClass() {
|
||||
const boardId = Session.get('currentBoard');
|
||||
const board = boardId ? ReactiveCache.getBoard(boardId) : null;
|
||||
return board ? board.colorClass() : 'board-color-belize';
|
||||
},
|
||||
|
||||
searchInstructions() {
|
||||
try {
|
||||
const tags = {
|
||||
operator_board: TAPi18n.__('operator-board'),
|
||||
operator_list: TAPi18n.__('operator-list'),
|
||||
operator_swimlane: TAPi18n.__('operator-swimlane'),
|
||||
operator_comment: TAPi18n.__('operator-comment'),
|
||||
operator_label: TAPi18n.__('operator-label'),
|
||||
operator_label_abbrev: TAPi18n.__('operator-label-abbrev'),
|
||||
operator_user: TAPi18n.__('operator-user'),
|
||||
operator_user_abbrev: TAPi18n.__('operator-user-abbrev'),
|
||||
operator_member: TAPi18n.__('operator-member'),
|
||||
operator_member_abbrev: TAPi18n.__('operator-member-abbrev'),
|
||||
operator_assignee: TAPi18n.__('operator-assignee'),
|
||||
operator_assignee_abbrev: TAPi18n.__('operator-assignee-abbrev'),
|
||||
operator_creator: TAPi18n.__('operator-creator'),
|
||||
operator_due: TAPi18n.__('operator-due'),
|
||||
operator_created: TAPi18n.__('operator-created'),
|
||||
operator_modified: TAPi18n.__('operator-modified'),
|
||||
operator_status: TAPi18n.__('operator-status'),
|
||||
operator_has: TAPi18n.__('operator-has'),
|
||||
operator_sort: TAPi18n.__('operator-sort'),
|
||||
operator_limit: TAPi18n.__('operator-limit'),
|
||||
operator_debug: TAPi18n.__('operator-debug'),
|
||||
operator_org: TAPi18n.__('operator-org'),
|
||||
operator_team: TAPi18n.__('operator-team'),
|
||||
predicate_overdue: TAPi18n.__('predicate-overdue'),
|
||||
predicate_archived: TAPi18n.__('predicate-archived'),
|
||||
predicate_all: TAPi18n.__('predicate-all'),
|
||||
predicate_ended: TAPi18n.__('predicate-ended'),
|
||||
predicate_week: TAPi18n.__('predicate-week'),
|
||||
predicate_month: TAPi18n.__('predicate-month'),
|
||||
predicate_quarter: TAPi18n.__('predicate-quarter'),
|
||||
predicate_year: TAPi18n.__('predicate-year'),
|
||||
predicate_attachment: TAPi18n.__('predicate-attachment'),
|
||||
predicate_description: TAPi18n.__('predicate-description'),
|
||||
predicate_checklist: TAPi18n.__('predicate-checklist'),
|
||||
predicate_public: TAPi18n.__('predicate-public'),
|
||||
predicate_private: TAPi18n.__('predicate-private'),
|
||||
predicate_due: TAPi18n.__('predicate-due'),
|
||||
predicate_created: TAPi18n.__('predicate-created'),
|
||||
predicate_modified: TAPi18n.__('predicate-modified'),
|
||||
predicate_start: TAPi18n.__('predicate-start'),
|
||||
predicate_end: TAPi18n.__('predicate-end'),
|
||||
predicate_assignee: TAPi18n.__('predicate-assignee'),
|
||||
predicate_member: TAPi18n.__('predicate-member'),
|
||||
predicate_selector: TAPi18n.__('predicate-selector'),
|
||||
predicate_projection: TAPi18n.__('predicate-projection'),
|
||||
};
|
||||
|
||||
let text = '';
|
||||
[
|
||||
['# ', 'globalSearch-instructions-heading'],
|
||||
['\n', 'globalSearch-instructions-description'],
|
||||
['\n\n', 'globalSearch-instructions-operators'],
|
||||
['\n- ', 'globalSearch-instructions-operator-board'],
|
||||
['\n- ', 'globalSearch-instructions-operator-list'],
|
||||
['\n- ', 'globalSearch-instructions-operator-swimlane'],
|
||||
['\n- ', 'globalSearch-instructions-operator-comment'],
|
||||
['\n- ', 'globalSearch-instructions-operator-label'],
|
||||
['\n- ', 'globalSearch-instructions-operator-hash'],
|
||||
['\n- ', 'globalSearch-instructions-operator-user'],
|
||||
['\n- ', 'globalSearch-instructions-operator-at'],
|
||||
['\n- ', 'globalSearch-instructions-operator-member'],
|
||||
['\n- ', 'globalSearch-instructions-operator-assignee'],
|
||||
['\n- ', 'globalSearch-instructions-operator-creator'],
|
||||
['\n- ', 'globalSearch-instructions-operator-org'],
|
||||
['\n- ', 'globalSearch-instructions-operator-team'],
|
||||
['\n- ', 'globalSearch-instructions-operator-due'],
|
||||
['\n- ', 'globalSearch-instructions-operator-created'],
|
||||
['\n- ', 'globalSearch-instructions-operator-modified'],
|
||||
['\n- ', 'globalSearch-instructions-operator-status'],
|
||||
['\n - ', 'globalSearch-instructions-status-archived'],
|
||||
['\n - ', 'globalSearch-instructions-status-public'],
|
||||
['\n - ', 'globalSearch-instructions-status-private'],
|
||||
['\n - ', 'globalSearch-instructions-status-all'],
|
||||
['\n - ', 'globalSearch-instructions-status-ended'],
|
||||
['\n- ', 'globalSearch-instructions-operator-has'],
|
||||
['\n- ', 'globalSearch-instructions-operator-sort'],
|
||||
['\n- ', 'globalSearch-instructions-operator-limit'],
|
||||
['\n## ', 'heading-notes'],
|
||||
['\n- ', 'globalSearch-instructions-notes-1'],
|
||||
['\n- ', 'globalSearch-instructions-notes-2'],
|
||||
['\n- ', 'globalSearch-instructions-notes-3'],
|
||||
['\n- ', 'globalSearch-instructions-notes-3-2'],
|
||||
['\n- ', 'globalSearch-instructions-notes-4'],
|
||||
['\n- ', 'globalSearch-instructions-notes-5'],
|
||||
].forEach(([prefix, instruction]) => {
|
||||
text += `${prefix}${TAPi18n.__(instruction, tags)}`
|
||||
// Replace *<text>* with `<text>` so markdown shows correctly
|
||||
.replace(/\*\</, '`<')
|
||||
.replace(/\>\*/, '\>\`');
|
||||
});
|
||||
return text;
|
||||
} catch (e) {
|
||||
console.error('Error building searchInstructions:', e);
|
||||
return '';
|
||||
}
|
||||
},
|
||||
|
||||
labelColors() {
|
||||
return LABEL_COLORS.map(
|
||||
color => {
|
||||
return { color, name: TAPi18n.__(`color-${color}`) };
|
||||
},
|
||||
);
|
||||
try {
|
||||
if (!LABEL_COLORS) return [];
|
||||
return LABEL_COLORS.map(
|
||||
color => {
|
||||
return { color, name: TAPi18n.__(`color-${color}`) };
|
||||
},
|
||||
);
|
||||
} catch (e) {
|
||||
console.error('Error building labelColors:', e);
|
||||
return [];
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
Template.globalSearch.events({
|
||||
'click input.global-search-query-input'(evt) {
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
},
|
||||
'focus input.global-search-query-input'(evt) {
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
},
|
||||
'keyup input.global-search-query-input'(evt, tpl) {
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
// Store the query value
|
||||
tpl.search.query.set(evt.target.value);
|
||||
},
|
||||
'keydown input.global-search-query-input'(evt, tpl) {
|
||||
// Allow normal key behavior but capture Enter key
|
||||
if (evt.key === 'Enter') {
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
searchAllBoards(tpl, evt.target.value);
|
||||
}
|
||||
},
|
||||
'submit .js-search-query-form'(evt, tpl) {
|
||||
evt.preventDefault();
|
||||
searchAllBoards(tpl, evt.target.searchQuery.value);
|
||||
@@ -269,30 +325,6 @@ Template.globalSearch.events({
|
||||
);
|
||||
document.getElementById('global-search-input').focus();
|
||||
},
|
||||
'click .js-copy-debug-selector'(evt) {
|
||||
/* Get the text field */
|
||||
const selector = document.getElementById("debug-selector");
|
||||
|
||||
try {
|
||||
navigator.clipboard.writeText(selector.textContent);
|
||||
alert("Selector copied to clipboard");
|
||||
} catch(err) {
|
||||
alert("Error copying text: " + err);
|
||||
}
|
||||
|
||||
},
|
||||
'click .js-copy-debug-projection'(evt) {
|
||||
/* Get the text field */
|
||||
const projection = document.getElementById("debug-projection");
|
||||
|
||||
try {
|
||||
navigator.clipboard.writeText(projection.textContent);
|
||||
alert("Projection copied to clipboard");
|
||||
} catch(err) {
|
||||
alert("Error copying text: " + err);
|
||||
}
|
||||
|
||||
},
|
||||
'click .js-board-title'(evt, tpl) {
|
||||
evt.preventDefault();
|
||||
const input = document.getElementById('global-search-input');
|
||||
@@ -340,47 +372,46 @@ Template.globalSearch.events({
|
||||
},
|
||||
});
|
||||
|
||||
// resultsPaged template helpers - this template is used by globalSearch, brokenCards, and brokenCardsReport.
|
||||
// It receives the parent's data context (which includes reactive vars) via +resultsPaged(this).
|
||||
// The jade accesses resultsHeading.get, results.get, getSearchHref, hasPreviousPage.get, hasNextPage.get
|
||||
// directly on the data context, so we don't need helpers for those when the parent passes
|
||||
// the right data context. However, we need to ensure the helpers exist for the template.
|
||||
// resultsPaged template helpers - receives search data context from parent template.
|
||||
Template.resultsPaged.helpers({
|
||||
resultsHeading() {
|
||||
const data = Template.currentData();
|
||||
if (data && data.resultsHeading) return data.resultsHeading;
|
||||
// fallback: check parent template
|
||||
const parentTpl = Template.instance().view.parentView.templateInstance && Template.instance().view.parentView.templateInstance();
|
||||
if (parentTpl && parentTpl.search) return parentTpl.search.resultsHeading;
|
||||
return new ReactiveVar('');
|
||||
if (data && data.resultsHeading) {
|
||||
const rv = data.resultsHeading;
|
||||
return rv && typeof rv.get === 'function' ? rv.get() : rv;
|
||||
}
|
||||
return '';
|
||||
},
|
||||
results() {
|
||||
const data = Template.currentData();
|
||||
if (data && data.results) return data.results;
|
||||
const parentTpl = Template.instance().view.parentView.templateInstance && Template.instance().view.parentView.templateInstance();
|
||||
if (parentTpl && parentTpl.search) return parentTpl.search.results;
|
||||
return new ReactiveVar([]);
|
||||
if (data && data.results) {
|
||||
const rv = data.results;
|
||||
return rv && typeof rv.get === 'function' ? rv.get() : rv;
|
||||
}
|
||||
return [];
|
||||
},
|
||||
getSearchHref() {
|
||||
const data = Template.currentData();
|
||||
if (data && data.getSearchHref) return data.getSearchHref();
|
||||
const parentTpl = Template.instance().view.parentView.templateInstance && Template.instance().view.parentView.templateInstance();
|
||||
if (parentTpl && parentTpl.search) return parentTpl.search.getSearchHref();
|
||||
if (data && typeof data.getSearchHref === 'function') {
|
||||
return data.getSearchHref();
|
||||
}
|
||||
return '';
|
||||
},
|
||||
hasPreviousPage() {
|
||||
const data = Template.currentData();
|
||||
if (data && data.hasPreviousPage) return data.hasPreviousPage;
|
||||
const parentTpl = Template.instance().view.parentView.templateInstance && Template.instance().view.parentView.templateInstance();
|
||||
if (parentTpl && parentTpl.search) return parentTpl.search.hasPreviousPage;
|
||||
return new ReactiveVar(false);
|
||||
if (data && data.hasPreviousPage) {
|
||||
const rv = data.hasPreviousPage;
|
||||
return rv && typeof rv.get === 'function' ? rv.get() : rv;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
hasNextPage() {
|
||||
const data = Template.currentData();
|
||||
if (data && data.hasNextPage) return data.hasNextPage;
|
||||
const parentTpl = Template.instance().view.parentView.templateInstance && Template.instance().view.parentView.templateInstance();
|
||||
if (parentTpl && parentTpl.search) return parentTpl.search.hasNextPage;
|
||||
return new ReactiveVar(false);
|
||||
if (data && data.hasNextPage) {
|
||||
const rv = data.hasNextPage;
|
||||
return rv && typeof rv.get === 'function' ? rv.get() : rv;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
+40
-98
@@ -32,10 +32,7 @@ export class CardSearchPaged {
|
||||
const that = this;
|
||||
this.subscriptionCallbacks = {
|
||||
onReady() {
|
||||
if (process.env.DEBUG === 'true') {
|
||||
console.log('Subscription ready, getting results...');
|
||||
console.log('Subscription ready - sessionId:', that.sessionId);
|
||||
}
|
||||
const cardsInCollection = Cards.find().count();
|
||||
|
||||
// Wait for session data to be available (with timeout)
|
||||
let waitCount = 0;
|
||||
@@ -44,21 +41,12 @@ export class CardSearchPaged {
|
||||
const waitForSessionData = () => {
|
||||
waitCount++;
|
||||
const sessionData = that.getSessionData();
|
||||
if (process.env.DEBUG === 'true') {
|
||||
console.log('waitForSessionData - attempt', waitCount, 'session data:', sessionData);
|
||||
}
|
||||
|
||||
if (sessionData) {
|
||||
const results = that.getResults();
|
||||
if (process.env.DEBUG === 'true') {
|
||||
console.log('Search results count:', results ? results.length : 0);
|
||||
}
|
||||
|
||||
// If no results and this is a due cards search, try to retry
|
||||
if ((!results || results.length === 0) && that.searchRetryCount !== undefined && that.searchRetryCount < that.maxRetries) {
|
||||
if (process.env.DEBUG === 'true') {
|
||||
console.log('No results found, retrying search...');
|
||||
}
|
||||
that.searchRetryCount++;
|
||||
Meteor.setTimeout(() => {
|
||||
if (that.performSearch) {
|
||||
@@ -68,47 +56,37 @@ export class CardSearchPaged {
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the results in the ReactiveVar so they display in the template
|
||||
that.results.set(results);
|
||||
that.resultsHeading.set(that.getResultsHeading());
|
||||
that.searching.set(false);
|
||||
that.hasResults.set(true);
|
||||
that.serverError.set(false);
|
||||
} else if (waitCount < maxWaitCount) {
|
||||
// Session data not available yet, wait a bit more
|
||||
if (process.env.DEBUG === 'true') {
|
||||
console.log('Session data not available yet, waiting... (attempt', waitCount, 'of', maxWaitCount, ')');
|
||||
}
|
||||
Meteor.setTimeout(waitForSessionData, 200);
|
||||
} else {
|
||||
// Timeout reached, try fallback search
|
||||
if (process.env.DEBUG === 'true') {
|
||||
console.log('Timeout reached waiting for session data, trying fallback search');
|
||||
}
|
||||
const results = that.getResults();
|
||||
if (process.env.DEBUG === 'true') {
|
||||
console.log('Fallback search results count:', results ? results.length : 0);
|
||||
}
|
||||
} else if (waitCount < maxWaitCount) {
|
||||
// Session data not available yet, wait a bit more
|
||||
Meteor.setTimeout(waitForSessionData, 200);
|
||||
} else {
|
||||
// Timeout reached, try fallback search
|
||||
const results = that.getResults();
|
||||
|
||||
if (results && results.length > 0) {
|
||||
that.searching.set(false);
|
||||
that.hasResults.set(true);
|
||||
that.serverError.set(false);
|
||||
} else {
|
||||
that.searching.set(false);
|
||||
that.hasResults.set(false);
|
||||
that.serverError.set(true);
|
||||
}
|
||||
}
|
||||
if (results && results.length > 0) {
|
||||
that.results.set(results);
|
||||
that.resultsHeading.set(that.getResultsHeading());
|
||||
that.searching.set(false);
|
||||
that.hasResults.set(true);
|
||||
that.serverError.set(false);
|
||||
} else {
|
||||
that.searching.set(false);
|
||||
that.hasResults.set(false);
|
||||
that.serverError.set(true);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Start waiting for session data
|
||||
Meteor.setTimeout(waitForSessionData, 100);
|
||||
},
|
||||
onError(error) {
|
||||
if (process.env.DEBUG === 'true') {
|
||||
console.log('Subscription error:', error);
|
||||
console.log('Error.reason:', error.reason);
|
||||
console.log('Error.message:', error.message);
|
||||
console.log('Error.stack:', error.stack);
|
||||
}
|
||||
that.searching.set(false);
|
||||
that.hasResults.set(false);
|
||||
that.serverError.set(true);
|
||||
@@ -131,56 +109,41 @@ export class CardSearchPaged {
|
||||
|
||||
getSessionData(sessionId) {
|
||||
const sessionIdToUse = sessionId || SessionData.getSessionId();
|
||||
if (process.env.DEBUG === 'true') {
|
||||
console.log('getSessionData - looking for sessionId:', sessionIdToUse);
|
||||
}
|
||||
|
||||
// Try using the raw SessionData collection instead of ReactiveCache
|
||||
// Use SessionData.findOne() directly - it's synchronous on the client
|
||||
const sessionData = SessionData.findOne({
|
||||
userId: Meteor.userId(),
|
||||
sessionId: sessionIdToUse,
|
||||
});
|
||||
if (process.env.DEBUG === 'true') {
|
||||
console.log('getSessionData - found session data (raw):', sessionData);
|
||||
}
|
||||
|
||||
// Also try ReactiveCache for comparison
|
||||
const reactiveSessionData = ReactiveCache.getSessionData({
|
||||
sessionId: sessionIdToUse,
|
||||
});
|
||||
if (process.env.DEBUG === 'true') {
|
||||
console.log('getSessionData - found session data (reactive):', reactiveSessionData);
|
||||
}
|
||||
|
||||
return sessionData || reactiveSessionData;
|
||||
return sessionData;
|
||||
}
|
||||
|
||||
getResults() {
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('getting results');
|
||||
this.sessionData = this.getSessionData();
|
||||
// eslint-disable-next-line no-console
|
||||
if (process.env.DEBUG === 'true') {
|
||||
console.log('getResults - sessionId:', this.sessionId);
|
||||
console.log('getResults - session data:', this.sessionData);
|
||||
}
|
||||
const cards = [];
|
||||
|
||||
if (this.sessionData && this.sessionData.cards) {
|
||||
if (process.env.DEBUG === 'true') {
|
||||
console.log('getResults - cards array length:', this.sessionData.cards.length);
|
||||
}
|
||||
this.sessionData.cards.forEach(cardId => {
|
||||
const card = ReactiveCache.getCard(cardId);
|
||||
if (process.env.DEBUG === 'true') {
|
||||
console.log('getResults - card:', cardId, card);
|
||||
if (card && card._id) {
|
||||
cards.push(card);
|
||||
}
|
||||
cards.push(card);
|
||||
});
|
||||
|
||||
// Fallback: if no cards found, try fetching directly from Cards collection
|
||||
if (cards.length === 0 && this.sessionData.cards && this.sessionData.cards.length > 0) {
|
||||
if (directCards && directCards.length > 0) {
|
||||
directCards.forEach(card => {
|
||||
if (card && card._id) {
|
||||
cards.push(card);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
this.queryErrors = this.sessionData.errors || [];
|
||||
} else {
|
||||
if (process.env.DEBUG === 'true') {
|
||||
console.log('getResults - no sessionData or no cards array, trying direct card search');
|
||||
}
|
||||
// Fallback: try to get cards directly from the client-side collection
|
||||
// Use a more efficient query with limit and sort
|
||||
const selector = {
|
||||
@@ -192,9 +155,6 @@ export class CardSearchPaged {
|
||||
limit: 100 // Limit to 100 cards for performance
|
||||
};
|
||||
const allCards = Cards.find(selector, options).fetch();
|
||||
if (process.env.DEBUG === 'true') {
|
||||
console.log('getResults - direct card search found:', allCards ? allCards.length : 0, 'cards');
|
||||
}
|
||||
|
||||
if (allCards && allCards.length > 0) {
|
||||
allCards.forEach(card => {
|
||||
@@ -212,11 +172,6 @@ export class CardSearchPaged {
|
||||
// return null;
|
||||
}
|
||||
this.debug.set(new QueryDebug(this.sessionData ? this.sessionData.debug : null));
|
||||
if (process.env.DEBUG === 'true') {
|
||||
console.log('debug:', this.debug.get().get());
|
||||
console.log('debug.show():', this.debug.get().show());
|
||||
console.log('debug.showSelector():', this.debug.get().showSelector());
|
||||
}
|
||||
|
||||
if (cards) {
|
||||
if (this.sessionData) {
|
||||
@@ -254,15 +209,7 @@ export class CardSearchPaged {
|
||||
}
|
||||
|
||||
getSubscription(queryParams) {
|
||||
if (process.env.DEBUG === 'true') {
|
||||
console.log('Subscribing to globalSearch with:', {
|
||||
sessionId: this.sessionId,
|
||||
params: queryParams.params,
|
||||
text: queryParams.text
|
||||
});
|
||||
}
|
||||
|
||||
// Subscribe to both globalSearch and sessionData
|
||||
// Subscribe to globalSearch which includes sessionData as the 11th cursor
|
||||
const globalSearchHandle = Meteor.subscribe(
|
||||
'globalSearch',
|
||||
this.sessionId,
|
||||
@@ -271,11 +218,6 @@ export class CardSearchPaged {
|
||||
this.subscriptionCallbacks,
|
||||
);
|
||||
|
||||
const sessionDataHandle = Meteor.subscribe('sessionData', this.sessionId);
|
||||
if (process.env.DEBUG === 'true') {
|
||||
console.log('Subscribed to sessionData with sessionId:', this.sessionId);
|
||||
}
|
||||
|
||||
return globalSearchHandle;
|
||||
}
|
||||
|
||||
|
||||
+5
-1
@@ -302,7 +302,11 @@ FlowRouter.route('/global-search', {
|
||||
// Set title with product name
|
||||
const settings = Settings.findOne({});
|
||||
const productName = (settings && settings.productName) ? settings.productName : 'Wekan';
|
||||
document.title = `${TAPi18n.__('globalSearch-title')} - ${productName}`;
|
||||
try {
|
||||
document.title = `${TAPi18n.__('globalSearch-title')} - ${productName}`;
|
||||
} catch (e) {
|
||||
document.title = `Search All Boards - ${productName}`;
|
||||
}
|
||||
|
||||
if (FlowRouter.getQueryParam('q')) {
|
||||
Session.set(
|
||||
|
||||
+9
-1
@@ -226,7 +226,15 @@ services:
|
||||
image: mongo:7
|
||||
container_name: wekan-db
|
||||
restart: always
|
||||
command: mongod --logpath /dev/null --oplogSize 128 --quiet
|
||||
#command: mongod --logpath /dev/null --oplogSize 128 --replSet rs0 --quiet
|
||||
#command: mongod --oplogSize 128 --replSet rs0 --quiet
|
||||
command: >
|
||||
sh -c "
|
||||
mongod --oplogSize 128 --replSet rs0 --quiet --bind_ip_all &
|
||||
until mongosh --eval 'rs.initiate()' > /dev/null 2>&1; do
|
||||
sleep 2
|
||||
done;
|
||||
wait"
|
||||
networks:
|
||||
- wekan-tier
|
||||
expose:
|
||||
|
||||
@@ -78,7 +78,17 @@ git clone git@github.com:YourGithubUsername/wekan.git
|
||||
|
||||
cd wekan
|
||||
```
|
||||
|
||||
### IMPORTANT: Do NOT `npm audit fix --force`
|
||||
|
||||
IMPORTANT: Do NOT `npm audit fix --force`, it downgrades @meteorjs/rspack and breaks builds.
|
||||
`npm audit` shows false info, it does not recognize that elliptic is already updated
|
||||
to 6.6.1 with override at package.json like you can see with `npm list elliptic`.
|
||||
https://github.com/wekan/wekan/blob/main/CHANGELOG.md#v850-2026-04-03-wekan--release
|
||||
|
||||
### 3. Select option 1 to install dependencies, and then Enter.
|
||||
|
||||
|
||||
```
|
||||
./rebuild-wekan.sh
|
||||
|
||||
@@ -119,83 +129,17 @@ git push
|
||||
```
|
||||
And then at your GitHub for `https://github.com/YOUR-GITHUB-USERNAME/wekan` click `Create pull request`.
|
||||
|
||||
# Meteor 3
|
||||
|
||||
At 2024-06-26, it looks like from https://nodejs.org/en that Node.js LTS version is 20.15.0 , so change to newest Node.js LTS, delete old Meteor:
|
||||
```
|
||||
sudo n 20.15.0
|
||||
|
||||
sudo npm -g install npm
|
||||
|
||||
cd
|
||||
|
||||
rm -rf .meteor
|
||||
```
|
||||
Check how to install newest Meteor from Meteor 3 PR at https://github.com/meteor/meteor/pull/13163 , for example:
|
||||
```
|
||||
npx meteor@rc
|
||||
```
|
||||
Check what branches there are:
|
||||
```
|
||||
cd repos/wekan
|
||||
|
||||
git branch -a
|
||||
```
|
||||
Change to Meteor 3 branch:
|
||||
```
|
||||
git checkout feature-meteor3
|
||||
```
|
||||
Build wekan:
|
||||
```
|
||||
./rebuild-wekan.sh
|
||||
|
||||
2
|
||||
```
|
||||
If there are errors, try to fix them.
|
||||
|
||||
Or try to run wekan:
|
||||
```
|
||||
./rebuild-wekan.sh
|
||||
|
||||
3
|
||||
```
|
||||
# Updating
|
||||
|
||||
There are usually updates both for npm packages and Meteor
|
||||
|
||||
Updating npm packages:
|
||||
```
|
||||
npm update
|
||||
```
|
||||
Checking for vulnerable packages:
|
||||
```
|
||||
npm audit
|
||||
```
|
||||
Fixing vulnerable npm packages by updating to newer packages:
|
||||
```
|
||||
npm audit fix
|
||||
```
|
||||
If that did not help, use force:
|
||||
```
|
||||
npm audit fix --force
|
||||
```
|
||||
If that did not help, read links from that `npm audit` command did show, remove deprecated dependencies, update to other maintained dependencies.
|
||||
## Updating
|
||||
|
||||
Updating to next Meteor release:
|
||||
```
|
||||
meteor update
|
||||
|
||||
meteor npm update
|
||||
```
|
||||
Updating to specific Meteor release:
|
||||
```
|
||||
meteor update --release METEOR@3.0-rc.4
|
||||
```
|
||||
Trying to update all Meteor packages:
|
||||
```
|
||||
meteor update --release METEOR@3.0-rc.4 --all-packages
|
||||
```
|
||||
Allowing incompatible updates, that may sometime work:
|
||||
```
|
||||
meteor update --release METEOR@3.0-rc.4 --all-packages --allow-incompatible-update
|
||||
meteor update --release METEOR@3.4
|
||||
```
|
||||
If you are changing Meteor and Node.js versions, you may need to reset Meteor:
|
||||
```
|
||||
|
||||
@@ -10,7 +10,7 @@ This is without container (without Docker or Snap).
|
||||
|
||||
Right click and download files 1-4:
|
||||
|
||||
1. [wekan-8.52-amd64-windows.zip](https://github.com/wekan/wekan/releases/download/v8.52/wekan-8.52-amd64-windows.zip)
|
||||
1. [wekan-8.71-amd64-windows.zip](https://github.com/wekan/wekan/releases/download/v8.71/wekan-8.71-amd64-windows.zip)
|
||||
|
||||
2. [node.exe](https://nodejs.org/dist/latest-v22.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.31-signed.msi` . In installer, uncheck downloading MongoDB compass.
|
||||
|
||||
7. Unzip `wekan-8.52-amd64-windows.zip` , inside it is directory `bundle`, to it copy other files:
|
||||
7. Unzip `wekan-8.71-amd64-windows.zip` , inside it is directory `bundle`, to it copy other files:
|
||||
|
||||
```
|
||||
bundle (directory)
|
||||
|
||||
+8
-3
@@ -1902,9 +1902,14 @@ Boards.userBoardIds = async (userId, archived = false, selector = {}) => {
|
||||
|
||||
Boards.colorMap = () => {
|
||||
const colors = {};
|
||||
const TAPi18n = getTAPi18n();
|
||||
for (const color of Boards.labelColors()) {
|
||||
colors[TAPi18n.__(`color-${color}`)] = color;
|
||||
try {
|
||||
const TAPi18n = getTAPi18n();
|
||||
for (const color of Boards.labelColors()) {
|
||||
colors[TAPi18n.__(`color-${color}`)] = color;
|
||||
}
|
||||
} catch (e) {
|
||||
// i18n not ready yet, return empty map
|
||||
// The colorMap will be regenerated when i18n is ready
|
||||
}
|
||||
return colors;
|
||||
};
|
||||
|
||||
Generated
+82
-18
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "wekan",
|
||||
"version": "v8.52.0",
|
||||
"version": "v8.71.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "wekan",
|
||||
"version": "v8.52.0",
|
||||
"version": "v8.71.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-s3": "^3.1019.0",
|
||||
@@ -259,9 +259,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/client-s3": {
|
||||
"version": "3.1023.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.1023.0.tgz",
|
||||
"integrity": "sha512-IvNy49sdoCWd3fgHQxail3y0UQdfKj1Xk0VPu9HTwlog60o9Lmp5ykjZ2LlIuHEPaxq4Siih707GB/ulUWgetw==",
|
||||
"version": "3.1024.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.1024.0.tgz",
|
||||
"integrity": "sha512-8qdO5aLCzaf9l0RdrSBW1iIroRKP2QBqtZ6lkrtHKiaaH0B18xEn+lrEgiN/eCf3uRAYk4cqbnI2XcWzm+7dDQ==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@aws-crypto/sha1-browser": "5.2.0",
|
||||
@@ -3401,9 +3401,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "25.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-25.5.0.tgz",
|
||||
"integrity": "sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw==",
|
||||
"version": "25.5.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-25.5.2.tgz",
|
||||
"integrity": "sha512-tO4ZIRKNC+MDWV4qKVZe3Ql/woTnmHDr5JD8UI5hn2pwBrHEwOEMZK7WlNb5RKB6EoJ02gwmQS9OrjuFnZYdpg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -4162,6 +4162,7 @@
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/assert/-/assert-2.1.0.tgz",
|
||||
"integrity": "sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.2",
|
||||
@@ -4187,6 +4188,7 @@
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
|
||||
"integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"possible-typed-array-names": "^1.0.0"
|
||||
@@ -4343,9 +4345,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/baseline-browser-mapping": {
|
||||
"version": "2.10.13",
|
||||
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.13.tgz",
|
||||
"integrity": "sha512-BL2sTuHOdy0YT1lYieUxTw/QMtPBC3pmlJC6xk8BBYVv6vcw3SGdKemQ+Xsx9ik2F/lYDO9tqsFQH1r9PFuHKw==",
|
||||
"version": "2.10.14",
|
||||
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.14.tgz",
|
||||
"integrity": "sha512-fOVLPAsFTsQfuCkvahZkzq6nf8KvGWanlYoTh0SVA0A/PIUxQGU2AOZAoD95n2gFLVDW/jP6sbGLny95nmEuHA==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
@@ -4632,6 +4634,7 @@
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz",
|
||||
"integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"pako": "~1.0.5"
|
||||
@@ -4704,6 +4707,7 @@
|
||||
"version": "5.7.1",
|
||||
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
|
||||
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
@@ -4752,6 +4756,7 @@
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz",
|
||||
"integrity": "sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/bundle-name": {
|
||||
@@ -4784,6 +4789,7 @@
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz",
|
||||
"integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind-apply-helpers": "^1.0.0",
|
||||
@@ -4802,6 +4808,7 @@
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
|
||||
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0",
|
||||
@@ -4815,6 +4822,7 @@
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
|
||||
"integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind-apply-helpers": "^1.0.2",
|
||||
@@ -4828,9 +4836,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001784",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001784.tgz",
|
||||
"integrity": "sha512-WU346nBTklUV9YfUl60fqRbU5ZqyXlqvo1SgigE1OAXK5bFL8LL9q1K7aap3N739l4BvNqnkm3YrGHiY9sfUQw==",
|
||||
"version": "1.0.30001785",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001785.tgz",
|
||||
"integrity": "sha512-blhOL/WNR+Km1RI/LCVAvA73xplXA7ZbjzI4YkMK9pa6T/P3F2GxjNpEkyw5repTw9IvkyrjyHpwjnhZ5FOvYQ==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
@@ -5075,12 +5083,14 @@
|
||||
"node_modules/console-browserify": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz",
|
||||
"integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA=="
|
||||
"integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/constants-browserify": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz",
|
||||
"integrity": "sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/content-disposition": {
|
||||
@@ -5434,6 +5444,7 @@
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
|
||||
"integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-define-property": "^1.0.0",
|
||||
@@ -5464,6 +5475,7 @@
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
|
||||
"integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"define-data-property": "^1.0.1",
|
||||
@@ -5590,6 +5602,7 @@
|
||||
"version": "4.22.0",
|
||||
"resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-4.22.0.tgz",
|
||||
"integrity": "sha512-IGBwjF7tNk3cwypFNH/7bfzBcgSCbaMOD3GsaY1AU/JRrnHnYgEM0+9kQt52iZxjNsjBtJYtao146V+f8jFZNw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
@@ -5655,6 +5668,7 @@
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
||||
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind-apply-helpers": "^1.0.1",
|
||||
@@ -5893,6 +5907,7 @@
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
|
||||
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
@@ -5902,6 +5917,7 @@
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
|
||||
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
@@ -5919,6 +5935,7 @@
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
|
||||
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0"
|
||||
@@ -6372,6 +6389,7 @@
|
||||
"version": "0.3.5",
|
||||
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz",
|
||||
"integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"is-callable": "^1.2.7"
|
||||
@@ -6452,6 +6470,7 @@
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
||||
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
@@ -6461,6 +6480,7 @@
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz",
|
||||
"integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
@@ -6470,6 +6490,7 @@
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
|
||||
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind-apply-helpers": "^1.0.2",
|
||||
@@ -6507,6 +6528,7 @@
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
|
||||
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"dunder-proto": "^1.0.1",
|
||||
@@ -6575,6 +6597,7 @@
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
|
||||
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
@@ -6626,6 +6649,7 @@
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
|
||||
"integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-define-property": "^1.0.0"
|
||||
@@ -6638,6 +6662,7 @@
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
|
||||
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
@@ -6650,6 +6675,7 @@
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
|
||||
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"has-symbols": "^1.0.3"
|
||||
@@ -6690,6 +6716,7 @@
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
|
||||
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"function-bind": "^1.1.2"
|
||||
@@ -6894,6 +6921,7 @@
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz",
|
||||
"integrity": "sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/hyperdyperid": {
|
||||
@@ -7021,6 +7049,7 @@
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz",
|
||||
"integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bound": "^1.0.2",
|
||||
@@ -7050,6 +7079,7 @@
|
||||
"version": "1.2.7",
|
||||
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
|
||||
"integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
@@ -7113,6 +7143,7 @@
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz",
|
||||
"integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bound": "^1.0.4",
|
||||
@@ -7164,6 +7195,7 @@
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz",
|
||||
"integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.0",
|
||||
@@ -7238,6 +7270,7 @@
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz",
|
||||
"integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bound": "^1.0.2",
|
||||
@@ -7268,6 +7301,7 @@
|
||||
"version": "1.1.15",
|
||||
"resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz",
|
||||
"integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"which-typed-array": "^1.1.16"
|
||||
@@ -7299,6 +7333,7 @@
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
|
||||
"integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/isexe": {
|
||||
@@ -7736,6 +7771,7 @@
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
|
||||
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
@@ -9478,6 +9514,7 @@
|
||||
"version": "1.13.4",
|
||||
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
|
||||
"integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
@@ -9490,6 +9527,7 @@
|
||||
"version": "1.1.6",
|
||||
"resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz",
|
||||
"integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.7",
|
||||
@@ -9506,6 +9544,7 @@
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
|
||||
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
@@ -9515,6 +9554,7 @@
|
||||
"version": "4.1.7",
|
||||
"resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz",
|
||||
"integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.8",
|
||||
@@ -9594,6 +9634,7 @@
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz",
|
||||
"integrity": "sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/p-limit": {
|
||||
@@ -9707,6 +9748,7 @@
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz",
|
||||
"integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/path-exists": {
|
||||
@@ -9720,9 +9762,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/path-expression-matcher": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.2.0.tgz",
|
||||
"integrity": "sha512-DwmPWeFn+tq7TiyJ2CxezCAirXjFxvaiD03npak3cRjlP9+OjTmSy1EpIrEbh+l6JgUundniloMLDQ/6VTdhLQ==",
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.2.1.tgz",
|
||||
"integrity": "sha512-d7gQQmLvAKXKXE2GeP9apIGbMYKz88zWdsn/BN2HRWVQsDFdUY36WSLTY0Jvd4HWi7Fb30gQ62oAOzdgJA6fZw==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
@@ -9844,6 +9886,7 @@
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
|
||||
"integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
@@ -10042,6 +10085,7 @@
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
|
||||
"integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/punycode.js": {
|
||||
@@ -10057,6 +10101,7 @@
|
||||
"version": "6.15.0",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz",
|
||||
"integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"side-channel": "^1.1.0"
|
||||
@@ -10072,6 +10117,7 @@
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz",
|
||||
"integrity": "sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.4.x"
|
||||
}
|
||||
@@ -10355,6 +10401,7 @@
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz",
|
||||
"integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bound": "^1.0.2",
|
||||
@@ -10579,6 +10626,7 @@
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
|
||||
"integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"define-data-property": "^1.1.4",
|
||||
@@ -10609,6 +10657,7 @@
|
||||
"version": "2.4.12",
|
||||
"resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.12.tgz",
|
||||
"integrity": "sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==",
|
||||
"dev": true,
|
||||
"license": "(MIT AND BSD-3-Clause)",
|
||||
"dependencies": {
|
||||
"inherits": "^2.0.4",
|
||||
@@ -10676,6 +10725,7 @@
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
|
||||
"integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0",
|
||||
@@ -10695,6 +10745,7 @@
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
|
||||
"integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0",
|
||||
@@ -10711,6 +10762,7 @@
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
|
||||
"integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bound": "^1.0.2",
|
||||
@@ -10729,6 +10781,7 @@
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
|
||||
"integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bound": "^1.0.2",
|
||||
@@ -11008,6 +11061,7 @@
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz",
|
||||
"integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"inherits": "~2.0.4",
|
||||
@@ -11018,6 +11072,7 @@
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/stream-http/-/stream-http-3.2.0.tgz",
|
||||
"integrity": "sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"builtin-status-codes": "^3.0.0",
|
||||
@@ -11324,6 +11379,7 @@
|
||||
"version": "2.0.12",
|
||||
"resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz",
|
||||
"integrity": "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"setimmediate": "^1.0.4"
|
||||
@@ -11345,6 +11401,7 @@
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.2.tgz",
|
||||
"integrity": "sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"isarray": "^2.0.5",
|
||||
@@ -11415,6 +11472,7 @@
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz",
|
||||
"integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/type-detect": {
|
||||
@@ -11457,6 +11515,7 @@
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz",
|
||||
"integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bound": "^1.0.3",
|
||||
@@ -11559,6 +11618,7 @@
|
||||
"version": "0.11.4",
|
||||
"resolved": "https://registry.npmjs.org/url/-/url-0.11.4.tgz",
|
||||
"integrity": "sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"punycode": "^1.4.1",
|
||||
@@ -11572,6 +11632,7 @@
|
||||
"version": "0.12.5",
|
||||
"resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz",
|
||||
"integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"inherits": "^2.0.3",
|
||||
@@ -11620,6 +11681,7 @@
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz",
|
||||
"integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/watchpack": {
|
||||
@@ -11962,6 +12024,7 @@
|
||||
"version": "1.1.20",
|
||||
"resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.20.tgz",
|
||||
"integrity": "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"available-typed-arrays": "^1.0.7",
|
||||
@@ -12131,6 +12194,7 @@
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
||||
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.4"
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "wekan",
|
||||
"version": "v8.52.0",
|
||||
"version": "v8.71.0",
|
||||
"description": "Open-Source kanban",
|
||||
"private": true,
|
||||
"repository": {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
<head>
|
||||
<meta charset="utf8" />
|
||||
<title>WeKan REST API v8.52</title>
|
||||
<title>WeKan REST API v8.71</title>
|
||||
<!-- needed for adaptive design -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style>
|
||||
@@ -390,7 +390,7 @@ data-styled.g138[id="sc-iJQrDi"]{content:"gtHWGb,"}/*!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-juTflS gfWNtA api-content"><div class="sc-eDDNvO eTiIZG"><div class="sc-iAEyYj cmAaWK"><div class="sc-hLseeT hoYmkG api-info"><h1 class="sc-fsQipe sc-crPCXn ePkAIL bSStQp">Wekan REST API<!-- --> <span>(<!-- -->v8.52<!-- -->)</span></h1><p>Download OpenAPI specification<!-- -->:</p><div class="sc-iKGpAq sc-cCYyou dXXcln dHaogz"></div><div data-role="redoc-summary" html="" class="sc-iKGpAq sc-cCYyou dXXcln dHaogz"></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-juTflS gfWNtA api-content"><div class="sc-eDDNvO eTiIZG"><div class="sc-iAEyYj cmAaWK"><div class="sc-hLseeT hoYmkG api-info"><h1 class="sc-fsQipe sc-crPCXn ePkAIL bSStQp">Wekan REST API<!-- --> <span>(<!-- -->v8.71<!-- -->)</span></h1><p>Download OpenAPI specification<!-- -->:</p><div class="sc-iKGpAq sc-cCYyou dXXcln dHaogz"></div><div data-role="redoc-summary" html="" class="sc-iKGpAq sc-cCYyou dXXcln dHaogz"></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>
|
||||
@@ -446,7 +446,7 @@ data-styled.g138[id="sc-iJQrDi"]{content:"gtHWGb,"}/*!sc*/
|
||||
" class="sc-iKGpAq sc-cCYyou sc-cjERFZ dXXcln fTBBlJ dkmSdy"><p>Error in registration</p>
|
||||
</div></button></div></div></div><div class="sc-jTrPJt sc-gLDzao dVngAA fYLqku"><div class="sc-fYzRkH dHdMVa"><button class="sc-jYvNnh iWrBta"><span type="post" class="sc-eGFuAY ejslkd http-verb post">post</span><span class="sc-GJyyy dkiPkt">/users/register</span><svg class="sc-fbJfz ivEQut" 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-fnxdBX dplsyJ"><div class="sc-llcuoK cNCbuV"><div html="" class="sc-iKGpAq sc-cCYyou dXXcln cFvDiF"></div><div tabindex="0" role="button"><div class="sc-jnsZEx eobUac"><span></span>/users/register</div></div></div></div></div></div></div></div></div><div class="sc-emEvRt jYOHCb"></div></div></div>
|
||||
<script>
|
||||
const __redoc_state = {"menu":{"activeItemIdx":-1},"spec":{"data":{"openapi":"3.0.0","info":{"title":"Wekan REST API","version":"v8.52","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"}}}}},"components":{"securitySchemes":{"UserSecurity":{"type":"apiKey","in":"header","name":"Authorization"}}}}},"searchIndex":{"store":["section/Production-Security-Concerns","tag/Login","tag/Login/operation/login","tag/Login/operation/register"],"index":{"version":"2.3.9","fields":["title","description"],"fieldVectors":[["title/0",[0,0.641,1,1.113,2,1.113]],["description/0",[0,0.353,3,1.592,4,0.613,5,0.613,6,0.995,7,0.613,8,0.995,9,1.257,10,0.613,11,0.613,12,0.613,13,0.295,14,0.353,15,0.613,16,0.613,17,0.613,18,0.613,19,0.613,20,0.613,21,0.613,22,0.182,23,0.182,24,0.613,25,0.613,26,0.613,27,0.353,28,0.724,29,0.613,30,0.613,31,0.613,32,0.353,33,0.613,34,0.613,35,0.613,36,0.613,37,0.613]],["title/1",[13,0.473]],["description/1",[]],["title/2",[13,0.33,22,0.33,23,0.33]],["description/2",[38,1.941]],["title/3",[22,0.33,23,0.33,39,1.113]],["description/3",[14,0.841,27,0.841,28,0.841,32,0.841,40,1.46,41,1.46,42,1.46,43,1.46]]],"invertedIndex":[["",{"_index":28,"title":{},"description":{"0":{},"3":{}}}],["api",{"_index":23,"title":{"2":{},"3":{}},"description":{"0":{}}}],["authent",{"_index":42,"title":{},"description":{"3":{}}}],["author",{"_index":31,"title":{},"description":{"0":{}}}],["call",{"_index":3,"title":{},"description":{"0":{}}}],["certif",{"_index":12,"title":{},"description":{"0":{}}}],["concern",{"_index":2,"title":{"0":{}},"description":{}}],["ensur",{"_index":6,"title":{},"description":{"0":{}}}],["expir",{"_index":33,"title":{},"description":{"0":{}}}],["few",{"_index":25,"title":{},"description":{"0":{}}}],["highli",{"_index":20,"title":{},"description":{"0":{}}}],["http",{"_index":9,"title":{},"description":{"0":{}}}],["implement",{"_index":29,"titLine truncated
|
||||
const __redoc_state = {"menu":{"activeItemIdx":-1},"spec":{"data":{"openapi":"3.0.0","info":{"title":"Wekan REST API","version":"v8.71","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"}}}}},"components":{"securitySchemes":{"UserSecurity":{"type":"apiKey","in":"header","name":"Authorization"}}}}},"searchIndex":{"store":["section/Production-Security-Concerns","tag/Login","tag/Login/operation/login","tag/Login/operation/register"],"index":{"version":"2.3.9","fields":["title","description"],"fieldVectors":[["title/0",[0,0.641,1,1.113,2,1.113]],["description/0",[0,0.353,3,1.592,4,0.613,5,0.613,6,0.995,7,0.613,8,0.995,9,1.257,10,0.613,11,0.613,12,0.613,13,0.295,14,0.353,15,0.613,16,0.613,17,0.613,18,0.613,19,0.613,20,0.613,21,0.613,22,0.182,23,0.182,24,0.613,25,0.613,26,0.613,27,0.353,28,0.724,29,0.613,30,0.613,31,0.613,32,0.353,33,0.613,34,0.613,35,0.613,36,0.613,37,0.613]],["title/1",[13,0.473]],["description/1",[]],["title/2",[13,0.33,22,0.33,23,0.33]],["description/2",[38,1.941]],["title/3",[22,0.33,23,0.33,39,1.113]],["description/3",[14,0.841,27,0.841,28,0.841,32,0.841,40,1.46,41,1.46,42,1.46,43,1.46]]],"invertedIndex":[["",{"_index":28,"title":{},"description":{"0":{},"3":{}}}],["api",{"_index":23,"title":{"2":{},"3":{}},"description":{"0":{}}}],["authent",{"_index":42,"title":{},"description":{"3":{}}}],["author",{"_index":31,"title":{},"description":{"0":{}}}],["call",{"_index":3,"title":{},"description":{"0":{}}}],["certif",{"_index":12,"title":{},"description":{"0":{}}}],["concern",{"_index":2,"title":{"0":{}},"description":{}}],["ensur",{"_index":6,"title":{},"description":{"0":{}}}],["expir",{"_index":33,"title":{},"description":{"0":{}}}],["few",{"_index":25,"title":{},"description":{"0":{}}}],["highli",{"_index":20,"title":{},"description":{"0":{}}}],["http",{"_index":9,"title":{},"description":{"0":{}}}],["implement",{"_index":29,"titLine truncated
|
||||
|
||||
var container = document.getElementById('redoc');
|
||||
Redoc.hydrate(__redoc_state, container);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
swagger: '2.0'
|
||||
info:
|
||||
title: Wekan REST API
|
||||
version: v8.52
|
||||
version: v8.71
|
||||
description: |
|
||||
The REST API allows you to control and extend Wekan with ease.
|
||||
|
||||
|
||||
+2
-2
@@ -69,8 +69,8 @@ do
|
||||
|
||||
"Build Wekan")
|
||||
echo "Building Wekan."
|
||||
rm -rf .build/bundle node_modules .meteor/local .build
|
||||
meteor npm install
|
||||
rm -rf node_modules .meteor/local .build
|
||||
meteor npm install --no-audit
|
||||
meteor build .build --directory --platforms=web.browser
|
||||
echo Done.
|
||||
break
|
||||
|
||||
@@ -9,6 +9,21 @@ fi
|
||||
|
||||
VERSION=$1
|
||||
|
||||
# Check is there script for deleting Docker containers
|
||||
W_DIR="../w"
|
||||
CLEANUP_DIR="$W_DIR/docker-cleanup-volumes"
|
||||
if [ ! -d "$W_DIR" ]; then
|
||||
mkdir -p "$W_DIR"
|
||||
fi
|
||||
if [ ! -d "$CLEANUP_DIR" ]; then
|
||||
(cd "$W_DIR" && git clone https://github.com/wekan/docker-cleanup-volumes)
|
||||
fi
|
||||
# Delete Docker containers
|
||||
(cd ../w/docker-cleanup-volumes && git pull && ./start.sh)
|
||||
|
||||
# Install Docker build deps
|
||||
./releases/docker-build-deps.sh
|
||||
|
||||
# Ensure you are using the correct builder
|
||||
docker buildx use mybuilder
|
||||
|
||||
|
||||
@@ -28,13 +28,7 @@ echo " You can still use any other locale as your main locale."
|
||||
|
||||
echo "Building Wekan."
|
||||
sudo chown -R $(id -u):$(id -g) $HOME/.npm $HOME/.meteor
|
||||
rm -rf node_modules
|
||||
meteor npm install
|
||||
rm -rf .build
|
||||
METEOR_PROFILE=100 meteor build .build --directory --platforms=web.browser
|
||||
# Remove legacy webbroser bundle, so that Wekan works also at Android Firefox, iOS Safari, etc.
|
||||
rm -rf .build/bundle/programs/web.browser.legacy
|
||||
cd .build/bundle/programs/server
|
||||
rm -rf node_modules
|
||||
meteor npm install
|
||||
cd ../../../..
|
||||
rm -rf .build node_modules .meteor/local
|
||||
meteor npm install --no-audit
|
||||
#METEOR_PROFILE=100 meteor build .build --directory --platforms=web.browser
|
||||
meteor build .build --directory --platforms=web.browser
|
||||
@@ -46,6 +46,9 @@ if ! echo "$OLD" | grep -qE '^[0-9]+\.[0-9]+$' || \
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Delete all GitHub Actions Caches, so that old stuff does not break builds.
|
||||
gh cache delete --all
|
||||
|
||||
# Resolve repo root from script location so this works regardless of CWD
|
||||
REPO_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
RELEASES_DIR="$REPO_DIR/releases"
|
||||
@@ -100,7 +103,7 @@ echo "=== GitHub Actions is now building and releasing v$NEW ==="
|
||||
echo " Building: amd64 (full Meteor build), arm64, s390x, ppc64le, armhf, win64 bundles"
|
||||
echo " Releasing: GitHub Release with CHANGELOG notes + all .zip bundles"
|
||||
echo " Docker: wekanteam/wekan, quay.io/wekan/wekan, ghcr.io/wekan/wekan"
|
||||
echo " Snap: published to candidate/beta/edge channels + uploaded to release"
|
||||
echo " Snap: published edge, released to candidate"
|
||||
echo " Follow at: https://github.com/wekan/wekan/actions"
|
||||
echo ""
|
||||
|
||||
|
||||
@@ -22,10 +22,10 @@ const pkgdef :Spk.PackageDefinition = (
|
||||
appTitle = (defaultText = "Wekan"),
|
||||
# The name of the app as it is displayed to the user.
|
||||
|
||||
appVersion = 852,
|
||||
appVersion = 871,
|
||||
# Increment this for every release.
|
||||
|
||||
appMarketingVersion = (defaultText = "8.52.0~2026-03-23"),
|
||||
appMarketingVersion = (defaultText = "8.71.0~2026-03-23"),
|
||||
# Human-readable presentation of the app version.
|
||||
|
||||
minUpgradableAppVersion = 0,
|
||||
|
||||
@@ -28,11 +28,11 @@ class AttachmentMigrationService {
|
||||
* @param {string} boardId - The board ID
|
||||
* @returns {boolean} - True if board has been migrated
|
||||
*/
|
||||
isBoardMigrated(boardId) {
|
||||
async isBoardMigrated(boardId) {
|
||||
const isMigrated = migratedBoards.has(boardId);
|
||||
|
||||
// Update status collection for pub/sub
|
||||
AttachmentMigrationStatus.upsert(
|
||||
await AttachmentMigrationStatus.upsertAsync(
|
||||
{ boardId },
|
||||
{
|
||||
$set: {
|
||||
@@ -53,7 +53,7 @@ class AttachmentMigrationService {
|
||||
async migrateBoardAttachments(boardId) {
|
||||
try {
|
||||
// Check if board has already been migrated
|
||||
if (this.isBoardMigrated(boardId)) {
|
||||
if (await this.isBoardMigrated(boardId)) {
|
||||
console.log(`Board ${boardId} has already been migrated, skipping`);
|
||||
return { success: true, message: 'Board already migrated' };
|
||||
}
|
||||
@@ -102,7 +102,7 @@ class AttachmentMigrationService {
|
||||
console.log(`Marked board ${boardId} as migrated`);
|
||||
|
||||
// Update status collection
|
||||
AttachmentMigrationStatus.upsert(
|
||||
await AttachmentMigrationStatus.upsertAsync(
|
||||
{ boardId },
|
||||
{
|
||||
$set: {
|
||||
@@ -224,7 +224,7 @@ class AttachmentMigrationService {
|
||||
const migratedCount = total - unconverted.length;
|
||||
|
||||
// Update status collection for pub/sub
|
||||
AttachmentMigrationStatus.upsert(
|
||||
await AttachmentMigrationStatus.upsertAsync(
|
||||
{ boardId },
|
||||
{
|
||||
$set: {
|
||||
|
||||
@@ -75,7 +75,7 @@ Meteor.startup(() => {
|
||||
process.env.ORACLE_OIM_ENABLED === 'true' ||
|
||||
process.env.ORACLE_OIM_ENABLED === true
|
||||
) {
|
||||
ServiceConfiguration.configurations.upsert(
|
||||
ServiceConfiguration.configurations.upsertAsync(
|
||||
// eslint-disable-line no-undef
|
||||
{ service: 'oidc' },
|
||||
{
|
||||
@@ -97,7 +97,7 @@ Meteor.startup(() => {
|
||||
process.env.OAUTH2_ENABLED === 'true' ||
|
||||
process.env.OAUTH2_ENABLED === true
|
||||
) {
|
||||
ServiceConfiguration.configurations.upsert(
|
||||
ServiceConfiguration.configurations.upsertAsync(
|
||||
// eslint-disable-line no-undef
|
||||
{ service: 'oidc' },
|
||||
{
|
||||
@@ -121,7 +121,7 @@ Meteor.startup(() => {
|
||||
process.env.CAS_ENABLED === 'true' ||
|
||||
process.env.CAS_ENABLED === true
|
||||
) {
|
||||
ServiceConfiguration.configurations.upsert(
|
||||
ServiceConfiguration.configurations.upsertAsync(
|
||||
// eslint-disable-line no-undef
|
||||
{ service: 'cas' },
|
||||
{
|
||||
@@ -145,7 +145,7 @@ Meteor.startup(() => {
|
||||
process.env.SAML_ENABLED === 'true' ||
|
||||
process.env.SAML_ENABLED === true
|
||||
) {
|
||||
ServiceConfiguration.configurations.upsert(
|
||||
ServiceConfiguration.configurations.upsertAsync(
|
||||
// eslint-disable-line no-undef
|
||||
{ service: 'saml' },
|
||||
{
|
||||
|
||||
@@ -1713,7 +1713,7 @@ class CronMigrationManager {
|
||||
this.startTime = Date.now();
|
||||
|
||||
// Update CronJobStatus for immediate pub/sub notification
|
||||
CronJobStatus.upsert(
|
||||
await CronJobStatus.upsertAsync(
|
||||
{ jobId: 'migration' },
|
||||
{
|
||||
$set: {
|
||||
@@ -1784,7 +1784,7 @@ class CronMigrationManager {
|
||||
this.isRunning = false;
|
||||
|
||||
// Update CronJobStatus
|
||||
CronJobStatus.upsert(
|
||||
await CronJobStatus.upsertAsync(
|
||||
{ jobId: 'migration' },
|
||||
{
|
||||
$set: {
|
||||
@@ -1800,7 +1800,7 @@ class CronMigrationManager {
|
||||
}
|
||||
|
||||
// Update to running state
|
||||
CronJobStatus.upsert(
|
||||
await CronJobStatus.upsertAsync(
|
||||
{ jobId: 'migration' },
|
||||
{
|
||||
$set: {
|
||||
@@ -2555,7 +2555,7 @@ class CronMigrationManager {
|
||||
cronMigrationStatus.set('Migrations paused');
|
||||
|
||||
// Update CronJobStatus for immediate pub/sub notification
|
||||
CronJobStatus.upsert(
|
||||
await CronJobStatus.upsertAsync(
|
||||
{ jobId: 'migration' },
|
||||
{
|
||||
$set: {
|
||||
@@ -2577,7 +2577,7 @@ class CronMigrationManager {
|
||||
}
|
||||
|
||||
// Update to final paused state
|
||||
CronJobStatus.upsert(
|
||||
await CronJobStatus.upsertAsync(
|
||||
{ jobId: 'migration' },
|
||||
{
|
||||
$set: {
|
||||
@@ -2597,7 +2597,7 @@ class CronMigrationManager {
|
||||
*/
|
||||
async stopAllMigrations() {
|
||||
// Update CronJobStatus for immediate pub/sub notification
|
||||
CronJobStatus.upsert(
|
||||
await CronJobStatus.upsertAsync(
|
||||
{ jobId: 'migration' },
|
||||
{
|
||||
$set: {
|
||||
@@ -2635,7 +2635,7 @@ class CronMigrationManager {
|
||||
cronMigrationStatus.set('All migrations stopped');
|
||||
|
||||
// Update to final stopped state
|
||||
CronJobStatus.upsert(
|
||||
await CronJobStatus.upsertAsync(
|
||||
{ jobId: 'migration' },
|
||||
{
|
||||
$set: {
|
||||
@@ -2649,9 +2649,9 @@ class CronMigrationManager {
|
||||
);
|
||||
|
||||
// Clear status message after delay
|
||||
Meteor.setTimeout(() => {
|
||||
Meteor.setTimeout(async () => {
|
||||
cronMigrationStatus.set('');
|
||||
CronJobStatus.upsert(
|
||||
await CronJobStatus.upsertAsync(
|
||||
{ jobId: 'migration' },
|
||||
{
|
||||
$set: {
|
||||
|
||||
@@ -148,7 +148,10 @@ Activities.after.insert(async (userId, doc) => {
|
||||
|
||||
if (activity.commentId) {
|
||||
const comment = await activity.comment();
|
||||
params.comment = normalizeActivityText(comment.text);
|
||||
if (!comment) {
|
||||
console.warn('[Activities.after.insert] Comment not found for commentId:', activity.commentId, '— skipping comment params.');
|
||||
}
|
||||
params.comment = normalizeActivityText(comment?.text);
|
||||
let hasMentions = false;
|
||||
if (board) {
|
||||
const knownUsers = [];
|
||||
@@ -237,7 +240,9 @@ Activities.after.insert(async (userId, doc) => {
|
||||
}
|
||||
}
|
||||
}
|
||||
params.commentId = comment._id;
|
||||
if (comment) {
|
||||
params.commentId = comment._id;
|
||||
}
|
||||
params.hasMentions = hasMentions;
|
||||
}
|
||||
|
||||
@@ -328,8 +333,11 @@ Activities.after.insert(async (userId, doc) => {
|
||||
}
|
||||
});
|
||||
|
||||
const integrationBoardIds = board
|
||||
? [board._id, Integrations.Const.GLOBAL_WEBHOOK_ID]
|
||||
: [Integrations.Const.GLOBAL_WEBHOOK_ID];
|
||||
const integrations = await ReactiveCache.getIntegrations({
|
||||
boardId: { $in: [board._id, Integrations.Const.GLOBAL_WEBHOOK_ID] },
|
||||
boardId: { $in: integrationBoardIds },
|
||||
enabled: true,
|
||||
activities: { $in: [description, 'all'] },
|
||||
});
|
||||
|
||||
@@ -8,6 +8,10 @@ import CardComments from '/models/cardComments';
|
||||
|
||||
async function commentCreation(userId, doc) {
|
||||
const card = await ReactiveCache.getCard(doc.cardId);
|
||||
if (!card) {
|
||||
console.warn('[commentCreation] Card not found for cardId:', doc.cardId, '— skipping activity insert.');
|
||||
return;
|
||||
}
|
||||
await Activities.insertAsync({
|
||||
userId,
|
||||
activityType: 'addComment',
|
||||
@@ -30,6 +34,10 @@ CardComments.after.insert(async (userId, doc) => {
|
||||
|
||||
CardComments.after.update(async (userId, doc) => {
|
||||
const card = await ReactiveCache.getCard(doc.cardId);
|
||||
if (!card) {
|
||||
console.warn('[CardComments.after.update] Card not found for cardId:', doc.cardId, '— skipping activity insert.');
|
||||
return;
|
||||
}
|
||||
await Activities.insertAsync({
|
||||
userId,
|
||||
activityType: 'editComment',
|
||||
@@ -42,19 +50,27 @@ CardComments.after.update(async (userId, doc) => {
|
||||
});
|
||||
|
||||
CardComments.before.remove(async (userId, doc) => {
|
||||
const card = await ReactiveCache.getCard(doc.cardId);
|
||||
await Activities.insertAsync({
|
||||
userId,
|
||||
activityType: 'deleteComment',
|
||||
boardId: doc.boardId,
|
||||
cardId: doc.cardId,
|
||||
commentId: doc._id,
|
||||
listId: card.listId,
|
||||
swimlaneId: card.swimlaneId,
|
||||
});
|
||||
const activity = await ReactiveCache.getActivity({ commentId: doc._id });
|
||||
if (activity) {
|
||||
await Activities.removeAsync(activity._id);
|
||||
try {
|
||||
const card = await ReactiveCache.getCard(doc.cardId);
|
||||
if (!card) {
|
||||
console.warn('[CardComments.before.remove] Card not found for cardId:', doc.cardId, '— skipping deleteComment activity.');
|
||||
} else {
|
||||
await Activities.insertAsync({
|
||||
userId,
|
||||
activityType: 'deleteComment',
|
||||
boardId: doc.boardId,
|
||||
cardId: doc.cardId,
|
||||
commentId: doc._id,
|
||||
listId: card.listId,
|
||||
swimlaneId: card.swimlaneId,
|
||||
});
|
||||
}
|
||||
const activity = await ReactiveCache.getActivity({ commentId: doc._id });
|
||||
if (activity) {
|
||||
await Activities.removeAsync(activity._id);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('[CardComments.before.remove] Error while processing comment deletion for doc._id:', doc._id, e);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -177,10 +177,10 @@ Meteor.methods({
|
||||
},
|
||||
|
||||
async getOrgsCollectionCount(query = {}) {
|
||||
check(query, Match.OneOf(Object, null, undefined));
|
||||
if (!(await ReactiveCache.getCurrentUser())?.isAdmin) {
|
||||
throw new Meteor.Error('not-authorized');
|
||||
}
|
||||
check(query, Match.OneOf(Object, null, undefined));
|
||||
const cursor = await ReactiveCache.getOrgs(query || {}, {}, true);
|
||||
return typeof cursor.countAsync === 'function' ? await cursor.countAsync() : cursor.count();
|
||||
},
|
||||
|
||||
@@ -155,10 +155,10 @@ Meteor.methods({
|
||||
},
|
||||
|
||||
async getTeamsCollectionCount(query = {}) {
|
||||
check(query, Match.OneOf(Object, null, undefined));
|
||||
if (!(await ReactiveCache.getCurrentUser())?.isAdmin) {
|
||||
throw new Meteor.Error('not-authorized');
|
||||
}
|
||||
check(query, Match.OneOf(Object, null, undefined));
|
||||
const cursor = await ReactiveCache.getTeams(query || {}, {}, true);
|
||||
return typeof cursor.countAsync === 'function' ? await cursor.countAsync() : cursor.count();
|
||||
},
|
||||
|
||||
@@ -858,7 +858,7 @@ const runNotificationCleanup = async function runNotificationCleanup() {
|
||||
for (const user of await ReactiveCache.getUsers()) {
|
||||
if (!user.profile || !user.profile.notifications) continue;
|
||||
for (const notification of user.profile.notifications) {
|
||||
if (notification.read) {
|
||||
if (notification && notification.read) {
|
||||
const removeDate = new Date(notification.read);
|
||||
removeDate.setDate(removeDate.getDate() + removeAge);
|
||||
if (removeDate <= new Date()) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import Attachments from '/models/attachments';
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
|
||||
Meteor.publish('attachmentsList', async function(limit) {
|
||||
|
||||
+57
-155
@@ -40,7 +40,6 @@ import {
|
||||
OPERATOR_COMMENT,
|
||||
OPERATOR_CREATED_AT,
|
||||
OPERATOR_CREATOR,
|
||||
OPERATOR_DEBUG,
|
||||
OPERATOR_DUE,
|
||||
OPERATOR_HAS,
|
||||
OPERATOR_LABEL,
|
||||
@@ -80,10 +79,10 @@ import { CARD_TYPES } from '../../config/const';
|
||||
import Org from "../../models/org";
|
||||
import Team from "../../models/team";
|
||||
|
||||
Meteor.publish('card', async cardId => {
|
||||
Meteor.publish('card', async function(cardId) {
|
||||
check(cardId, String);
|
||||
|
||||
const userId = Meteor.userId();
|
||||
const userId = this.userId;
|
||||
const card = await ReactiveCache.getCard({ _id: cardId });
|
||||
|
||||
if (!card || !card.boardId) {
|
||||
@@ -233,14 +232,14 @@ Meteor.publish('myCards', async function(sessionId) {
|
||||
queryParams.addPredicate(OPERATOR_USER, (await ReactiveCache.getCurrentUser()).username);
|
||||
queryParams.setPredicate(OPERATOR_LIMIT, 200);
|
||||
|
||||
const query = Promise.await(buildQuery(queryParams));
|
||||
const query = Promise.await(buildQuery(queryParams, this.userId));
|
||||
query.projection.sort = {
|
||||
boardId: 1,
|
||||
swimlaneId: 1,
|
||||
listId: 1,
|
||||
};
|
||||
|
||||
const ret = findCards(sessionId, query);
|
||||
const ret = await findCards(sessionId, query, this.userId);
|
||||
return ret;
|
||||
});
|
||||
|
||||
@@ -253,10 +252,6 @@ Meteor.publish('dueCards', async function(allUsers = false) {
|
||||
return this.ready();
|
||||
}
|
||||
|
||||
if (process.env.DEBUG === 'true') {
|
||||
console.log('dueCards publication called for user:', userId, 'allUsers:', allUsers);
|
||||
}
|
||||
|
||||
// Get user's board memberships for efficient filtering
|
||||
const userBoards = (await ReactiveCache.getBoards({
|
||||
$or: [
|
||||
@@ -265,24 +260,7 @@ Meteor.publish('dueCards', async function(allUsers = false) {
|
||||
]
|
||||
})).map(board => board._id);
|
||||
|
||||
if (process.env.DEBUG === 'true') {
|
||||
console.log('dueCards userBoards:', userBoards);
|
||||
console.log('dueCards userBoards count:', userBoards.length);
|
||||
|
||||
// Also check if there are any cards with due dates in the system at all
|
||||
const cursor = Cards.find({
|
||||
type: 'cardType-card',
|
||||
archived: false,
|
||||
dueAt: { $exists: true, $nin: [null, ''] }
|
||||
});
|
||||
const allCardsWithDueDates = typeof cursor.countAsync === 'function' ? await cursor.countAsync() : cursor.count();
|
||||
console.log('dueCards: total cards with due dates in system:', allCardsWithDueDates);
|
||||
}
|
||||
|
||||
if (userBoards.length === 0) {
|
||||
if (process.env.DEBUG === 'true') {
|
||||
console.log('dueCards: No boards found for user, returning ready');
|
||||
}
|
||||
return this.ready();
|
||||
}
|
||||
|
||||
@@ -320,27 +298,8 @@ Meteor.publish('dueCards', async function(allUsers = false) {
|
||||
}
|
||||
};
|
||||
|
||||
if (process.env.DEBUG === 'true') {
|
||||
console.log('dueCards selector:', JSON.stringify(selector, null, 2));
|
||||
console.log('dueCards options:', JSON.stringify(options, null, 2));
|
||||
}
|
||||
|
||||
const result = Cards.find(selector, options);
|
||||
|
||||
if (process.env.DEBUG === 'true') {
|
||||
const count = typeof result.countAsync === 'function' ? await result.countAsync() : result.count();
|
||||
console.log('dueCards publication: returning', count, 'cards');
|
||||
if (count > 0) {
|
||||
const sampleCards = (typeof result.fetchAsync === 'function' ? await result.fetchAsync() : result.fetch()).slice(0, 3);
|
||||
console.log('dueCards publication: sample cards:', sampleCards.map(c => ({
|
||||
id: c._id,
|
||||
title: c.title,
|
||||
dueAt: c.dueAt,
|
||||
boardId: c.boardId
|
||||
})));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
});
|
||||
|
||||
@@ -349,44 +308,46 @@ Meteor.publish('globalSearch', async function(sessionId, params, text) {
|
||||
check(params, Object);
|
||||
check(text, String);
|
||||
|
||||
if (process.env.DEBUG === 'true') {
|
||||
console.log('globalSearch publication called with:', { sessionId, params, text });
|
||||
const ret = await findCards(sessionId, await buildQuery(new QueryParams(params, text), this.userId), this.userId);
|
||||
|
||||
if (!Array.isArray(ret)) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
const ret = findCards(sessionId, await buildQuery(new QueryParams(params, text)));
|
||||
if (process.env.DEBUG === 'true') {
|
||||
console.log('globalSearch publication returning:', ret);
|
||||
// Check if last item is the sessiondata marker
|
||||
let sessionDataToPublish = null;
|
||||
if (ret.length > 0 && ret[ret.length - 1] && ret[ret.length - 1]._sessionDataToFetch) {
|
||||
sessionDataToPublish = ret[ret.length - 1]._sessionDataToFetch;
|
||||
ret.pop(); // Remove the marker
|
||||
}
|
||||
|
||||
// Manually publish sessiondata if it exists
|
||||
if (sessionDataToPublish) {
|
||||
this.added('sessiondata', sessionDataToPublish._id, sessionDataToPublish);
|
||||
}
|
||||
|
||||
return ret;
|
||||
});
|
||||
|
||||
Meteor.publish('sessionData', function(sessionId) {
|
||||
Meteor.publish('sessionData', async function(sessionId) {
|
||||
check(sessionId, String);
|
||||
const userId = Meteor.userId();
|
||||
if (process.env.DEBUG === 'true') {
|
||||
console.log('sessionData publication called with:', { sessionId, userId });
|
||||
const userId = this.userId;
|
||||
|
||||
if (!userId) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Return the cursor immediately - data should already be in the collection
|
||||
// from the globalSearch publication or earlier searches
|
||||
const cursor = SessionData.find({ userId, sessionId });
|
||||
const countPromise = typeof cursor.countAsync === 'function' ? cursor.countAsync() : Promise.resolve(cursor.count());
|
||||
if (process.env.DEBUG === 'true') {
|
||||
countPromise.then(count => {
|
||||
console.log('sessionData publication returning cursor with count:', count);
|
||||
});
|
||||
}
|
||||
return cursor;
|
||||
});
|
||||
|
||||
async function buildSelector(queryParams) {
|
||||
const userId = Meteor.userId();
|
||||
|
||||
async function buildSelector(queryParams, userId) {
|
||||
const errors = new QueryErrors();
|
||||
|
||||
let selector = {};
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('queryParams:', queryParams);
|
||||
|
||||
if (queryParams.selector) {
|
||||
selector = queryParams.selector;
|
||||
} else {
|
||||
@@ -485,9 +446,6 @@ async function buildSelector(queryParams) {
|
||||
}
|
||||
} else {
|
||||
const userBoardIds = await Boards.userBoardIds(userId, null, boardsSelector);
|
||||
if (process.env.DEBUG === 'true') {
|
||||
console.log('buildSelector - userBoardIds:', userBoardIds);
|
||||
}
|
||||
selector.boardId = {
|
||||
$in: userBoardIds,
|
||||
};
|
||||
@@ -662,8 +620,6 @@ async function buildSelector(queryParams) {
|
||||
}
|
||||
}
|
||||
if (queryLabels.length) {
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('queryLabels:', queryLabels);
|
||||
selector.labelIds = { $in: [...new Set(queryLabels)] };
|
||||
}
|
||||
}
|
||||
@@ -805,10 +761,6 @@ async function buildSelector(queryParams) {
|
||||
}
|
||||
}
|
||||
|
||||
if (process.env.DEBUG === 'true') {
|
||||
console.log('buildSelector - final selector:', JSON.stringify(selector, null, 2));
|
||||
}
|
||||
|
||||
const query = new Query();
|
||||
query.selector = selector;
|
||||
query.setQueryParams(queryParams);
|
||||
@@ -818,8 +770,7 @@ async function buildSelector(queryParams) {
|
||||
}
|
||||
|
||||
function buildProjection(query) {
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('query:', query);
|
||||
|
||||
let skip = 0;
|
||||
if (query.getQueryParams().skip) {
|
||||
skip = query.getQueryParams().skip;
|
||||
@@ -913,16 +864,15 @@ function buildProjection(query) {
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('projection:', projection);
|
||||
|
||||
|
||||
query.projection = projection;
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
async function buildQuery(queryParams) {
|
||||
const query = await buildSelector(queryParams);
|
||||
async function buildQuery(queryParams, userId) {
|
||||
const query = await buildSelector(queryParams, userId);
|
||||
|
||||
return buildProjection(query);
|
||||
}
|
||||
@@ -932,16 +882,15 @@ Meteor.publish('brokenCards', async function(sessionId) {
|
||||
|
||||
const params = new QueryParams();
|
||||
params.addPredicate(OPERATOR_STATUS, PREDICATE_ALL);
|
||||
const query = await buildQuery(params);
|
||||
const query = await buildQuery(params, this.userId);
|
||||
query.selector.$or = [
|
||||
{ boardId: { $in: [null, ''] } },
|
||||
{ swimlaneId: { $in: [null, ''] } },
|
||||
{ listId: { $in: [null, ''] } },
|
||||
{ type: { $nin: CARD_TYPES } },
|
||||
];
|
||||
// console.log('brokenCards selector:', query.selector);
|
||||
|
||||
const ret = findCards(sessionId, query);
|
||||
const ret = await findCards(sessionId, query, this.userId);
|
||||
return ret;
|
||||
});
|
||||
|
||||
@@ -952,7 +901,7 @@ Meteor.publish('nextPage', async function(sessionId) {
|
||||
const projection = session.getProjection();
|
||||
projection.skip = session.lastHit;
|
||||
|
||||
const ret = findCards(sessionId, new Query(session.getSelector(), projection));
|
||||
const ret = await findCards(sessionId, new Query(session.getSelector(), projection), this.userId);
|
||||
return ret;
|
||||
});
|
||||
|
||||
@@ -963,21 +912,11 @@ Meteor.publish('previousPage', async function(sessionId) {
|
||||
const projection = session.getProjection();
|
||||
projection.skip = session.lastHit - session.resultsCount - projection.limit;
|
||||
|
||||
const ret = findCards(sessionId, new Query(session.getSelector(), projection));
|
||||
const ret = await findCards(sessionId, new Query(session.getSelector(), projection), this.userId);
|
||||
return ret;
|
||||
});
|
||||
|
||||
async function findCards(sessionId, query) {
|
||||
const userId = Meteor.userId();
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
if (process.env.DEBUG === 'true') {
|
||||
console.log('findCards - userId:', userId);
|
||||
console.log('findCards - selector:', JSON.stringify(query.selector, null, 2));
|
||||
console.log('findCards - selector.$and:', query.selector.$and);
|
||||
console.log('findCards - projection:', query.projection);
|
||||
}
|
||||
|
||||
async function findCards(sessionId, query, userId) {
|
||||
let textMatches = query.getQueryParams().text;
|
||||
let isTextSearch = !!textMatches;
|
||||
let dbProjection = query.projection;
|
||||
@@ -1014,9 +953,7 @@ async function findCards(sessionId, query) {
|
||||
cards = await ReactiveCache.getCards({ _id: { $in: orderedIds } }, { fields: query.projection.fields }, true);
|
||||
}
|
||||
|
||||
if (process.env.DEBUG === 'true') {
|
||||
console.log('findCards - cards count:', totalCardsCount);
|
||||
}
|
||||
|
||||
|
||||
const update = {
|
||||
$set: {
|
||||
@@ -1027,12 +964,11 @@ async function findCards(sessionId, query) {
|
||||
selector: SessionData.pickle(query.selector),
|
||||
projection: SessionData.pickle(query.projection),
|
||||
errors: query.errors(),
|
||||
debug: query.getQueryParams().getPredicate(OPERATOR_DEBUG),
|
||||
modifiedAt: new Date()
|
||||
},
|
||||
};
|
||||
|
||||
if (cards) {
|
||||
if (cards && totalCardsCount > 0) {
|
||||
update.$set.totalHits = totalCardsCount;
|
||||
update.$set.lastHit =
|
||||
query.projection.skip + query.projection.limit < totalCardsCount
|
||||
@@ -1043,27 +979,17 @@ async function findCards(sessionId, query) {
|
||||
if (isTextSearch) {
|
||||
update.$set.cards = orderedIds;
|
||||
} else {
|
||||
update.$set.cards = cards.map(card => card._id);
|
||||
const cardArray = typeof cards.fetchAsync === 'function' ? await cards.fetchAsync() : cards.fetch();
|
||||
update.$set.cards = cardArray.map(card => card._id);
|
||||
}
|
||||
update.$set.resultsCount = update.$set.cards.length;
|
||||
}
|
||||
|
||||
if (process.env.DEBUG === 'true') {
|
||||
console.log('findCards - sessionId:', sessionId);
|
||||
console.log('findCards - userId:', userId);
|
||||
console.log('findCards - update:', JSON.stringify(update, null, 2));
|
||||
}
|
||||
const upsertResult = SessionData.upsert({ userId, sessionId }, update);
|
||||
if (process.env.DEBUG === 'true') {
|
||||
console.log('findCards - upsertResult:', upsertResult);
|
||||
}
|
||||
|
||||
const upsertResult = typeof SessionData.upsertAsync === 'function' ? await SessionData.upsertAsync({ userId, sessionId }, update) : SessionData.upsert({ userId, sessionId }, update);
|
||||
|
||||
// Check if the session data was actually stored
|
||||
const storedSessionData = typeof SessionData.findOneAsync === 'function' ? await SessionData.findOneAsync({ userId, sessionId }) : SessionData.findOne({ userId, sessionId });
|
||||
if (process.env.DEBUG === 'true') {
|
||||
console.log('findCards - stored session data:', storedSessionData);
|
||||
console.log('findCards - stored session data count:', storedSessionData ? 1 : 0);
|
||||
}
|
||||
|
||||
// remove old session data
|
||||
const removeSelector = {
|
||||
@@ -1080,14 +1006,17 @@ async function findCards(sessionId, query) {
|
||||
SessionData.remove(removeSelector);
|
||||
}
|
||||
|
||||
if (cards) {
|
||||
if (cards && totalCardsCount > 0) {
|
||||
const boards = [];
|
||||
const swimlanes = [];
|
||||
const lists = [];
|
||||
const customFieldIds = [];
|
||||
const users = [this.userId];
|
||||
const users = [userId];
|
||||
|
||||
cards.forEach(card => {
|
||||
const cardArray = typeof cards.fetchAsync === 'function' ? await cards.fetchAsync() : cards.fetch();
|
||||
const cardIds = cardArray.map(c => c._id);
|
||||
|
||||
cardArray.forEach(card => {
|
||||
if (card.boardId) boards.push(card.boardId);
|
||||
if (card.swimlaneId) swimlanes.push(card.swimlaneId);
|
||||
if (card.listId) lists.push(card.listId);
|
||||
@@ -1119,27 +1048,7 @@ async function findCards(sessionId, query) {
|
||||
type: 1,
|
||||
};
|
||||
|
||||
// Add a small delay to ensure the session data is committed to the database
|
||||
Meteor.setTimeout(() => {
|
||||
const sessionDataCursor = SessionData.find({ userId, sessionId });
|
||||
if (process.env.DEBUG === 'true') {
|
||||
console.log('findCards - publishing session data cursor (after delay):', sessionDataCursor);
|
||||
const countPromise = typeof sessionDataCursor.countAsync === 'function' ? sessionDataCursor.countAsync() : Promise.resolve(sessionDataCursor.count());
|
||||
countPromise.then(count => {
|
||||
console.log('findCards - session data count (after delay):', count);
|
||||
});
|
||||
}
|
||||
}, 100);
|
||||
|
||||
const sessionDataCursor = SessionData.find({ userId, sessionId });
|
||||
if (process.env.DEBUG === 'true') {
|
||||
console.log('findCards - publishing session data cursor:', sessionDataCursor);
|
||||
const countPromise = typeof sessionDataCursor.countAsync === 'function' ? sessionDataCursor.countAsync() : Promise.resolve(sessionDataCursor.count());
|
||||
countPromise.then(count => {
|
||||
console.log('findCards - session data count:', count);
|
||||
});
|
||||
}
|
||||
|
||||
// Return all cursors except sessiondata - we'll add sessiondata separately after fetch
|
||||
return [
|
||||
cards,
|
||||
await ReactiveCache.getBoards(
|
||||
@@ -1155,21 +1064,14 @@ async function findCards(sessionId, query) {
|
||||
await ReactiveCache.getLists({ _id: { $in: lists } }, { fields: { ...fields, color: 1 } }, true),
|
||||
await ReactiveCache.getCustomFields({ _id: { $in: customFieldIds } }, {}, true),
|
||||
await ReactiveCache.getUsers({ _id: { $in: users } }, { fields: Users.safeFields }, true),
|
||||
await ReactiveCache.getChecklists({ cardId: { $in: cards.map(c => c._id) } }, {}, true),
|
||||
await ReactiveCache.getChecklistItems({ cardId: { $in: cards.map(c => c._id) } }, {}, true),
|
||||
(await ReactiveCache.getAttachments({ 'meta.cardId': { $in: cards.map(c => c._id) } }, {}, true)).cursor,
|
||||
await ReactiveCache.getCardComments({ cardId: { $in: cards.map(c => c._id) } }, {}, true),
|
||||
sessionDataCursor,
|
||||
await ReactiveCache.getChecklists({ cardId: { $in: cardIds } }, {}, true),
|
||||
await ReactiveCache.getChecklistItems({ cardId: { $in: cardIds } }, {}, true),
|
||||
(await ReactiveCache.getAttachments({ 'meta.cardId': { $in: cardIds } }, {}, true)).cursor,
|
||||
await ReactiveCache.getCardComments({ cardId: { $in: cardIds } }, {}, true),
|
||||
{ _sessionDataToFetch: storedSessionData }, // Pass sessiondata separately
|
||||
];
|
||||
} else {
|
||||
// Return just a marker for sessiondata
|
||||
return [{ _sessionDataToFetch: storedSessionData }];
|
||||
}
|
||||
|
||||
const sessionDataCursor = SessionData.find({ userId, sessionId });
|
||||
if (process.env.DEBUG === 'true') {
|
||||
console.log('findCards - publishing session data cursor (no cards):', sessionDataCursor);
|
||||
const countPromise = typeof sessionDataCursor.countAsync === 'function' ? sessionDataCursor.countAsync() : Promise.resolve(sessionDataCursor.count());
|
||||
countPromise.then(count => {
|
||||
console.log('findCards - session data count (no cards):', count);
|
||||
});
|
||||
}
|
||||
return [sessionDataCursor];
|
||||
}
|
||||
+5
-1
@@ -3,7 +3,7 @@
|
||||
# All supported keys are defined here together with descriptions and default values
|
||||
|
||||
# list of supported keys
|
||||
keys="DEBUG S3 MONGO_LOG_DESTINATION MONGO_URL MONGODB_BIND_UNIX_SOCKET MONGO_URL MONGODB_BIND_IP MONGODB_PORT MAIL_URL MAIL_FROM MAIL_SERVICE MAIL_SERVICE_USER MAIL_SERVICE_PASSWORD ROOT_URL PORT DISABLE_MONGODB CADDY_ENABLED CADDY_BIND_PORT WITH_API RICHER_CARD_COMMENT_EDITOR CARD_OPENED_WEBHOOK_ENABLED ACCOUNTS_LOCKOUT_KNOWN_USERS_FAILURES_BEFORE ACCOUNTS_LOCKOUT_KNOWN_USERS_PERIOD ACCOUNTS_LOCKOUT_KNOWN_USERS_FAILURE_WINDOW ACCOUNTS_LOCKOUT_UNKNOWN_USERS_FAILURES_BERORE ACCOUNTS_LOCKOUT_UNKNOWN_USERS_LOCKOUT_PERIOD ACCOUNTS_LOCKOUT_UNKNOWN_USERS_FAILURE_WINDOW ACCOUNTS_COMMON_LOGIN_EXPIRATION_IN_DAYS ATTACHMENTS_UPLOAD_EXTERNAL_PROGRAM ATTACHMENTS_UPLOAD_MIME_TYPES ATTACHMENTS_UPLOAD_MAX_SIZE AVATARS_UPLOAD_EXTERNAL_PROGRAM AVATARS_UPLOAD_MIME_TYPES AVATARS_UPLOAD_MAX_SIZE MAX_IMAGE_PIXEL IMAGE_COMPRESS_RATIO BIGEVENTS_PATTERN NOTIFICATION_TRAY_AFTER_READ_DAYS_BEFORE_REMOVE NOTIFY_DUE_DAYS_BEFORE_AND_AFTER NOTIFY_DUE_AT_HOUR_OF_DAY DEFAULT_BOARD_ID EMAIL_NOTIFICATION_TIMEOUT CORS CORS_ALLOW_HEADERS CORS_EXPOSE_HEADERS MATOMO_ADDRESS MATOMO_SITE_ID MATOMO_DO_NOT_TRACK MATOMO_WITH_USERNAME METRICS_ALLOWED_IP_ADDRESSES BROWSER_POLICY_ENABLED TRUSTED_URL WEBHOOKS_ATTRIBUTES OAUTH2_ENABLED OIDC_REDIRECTION_ENABLED OAUTH2_CA_CERT OAUTH2_LOGIN_STYLE OAUTH2_CLIENT_ID OAUTH2_SECRET OAUTH2_SERVER_URL OAUTH2_AUTH_ENDPOINT OAUTH2_USERINFO_ENDPOINT OAUTH2_TOKEN_ENDPOINT OAUTH2_ID_MAP OAUTH2_USERNAME_MAP OAUTH2_FULLNAME_MAP OAUTH2_ID_TOKEN_WHITELIST_FIELDS OAUTH2_EMAIL_MAP OAUTH2_REQUEST_PERMISSIONS OAUTH2_ADFS_ENABLED OAUTH2_B2C_ENABLED LDAP_ENABLE LDAP_PORT LDAP_HOST LDAP_AD_SIMPLE_AUTH LDAP_BASEDN LDAP_LOGIN_FALLBACK LDAP_RECONNECT LDAP_TIMEOUT LDAP_IDLE_TIMEOUT LDAP_CONNECT_TIMEOUT LDAP_AUTHENTIFICATION LDAP_AUTHENTIFICATION_USERDN LDAP_AUTHENTIFICATION_PASSWORD LDAP_LOG_ENABLED LDAP_BACKGROUND_SYNC LDAP_BACKGROUND_SYNC_INTERVAL LDAP_BACKGROUND_SYNC_KEEP_EXISTANT_USERS_UPDATED LDAP_BACKGROUND_SYNC_IMPORT_NEW_USERS LDAP_ENCRYPTION LDAP_CA_CERT LDAP_REJECT_UNAUTHORIZED LDAP_USER_AUTHENTICATION LDAP_USER_AUTHENTICATION_FIELD LDAP_USER_SEARCH_FILTER LDAP_USER_SEARCH_SCOPE LDAP_USER_SEARCH_FIELD LDAP_SEARCH_PAGE_SIZE LDAP_SEARCH_SIZE_LIMIT LDAP_GROUP_FILTER_ENABLE LDAP_GROUP_FILTER_OBJECTCLASS LDAP_GROUP_FILTER_GROUP_ID_ATTRIBUTE LDAP_GROUP_FILTER_GROUP_MEMBER_ATTRIBUTE LDAP_GROUP_FILTER_GROUP_MEMBER_FORMAT LDAP_GROUP_FILTER_GROUP_NAME LDAP_UNIQUE_IDENTIFIER_FIELD LDAP_UTF8_NAMES_SLUGIFY LDAP_USERNAME_FIELD LDAP_FULLNAME_FIELD LDAP_MERGE_EXISTING_USERS LDAP_SYNC_USER_DATA LDAP_SYNC_USER_DATA_FIELDMAP LDAP_SYNC_GROUP_ROLES LDAP_DEFAULT_DOMAIN LDAP_EMAIL_MATCH_ENABLE LDAP_EMAIL_MATCH_REQUIRE LDAP_EMAIL_MATCH_VERIFIED LDAP_EMAIL_FIELD LDAP_SYNC_ADMIN_STATUS LDAP_SYNC_ADMIN_GROUPS HEADER_LOGIN_ID HEADER_LOGIN_FIRSTNAME HEADER_LOGIN_LASTNAME HEADER_LOGIN_EMAIL LOGOUT_WITH_TIMER LOGOUT_IN LOGOUT_ON_HOURS LOGOUT_ON_MINUTES DEFAULT_AUTHENTICATION_METHOD PASSWORD_LOGIN_ENABLED CAS_ENABLED CAS_BASE_URL CAS_LOGIN_URL CAS_VALIDATE_URL SAML_ENABLED SAML_PROVIDER SAML_ENTRYPOINT SAML_ISSUER SAML_CERT SAML_IDPSLO_REDIRECTURL SAML_PRIVATE_KEYFILE SAML_PUBLIC_CERTFILE SAML_IDENTIFIER_FORMAT SAML_LOCAL_PROFILE_MATCH_ATTRIBUTE SAML_ATTRIBUTES ORACLE_OIM_ENABLED RESULTS_PER_PAGE WAIT_SPINNER NODE_OPTIONS LDAP_AUTHENTIFICATION_PASSWORD_FILE OAUTH2_SECRET_FILE MAIL_SERVICE_PASSWORD_FILE MONGO_PASSWORD_FILE S3_SECRET_FILE"
|
||||
keys="DEBUG S3 MONGO_LOG_DESTINATION MONGO_URL MONGO_OPLOG_URL MONGODB_BIND_UNIX_SOCKET MONGO_URL MONGODB_BIND_IP MONGODB_PORT MAIL_URL MAIL_FROM MAIL_SERVICE MAIL_SERVICE_USER MAIL_SERVICE_PASSWORD ROOT_URL PORT DISABLE_MONGODB CADDY_ENABLED CADDY_BIND_PORT WITH_API RICHER_CARD_COMMENT_EDITOR CARD_OPENED_WEBHOOK_ENABLED ACCOUNTS_LOCKOUT_KNOWN_USERS_FAILURES_BEFORE ACCOUNTS_LOCKOUT_KNOWN_USERS_PERIOD ACCOUNTS_LOCKOUT_KNOWN_USERS_FAILURE_WINDOW ACCOUNTS_LOCKOUT_UNKNOWN_USERS_FAILURES_BERORE ACCOUNTS_LOCKOUT_UNKNOWN_USERS_LOCKOUT_PERIOD ACCOUNTS_LOCKOUT_UNKNOWN_USERS_FAILURE_WINDOW ACCOUNTS_COMMON_LOGIN_EXPIRATION_IN_DAYS ATTACHMENTS_UPLOAD_EXTERNAL_PROGRAM ATTACHMENTS_UPLOAD_MIME_TYPES ATTACHMENTS_UPLOAD_MAX_SIZE AVATARS_UPLOAD_EXTERNAL_PROGRAM AVATARS_UPLOAD_MIME_TYPES AVATARS_UPLOAD_MAX_SIZE MAX_IMAGE_PIXEL IMAGE_COMPRESS_RATIO BIGEVENTS_PATTERN NOTIFICATION_TRAY_AFTER_READ_DAYS_BEFORE_REMOVE NOTIFY_DUE_DAYS_BEFORE_AND_AFTER NOTIFY_DUE_AT_HOUR_OF_DAY DEFAULT_BOARD_ID EMAIL_NOTIFICATION_TIMEOUT CORS CORS_ALLOW_HEADERS CORS_EXPOSE_HEADERS MATOMO_ADDRESS MATOMO_SITE_ID MATOMO_DO_NOT_TRACK MATOMO_WITH_USERNAME METRICS_ALLOWED_IP_ADDRESSES BROWSER_POLICY_ENABLED TRUSTED_URL WEBHOOKS_ATTRIBUTES OAUTH2_ENABLED OIDC_REDIRECTION_ENABLED OAUTH2_CA_CERT OAUTH2_LOGIN_STYLE OAUTH2_CLIENT_ID OAUTH2_SECRET OAUTH2_SERVER_URL OAUTH2_AUTH_ENDPOINT OAUTH2_USERINFO_ENDPOINT OAUTH2_TOKEN_ENDPOINT OAUTH2_ID_MAP OAUTH2_USERNAME_MAP OAUTH2_FULLNAME_MAP OAUTH2_ID_TOKEN_WHITELIST_FIELDS OAUTH2_EMAIL_MAP OAUTH2_REQUEST_PERMISSIONS OAUTH2_ADFS_ENABLED OAUTH2_B2C_ENABLED LDAP_ENABLE LDAP_PORT LDAP_HOST LDAP_AD_SIMPLE_AUTH LDAP_BASEDN LDAP_LOGIN_FALLBACK LDAP_RECONNECT LDAP_TIMEOUT LDAP_IDLE_TIMEOUT LDAP_CONNECT_TIMEOUT LDAP_AUTHENTIFICATION LDAP_AUTHENTIFICATION_USERDN LDAP_AUTHENTIFICATION_PASSWORD LDAP_LOG_ENABLED LDAP_BACKGROUND_SYNC LDAP_BACKGROUND_SYNC_INTERVAL LDAP_BACKGROUND_SYNC_KEEP_EXISTANT_USERS_UPDATED LDAP_BACKGROUND_SYNC_IMPORT_NEW_USERS LDAP_ENCRYPTION LDAP_CA_CERT LDAP_REJECT_UNAUTHORIZED LDAP_USER_AUTHENTICATION LDAP_USER_AUTHENTICATION_FIELD LDAP_USER_SEARCH_FILTER LDAP_USER_SEARCH_SCOPE LDAP_USER_SEARCH_FIELD LDAP_SEARCH_PAGE_SIZE LDAP_SEARCH_SIZE_LIMIT LDAP_GROUP_FILTER_ENABLE LDAP_GROUP_FILTER_OBJECTCLASS LDAP_GROUP_FILTER_GROUP_ID_ATTRIBUTE LDAP_GROUP_FILTER_GROUP_MEMBER_ATTRIBUTE LDAP_GROUP_FILTER_GROUP_MEMBER_FORMAT LDAP_GROUP_FILTER_GROUP_NAME LDAP_UNIQUE_IDENTIFIER_FIELD LDAP_UTF8_NAMES_SLUGIFY LDAP_USERNAME_FIELD LDAP_FULLNAME_FIELD LDAP_MERGE_EXISTING_USERS LDAP_SYNC_USER_DATA LDAP_SYNC_USER_DATA_FIELDMAP LDAP_SYNC_GROUP_ROLES LDAP_DEFAULT_DOMAIN LDAP_EMAIL_MATCH_ENABLE LDAP_EMAIL_MATCH_REQUIRE LDAP_EMAIL_MATCH_VERIFIED LDAP_EMAIL_FIELD LDAP_SYNC_ADMIN_STATUS LDAP_SYNC_ADMIN_GROUPS HEADER_LOGIN_ID HEADER_LOGIN_FIRSTNAME HEADER_LOGIN_LASTNAME HEADER_LOGIN_EMAIL LOGOUT_WITH_TIMER LOGOUT_IN LOGOUT_ON_HOURS LOGOUT_ON_MINUTES DEFAULT_AUTHENTICATION_METHOD PASSWORD_LOGIN_ENABLED CAS_ENABLED CAS_BASE_URL CAS_LOGIN_URL CAS_VALIDATE_URL SAML_ENABLED SAML_PROVIDER SAML_ENTRYPOINT SAML_ISSUER SAML_CERT SAML_IDPSLO_REDIRECTURL SAML_PRIVATE_KEYFILE SAML_PUBLIC_CERTFILE SAML_IDENTIFIER_FORMAT SAML_LOCAL_PROFILE_MATCH_ATTRIBUTE SAML_ATTRIBUTES ORACLE_OIM_ENABLED RESULTS_PER_PAGE WAIT_SPINNER NODE_OPTIONS LDAP_AUTHENTIFICATION_PASSWORD_FILE OAUTH2_SECRET_FILE MAIL_SERVICE_PASSWORD_FILE MONGO_PASSWORD_FILE S3_SECRET_FILE"
|
||||
|
||||
DESCRIPTION_S3='AWS S3 for files. Example: {"s3":{"key": "xxx", "secret": "xxx", "bucket": "xxx", "region": "eu-west-1"}}'
|
||||
DEFAULT_S3=""
|
||||
@@ -49,6 +49,10 @@ DESCRIPTION_MONGO_URL="MONGO_URL. Default: ''"
|
||||
DEFAULT_MONGO_URL=""
|
||||
KEY_MONGO_URL='mongo-url'
|
||||
|
||||
DESCRIPTION_MONGO_OPLOG_URL="MongoDB Oplog URL. Default: 'mongodb://127.0.0.1:27017/local?replicaSet=rs0'"
|
||||
DEFAULT_MONGO_OPLOG_URL=""
|
||||
KEY_MONGO_OPLOG_URL="mongo-oplog-url"
|
||||
|
||||
DESCRIPTION_MONGODB_BIND_UNIX_SOCKET="mongodb binding unix socket. Example: /var/snap/wekan/current/share . Default: ''\n"\
|
||||
"\t\t\t Default behaviour will preffer binding over unix socket, to disable unix socket binding set value to 'nill' string\n"\
|
||||
"\t\t\t To bind to instance of mongodb provided through content interface,set value to relative path to the socket inside '$SNAP_DATA/shared' directory"
|
||||
|
||||
@@ -129,7 +129,44 @@ fi
|
||||
echo "Starting MongoDB 7.x server..."
|
||||
# Create PID file
|
||||
echo $$ > "${SNAP_COMMON}/mongodb.pid"
|
||||
|
||||
# Check if this is the first time MongoDB is starting
|
||||
INIT_MARKER="${SNAP_COMMON}/.replica_set_initialized"
|
||||
|
||||
# Start MongoDB directly in foreground with replica set
|
||||
# The replica set will be initialized by the init marker check below
|
||||
echo "Starting MongoDB 7.x server in foreground..."
|
||||
|
||||
# Start in background briefly to initialize replica set if needed
|
||||
if [ ! -f "$INIT_MARKER" ]; then
|
||||
echo "First startup detected - initializing replica set..."
|
||||
/snap/${SNAP_NAME}/current/bin/mongod \
|
||||
--dbpath="$MONGO_DATA_DIR" \
|
||||
--logpath="$MONGO_LOG_FILE" \
|
||||
--logappend $BIND_OPTIONS \
|
||||
--replSet rs0 --oplogSize 128 --fork
|
||||
|
||||
sleep 5
|
||||
|
||||
# Initialize replica set
|
||||
/snap/${SNAP_NAME}/current/bin/mongosh --port ${MONGODB_PORT:-27019} --eval "rs.initiate({_id: 'rs0', members: [{_id: 0, host: '127.0.0.1:${MONGODB_PORT:-27019}'}]})" 2>/dev/null || true
|
||||
|
||||
# Mark initialization as done
|
||||
touch "$INIT_MARKER"
|
||||
|
||||
# Kill the forked process gracefully
|
||||
echo "Stopping temporary MongoDB process..."
|
||||
/snap/${SNAP_NAME}/current/bin/mongosh --port ${MONGODB_PORT:-27019} --eval "db.getSiblingDB('admin').shutdownServer()" 2>/dev/null || true
|
||||
sleep 2
|
||||
|
||||
# Clean up any remaining process
|
||||
pkill -f "mongod.*${MONGODB_PORT:-27019}" 2>/dev/null || true
|
||||
sleep 1
|
||||
fi
|
||||
|
||||
# Final start of MongoDB in foreground (this becomes the main process)
|
||||
exec /snap/${SNAP_NAME}/current/bin/mongod \
|
||||
--dbpath="$MONGO_DATA_DIR" \
|
||||
--logpath="$MONGO_LOG_FILE" \
|
||||
--logappend $BIND_OPTIONS
|
||||
--logappend $BIND_OPTIONS \
|
||||
--replSet rs0 --oplogSize 128
|
||||
@@ -14,6 +14,9 @@ if [ "nill" != "$MONGODB_BIND_UNIX_SOCKET" ] && [ "x" != "x$MONGODB_BIND_UNIX_SO
|
||||
else
|
||||
[ "x" == "x$MONGODB_BIND_IP" ] && MONGODB_BIND_IP="127.0.0.1"
|
||||
export MONGO_URL="mongodb://$MONGODB_BIND_IP:$MONGODB_PORT/wekan"
|
||||
if [ -z "$MONGO_OPLOG_URL" ]; then
|
||||
export MONGO_OPLOG_URL="mongodb://$MONGODB_BIND_IP:$MONGODB_PORT/local?replicaSet=rs0"
|
||||
fi
|
||||
fi
|
||||
|
||||
# If uploads directory does not exist, create it.
|
||||
|
||||
+51
-162
@@ -1,5 +1,5 @@
|
||||
name: wekan
|
||||
adopt-info: wekan
|
||||
version: '8.71'
|
||||
base: core24
|
||||
summary: Open Source kanban
|
||||
description: |
|
||||
@@ -22,22 +22,11 @@ issues: https://github.com/wekan/wekan/issues
|
||||
source-code: https://github.com/wekan/wekan
|
||||
website: https://wekan.fi
|
||||
|
||||
# Use platforms instead of architectures for core24 base
|
||||
platforms:
|
||||
amd64:
|
||||
build-on: amd64
|
||||
build-for: amd64
|
||||
arm64:
|
||||
build-on: arm64
|
||||
build-for: arm64
|
||||
armhf:
|
||||
build-on: armhf
|
||||
build-for: armhf
|
||||
s390x:
|
||||
build-on: s390x
|
||||
build-for: s390x
|
||||
ppc64el:
|
||||
build-on: ppc64el
|
||||
build-for: ppc64el
|
||||
|
||||
plugs:
|
||||
mongodb-plug:
|
||||
@@ -86,13 +75,11 @@ apps:
|
||||
command: ./bin/mongodb-restore
|
||||
plugs: [network, network-bind]
|
||||
|
||||
|
||||
parts:
|
||||
mongodb:
|
||||
plugin: nil
|
||||
build-packages:
|
||||
- wget
|
||||
- ca-certificates
|
||||
- qemu-user-static
|
||||
source: https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-ubuntu2204-7.0.31.tgz
|
||||
plugin: dump
|
||||
stage-packages:
|
||||
- libssl3
|
||||
- libcurl4
|
||||
@@ -107,116 +94,21 @@ parts:
|
||||
- libboost-filesystem1.74.0
|
||||
- libboost-program-options1.74.0
|
||||
- libgoogle-perftools4
|
||||
override-build: |
|
||||
SNAP_ARCH=$(dpkg --print-architecture)
|
||||
MONGODB_VERSION="7.0.14"
|
||||
mkdir -p "$SNAPCRAFT_PART_INSTALL/bin" "$SNAPCRAFT_PART_INSTALL/usr"
|
||||
|
||||
case "$SNAP_ARCH" in
|
||||
amd64)
|
||||
wget -q "https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-ubuntu2204-${MONGODB_VERSION}.tgz"
|
||||
tar xzf "mongodb-linux-x86_64-ubuntu2204-${MONGODB_VERSION}.tgz" \
|
||||
--strip-components=1 -C "$SNAPCRAFT_PART_INSTALL"
|
||||
rm "mongodb-linux-x86_64-ubuntu2204-${MONGODB_VERSION}.tgz"
|
||||
wget -q https://downloads.mongodb.com/compass/mongosh-2.8.2-linux-x64.tgz
|
||||
tar xzf mongosh-2.8.2-linux-x64.tgz --strip-components=1 -C "$SNAPCRAFT_PART_INSTALL"
|
||||
rm mongosh-2.8.2-linux-x64.tgz
|
||||
wget -q https://fastdl.mongodb.org/tools/db/mongodb-database-tools-ubuntu2404-x86_64-100.13.0.tgz
|
||||
tar xzf mongodb-database-tools-ubuntu2404-x86_64-100.13.0.tgz \
|
||||
--strip-components=1 -C "$SNAPCRAFT_PART_INSTALL"
|
||||
rm mongodb-database-tools-ubuntu2404-x86_64-100.13.0.tgz
|
||||
cp /usr/bin/qemu-x86_64-static "$SNAPCRAFT_PART_INSTALL/bin/"
|
||||
;;
|
||||
|
||||
arm64)
|
||||
wget -q "https://fastdl.mongodb.org/linux/mongodb-linux-aarch64-ubuntu2204-${MONGODB_VERSION}.tgz"
|
||||
tar xzf "mongodb-linux-aarch64-ubuntu2204-${MONGODB_VERSION}.tgz" \
|
||||
--strip-components=1 -C "$SNAPCRAFT_PART_INSTALL"
|
||||
rm "mongodb-linux-aarch64-ubuntu2204-${MONGODB_VERSION}.tgz"
|
||||
wget -q https://downloads.mongodb.com/compass/mongosh-2.8.2-linux-arm64.tgz
|
||||
tar xzf mongosh-2.8.2-linux-arm64.tgz --strip-components=1 -C "$SNAPCRAFT_PART_INSTALL"
|
||||
rm mongosh-2.8.2-linux-arm64.tgz
|
||||
wget -q https://fastdl.mongodb.org/tools/db/mongodb-database-tools-ubuntu2404-arm64-100.13.0.tgz
|
||||
tar xzf mongodb-database-tools-ubuntu2404-arm64-100.13.0.tgz \
|
||||
--strip-components=1 -C "$SNAPCRAFT_PART_INSTALL"
|
||||
rm mongodb-database-tools-ubuntu2404-arm64-100.13.0.tgz
|
||||
cp /usr/bin/qemu-aarch64-static "$SNAPCRAFT_PART_INSTALL/bin/"
|
||||
;;
|
||||
|
||||
armhf|s390x|ppc64el)
|
||||
apt-get install -y qemu-user-static
|
||||
cp /usr/bin/qemu-x86_64-static "$SNAPCRAFT_PART_INSTALL/bin/"
|
||||
wget -q "https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-ubuntu2204-${MONGODB_VERSION}.tgz"
|
||||
tar xzf "mongodb-linux-x86_64-ubuntu2204-${MONGODB_VERSION}.tgz" \
|
||||
--strip-components=1 -C "$SNAPCRAFT_PART_INSTALL"
|
||||
rm "mongodb-linux-x86_64-ubuntu2204-${MONGODB_VERSION}.tgz"
|
||||
|
||||
mv "$SNAPCRAFT_PART_INSTALL/bin/mongod" "$SNAPCRAFT_PART_INSTALL/bin/mongod.x86_64"
|
||||
|
||||
printf 'exec "$SNAP/bin/qemu-x86_64-static" -L "$SNAP/lib/x86_64-sysroot" "$SNAP/bin/mongod.x86_64" "$@"\n' \
|
||||
> "$SNAPCRAFT_PART_INSTALL/bin/mongod"
|
||||
chmod +x "$SNAPCRAFT_PART_INSTALL/bin/mongod"
|
||||
|
||||
wget -q https://downloads.mongodb.com/compass/mongosh-2.8.2-linux-x64.tgz
|
||||
tar xzf mongosh-2.8.2-linux-x64.tgz --strip-components=1 -C "$SNAPCRAFT_PART_INSTALL"
|
||||
rm mongosh-2.8.2-linux-x64.tgz
|
||||
mv "$SNAPCRAFT_PART_INSTALL/bin/mongosh" "$SNAPCRAFT_PART_INSTALL/bin/mongosh.x86_64"
|
||||
printf '#!/bin/sh\nexec "$SNAP/bin/qemu-x86_64-static" -L "$SNAP/lib/x86_64-sysroot" "$SNAP/bin/mongosh.x86_64" "$@"\n' \
|
||||
> "$SNAPCRAFT_PART_INSTALL/bin/mongosh"
|
||||
chmod +x "$SNAPCRAFT_PART_INSTALL/bin/mongosh"
|
||||
|
||||
wget -q https://fastdl.mongodb.org/tools/db/mongodb-database-tools-ubuntu2404-x86_64-100.13.0.tgz
|
||||
tar xzf mongodb-database-tools-ubuntu2404-x86_64-100.13.0.tgz \
|
||||
--strip-components=1 -C "$SNAPCRAFT_PART_INSTALL"
|
||||
rm mongodb-database-tools-ubuntu2404-x86_64-100.13.0.tgz
|
||||
for tool in mongodump mongorestore mongoexport mongoimport \
|
||||
mongostat mongotop mongofiles bsondump; do
|
||||
if [ -f "$SNAPCRAFT_PART_INSTALL/bin/$tool" ]; then
|
||||
mv "$SNAPCRAFT_PART_INSTALL/bin/$tool" \
|
||||
"$SNAPCRAFT_PART_INSTALL/bin/${tool}.x86_64"
|
||||
printf '#!/bin/sh\nexec "$SNAP/bin/qemu-x86_64-static" -L "$SNAP/lib/x86_64-sysroot" "$SNAP/bin/%s.x86_64" "$@"\n' \
|
||||
"$tool" > "$SNAPCRAFT_PART_INSTALL/bin/$tool"
|
||||
chmod +x "$SNAPCRAFT_PART_INSTALL/bin/$tool"
|
||||
fi
|
||||
done
|
||||
|
||||
SYSROOT="$SNAPCRAFT_PART_INSTALL/lib/x86_64-sysroot"
|
||||
mkdir -p "$SYSROOT"
|
||||
dpkg --add-architecture amd64
|
||||
apt-get update -qq
|
||||
mkdir -p /tmp/amd64-debs
|
||||
cd /tmp/amd64-debs
|
||||
apt-get download \
|
||||
libc6:amd64 \
|
||||
libstdc++6:amd64 \
|
||||
libgcc-s1:amd64 \
|
||||
libssl3:amd64 \
|
||||
libcurl4:amd64 \
|
||||
zlib1g:amd64 \
|
||||
libsnappy1v5:amd64 \
|
||||
libyaml-cpp0.8:amd64 \
|
||||
libboost-filesystem1.74.0:amd64 \
|
||||
libboost-iostreams1.74.0:amd64 \
|
||||
libboost-program-options1.74.0:amd64 \
|
||||
libboost-system1.74.0:amd64 \
|
||||
2>/dev/null || true
|
||||
for deb in /tmp/amd64-debs/*.deb; do
|
||||
[ -f "$deb" ] && dpkg-deb -x "$deb" "$SYSROOT/" || true
|
||||
done
|
||||
cd "$SNAPCRAFT_PART_INSTALL"
|
||||
;;
|
||||
esac
|
||||
echo "mongodb" > "$SNAPCRAFT_PART_INSTALL/DATABASE_BACKEND"
|
||||
stage:
|
||||
- bin
|
||||
- usr
|
||||
- lib
|
||||
- DATABASE_BACKEND
|
||||
prime:
|
||||
- bin
|
||||
- usr
|
||||
- lib
|
||||
- DATABASE_BACKEND
|
||||
|
||||
mongosh:
|
||||
source: https://downloads.mongodb.com/compass/mongosh-2.8.2-linux-x64.tgz
|
||||
plugin: dump
|
||||
|
||||
mongotools:
|
||||
source: https://fastdl.mongodb.org/tools/db/mongodb-database-tools-ubuntu2404-x86_64-100.16.0.tgz
|
||||
plugin: dump
|
||||
|
||||
|
||||
wekan:
|
||||
source: .
|
||||
@@ -236,56 +128,33 @@ parts:
|
||||
- execstack
|
||||
- nodejs
|
||||
- npm
|
||||
- git
|
||||
stage-packages:
|
||||
- libfontconfig1
|
||||
override-build: |
|
||||
echo "Cleaning environment first"
|
||||
rm -rf .build
|
||||
# Haetaan versio package.jsonista
|
||||
RAW_VERSION=$(python3 -c "import json; print(json.load(open('package.json'))['version'])")
|
||||
# Siivotaan versio: poistetaan 'v' alusta ja '.0' lopusta (esim. 8.44.0 -> 8.44)
|
||||
# Wekan julkaisu-URLit ja tiedostonimet eivät käytä .0-päätettä.
|
||||
CLEAN_VERSION=$(echo $RAW_VERSION | sed 's/^v//' | sed 's/\.0$//')
|
||||
snapcraftctl set-version "${CLEAN_VERSION}"
|
||||
SNAP_ARCH=$(dpkg --print-architecture)
|
||||
case "$SNAP_ARCH" in
|
||||
amd64) WEKAN_ARCH="amd64" NODE_ARCH="x64" ;;
|
||||
arm64) WEKAN_ARCH="arm64" NODE_ARCH="arm64" ;;
|
||||
armhf) WEKAN_ARCH="armhf" NODE_ARCH="armv7l" ;;
|
||||
ppc64el) WEKAN_ARCH="ppc64le" NODE_ARCH="ppc64le" ;;
|
||||
s390x) WEKAN_ARCH="s390x" NODE_ARCH="s390x" ;;
|
||||
*) echo "Unsupported snap architecture: $SNAP_ARCH"; exit 1 ;;
|
||||
esac
|
||||
mkdir .build
|
||||
cd .build
|
||||
# Käytetään siivottua versiota URL-osoitteessa ja tiedostonimessä
|
||||
wget -q "https://github.com/wekan/wekan/releases/download/v${CLEAN_VERSION}/wekan-${CLEAN_VERSION}-${WEKAN_ARCH}.zip"
|
||||
unzip -q "wekan-${CLEAN_VERSION}-${WEKAN_ARCH}.zip"
|
||||
#npm install -g npm@10
|
||||
npm install --production --no-audit --prefix ./bundle/programs/server
|
||||
#npm install --production --no-audit --prefix ./bundle/programs/server @babel/parser underscore
|
||||
rm "wekan-${CLEAN_VERSION}-${WEKAN_ARCH}.zip"
|
||||
wget https://github.com/wekan/wekan/releases/download/v8.71/wekan-8.71-amd64.zip
|
||||
unzip wekan-8.71-amd64.zip
|
||||
rm wekan-8.71-amd64.zip
|
||||
cd ..
|
||||
NODE_VERSION="22.22.2"
|
||||
wget -q https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-${NODE_ARCH}.tar.gz
|
||||
tar -xf node-v${NODE_VERSION}-linux-${NODE_ARCH}.tar.gz \
|
||||
node-v${NODE_VERSION}-linux-${NODE_ARCH}/bin/node
|
||||
rm node-v${NODE_VERSION}-linux-${NODE_ARCH}.tar.gz
|
||||
mkdir -p $SNAPCRAFT_PART_INSTALL/bin
|
||||
cp -p node-v${NODE_VERSION}-linux-${NODE_ARCH}/bin/node $SNAPCRAFT_PART_INSTALL/bin/
|
||||
rm -rf node-v${NODE_VERSION}-linux-${NODE_ARCH}
|
||||
# Copy to Snap
|
||||
wget https://nodejs.org/dist/latest-v22.x/node-v22.22.2-linux-x64.tar.xz
|
||||
tar -xf node-v22.22.2-linux-x64.tar.xz node-v22.22.2-linux-x64/bin/node
|
||||
rm node-v22.22.2-linux-x64.tar.xz
|
||||
mkdir $SNAPCRAFT_PART_INSTALL/bin
|
||||
cp -p node-v22.22.2-linux-x64/bin/node $SNAPCRAFT_PART_INSTALL/bin/
|
||||
rm -rf node-v22.22.2-linux-x64
|
||||
cp -r .build/bundle/* $SNAPCRAFT_PART_INSTALL/
|
||||
cp .build/bundle/.node_version.txt $SNAPCRAFT_PART_INSTALL/
|
||||
rm -f $SNAPCRAFT_PART_INSTALL/lib/node_modules/wekan
|
||||
echo "Cloning migratemongo (CPU-feature QEMU wrappers)..."
|
||||
git clone https://github.com/wekan/migratemongo.git
|
||||
cp -pR migratemongo "$SNAPCRAFT_PART_INSTALL/"
|
||||
rm -rf migratemongo
|
||||
|
||||
organize:
|
||||
README: README.wekan
|
||||
prime:
|
||||
- -lib/node_modules/node-pre-gyp/node_modules/tar/lib/.unpack.js.swp
|
||||
- -lib/node_modules/weka*
|
||||
#prime:
|
||||
# - -lib/node_modules/node-pre-gyp/node_modules/tar/lib/.unpack.js.swp
|
||||
# - -lib/node_modules/weka*
|
||||
|
||||
helpers:
|
||||
source: snap-src
|
||||
@@ -300,6 +169,7 @@ parts:
|
||||
- gnupg
|
||||
- curl
|
||||
override-build: |
|
||||
# Add Caddy repository
|
||||
echo "Installing Caddy 2 from the official repository..."
|
||||
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | gpg --dearmor -o /tmp/caddy-stable-archive-keyring.gpg
|
||||
mkdir -p /etc/apt/keyrings
|
||||
@@ -307,13 +177,32 @@ parts:
|
||||
echo "deb [signed-by=/etc/apt/keyrings/caddy-stable-archive-keyring.gpg] https://dl.cloudsmith.io/public/caddy/stable/deb/debian any-version main" > /etc/apt/sources.list.d/caddy-stable.list
|
||||
apt update
|
||||
apt -y install caddy
|
||||
|
||||
# Display installed Caddy version for confirmation
|
||||
echo "Installed Caddy version:"
|
||||
/usr/bin/caddy version
|
||||
|
||||
# Create directory structure in the snap
|
||||
mkdir -p $SNAPCRAFT_PART_INSTALL/bin
|
||||
|
||||
# Copy Caddy binary
|
||||
cp /usr/bin/caddy $SNAPCRAFT_PART_INSTALL/bin/
|
||||
chmod +x $SNAPCRAFT_PART_INSTALL/bin/caddy
|
||||
|
||||
# Create license files manually since they don't exist in the package
|
||||
mkdir -p $SNAPCRAFT_PART_INSTALL/license
|
||||
echo "Caddy is licensed under the Apache License 2.0." > $SNAPCRAFT_PART_INSTALL/license/CADDY_LICENSE
|
||||
echo "Caddy is licensed under the Apache License 2.0. See https://github.com/caddyserver/caddy/blob/master/LICENSE" > $SNAPCRAFT_PART_INSTALL/license/CADDY_LICENSE
|
||||
|
||||
# Create a basic default Caddyfile for the snap
|
||||
mkdir -p $SNAPCRAFT_PART_INSTALL/etc
|
||||
printf ":8080 {\n reverse_proxy localhost:3000\n}\n" > $SNAPCRAFT_PART_INSTALL/etc/Caddyfile
|
||||
cat > $SNAPCRAFT_PART_INSTALL/etc/Caddyfile << 'EOF'
|
||||
# Default Caddyfile for Wekan
|
||||
# This is loaded by caddy-control script if no other config is provided
|
||||
|
||||
:8080 {
|
||||
reverse_proxy localhost:3000
|
||||
}
|
||||
EOF
|
||||
stage:
|
||||
- bin/caddy
|
||||
- license/CADDY_LICENSE
|
||||
|
||||
Reference in new issue
Block a user