mirror of
https://github.com/wekan/wekan.git
synced 2026-11-08 11:25:19 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1b57d09d0d | ||
|
|
e7d67e3ddb | ||
|
|
a4b5ac6c4e | ||
|
|
9b22f9e157 | ||
|
|
2ab0f59f13 | ||
|
|
611368abc6 | ||
|
|
d3b3be2a52 | ||
|
|
11a2c95ea7 | ||
|
|
3e612c39b7 | ||
|
|
58de6bb737 | ||
|
|
f6d8befb56 | ||
|
|
b49aa050e9 | ||
|
|
2ef8465e8d | ||
|
|
7878596608 | ||
|
|
1f2f9f571e | ||
|
|
855cb86088 | ||
|
|
ed3cf96c6f | ||
|
|
fdb477f351 | ||
|
|
ac6cc1041a | ||
|
|
7d09a649ac | ||
|
|
040ed6e605 | ||
|
|
d7e36f5157 | ||
|
|
1a08003834 | ||
|
|
64bc6ea71c | ||
|
|
ef4161889a | ||
|
|
dd9d6083c0 | ||
|
|
027b6a45a1 | ||
|
|
b717e5d7ad | ||
|
|
74965f5f95 | ||
|
|
fa812faf6d | ||
|
|
b459151798 | ||
|
|
73679919fb | ||
|
|
58b0ae29e1 | ||
|
|
773931a538 | ||
|
|
1ef814fe6b | ||
|
|
b010c687f3 | ||
|
|
05950fb287 | ||
|
|
56a685983b | ||
|
|
339c0a2bb7 | ||
|
|
a790453c9a | ||
|
|
04eb8a8fbb | ||
|
|
4ab1bc9638 | ||
|
|
699b9a9c71 | ||
|
|
3a203d274d | ||
|
|
887511fdda | ||
|
|
64f58455ff | ||
|
|
5163ec0da2 | ||
|
|
c47eb013b4 | ||
|
|
d4cbe12316 | ||
|
|
794222c85e | ||
|
|
675c661114 | ||
|
|
7700efde1f | ||
|
|
16832124ce | ||
|
|
bf5ca3d3eb | ||
|
|
189b6cae84 | ||
|
|
9bf0114148 | ||
|
|
9f3bbb5ed2 | ||
|
|
85b981e1c7 | ||
|
|
eb5ac8b7dd | ||
|
|
5ef32af248 | ||
|
|
9cb5837e3e | ||
|
|
5ae9c2b7ac | ||
|
|
7d16fed34e | ||
|
|
db2701f1d7 | ||
|
|
76818e2c98 | ||
|
|
c4e084ffbb | ||
|
|
a10b28bf6a | ||
|
|
90c0110615 | ||
|
|
73c594bb36 | ||
|
|
903544c680 | ||
|
|
32e1ec9d22 | ||
|
|
3516a21329 | ||
|
|
f6198dee30 | ||
|
|
13f14df880 | ||
|
|
f3ae64cf21 | ||
|
|
1820804b9f | ||
|
|
d3d76b12f7 | ||
|
|
51ad6ed99d | ||
|
|
1c8cea9ada | ||
|
|
a0c190137d | ||
|
|
83e1845290 | ||
|
|
052d8c1584 | ||
|
|
7b0e2213cf | ||
|
|
05e6d15478 | ||
|
|
be0283381b | ||
|
|
379a92846e | ||
|
|
bb6163a70f | ||
|
|
10f009f5b1 | ||
|
|
19c882ed2f | ||
|
|
e7cb6ac6f0 | ||
|
|
38e488ee4a | ||
|
|
589fa30fd1 | ||
|
|
64d351d835 | ||
|
|
4151ecb7e7 | ||
|
|
f4b5e5f07d | ||
|
|
c1639ea589 | ||
|
|
21b0ab064c | ||
|
|
1c0d8e9964 | ||
|
|
8a7949a8ab | ||
|
|
3c36db33e9 | ||
|
|
59d0cfc457 | ||
|
|
72f6d96dbc | ||
|
|
49c81f5426 | ||
|
|
08ed1705b1 | ||
|
|
47088c30c0 | ||
|
|
539dbdc034 | ||
|
|
129af0bad9 | ||
|
|
a9d95dd6b7 | ||
|
|
6d0978d0ed | ||
|
|
13cdf08e22 | ||
|
|
e59bc9cd86 | ||
|
|
6478d27d1c | ||
|
|
76d1800ec7 | ||
|
|
03ba747bc0 | ||
|
|
9eb3889d51 | ||
|
|
5d4bc7a886 | ||
|
|
135af977af | ||
|
|
6dfe81cbcb | ||
|
|
3ec2821058 | ||
|
|
1c5ac8efba | ||
|
|
ce7fa0e314 | ||
|
|
0f464b21a3 | ||
|
|
7169da8dae | ||
|
|
0f56e2dfc3 | ||
|
|
1b086c80a7 | ||
|
|
c27d5d0412 | ||
|
|
7b3043bf46 | ||
|
|
da19160e87 | ||
|
|
790a801f30 | ||
|
|
b08c66a483 | ||
|
|
524aa9124d | ||
|
|
df85b5ac45 | ||
|
|
c009ddc915 | ||
|
|
5407e4533c | ||
|
|
98088c7734 | ||
|
|
0d6fb33043 | ||
|
|
1dbad1b454 | ||
|
|
2c8a6c8ec6 | ||
|
|
06b9946dd8 | ||
|
|
dbcdf15244 | ||
|
|
7e2067d0b1 | ||
|
|
7489f720ea | ||
|
|
140e844238 | ||
|
|
de55d5afbe | ||
|
|
c5fccb52cc | ||
|
|
507ca57a50 | ||
|
|
b2e072e02c | ||
|
|
357f63d01f | ||
|
|
e6422d842a | ||
|
|
99519af83a | ||
|
|
514ce6ad24 | ||
|
|
f57ce52198 | ||
|
|
2a9c921ba6 | ||
|
|
0dd924f148 | ||
|
|
678eb0896d | ||
|
|
233c1c8e81 | ||
|
|
f6a851a3d8 | ||
|
|
4fba9d7802 | ||
|
|
d41ecb054c | ||
|
|
ec0c1bc9af | ||
|
|
05b77d24fa | ||
|
|
4535303807 | ||
|
|
f232fdc30b | ||
|
|
dab72d80dc | ||
|
|
6f83464b24 | ||
|
|
41cd0a8925 | ||
|
|
fc02a15753 | ||
|
|
bd9c5a058a | ||
|
|
c1692cc6b9 | ||
|
|
5259c09a5c | ||
|
|
10f801d31b | ||
|
|
28d19db328 | ||
|
|
0e13bfc50e | ||
|
|
4f4aa22ca1 | ||
|
|
6bec01198d | ||
|
|
5dbceb43b4 | ||
|
|
bc92978fa9 | ||
|
|
893f83b79e | ||
|
|
bde23f6c4d | ||
|
|
e6d4b38c64 | ||
|
|
23264044e6 | ||
|
|
d51a381a79 | ||
|
|
da4459304f | ||
|
|
085699f202 | ||
|
|
2c43aa463a | ||
|
|
41db7b4ad1 | ||
|
|
d0a9fa9a71 | ||
|
|
ed0675aaff | ||
|
|
cad8f58468 | ||
|
|
819d58cf31 | ||
|
|
b951515e3e | ||
|
|
4c3265bca5 | ||
|
|
11672a13f7 | ||
|
|
9a8141a0eb | ||
|
|
5462fb0647 | ||
|
|
6b74b8f770 | ||
|
|
99fff1a1a1 | ||
|
|
645f233b83 | ||
|
|
643e2738bd | ||
|
|
cd356a29ce | ||
|
|
341be982f9 | ||
|
|
2e7565f9eb | ||
|
|
1637a9c938 | ||
|
|
67c2be1858 | ||
|
|
b8d4c01e60 | ||
|
|
e259ab86f7 | ||
|
|
029b3523cb | ||
|
|
f4657ad817 | ||
|
|
5efddff154 | ||
|
|
25efe93507 | ||
|
|
a393e67ef8 | ||
|
|
7f6758cbe9 | ||
|
|
c5644a3321 | ||
|
|
4fec03101f | ||
|
|
10fed0a85c | ||
|
|
fff6316192 | ||
|
|
61623f50b1 | ||
|
|
9f626407cf | ||
|
|
3a51678495 | ||
|
|
c730a0e733 | ||
|
|
80a9971508 | ||
|
|
85788e1d7d | ||
|
|
23680547ea | ||
|
|
9767ead9f3 | ||
|
|
910c9a7f1f | ||
|
|
0bc6c6abb6 | ||
|
|
6361e16dba | ||
|
|
8572cbd761 | ||
|
|
1c0b91c5f4 | ||
|
|
2ebefdd0bf | ||
|
|
29f1384945 | ||
|
|
334e569fda | ||
|
|
2d4170a9bf | ||
|
|
6b2759f97d | ||
|
|
adf4312e5a | ||
|
|
b1707b8691 | ||
|
|
25dff3f2da | ||
|
|
bc88c0dfc2 | ||
|
|
1ca2dfd1b1 | ||
|
|
bdb9274485 | ||
|
|
14f9ac39ad | ||
|
|
d4b52f7de9 | ||
|
|
bdc65ec6f4 | ||
|
|
74966a0bc7 | ||
|
|
7fb31cecd5 | ||
|
|
317c82a9f0 | ||
|
|
9b5c89d235 | ||
|
|
c23e190e8e | ||
|
|
4a73371499 | ||
|
|
6f8af55489 | ||
|
|
2a05f62bf9 | ||
|
|
d6eb1eb76f | ||
|
|
27542f3a51 | ||
|
|
0328e70d5f | ||
|
|
c46932ee30 | ||
|
|
c7408ad8d1 | ||
|
|
05dc8f8f93 | ||
|
|
aea8c285c2 | ||
|
|
a859137971 | ||
|
|
08ebad0fe4 | ||
|
|
d54ebfa0e1 | ||
|
|
304a007d07 | ||
|
|
b6b58c9d95 | ||
|
|
7f0c42cca5 | ||
|
|
9508d46ebd | ||
|
|
bcbf4771ea | ||
|
|
9da5ec25c6 | ||
|
|
028b404377 | ||
|
|
8da0f34ee6 | ||
|
|
cac2628b19 | ||
|
|
9c69530256 | ||
|
|
6e108358d7 | ||
|
|
87f592c67f | ||
|
|
fc95abd587 | ||
|
|
ce3e51b147 | ||
|
|
bb48b23266 | ||
|
|
fdf00e06f5 | ||
|
|
950b246da8 | ||
|
|
6ac0df8448 | ||
|
|
80ae3a18a8 | ||
|
|
972bfb9677 | ||
|
|
b1149e4d6e | ||
|
|
3cd2ba847b | ||
|
|
8bf869654c | ||
|
|
3b98f862bc | ||
|
|
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 | ||
|
|
09e65ccac2 | ||
|
|
03e0cfdc15 | ||
|
|
7634cd6c2e | ||
|
|
4594711be4 | ||
|
|
c267933bf7 | ||
|
|
edc6b18b5f | ||
|
|
60657c6e94 | ||
|
|
3c189f9c7f | ||
|
|
bf02c9a453 | ||
|
|
e6b6cd3036 | ||
|
|
6e8589b1f9 | ||
|
|
1354f84a70 | ||
|
|
d07cf92f7c | ||
|
|
e079644ed6 | ||
|
|
6b393178dc | ||
|
|
26e1c9ab69 | ||
|
|
145a17fee5 | ||
|
|
ccc9301ed4 | ||
|
|
f2e46d660f | ||
|
|
8b4676175c | ||
|
|
e9a547c89b | ||
|
|
d07fcceb6a | ||
|
|
6b5002f314 | ||
|
|
5418ffd558 | ||
|
|
ea98afeb68 | ||
|
|
be7d7e26fb | ||
|
|
56377aaf4c | ||
|
|
43601c5e3e | ||
|
|
1db7f3a57d | ||
|
|
e58e99c285 | ||
|
|
b38e25c9f1 | ||
|
|
ce52b8a0ab | ||
|
|
f7800846a5 | ||
|
|
02b75824e5 | ||
|
|
cf52c2f6e4 | ||
|
|
6bc68ba57b | ||
|
|
5ec9cfa537 | ||
|
|
3457cab0b1 | ||
|
|
8349fb6b63 | ||
|
|
33267fa2e4 | ||
|
|
5c4130311a | ||
|
|
ed718f083a | ||
|
|
2aa8ecfc39 | ||
|
|
cdf1d3305b | ||
|
|
fd58bb9e4d | ||
|
|
55ec0b5ff5 | ||
|
|
e5c551f009 | ||
|
|
7666c6c0e1 | ||
|
|
e6ccbfd3b8 | ||
|
|
d8a2e06a95 | ||
|
|
c38fa1c272 | ||
|
|
1a5e23617d | ||
|
|
87916c20bf | ||
|
|
12c223d226 | ||
|
|
9ae2842fa4 | ||
|
|
79853a2fb7 | ||
|
|
ec1e383558 | ||
|
|
df067f01e8 | ||
|
|
4b8cc0683e | ||
|
|
f43b76c323 | ||
|
|
e90b2e384c | ||
|
|
6125822cf7 | ||
|
|
4223c2a79f |
No files matched your search
@@ -251,7 +251,7 @@ gosu wekan:wekan /home/wekan/.meteor/meteor -- help
|
||||
# Build app (Development)
|
||||
cd /home/wekan/app
|
||||
gosu wekan:wekan /home/wekan/.meteor/meteor add standard-minifier-js
|
||||
gosu wekan:wekan /home/wekan/.meteor/meteor npm install
|
||||
gosu wekan:wekan /home/wekan/.meteor/meteor npm install --no-audit
|
||||
|
||||
# Put back the original tar
|
||||
mv $(which tar)~ $(which tar)
|
||||
|
||||
@@ -0,0 +1,686 @@
|
||||
name: Release All Platforms
|
||||
|
||||
# Triggered manually via GitHub CLI or Actions UI.
|
||||
# Usage:
|
||||
# gh workflow run release-all.yml -f old_version=8.42 -f new_version=8.43
|
||||
#
|
||||
# Or use the convenience script (commits pending changes, pushes, and triggers):
|
||||
# ./releases/release-all.sh 8.42 8.43
|
||||
#
|
||||
# Required GitHub Secrets:
|
||||
# GHCR_AUTH - base64(username:token) for ghcr.io
|
||||
# DOCKERHUB_AUTH - base64(username:token) for Docker Hub
|
||||
# QUAY_AUTH - base64(username:token) for Quay.io
|
||||
# SNAP_AUTH - Snapcraft store credentials
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
old_version:
|
||||
description: 'Previous version number (e.g. 8.42, without v prefix)'
|
||||
required: true
|
||||
type: string
|
||||
new_version:
|
||||
description: 'New version number (e.g. 8.43, without v prefix)'
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
packages: write
|
||||
pages: write
|
||||
id-token: write
|
||||
|
||||
jobs:
|
||||
|
||||
# ─── 1. Extract version and release notes ───────────────────────────────────
|
||||
prepare:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
version: ${{ steps.version.outputs.version }}
|
||||
changelog: ${{ steps.changelog.outputs.content }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
ref: refs/tags/v${{ needs.prepare.outputs.version }}
|
||||
|
||||
- name: Set version from input
|
||||
id: version
|
||||
run: |
|
||||
VERSION="${{ needs.prepare.outputs.version }}"
|
||||
VERSION="${VERSION#v}"
|
||||
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Extract release notes from CHANGELOG.md
|
||||
id: changelog
|
||||
run: |
|
||||
VERSION="${{ steps.version.outputs.version }}"
|
||||
# Try to find the version-specific section first, then fall back to Upcoming
|
||||
NOTES=$(python3 - <<PYEOF
|
||||
import re, sys
|
||||
version = "$VERSION"
|
||||
with open("CHANGELOG.md", encoding="utf-8") as f:
|
||||
content = f.read()
|
||||
# Pattern: section heading through (but not including) the next heading
|
||||
patterns = [
|
||||
rf"(# v{re.escape(version)} .*?)(?=\n# v[0-9]|\Z)",
|
||||
r"(# Upcoming WeKan.*?)(?=\n# v[0-9]|\Z)",
|
||||
]
|
||||
for pat in patterns:
|
||||
m = re.search(pat, content, re.DOTALL)
|
||||
if m:
|
||||
print(m.group(1).strip())
|
||||
sys.exit(0)
|
||||
print(f"WeKan v{version}")
|
||||
PYEOF
|
||||
)
|
||||
echo "content<<GHEOF" >> $GITHUB_OUTPUT
|
||||
echo "$NOTES" >> $GITHUB_OUTPUT
|
||||
echo "GHEOF" >> $GITHUB_OUTPUT
|
||||
|
||||
# ─── 2. Build amd64 bundle (full Meteor 3 build) ────────────────────────────
|
||||
# Meteor 3.5-beta.7 installer supports only: Linux x86_64, Linux aarch64, macOS, Windows.
|
||||
# It explicitly rejects armhf, s390x, and ppc64le at install time.
|
||||
# Therefore the full Meteor build always runs here on x86_64.
|
||||
# All other Linux architectures then rebuild only the native npm modules
|
||||
# from this bundle (much faster than a full Meteor build).
|
||||
# Node.js version must match what Meteor 3.5-beta.7 bundles (detected automatically).
|
||||
build-amd64:
|
||||
needs: prepare
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 180
|
||||
env:
|
||||
VERSION: ${{ needs.prepare.outputs.version }}
|
||||
NODE_VERSION: ${{ needs.prepare.outputs.version }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
ref: refs/tags/v${{ inputs.new_version }}
|
||||
|
||||
- name: Cache Meteor installation
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: ~/.meteor
|
||||
key: meteor-${{ hashFiles('.meteor/release') }}-${{ hashFiles('.meteor/packages') }}
|
||||
restore-keys: meteor-
|
||||
|
||||
- name: Cache npm packages
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: ~/.npm
|
||||
key: npm-${{ hashFiles('package-lock.json') }}
|
||||
|
||||
- name: Install system dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y build-essential g++ make python3 curl wget zip unzip
|
||||
|
||||
# Pin to detected latest Node.js 24.x — must match Meteor's bundled version.
|
||||
# Using the same version for build and npm rebuild ensures consistent native module ABI.
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: '${{ needs.prepare.outputs.version }}'
|
||||
|
||||
- name: Install Meteor
|
||||
run: |
|
||||
if [ ! -f ~/.meteor/meteor ]; then
|
||||
curl https://install.meteor.com/ | sh
|
||||
fi
|
||||
echo "$HOME/.meteor" >> $GITHUB_PATH
|
||||
|
||||
- name: Build WeKan bundle
|
||||
run: |
|
||||
rm -rf .build node_modules .meteor/local
|
||||
(meteor update --npm 2>/dev/null || true) && meteor npm install
|
||||
meteor build .build --directory
|
||||
|
||||
- name: Create amd64 zip
|
||||
run: |
|
||||
cd .build
|
||||
zip -r wekan-${VERSION}-amd64.zip bundle
|
||||
|
||||
- uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: bundle-amd64
|
||||
path: .build/wekan-${{ needs.prepare.outputs.version }}-amd64.zip
|
||||
retention-days: 1
|
||||
|
||||
# ─── 3. Build arm64 bundle (rebuild native modules natively) ─────────────────
|
||||
# Meteor 3.5-beta.7 does support Linux aarch64, but running a full Meteor build a
|
||||
# second time would double the build time for the same result. npm rebuild on
|
||||
# the native arm64 GitHub Actions runner is much faster and produces the same
|
||||
# platform-specific native modules.
|
||||
build-arm64:
|
||||
needs: [prepare, build-amd64]
|
||||
runs-on: ubuntu-24.04-arm
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
VERSION: ${{ needs.prepare.outputs.version }}
|
||||
NODE_VERSION: ${{ needs.prepare.outputs.version }}
|
||||
NODE_VERSION_ARM64: ''
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y build-essential g++ make python3 curl unzip zip
|
||||
|
||||
|
||||
- name: Set Node.js version for arm64
|
||||
id: node_arm64
|
||||
run: |
|
||||
echo "NODE_VERSION_ARM64=24" >> $GITHUB_ENV
|
||||
|
||||
- name: Download amd64 bundle
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: bundle-amd64
|
||||
|
||||
- name: Rebuild native modules for arm64 in container
|
||||
run: |
|
||||
unzip wekan-${VERSION}-amd64.zip
|
||||
# Fix: bcrypt 5.0.1 (Meteor accounts-password) ships node-addon-api@3
|
||||
# which fails to compile on Node.js 24. Replace with bcrypt 6.0.0.
|
||||
BCRYPT_DIR="$(pwd)/bundle/programs/server/npm/node_modules/meteor/accounts-password/node_modules/bcrypt"
|
||||
if [ -d "$BCRYPT_DIR" ]; then
|
||||
rm -rf "$BCRYPT_DIR"
|
||||
TMP=$(mktemp -d)
|
||||
pushd "$TMP" > /dev/null
|
||||
npm pack bcrypt@6.0.0
|
||||
mkdir bcrypt && tar xzf bcrypt-*.tgz --strip-components=1 -C bcrypt
|
||||
cd bcrypt && npm install --ignore-scripts && cd ..
|
||||
cp -a bcrypt "$BCRYPT_DIR"
|
||||
popd > /dev/null
|
||||
rm -rf "$TMP"
|
||||
fi
|
||||
# Use the latest available Node.js 24.x slim image for arm64
|
||||
docker run --rm --platform linux/arm64 \
|
||||
-v "$(pwd)/bundle:/bundle" \
|
||||
-w /bundle/programs/server \
|
||||
node:24-slim \
|
||||
sh -c "apt-get update -qq && apt-get install -y -q build-essential python3 && npm install"
|
||||
|
||||
- name: Clean up and create arm64 zip
|
||||
run: |
|
||||
zip -r wekan-${VERSION}-arm64.zip bundle
|
||||
|
||||
- uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: bundle-arm64
|
||||
path: wekan-${{ needs.prepare.outputs.version }}-arm64.zip
|
||||
retention-days: 1
|
||||
|
||||
# ─── 4. Build s390x bundle (rebuild native modules via QEMU container) ───────
|
||||
# Meteor 3.5-beta.7 does NOT support s390x (installer exits with error on that arch).
|
||||
# GitHub Actions has no native s390x runners.
|
||||
# Solution: QEMU emulation + node:<version>-slim (s390x variant) for npm rebuild.
|
||||
build-s390x:
|
||||
needs: [prepare, build-amd64]
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 90
|
||||
env:
|
||||
VERSION: ${{ needs.prepare.outputs.version }}
|
||||
NODE_VERSION: ${{ needs.prepare.outputs.version }}
|
||||
NODE_VERSION_S390X: ''
|
||||
steps:
|
||||
- name: Set up QEMU for s390x
|
||||
uses: docker/setup-qemu-action@v4
|
||||
with:
|
||||
platforms: s390x
|
||||
|
||||
- name: Install unzip/zip
|
||||
run: sudo apt-get update && sudo apt-get install -y unzip zip
|
||||
|
||||
- name: Download amd64 bundle
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: bundle-amd64
|
||||
|
||||
- name: Set Node.js version for s390x
|
||||
id: node_s390x
|
||||
run: |
|
||||
echo "NODE_VERSION_S390X=24" >> $GITHUB_ENV
|
||||
|
||||
- name: Rebuild native modules for s390x in container
|
||||
run: |
|
||||
unzip wekan-${VERSION}-amd64.zip
|
||||
rm -rf bundle/programs/server/node_modules
|
||||
# Fix: bcrypt 5.0.1 (Meteor accounts-password) ships node-addon-api@3
|
||||
# which fails to compile on Node.js 24. Replace with bcrypt 6.0.0.
|
||||
BCRYPT_DIR="$(pwd)/bundle/programs/server/npm/node_modules/meteor/accounts-password/node_modules/bcrypt"
|
||||
if [ -d "$BCRYPT_DIR" ]; then
|
||||
rm -rf "$BCRYPT_DIR"
|
||||
TMP=$(mktemp -d)
|
||||
pushd "$TMP" > /dev/null
|
||||
npm pack bcrypt@6.0.0
|
||||
mkdir bcrypt && tar xzf bcrypt-*.tgz --strip-components=1 -C bcrypt
|
||||
cd bcrypt && npm install --ignore-scripts && cd ..
|
||||
cp -a bcrypt "$BCRYPT_DIR"
|
||||
popd > /dev/null
|
||||
rm -rf "$TMP"
|
||||
fi
|
||||
# Use the latest available Node.js 24.x slim image for s390x
|
||||
docker run --rm --platform linux/s390x \
|
||||
-v "$(pwd)/bundle:/bundle" \
|
||||
-w /bundle/programs/server \
|
||||
node:24-slim \
|
||||
sh -c "apt-get update -qq && apt-get install -y -q build-essential python3 && npm install"
|
||||
|
||||
- name: Clean up and create s390x zip
|
||||
run: |
|
||||
zip -r wekan-${VERSION}-s390x.zip bundle
|
||||
|
||||
- uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: bundle-s390x
|
||||
path: wekan-${{ needs.prepare.outputs.version }}-s390x.zip
|
||||
retention-days: 1
|
||||
|
||||
# ─── 4b. Build ppc64le bundle (rebuild native modules via QEMU container) ────
|
||||
# Meteor 3.5-beta.7 does NOT support ppc64le (installer exits with error on that arch).
|
||||
# GitHub Actions has no native ppc64le runners.
|
||||
# Solution: QEMU emulation + node:<version>-slim (ppc64le variant) for npm rebuild.
|
||||
build-ppc64le:
|
||||
needs: [prepare, build-amd64]
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 90
|
||||
env:
|
||||
VERSION: ${{ needs.prepare.outputs.version }}
|
||||
NODE_VERSION: ${{ needs.prepare.outputs.version }}
|
||||
NODE_VERSION_PPC64LE: ''
|
||||
steps:
|
||||
- name: Set up QEMU for ppc64le
|
||||
uses: docker/setup-qemu-action@v4
|
||||
with:
|
||||
platforms: ppc64le
|
||||
|
||||
- name: Install unzip/zip
|
||||
run: sudo apt-get update && sudo apt-get install -y unzip zip
|
||||
|
||||
- name: Download amd64 bundle
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: bundle-amd64
|
||||
|
||||
- name: Set Node.js version for ppc64le
|
||||
id: node_ppc64le
|
||||
run: |
|
||||
echo "NODE_VERSION_PPC64LE=24" >> $GITHUB_ENV
|
||||
|
||||
- name: Rebuild native modules for ppc64le in container
|
||||
run: |
|
||||
unzip wekan-${VERSION}-amd64.zip
|
||||
rm -rf bundle/programs/server/node_modules
|
||||
# Fix: bcrypt 5.0.1 (Meteor accounts-password) ships node-addon-api@3
|
||||
# which fails to compile on Node.js 24. Replace with bcrypt 6.0.0.
|
||||
BCRYPT_DIR="$(pwd)/bundle/programs/server/npm/node_modules/meteor/accounts-password/node_modules/bcrypt"
|
||||
if [ -d "$BCRYPT_DIR" ]; then
|
||||
rm -rf "$BCRYPT_DIR"
|
||||
TMP=$(mktemp -d)
|
||||
pushd "$TMP" > /dev/null
|
||||
npm pack bcrypt@6.0.0
|
||||
mkdir bcrypt && tar xzf bcrypt-*.tgz --strip-components=1 -C bcrypt
|
||||
cd bcrypt && npm install --ignore-scripts && cd ..
|
||||
cp -a bcrypt "$BCRYPT_DIR"
|
||||
popd > /dev/null
|
||||
rm -rf "$TMP"
|
||||
fi
|
||||
# Use the latest available Node.js 24.x slim image for ppc64le
|
||||
docker run --rm --platform linux/ppc64le \
|
||||
-v "$(pwd)/bundle:/bundle" \
|
||||
-w /bundle/programs/server \
|
||||
node:24-slim \
|
||||
sh -c "apt-get update -qq && apt-get install -y -q build-essential python3 && npm install"
|
||||
|
||||
- name: Clean up and create ppc64le zip
|
||||
run: |
|
||||
zip -r wekan-${VERSION}-ppc64le.zip bundle
|
||||
|
||||
- uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: bundle-ppc64le
|
||||
path: wekan-${{ needs.prepare.outputs.version }}-ppc64le.zip
|
||||
retention-days: 1
|
||||
|
||||
# ─── 4c. Build armhf bundle — COMMENTED OUT ─────────────────────────────────
|
||||
# No official Node.js binaries exist for armhf (arm/v7).
|
||||
#build-armhf:
|
||||
# needs: [prepare, build-amd64]
|
||||
# runs-on: ubuntu-latest
|
||||
# timeout-minutes: 120
|
||||
# env:
|
||||
# VERSION: ${{ needs.prepare.outputs.version }}
|
||||
# steps:
|
||||
# - name: Set up QEMU for arm/v7
|
||||
# uses: docker/setup-qemu-action@v4
|
||||
# with:
|
||||
# platforms: arm
|
||||
#
|
||||
# - name: Install unzip/zip
|
||||
# run: sudo apt-get update && sudo apt-get install -y unzip zip
|
||||
#
|
||||
# - name: Download amd64 bundle
|
||||
# uses: actions/download-artifact@v8
|
||||
# with:
|
||||
# name: bundle-amd64
|
||||
#
|
||||
# - name: Rebuild native modules for armhf in container
|
||||
# run: |
|
||||
# unzip wekan-${VERSION}-amd64.zip
|
||||
# rm -rf bundle/programs/server/node_modules
|
||||
# # Fix: bcrypt 5.0.1 (Meteor accounts-password) ships node-addon-api@3
|
||||
# # which fails to compile on Node.js 24. Replace with bcrypt 6.0.0.
|
||||
# BCRYPT_DIR="$(pwd)/bundle/programs/server/npm/node_modules/meteor/accounts-password/node_modules/bcrypt"
|
||||
# if [ -d "$BCRYPT_DIR" ]; then
|
||||
# rm -rf "$BCRYPT_DIR"
|
||||
# TMP=$(mktemp -d)
|
||||
# pushd "$TMP" > /dev/null
|
||||
# npm pack bcrypt@6.0.0
|
||||
# mkdir bcrypt && tar xzf bcrypt-*.tgz --strip-components=1 -C bcrypt
|
||||
# cd bcrypt && npm install --ignore-scripts && cd ..
|
||||
# cp -a bcrypt "$BCRYPT_DIR"
|
||||
# popd > /dev/null
|
||||
# rm -rf "$TMP"
|
||||
# fi
|
||||
# # node:<version>-slim arm/v7 — same Node.js version as Meteor bundled
|
||||
# docker run --rm --platform linux/arm/v7 \
|
||||
# -v "$(pwd)/bundle:/bundle" \
|
||||
# -w /bundle/programs/server \
|
||||
# node:${NODE_VERSION}-slim \
|
||||
# sh -c "apt-get update -qq && apt-get install -y -q build-essential python3 && npm install"
|
||||
#
|
||||
# - name: Clean up and create armhf zip
|
||||
# run: |
|
||||
# zip -r wekan-${VERSION}-armhf.zip bundle
|
||||
#
|
||||
# - uses: actions/upload-artifact@v7
|
||||
# with:
|
||||
# name: bundle-armhf
|
||||
# path: wekan-${{ needs.prepare.outputs.version }}-armhf.zip
|
||||
# retention-days: 1
|
||||
|
||||
# ─── 5. Build win64 bundle (rebuild native modules on Windows) ───────────────
|
||||
build-win64:
|
||||
needs: [prepare, build-amd64]
|
||||
runs-on: windows-latest
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
VERSION: ${{ needs.prepare.outputs.version }}
|
||||
steps:
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: '${{ needs.prepare.outputs.version }}'
|
||||
|
||||
## With Node 24 these are already preinstalled at GitHub Windows runners
|
||||
#- name: Install node-gyp and build tools
|
||||
# run: |
|
||||
# npm install -g windows-build-tools --vs2019 2>$null; exit 0
|
||||
|
||||
- name: Install 7-zip
|
||||
run: choco install -y 7zip
|
||||
|
||||
- name: Download amd64 bundle
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: bundle-amd64
|
||||
|
||||
- name: Fix bcrypt for Node.js 24
|
||||
shell: bash
|
||||
run: |
|
||||
7z x wekan-${VERSION}-amd64.zip
|
||||
# Fix: bcrypt 5.0.1 (Meteor accounts-password) ships node-addon-api@3
|
||||
# which fails to compile on Node.js 24. Replace with bcrypt 6.0.0.
|
||||
BCRYPT_DIR="$(pwd)/bundle/programs/server/npm/node_modules/meteor/accounts-password/node_modules/bcrypt"
|
||||
if [ -d "$BCRYPT_DIR" ]; then
|
||||
rm -rf "$BCRYPT_DIR"
|
||||
TMP=$(mktemp -d)
|
||||
pushd "$TMP" > /dev/null
|
||||
npm pack bcrypt@6.0.0
|
||||
mkdir bcrypt && tar xzf bcrypt-*.tgz --strip-components=1 -C bcrypt
|
||||
cd bcrypt && npm install --ignore-scripts && cd ..
|
||||
cp -r bcrypt "$BCRYPT_DIR"
|
||||
popd > /dev/null
|
||||
rm -rf "$TMP"
|
||||
fi
|
||||
|
||||
- name: Rebuild native modules for Windows
|
||||
shell: cmd
|
||||
run: |
|
||||
cd bundle\programs\server
|
||||
rmdir /s /q node_modules
|
||||
npm install
|
||||
cd ..\..\..
|
||||
|
||||
- name: Create win64 zip
|
||||
shell: cmd
|
||||
run: 7z a wekan-%VERSION%-win64.zip bundle
|
||||
|
||||
- uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: bundle-win64
|
||||
path: wekan-${{ needs.prepare.outputs.version }}-win64.zip
|
||||
retention-days: 1
|
||||
|
||||
# ─── 6. Create GitHub Release and upload all bundles ────────────────────────
|
||||
release:
|
||||
needs: [prepare, build-amd64, build-arm64, build-s390x, build-ppc64le, build-win64]
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
VERSION: ${{ needs.prepare.outputs.version }}
|
||||
steps:
|
||||
- name: Download all bundles
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
pattern: bundle-*
|
||||
merge-multiple: true
|
||||
|
||||
- name: Create GitHub Release with all bundles
|
||||
uses: softprops/action-gh-release@v3
|
||||
with:
|
||||
tag_name: v${{ needs.prepare.outputs.version }}
|
||||
name: v${{ needs.prepare.outputs.version }}
|
||||
body: ${{ needs.prepare.outputs.changelog }}
|
||||
files: |
|
||||
wekan-${{ needs.prepare.outputs.version }}-amd64.zip
|
||||
wekan-${{ needs.prepare.outputs.version }}-arm64.zip
|
||||
wekan-${{ needs.prepare.outputs.version }}-s390x.zip
|
||||
wekan-${{ needs.prepare.outputs.version }}-ppc64le.zip
|
||||
wekan-${{ needs.prepare.outputs.version }}-win64.zip
|
||||
|
||||
# ─── 7. Build and push multi-platform Docker image ──────────────────────────
|
||||
docker:
|
||||
needs: [prepare, release]
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
VERSION: ${{ needs.prepare.outputs.version }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
ref: refs/tags/v${{ inputs.new_version }}
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v4
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v4
|
||||
|
||||
- name: Create Docker config with registry credentials
|
||||
run: |
|
||||
mkdir -p ~/.docker
|
||||
cat > ~/.docker/config.json <<EOF
|
||||
{
|
||||
"auths": {
|
||||
"ghcr.io": {
|
||||
"auth": "${{ secrets.GHCR_AUTH }}"
|
||||
},
|
||||
"https://index.docker.io/v1/": {
|
||||
"auth": "${{ secrets.DOCKERHUB_AUTH }}"
|
||||
},
|
||||
"quay.io": {
|
||||
"auth": "${{ secrets.QUAY_AUTH }}"
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
- name: Create and use buildx builder
|
||||
run: |
|
||||
docker buildx create --name mybuilder --driver docker-container --use
|
||||
docker buildx inspect --bootstrap
|
||||
|
||||
- name: Build and push Docker image to all registries
|
||||
run: |
|
||||
docker buildx build \
|
||||
--platform linux/amd64,linux/arm64,linux/s390x,linux/ppc64le \
|
||||
-t wekanteam/wekan:v${VERSION} \
|
||||
-t wekanteam/wekan:latest \
|
||||
-t quay.io/wekan/wekan:v${VERSION} \
|
||||
-t quay.io/wekan/wekan:latest \
|
||||
-t ghcr.io/wekan/wekan:v${VERSION} \
|
||||
-t ghcr.io/wekan/wekan:latest \
|
||||
--push .
|
||||
|
||||
# ─── 8. Build and publish snap packages ──────────────────────────────────────
|
||||
# Build snap with snapcraft pack (like releases/snap-build.sh) using LXD,
|
||||
# then push to Snap Store edge channel (like releases/snap-push-to-store.sh).
|
||||
# Promote to stable manually via the Snap Store dashboard when ready.
|
||||
snap:
|
||||
needs: [prepare, release]
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
VERSION: ${{ needs.prepare.outputs.version }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
ref: refs/tags/v${{ inputs.new_version }}
|
||||
|
||||
- name: Install snapcraft
|
||||
run: sudo snap install snapcraft --classic
|
||||
|
||||
- name: Build snap
|
||||
run: sudo snapcraft pack --destructive-mode
|
||||
|
||||
- name: Upload snap files as artifacts
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: snaps
|
||||
path: "*.snap"
|
||||
retention-days: 30
|
||||
|
||||
- name: Push all snaps to Snap Store edge channel
|
||||
env:
|
||||
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAP_AUTH }}
|
||||
run: |
|
||||
for snap_file in *.snap; do
|
||||
echo "Publishing $snap_file ..."
|
||||
snapcraft upload --release=edge "$snap_file"
|
||||
done
|
||||
|
||||
- name: Upload all snaps to GitHub Release
|
||||
uses: softprops/action-gh-release@v3
|
||||
with:
|
||||
tag_name: v${{ needs.prepare.outputs.version }}
|
||||
files: "*.snap"
|
||||
|
||||
# ─── 9. Update Helm charts and deploy to GitHub Pages ─────────────────────────
|
||||
# Chart source is in helm/wekan/, published packages + index.yaml in docs/wekan/.
|
||||
# GitHub Pages deploys docs/wekan/ via Actions, serving at https://wekan.fi/wekan/
|
||||
helm:
|
||||
needs: [prepare, docker]
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
VERSION: ${{ needs.prepare.outputs.version }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
ref: refs/tags/v${{ inputs.new_version }}
|
||||
|
||||
- name: Install Helm
|
||||
run: |
|
||||
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
|
||||
|
||||
- name: Update Chart.yaml and values.yaml with new version
|
||||
run: |
|
||||
CHART_PATH=docs/wekan
|
||||
CHART_FILE=$CHART_PATH/Chart.yaml
|
||||
VALUES_FILE=$CHART_PATH/values.yaml
|
||||
CHARTS_DIR=docs/charts
|
||||
INDEX_FILE=$CHARTS_DIR/index.yaml
|
||||
VERSION=${VERSION}
|
||||
# Update Chart.yaml (appVersion and version)
|
||||
sed -i "s/^appVersion: .*/appVersion: \"$VERSION\"/" "$CHART_FILE"
|
||||
sed -i "s/^version: .*/version: $VERSION.0/" "$CHART_FILE"
|
||||
# Update values.yaml (image.tag)
|
||||
sed -i "s/^ tag: v.*/ tag: v$VERSION/" "$VALUES_FILE"
|
||||
|
||||
- name: Build Helm dependencies
|
||||
run: |
|
||||
cd docs/wekan
|
||||
helm repo add mongo https://groundhog2k.github.io/helm-charts/ || true
|
||||
helm dependency update
|
||||
helm dependency build
|
||||
|
||||
- name: Package chart to docs/charts and update index.yaml
|
||||
run: |
|
||||
CHART_PATH=docs/wekan
|
||||
CHARTS_DIR=docs/charts
|
||||
INDEX_FILE=$CHARTS_DIR/index.yaml
|
||||
VERSION=${VERSION}
|
||||
cd $CHARTS_DIR
|
||||
helm package ../wekan -d .
|
||||
ARCHIVE=wekan-$VERSION.0.tgz
|
||||
SHA256=$(sha256sum "$ARCHIVE" | awk '{print $1}')
|
||||
CREATED=$(TZ='Europe/Helsinki' date '+%Y-%m-%dT%H:%M:%S.000000000%:z')
|
||||
if [ -f "$INDEX_FILE" ]; then
|
||||
awk '/^- apiVersion: v2/{flag=1;print;next}/^- apiVersion: v2/{flag=0}flag' "$INDEX_FILE" | head -n 30 > /tmp/topentry.yaml
|
||||
sed -i "s/appVersion: .*/appVersion: \"$VERSION\"/" /tmp/topentry.yaml
|
||||
sed -i "s/created: .*/created: \"$CREATED\"/" /tmp/topentry.yaml
|
||||
sed -i "s/digest: .*/digest: $SHA256/" /tmp/topentry.yaml
|
||||
sed -i "s|urls:.*|urls:\n - https://wekan.github.io/wekan/wekan-$VERSION.0.tgz|" /tmp/topentry.yaml
|
||||
sed -i "s/version: .*/version: $VERSION.0/" /tmp/topentry.yaml
|
||||
awk 'NR==1{print;system("cat /tmp/topentry.yaml");next} /^ - apiVersion: v2/ && !p{p=1;next} 1' "$INDEX_FILE" > /tmp/index.yaml
|
||||
mv /tmp/index.yaml "$INDEX_FILE"
|
||||
rm /tmp/topentry.yaml
|
||||
else
|
||||
echo "index.yaml not found, skipping index update."
|
||||
fi
|
||||
|
||||
- name: Commit updated chart and index
|
||||
run: |
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git add docs/wekan/ docs/charts/
|
||||
git commit -m "${VERSION}.0"
|
||||
git push origin HEAD:refs/heads/main
|
||||
|
||||
- name: Upload docs/charts/ as Pages artifact
|
||||
uses: actions/upload-pages-artifact@v5
|
||||
with:
|
||||
path: docs/charts/
|
||||
|
||||
- name: Commit updated chart
|
||||
run: |
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git add docs/wekan/
|
||||
git commit -m "${VERSION}.0"
|
||||
git push origin HEAD:refs/heads/main
|
||||
|
||||
- name: Upload docs/wekan/ as Pages artifact
|
||||
uses: actions/upload-pages-artifact@v5
|
||||
with:
|
||||
path: docs/wekan/
|
||||
|
||||
# ─── 10. Deploy Helm chart to GitHub Pages ───────────────────────────────────
|
||||
deploy-pages:
|
||||
needs: helm
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
pages: write
|
||||
id-token: write
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
steps:
|
||||
- name: Deploy to GitHub Pages
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v5
|
||||
@@ -124,13 +124,18 @@ jobs:
|
||||
restore-keys: |
|
||||
v1-meteor_build_cache-
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: '24.15.0'
|
||||
|
||||
- name: Setup meteor
|
||||
uses: meteorengineer/setup-meteor@v3
|
||||
with:
|
||||
meteor-release: '2.2'
|
||||
meteor-release: '3.5-beta.7'
|
||||
|
||||
- name: Install NPM Dependencies
|
||||
run: meteor npm ci
|
||||
run: meteor npm install
|
||||
|
||||
- name: Run Tests
|
||||
run: sh ./test-wekan.sh -cv
|
||||
@@ -38,7 +38,7 @@ jobs:
|
||||
# https://github.com/docker/login-action
|
||||
- name: Log into registry ${{ env.REGISTRY }}
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2
|
||||
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
@@ -55,7 +55,7 @@ jobs:
|
||||
# Build and push Docker image with Buildx (don't push on PR)
|
||||
# https://github.com/docker/build-push-action
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294
|
||||
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f
|
||||
with:
|
||||
context: .
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
|
||||
@@ -1,494 +0,0 @@
|
||||
name: Release All Platforms
|
||||
|
||||
# Triggered when maintainer pushes a version tag, e.g.: git tag v8.43 && git push --tags
|
||||
# Required GitHub Secrets:
|
||||
# DOCKERHUB_USERNAME - Docker Hub username
|
||||
# DOCKERHUB_TOKEN - Docker Hub access token
|
||||
# QUAY_USERNAME - Quay.io username
|
||||
# QUAY_PASSWORD - Quay.io password or token
|
||||
# SNAP_STORE_LOGIN - Snapcraft store credentials: run 'snapcraft export-login --snaps wekan --channels stable -' and base64-encode the output
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*.*'
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
# ─── 1. Extract version and release notes ───────────────────────────────────
|
||||
prepare:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
version: ${{ steps.version.outputs.version }}
|
||||
changelog: ${{ steps.changelog.outputs.content }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Extract version from tag
|
||||
id: version
|
||||
run: echo "version=${GITHUB_REF_NAME#v}" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Extract release notes from CHANGELOG.md
|
||||
id: changelog
|
||||
run: |
|
||||
VERSION="${{ steps.version.outputs.version }}"
|
||||
# Try to find the version-specific section first, then fall back to Upcoming
|
||||
NOTES=$(python3 - <<PYEOF
|
||||
import re, sys
|
||||
version = "$VERSION"
|
||||
with open("CHANGELOG.md", encoding="utf-8") as f:
|
||||
content = f.read()
|
||||
# Pattern: section heading through (but not including) the next heading
|
||||
patterns = [
|
||||
rf"(# v{re.escape(version)} .*?)(?=\n# v[0-9]|\Z)",
|
||||
r"(# Upcoming WeKan.*?)(?=\n# v[0-9]|\Z)",
|
||||
]
|
||||
for pat in patterns:
|
||||
m = re.search(pat, content, re.DOTALL)
|
||||
if m:
|
||||
print(m.group(1).strip())
|
||||
sys.exit(0)
|
||||
print(f"WeKan v{version}")
|
||||
PYEOF
|
||||
)
|
||||
echo "content<<GHEOF" >> $GITHUB_OUTPUT
|
||||
echo "$NOTES" >> $GITHUB_OUTPUT
|
||||
echo "GHEOF" >> $GITHUB_OUTPUT
|
||||
|
||||
# ─── 2. Build amd64 bundle (full Meteor 3 build) ────────────────────────────
|
||||
# Meteor 3.4 installer supports only: Linux x86_64, Linux aarch64, macOS, Windows.
|
||||
# It explicitly rejects armhf, s390x, and ppc64le at install time.
|
||||
# Therefore the full Meteor build always runs here on x86_64.
|
||||
# All other Linux architectures then rebuild only the native npm modules
|
||||
# from this bundle (much faster than a full Meteor build).
|
||||
# Node.js version must match what Meteor 3.4 bundles: 22.22.2 (ABI 127).
|
||||
build-amd64:
|
||||
needs: prepare
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 180
|
||||
env:
|
||||
VERSION: ${{ needs.prepare.outputs.version }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Cache Meteor installation
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.meteor
|
||||
key: meteor-${{ hashFiles('.meteor/release') }}-${{ hashFiles('.meteor/packages') }}
|
||||
restore-keys: meteor-
|
||||
|
||||
- name: Cache npm packages
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.npm
|
||||
key: npm-${{ hashFiles('package-lock.json') }}
|
||||
|
||||
- name: Install system dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y build-essential g++ make python3 curl wget zip unzip
|
||||
|
||||
# Pin to Node 22.22.2 — the exact version bundled by Meteor 3.4.
|
||||
# Using the same version for build and npm rebuild ensures consistent native module ABI.
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '22.22.2'
|
||||
|
||||
- name: Install Meteor
|
||||
run: |
|
||||
if [ ! -f ~/.meteor/meteor ]; then
|
||||
curl https://install.meteor.com/ | sh
|
||||
fi
|
||||
echo "$HOME/.meteor" >> $GITHUB_PATH
|
||||
|
||||
- name: Build WeKan bundle
|
||||
run: |
|
||||
rm -rf .build node_modules .meteor/local
|
||||
npm install
|
||||
meteor build .build --directory --platforms=web.browser
|
||||
rm -rf .build/bundle/programs/web.browser.legacy
|
||||
|
||||
- name: Create amd64 zip
|
||||
run: |
|
||||
cd .build
|
||||
zip -r wekan-${VERSION}-amd64.zip bundle
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: bundle-amd64
|
||||
path: .build/wekan-${{ needs.prepare.outputs.version }}-amd64.zip
|
||||
retention-days: 1
|
||||
|
||||
# ─── 3. Build arm64 bundle (rebuild native modules natively) ─────────────────
|
||||
# Meteor 3.4 does support Linux aarch64, but running a full Meteor build a
|
||||
# second time would double the build time for the same result. npm rebuild on
|
||||
# the native arm64 GitHub Actions runner is much faster and produces the same
|
||||
# platform-specific native modules.
|
||||
build-arm64:
|
||||
needs: [prepare, build-amd64]
|
||||
runs-on: ubuntu-24.04-arm
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
VERSION: ${{ needs.prepare.outputs.version }}
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y build-essential g++ make python3 curl unzip zip
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '22.22.2'
|
||||
|
||||
- name: Download amd64 bundle
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: bundle-amd64
|
||||
|
||||
- name: Rebuild native modules for arm64
|
||||
run: |
|
||||
unzip wekan-${VERSION}-amd64.zip
|
||||
cd bundle/programs/server
|
||||
npm rebuild
|
||||
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
|
||||
with:
|
||||
name: bundle-arm64
|
||||
path: wekan-${{ needs.prepare.outputs.version }}-arm64.zip
|
||||
retention-days: 1
|
||||
|
||||
# ─── 4. Build s390x bundle (rebuild native modules via QEMU container) ───────
|
||||
# Meteor 3.4 does NOT support s390x (installer exits with error on that arch).
|
||||
# GitHub Actions has no native s390x runners.
|
||||
# Solution: QEMU emulation + node:22.22.2-slim (s390x variant) for npm rebuild.
|
||||
# node:22.22.2-slim is pinned to match Meteor 3.4's bundled Node.js version exactly.
|
||||
build-s390x:
|
||||
needs: [prepare, build-amd64]
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 90
|
||||
env:
|
||||
VERSION: ${{ needs.prepare.outputs.version }}
|
||||
steps:
|
||||
- name: Set up QEMU for s390x
|
||||
uses: docker/setup-qemu-action@v3
|
||||
with:
|
||||
platforms: s390x
|
||||
|
||||
- name: Install unzip/zip
|
||||
run: sudo apt-get update && sudo apt-get install -y unzip zip
|
||||
|
||||
- name: Download amd64 bundle
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: bundle-amd64
|
||||
|
||||
- name: Rebuild native modules for s390x in container
|
||||
run: |
|
||||
unzip wekan-${VERSION}-amd64.zip
|
||||
# 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"
|
||||
|
||||
- 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
|
||||
with:
|
||||
name: bundle-s390x
|
||||
path: wekan-${{ needs.prepare.outputs.version }}-s390x.zip
|
||||
retention-days: 1
|
||||
|
||||
# ─── 4b. Build ppc64le bundle (rebuild native modules via QEMU container) ────
|
||||
# Meteor 3.4 does NOT support ppc64le (installer exits with error on that arch).
|
||||
# GitHub Actions has no native ppc64le runners.
|
||||
# Solution: QEMU emulation + node:22.22.2-slim (ppc64le variant) for npm rebuild.
|
||||
build-ppc64le:
|
||||
needs: [prepare, build-amd64]
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 90
|
||||
env:
|
||||
VERSION: ${{ needs.prepare.outputs.version }}
|
||||
steps:
|
||||
- name: Set up QEMU for ppc64le
|
||||
uses: docker/setup-qemu-action@v3
|
||||
with:
|
||||
platforms: ppc64le
|
||||
|
||||
- name: Install unzip/zip
|
||||
run: sudo apt-get update && sudo apt-get install -y unzip zip
|
||||
|
||||
- name: Download amd64 bundle
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: bundle-amd64
|
||||
|
||||
- name: Rebuild native modules for ppc64le in container
|
||||
run: |
|
||||
unzip wekan-${VERSION}-amd64.zip
|
||||
# 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"
|
||||
|
||||
- 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
|
||||
with:
|
||||
name: bundle-ppc64le
|
||||
path: wekan-${{ needs.prepare.outputs.version }}-ppc64le.zip
|
||||
retention-days: 1
|
||||
|
||||
# ─── 4c. Build armhf bundle (rebuild native modules via QEMU container) ──────
|
||||
# Meteor 3.4 does NOT support arm/v7 (armhf). Installer explicitly rejects it.
|
||||
# GitHub Actions has no native arm/v7 runners.
|
||||
# Solution: QEMU emulation + node:22.22.2-slim (arm/v7 variant) for npm rebuild.
|
||||
# arm/v7 under QEMU is slowest — timeout set to 120 min.
|
||||
build-armhf:
|
||||
needs: [prepare, build-amd64]
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 120
|
||||
env:
|
||||
VERSION: ${{ needs.prepare.outputs.version }}
|
||||
steps:
|
||||
- name: Set up QEMU for arm/v7
|
||||
uses: docker/setup-qemu-action@v3
|
||||
with:
|
||||
platforms: arm
|
||||
|
||||
- name: Install unzip/zip
|
||||
run: sudo apt-get update && sudo apt-get install -y unzip zip
|
||||
|
||||
- name: Download amd64 bundle
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: bundle-amd64
|
||||
|
||||
- name: Rebuild native modules for armhf in container
|
||||
run: |
|
||||
unzip wekan-${VERSION}-amd64.zip
|
||||
# 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"
|
||||
|
||||
- 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
|
||||
with:
|
||||
name: bundle-armhf
|
||||
path: wekan-${{ needs.prepare.outputs.version }}-armhf.zip
|
||||
retention-days: 1
|
||||
|
||||
# ─── 5. Build win64 bundle (rebuild native modules on Windows) ───────────────
|
||||
build-win64:
|
||||
needs: [prepare, build-amd64]
|
||||
runs-on: windows-latest
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
VERSION: ${{ needs.prepare.outputs.version }}
|
||||
steps:
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '22.22.2'
|
||||
|
||||
- name: Install node-gyp and build tools
|
||||
run: |
|
||||
npm install -g windows-build-tools --vs2019 2>$null; exit 0
|
||||
|
||||
- name: Install 7-zip
|
||||
run: choco install -y 7zip
|
||||
|
||||
- name: Download amd64 bundle
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: bundle-amd64
|
||||
|
||||
- name: Rebuild native modules for Windows
|
||||
shell: cmd
|
||||
run: |
|
||||
7z x wekan-%VERSION%-amd64.zip
|
||||
cd bundle\programs\server
|
||||
npm rebuild
|
||||
cd ..\..\..
|
||||
|
||||
- name: Create win64 zip
|
||||
shell: cmd
|
||||
run: 7z a wekan-%VERSION%-win64.zip bundle
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: bundle-win64
|
||||
path: wekan-${{ needs.prepare.outputs.version }}-win64.zip
|
||||
retention-days: 1
|
||||
|
||||
# ─── 6. Create GitHub Release and upload all bundles ────────────────────────
|
||||
release:
|
||||
needs: [prepare, build-amd64, build-arm64, build-s390x, build-ppc64le, build-armhf, build-win64]
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
VERSION: ${{ needs.prepare.outputs.version }}
|
||||
steps:
|
||||
- name: Download all bundles
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: bundle-*
|
||||
merge-multiple: true
|
||||
|
||||
- name: Create GitHub Release with all bundles
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
name: v${{ needs.prepare.outputs.version }}
|
||||
body: ${{ needs.prepare.outputs.changelog }}
|
||||
files: |
|
||||
wekan-${{ needs.prepare.outputs.version }}-amd64.zip
|
||||
wekan-${{ needs.prepare.outputs.version }}-arm64.zip
|
||||
wekan-${{ needs.prepare.outputs.version }}-s390x.zip
|
||||
wekan-${{ needs.prepare.outputs.version }}-ppc64le.zip
|
||||
wekan-${{ needs.prepare.outputs.version }}-armhf.zip
|
||||
wekan-${{ needs.prepare.outputs.version }}-win64.zip
|
||||
|
||||
# ─── 7. Build and push multi-platform Docker image ──────────────────────────
|
||||
docker:
|
||||
needs: [prepare, release]
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
VERSION: ${{ needs.prepare.outputs.version }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Log in to Quay.io
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: quay.io
|
||||
username: ${{ secrets.QUAY_USERNAME }}
|
||||
password: ${{ secrets.QUAY_PASSWORD }}
|
||||
|
||||
- name: Log in to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push Docker image to all registries
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64,linux/arm/v7,linux/ppc64le,linux/s390x
|
||||
push: true
|
||||
build-args: VERSION=${{ needs.prepare.outputs.version }}
|
||||
tags: |
|
||||
wekanteam/wekan:v${{ needs.prepare.outputs.version }}
|
||||
wekanteam/wekan:latest
|
||||
quay.io/wekan/wekan:v${{ needs.prepare.outputs.version }}
|
||||
quay.io/wekan/wekan:latest
|
||||
ghcr.io/wekan/wekan:v${{ needs.prepare.outputs.version }}
|
||||
ghcr.io/wekan/wekan:latest
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
|
||||
# ─── 8. Build and publish snap packages (all architectures via Launchpad) ────
|
||||
# Uses snapcraft remote-build on Launchpad's native builders (more reliable
|
||||
# than QEMU for snap builds). Each architecture bundles its own database:
|
||||
# amd64, arm64 — MongoDB 7.x prebuilt native binary
|
||||
# armhf, s390x, ppc64el — MongoDB 7.x amd64 binary run via qemu-x86_64-static
|
||||
# (no prebuilt MongoDB binaries exist for these arches)
|
||||
snap:
|
||||
needs: [prepare, release]
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
VERSION: ${{ needs.prepare.outputs.version }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install snapcraft
|
||||
run: sudo snap install snapcraft --classic
|
||||
|
||||
- name: Remote-build snap for all architectures via Launchpad
|
||||
env:
|
||||
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAP_STORE_LOGIN }}
|
||||
run: |
|
||||
snapcraft remote-build \
|
||||
--build-for=amd64,arm64,armhf,s390x,ppc64el \
|
||||
--launchpad-accept-public-upload
|
||||
|
||||
- name: Upload all snap files as artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: snaps-all-arches
|
||||
path: "*.snap"
|
||||
retention-days: 30
|
||||
|
||||
# Publish to edge — NOT stable.
|
||||
# Stable channel holds the old WeKan version until database migrations are ready.
|
||||
# Promote to stable manually via the Snap Store dashboard when migrations exist.
|
||||
- name: Publish all snaps to Snap Store (candidate, beta, edge)
|
||||
env:
|
||||
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAP_STORE_LOGIN }}
|
||||
run: |
|
||||
for snap_file in *.snap; do
|
||||
echo "Publishing $snap_file ..."
|
||||
snapcraft upload --release=edge "$snap_file"
|
||||
done
|
||||
|
||||
- name: Upload all snaps to GitHub Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
files: "*.snap"
|
||||
+23
-28
@@ -3,12 +3,12 @@
|
||||
# 'meteor add' and 'meteor remove' will edit this file for you,
|
||||
# but you can also edit it by hand.
|
||||
|
||||
meteor-base
|
||||
meteor-base@1.5.2
|
||||
|
||||
# Build system
|
||||
ecmascript
|
||||
standard-minifier-js
|
||||
rspack
|
||||
ecmascript@0.17.0
|
||||
standard-minifier-js@3.2.0
|
||||
rspack@1.0.0
|
||||
|
||||
blaze@3.0.2
|
||||
|
||||
@@ -16,18 +16,10 @@ blaze@3.0.2
|
||||
aldeed:collection2
|
||||
aldeed:schema-index@4.0.0-beta.5
|
||||
reywood:publish-composite
|
||||
mongo
|
||||
|
||||
# The holy trifecta - this is a replacement for subs-manager
|
||||
# for IndexedDB persistence and auto-sync
|
||||
jam:offline
|
||||
# for optimistic methods with offline queuing
|
||||
jam:method
|
||||
# global subscription caching
|
||||
jam:pub-sub
|
||||
mongo@2.3.0-beta350.7
|
||||
|
||||
# Account system
|
||||
accounts-password
|
||||
accounts-password@3.2.3-beta350.7
|
||||
communitypackages:core
|
||||
communitypackages:unstyled
|
||||
communitypackages:flow-routing
|
||||
@@ -41,19 +33,19 @@ wekan-oidc
|
||||
wekan-accounts-oidc
|
||||
|
||||
# Utilities
|
||||
check
|
||||
random
|
||||
reactive-dict
|
||||
session
|
||||
tracker
|
||||
audit-argument-checks
|
||||
check@1.5.0
|
||||
random@1.2.2
|
||||
reactive-dict@1.3.2
|
||||
session@1.2.2
|
||||
tracker@1.3.4
|
||||
audit-argument-checks@1.0.8
|
||||
|
||||
# UI components
|
||||
ostrio:i18n
|
||||
reactive-var
|
||||
shell-server
|
||||
email
|
||||
dynamic-import
|
||||
reactive-var@1.0.13
|
||||
shell-server@0.7.0
|
||||
email@3.2.0-beta350.7
|
||||
dynamic-import@0.7.4
|
||||
wekan-markdown
|
||||
quave:synced-cron
|
||||
ostrio:cookies
|
||||
@@ -61,9 +53,12 @@ ostrio:files
|
||||
# lmieulet:meteor-coverage
|
||||
meteortesting:mocha
|
||||
matb33:collection-hooks
|
||||
service-configuration
|
||||
minifier-css
|
||||
ejson
|
||||
logging
|
||||
service-configuration@1.3.5
|
||||
minifier-css@2.0.1
|
||||
ejson@1.2.0-beta350.7
|
||||
logging@1.3.6
|
||||
wekan-fullcalendar
|
||||
wekan-fontawesome
|
||||
jam:offline
|
||||
jam:method
|
||||
jam:pub-sub
|
||||
+1
-1
@@ -1 +1 @@
|
||||
METEOR@3.4
|
||||
METEOR@3.5-beta.7
|
||||
+13
-13
@@ -1,6 +1,6 @@
|
||||
accounts-base@3.2.0
|
||||
accounts-base@3.3.0-beta350.7
|
||||
accounts-oauth@1.4.6
|
||||
accounts-password@3.2.2
|
||||
accounts-password@3.2.3-beta350.7
|
||||
aldeed:collection2@4.1.5
|
||||
aldeed:schema-index@4.0.0
|
||||
aldeed:simple-schema@1.13.1
|
||||
@@ -23,18 +23,18 @@ communitypackages:flow-routing@2.1.0
|
||||
communitypackages:unstyled@2.0.1
|
||||
core-runtime@1.0.0
|
||||
ddp@1.4.2
|
||||
ddp-client@3.1.1
|
||||
ddp-client@3.2.0-beta350.7
|
||||
ddp-common@1.4.4
|
||||
ddp-rate-limiter@1.2.2
|
||||
ddp-server@3.1.2
|
||||
ddp-rate-limiter@1.3.0-beta350.7
|
||||
ddp-server@3.2.0-beta350.7
|
||||
diff-sequence@1.1.3
|
||||
dynamic-import@0.7.4
|
||||
ecmascript@0.17.0
|
||||
ecmascript-runtime@0.8.3
|
||||
ecmascript-runtime-client@0.12.3
|
||||
ecmascript-runtime-server@0.11.1
|
||||
ejson@1.1.5
|
||||
email@3.1.2
|
||||
ejson@1.2.0-beta350.7
|
||||
email@3.2.0-beta350.7
|
||||
es5-shim@4.8.1
|
||||
facts-base@1.0.2
|
||||
fetch@0.1.6
|
||||
@@ -60,11 +60,11 @@ meteortesting:mocha@2.1.0
|
||||
meteortesting:mocha-core@8.0.1
|
||||
minifier-css@2.0.1
|
||||
minifier-js@3.1.0
|
||||
minimongo@2.0.5
|
||||
minimongo@2.1.0-beta350.7
|
||||
modern-browsers@0.2.3
|
||||
modules@0.20.3
|
||||
modules-runtime@0.13.2
|
||||
mongo@2.2.0
|
||||
mongo@2.3.0-beta350.7
|
||||
mongo-decimal@0.2.0
|
||||
mongo-dev-server@1.1.1
|
||||
mongo-id@1.0.9
|
||||
@@ -76,13 +76,13 @@ ordered-dict@1.2.0
|
||||
ostrio:cookies@2.9.1
|
||||
ostrio:cstorage@4.0.1
|
||||
ostrio:files@3.0.1
|
||||
ostrio:flow-router-extra@3.12.1
|
||||
ostrio:flow-router-extra@3.13.0
|
||||
ostrio:i18n@3.2.1
|
||||
promise@1.0.0
|
||||
quave:synced-cron@2.4.0
|
||||
raix:eventemitter@1.0.0
|
||||
random@1.2.2
|
||||
rate-limit@1.1.2
|
||||
rate-limit@1.2.0-beta350.7
|
||||
react-fast-refresh@0.3.0
|
||||
reactive-dict@1.3.2
|
||||
reactive-var@1.0.13
|
||||
@@ -95,7 +95,7 @@ service-configuration@1.3.5
|
||||
session@1.2.2
|
||||
sha@1.0.10
|
||||
shell-server@0.7.0
|
||||
socket-stream-client@0.6.1
|
||||
socket-stream-client@0.7.0-beta350.7
|
||||
spacebars@2.0.0
|
||||
spacebars-compiler@2.0.0
|
||||
standard-minifier-js@3.2.0
|
||||
@@ -107,7 +107,7 @@ tools-core@1.0.0
|
||||
tracker@1.3.4
|
||||
typescript@5.9.3
|
||||
url@1.3.5
|
||||
webapp@2.1.0
|
||||
webapp@2.2.0-beta350.7
|
||||
webapp-hashing@1.1.2
|
||||
wekan-accounts-cas@0.2.0
|
||||
wekan-accounts-lockout@1.1.0
|
||||
|
||||
+789
-10
@@ -2,6 +2,7 @@
|
||||
|
||||
Newest WeKan at these platforms:
|
||||
|
||||
- [Upgrade WeKan](https://wekan.fi/upgrade/)
|
||||
- [bundle zip at releases](https://github.com/wekan/wekan/releases), docs at
|
||||
- [Linux amd64, arm64, s390x](https://github.com/wekan/wekan/blob/main/docs/Platforms/FOSS/RaspberryPi/Raspberry-Pi.md)
|
||||
- [Windows amd64, works also at Windows arm64](https://github.com/wekan/wekan/blob/main/docs/Platforms/Propietary/Windows/Offline.md)
|
||||
@@ -11,23 +12,801 @@ Newest WeKan at these platforms:
|
||||
- Docker amd64/arm64/s390x
|
||||
- Kubernetes Docker amd64
|
||||
- Bitnami MongoDB Docker images do not exist anymore. [MongoDump/MongoRestore to groundhog2k MongoDB images](https://github.com/wekan/charts/issues/45)
|
||||
- Fixing other platforms In Progress.
|
||||
|
||||
Fixing other platforms In Progress.
|
||||
Versions:
|
||||
|
||||
- [Node.js 22.x](https://nodejs.org/dist/latest-v22.x/)
|
||||
- MongoDB 6.x and 7.x, or [FerretDB2/PostgreSQL](https://github.com/wekan/wekan/blob/main/docs/Databases/FerretDB2-PostgreSQL.md)
|
||||
- WeKan 8.75 and newer uses Meteor 3.5-beta.7, [Node.js 24.x](https://nodejs.org/dist/latest-v24.x/),
|
||||
MongoDB 7.x (or 6.x), or [FerretDB2/PostgreSQL](https://github.com/wekan/wekan/blob/main/docs/Databases/FerretDB2-PostgreSQL.md)
|
||||
- WeKan 8.43 upgraded to Meteor 3.x, huge thanks to harryadel:
|
||||
- https://harryadel.com/dev-diary-24/
|
||||
- https://harryadel.com/dev-diary-25/
|
||||
- https://harryadel.com/dev-diary-26/
|
||||
- WeKan 8.00-8.24 used Colorful Unicode Emoji Icons, versions before and after use mostly Font Awesome 4.7 icons.
|
||||
- WeKan 8.00-8.06 had wrong raw database directory setting /var/snap/wekan/common/wekan and some cards were not visible,
|
||||
it was fixed at WeKan 8.07 where database directory is back to /var/snap/wekan/common and all cards are visible.
|
||||
|
||||
[Upgrade WeKan](https://wekan.fi/upgrade/)
|
||||
# v9.02 2026-04-28 WeKan ® release
|
||||
|
||||
WeKan 8.00-8.06 had wrong raw database directory setting /var/snap/wekan/common/wekan and some cards were not visible.
|
||||
Those are fixed at WeKan 8.07 where database directory is back to /var/snap/wekan/common and all cards are visible.
|
||||
This release fixes the following bugs:
|
||||
|
||||
WeKan 8.00-8.24 used Colorful Unicode Emoji Icons, versions before and after use mostly Font Awesome 4.7 icons.
|
||||
- [Fix mongodb in snap 9.01 on Ubuntu 24.04 crashes because of missing libcrypto.so.1.1](https://github.com/wekan/wekan/commit/a4b5ac6c4e2cfba6983b81ff0282e1c787576d06).
|
||||
Thanks to sbaecker.
|
||||
|
||||
Upgrading to Meteor 3 progress:
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
- https://harryadel.com/dev-diary-24/
|
||||
- https://harryadel.com/dev-diary-25/
|
||||
# v9.01 2026-04-28 WeKan ® release
|
||||
|
||||
This release adds the following updates:
|
||||
|
||||
- [Updated Docker platforms for what currently builds successfully](https://github.com/wekan/wekan/commit/fdb477f3517383eb17169b1dfff2ef94c12b6296).
|
||||
Thanks to xet7.
|
||||
- [Docs: Updated s390x page](https://github.com/wekan/wekan/commit/855cb86088c7c54734eddb1ddc5a007b432a0d91).
|
||||
Thanks to xet7.
|
||||
- [Removed charts, that are moved back to github.com/wekan/charts](https://github.com/wekan/wekan/commit/b49aa050e91b4bd560512af1beece791c6e39114).
|
||||
Thanks to xet7.
|
||||
- [Moved website to separate repo. Moved docs2 back to docs](https://github.com/wekan/wekan/commit/f6d8befb56c88eb0867c70bac708f867fe731a5a).
|
||||
Thanks to xet7.
|
||||
- [Disable not working GitHub workflows](https://github.com/wekan/wekan/commit/58de6bb73714e6c6d4010de5c72499f429bd9a41).
|
||||
Thanks to xet7.
|
||||
- [Fix Snap mongodb port wrong](https://github.com/wekan/wekan/commit/11a2c95ea70a3dcf9243369f8feeaea301a93bb6).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v9.00 2026-04-27 WeKan ® release
|
||||
|
||||
This release adds the following updates:
|
||||
|
||||
- [Bump actions/upload-pages-artifact from 4 to 5](https://github.com/wekan/wekan/pull/6304).
|
||||
Thanks to dependabot.
|
||||
- [Bump docker/setup-buildx-action from 3 to 4](https://github.com/wekan/wekan/pull/6305).
|
||||
Thanks to dependabot.
|
||||
- [Bump actions/deploy-pages from 4 to 5](https://github.com/wekan/wekan/pull/6306).
|
||||
Thanks to dependabot.
|
||||
- [Update release scripts](https://github.com/wekan/wekan/commit/db2701f1d731898c80b44606a985d5d132f7f6ed).
|
||||
Thanks to xet7.
|
||||
- [Added back jam packages. Updated dependencies](https://github.com/wekan/wekan/commit/bf5ca3d3ebef7f00778eb1a518fcfaf5b5fc5d5c).
|
||||
Thanks to xet7.
|
||||
- [Updated dependencies](https://github.com/wekan/wekan/commit/16832124ce169c823ab1f95a43a85bec22d5556f).
|
||||
Thanks to xet7.
|
||||
- [Update security.md etc](https://github.com/wekan/wekan/commit/7700efde1fba8483a78c67d03e3a0d214cedb67b).
|
||||
Thanks to xet7.
|
||||
- [Updated HoF](https://github.com/wekan/wekan/commit/675c6611146a4a47eee1e513b83152007e3b9aee).
|
||||
Thanks to xet7.
|
||||
- [Update releases scripts](https://github.com/wekan/wekan/commit/64f58455ff471b5a5567d7230850124cf0afacb0).
|
||||
Thanks to xet7.
|
||||
- [Update release and version scripts](https://github.com/wekan/wekan/commit/699b9a9c712f01068324c051be4fb149dfc6f100).
|
||||
Thanks to xet7.
|
||||
- Updated dependencies.
|
||||
[Part 1](https://github.com/wekan/wekan/commit/b459151798d9808b4243d230ff6759a58d4016f5),
|
||||
[Part 2](https://github.com/wekan/wekan/commit/74965f5f95ba4e4dfd7381becd55184731a60fca).
|
||||
Thanks to developers of dependencies.
|
||||
- [Updated website](https://github.com/wekan/wekan/commit/ef4161889af58827f105749362196fd471e3e38c).
|
||||
Thanks to xet7.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Update cards.js](https://github.com/wekan/wekan/pull/6299).
|
||||
Thanks to snowsky.
|
||||
- [Fix MongoDB replicaset setup at docker-compose.yml](https://github.com/wekan/wekan/commit/c4e084ffbbc5870a13e79f80a2982d2eb7f2f04e).
|
||||
Thanks to C0rn3j.
|
||||
- [Add permission checks to list width method](https://github.com/wekan/wekan/pull/6303).
|
||||
Thanks to Raawen-dev.
|
||||
- [Fix UI hangs and data loss by disabling changeStreams, until there is new Meteor release that included bugfix to changeStreams](https://github.com/wekan/wekan/commit/c47eb013b4d8d0f2dea7b801adc60151f6e3aee1).
|
||||
Thanks to bcook-konza and italojs.
|
||||
- [Fix list actions popup overflow](https://github.com/wekan/wekan/pull/6310).
|
||||
Thanks to Raawen-dev.
|
||||
- [Fix mycards subscription](https://github.com/wekan/wekan/pull/6314).
|
||||
Thanks to aminsaidane.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.99 2026-04-16 WeKan ® release
|
||||
|
||||
This release adds the following updates:
|
||||
|
||||
- [Release scripts: Update versions](https://github.com/wekan/wekan/commit/32e1ec9d2251840dc2d57ffa7976f2c60546ca9d).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.98 2026-04-16 WeKan ® release
|
||||
|
||||
This release adds the following updates:
|
||||
|
||||
- [Release scripts: Detect newest Node.js 24.x version](https://github.com/wekan/wekan/commit/fde59148dc8bd712e30cbf969d4007b2a7f01e6f).
|
||||
Thanks to xet7.
|
||||
- [Release scripts: Update versions at website with release-website.sh script](https://github.com/wekan/wekan/commit/9174001862f1545626730b9a51754ab77b645338).
|
||||
Thanks to xet7.
|
||||
- [Release scripts: Detect newest MongoDB 7.x stable version and update to use it](https://github.com/wekan/wekan/commit/72f6d96dbc3becc2767eb6f88b0f218679d1ac78).
|
||||
Thanks to xet7.
|
||||
- [Moved website from repo wekan/wekan.fi to wekan/wekan/docs](https://github.com/wekan/wekan/commit/3c36db33e91e504722edc60faec5d6b4aa301850).
|
||||
Thanks to xet7.
|
||||
- [Moved docs to docs2, and wekan.fi to docs, to be able publish with GitHub Pages](https://github.com/wekan/wekan/commit/1c0d8e9964af40be91eda9668dfeebd01b3a5720).
|
||||
Thanks to xet7.
|
||||
- [Update markdown docs links from docs to docs2](https://github.com/wekan/wekan/commit/c1639ea58973efcae0758385cc5d8d7ffbf1e8d9).
|
||||
Thanks to xet7.
|
||||
- [Commented out requirement to update website manually](https://github.com/wekan/wekan/commit/64d351d835628dad80062e3c362701b35ae5bb33).
|
||||
Thanks to xet7.
|
||||
- [Moved Helm Charts from helm directory to docs/wekan and docs/charts to be at wekan.fi/wekan and wekan.fi/charts](https://github.com/wekan/wekan/commit/38e488ee4a63d61159d8efcddb6e454347bce91a).
|
||||
Thanks to xet7.
|
||||
- [Release scripts: Fix indentation at release-all.yml](https://github.com/wekan/wekan/commit/10f009f5b15fd077577a71504b0e0c89c4e6fd95).
|
||||
Thanks to xet7.
|
||||
- [Release scripts: Use latest available Node.js slim docker images when building](https://github.com/wekan/wekan/commit/d998e8cb4a5280c93448d144ab01335ce29b43dc).
|
||||
Thanks to xet7.
|
||||
- [Release scripts: Fix updating version numbers](https://github.com/wekan/wekan/commit/7b0e2213cfbf0e2a17a143aa7ad9f979fb0fbf07).
|
||||
Thanks to xet7.
|
||||
- [Release scripts: Require only newest version number when releasing](https://github.com/wekan/wekan/commit/052d8c15844dfc709dc3ac281795629c175869e0).
|
||||
Thanks to xet7.
|
||||
- [Release scripts: Use 24-slim fallback](https://github.com/wekan/wekan/commit/a0c190137dfe9fd8da71380f6c67344812561f9f).
|
||||
Thanks to xet7.
|
||||
- [Release scripts: use node:24-slim directly](https://github.com/wekan/wekan/commit/51ad6ed99df7ecdc925d314a6c5fab345f75d549).
|
||||
Thanks to xet7.
|
||||
- [Fix Helm Chart parts to docs/wekan and docs/charts](https://github.com/wekan/wekan/commit/1820804b9f46e510c4bf05324755a5eeec5a3b13).
|
||||
Thanks to xet7.
|
||||
- [Release scripts: Updated creating Helm Charts to docs/wekan and docs/charts](https://github.com/wekan/wekan/commit/f6198dee30ed6514974d2e821997d340e67fc954).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.97 2026-04-16 WeKan ® release
|
||||
|
||||
This release adds the following updates:
|
||||
|
||||
- Release Scripts: Clean GitHub Cache.
|
||||
[Part 1](https://github.com/wekan/wekan/commit/e59bc9cd86cc16333e24b2e7e8e5d5cf72f81e3e),
|
||||
[Part 2](https://github.com/wekan/wekan/commit/13cdf08e223e83ef9a2f36417c11ad002e884f29),
|
||||
[Part 3](https://github.com/wekan/wekan/commit/6d0978d0ede8316a1d9ac6afc0ecf7f02d9193d6).
|
||||
Thanks to xet7.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Fix GitHub Actions builds](https://github.com/wekan/wekan/commit/6478d27d1ca2f6e27c025e0cc97b618bc255083f).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.96 2026-04-16 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Fix GitHub Actions builds](https://github.com/wekan/wekan/commit/03ba747bc073f3993d933b814d35c7380fea745d).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.95 2026-04-16 WeKan ® release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Helm Chart: Add single-node ReplicaSet support with auto MONGO_OPLOG_URL](https://github.com/wekan/wekan/pull/6292).
|
||||
Thanks to titver968.
|
||||
- [Helm Chart: Use current Finland time for created field at index.yaml for newest built Helm Chart release](https://github.com/wekan/wekan/commit/135af977af4a1c598d2e067de0facb6eae8f8de1).
|
||||
Thanks to xet7.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Fix Cannot find module /build/main.js error in latest Docker image](https://github.com/wekan/wekan/commit/6dfe81cbcb0c6e2003b1984586d56042a6408e70).
|
||||
Thanks to s8321414 and xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.94 2026-04-16 WeKan ® release
|
||||
|
||||
This release adds the following updates:
|
||||
|
||||
- [Updated dompurify](https://github.com/wekan/wekan/commit/c27d5d04124f3eec659bbe5187a625c43176fc4f).
|
||||
Thanks to developers of dompurify.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Fix Can't start latest docker image because of MongoDB Index errors](https://github.com/wekan/wekan/commit/d537b7c9f3505fd4c1653f87d5f86d7e7729a514).
|
||||
Thanks to s8321414 and xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.93 2026-04-16 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Fix SSO Login broken. Part 2](https://github.com/wekan/wekan/commit/4aa7b6aa2034f27efeb67d5dfa8f6acbe0005786).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.92 2026-04-16 WeKan ® release
|
||||
|
||||
This release adds the following updates:
|
||||
|
||||
- [Updated Helm Charts versions](https://github.com/wekan/wekan/commit/24ebb4ba45344ad152747c31e7df76217e5b8909).
|
||||
Thanks to xet7.
|
||||
- [GitHub Actions: Added missing sudo to snap build](https://github.com/wekan/wekan/commit/2c8a6c8ec6e24b6b6bb153da3edd089e0f0087cc).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.91 2026-04-16 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Fix building Snap at GitHub Actions](https://github.com/wekan/wekan/commit/89de05ee91612cef4f13fa8ad32d112dca5bdb43).
|
||||
Thanks to xet7.
|
||||
- [Updated Helm Chart URL at readme](https://github.com/wekan/wekan/commit/529e0d25ef2ea84953d1c1e6a23b5798d34583fb).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.90 2026-04-16 WeKan ® release
|
||||
|
||||
This release adds the following updates:
|
||||
|
||||
- [Added GitHub Actions builds for Docker and Snap. Moved Helm Charts from charts repo to wekan repo](https://github.com/wekan/wekan/commit/f57ce521984f6f358410863c71fcaee342bb8107).
|
||||
Thanks to xet7.
|
||||
- [Changed ArtifactHub from wekan/charts repo to wekan/wekan repo](https://github.com/wekan/wekan/commit/99519af83adc45eca7beb40a4e82f5b73764b7fc).
|
||||
Thanks to xet7.
|
||||
- [Release scripts: Moved more steps to GitHub Actions](https://github.com/wekan/wekan/commit/357f63d01fc013ea412501dabbdd977e5f1efa61).
|
||||
Thanks to xet7.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Removed jam:offline jam:method jam:pub-sub, because they are not used, and they cause too much database usage](https://github.com/wekan/wekan/commit/0dd924f14889100e74fbd5e8d17bb3a7209025ca).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.89 2026-04-15 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Disable jam:offline keepAll BEFORE any collections are created. Part 2](https://github.com/wekan/wekan/commit/f6a851a3d887ce9fa2fa5f62aad2a2ecf326c863).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.88 2026-04-15 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Disable jam:offline keepAll to prevent full-collection COLLSCAN queries and Ensure standard GridFS index on attachments.chunks for efficient chunk lookups](https://github.com/wekan/wekan/commit/ec0c1bc9afd6e3fd8b60f9f17f96dc5df52dbfc2).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.87 2026-04-15 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Try to fix Snap](https://github.com/wekan/wekan/commit/fc02a15753badc8d06d020aa97daae28ac05a310).
|
||||
Thanks to xet7.
|
||||
- [Improve handling of ROOT_URL as an environement variable](https://github.com/wekan/wekan/pull/6286).
|
||||
Thanks to FlorentDotMe.
|
||||
- [UI: Enable the horizontal scroll in the quick access menu boards list](https://github.com/wekan/wekan/pull/6287).
|
||||
Thanks to FlorentDotMe.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.86 2026-04-15 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Try to fix Snap](https://github.com/wekan/wekan/commit/10f801d31b7e2b1a8c562bf24f65c4cc6efe6013).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.85 2026-04-15 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Try to fix Snap](https://github.com/wekan/wekan/commit/0e13bfc50eadc72adccfe785a1b47c30d0ba5429).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.84 2026-04-15 WeKan ® release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Helm Chart: Make readiness, liveness and startup probes configurable](https://github.com/wekan/charts/pull/51).
|
||||
Thanks to snowsky.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Fix SSO Login OIDC and OpenID Connect](https://github.com/wekan/wekan/pull/6284).
|
||||
Thanks to sbaecker and nebulade.
|
||||
- [Try to fix Snap Candidate](https://github.com/wekan/wekan/commit/bc92978fa9c9373947de40fe9ca584e133825610).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.83 2026-04-14 WeKan ® release
|
||||
|
||||
This release adds the following updates:
|
||||
|
||||
- [Release scripts: Removed armhf, there is no official Node.js binary for it](https://github.com/wekan/wekan/commit/d0a9fa9a71029a5586cf5bc87488619c7db9d0e3).
|
||||
Thanks to xet7.
|
||||
- [Release scripts: Docker not for armhf, no official Node.js binary for it](https://github.com/wekan/wekan/commit/41db7b4ad18359283602b8bfdb42b15acf51782d).
|
||||
Thanks to xet7.
|
||||
- [Release scripts: Fix Node.js 24.x download URL for Snap builds](https://github.com/wekan/wekan/commit/2c43aa463a0baadcae3db9f34066a9ddf6e77594).
|
||||
Thanks to xet7.
|
||||
- [Changed start-wekan.sh and start-wekan.bat to not use Change Streams](https://github.com/wekan/wekan/commit/da4459304fe7d068b1db91938f7fd4ffd04c5bcb).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.82 2026-04-14 WeKan ® release
|
||||
|
||||
This release adds the following updates:
|
||||
|
||||
- [Release scripts: Added script for deleting repo git tag](https://github.com/wekan/wekan/commit/11672a13f7b102b764978600a8fce2f757c9401a).
|
||||
Thanks to xet7.
|
||||
- [Bump softprops/action-gh-release from 2 to 3](https://github.com/wekan/wekan/pull/6281).
|
||||
Thanks to dependabot.
|
||||
- [Bump docker/build-push-action from 7.0.0 to 7.1.0](https://github.com/wekan/wekan/pull/6282).
|
||||
Thanks to dependabot.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.81 2026-04-14 WeKan ® release
|
||||
|
||||
This release adds the following updates:
|
||||
|
||||
- Updated dependencies
|
||||
[Part 1](https://github.com/wekan/wekan/commit/7b91439b0f9ec0e409c14ecebab389d41b40a990),
|
||||
[Part 2](https://github.com/wekan/wekan/commit/1637a9c938134ef26846ba3c0cd53c065f434e3e).
|
||||
Thanks to developers of dependencies.
|
||||
- [Docs: Added History of Schema Migration Systems](https://github.com/wekan/wekan/commit/2e7565f9eb744bc59e454745e06fd43a85a02f97).
|
||||
Thanks to xet7.
|
||||
- [Release scripts: Comment out build for armhf because no official Node.js 24.x binaries exist for armhf (arm/v7)](https://github.com/wekan/wekan/commit/5462fb06477bc3a83f1d5c754ecd60ebe7643ee6).
|
||||
Thanks to xet7.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Fix activities are not showing](https://github.com/wekan/wekan/pull/6272).
|
||||
Thanks to snowsky.
|
||||
- [Fix Link Card modal overflow in Docker environment](https://github.com/wekan/wekan/pull/6273).
|
||||
Thanks to AymenHassini19.
|
||||
- [Fix/readme node version and changes made](https://github.com/wekan/wekan/pull/6271).
|
||||
Thanks to YosserDerbali.
|
||||
- [Clarify board drag tooltip text in Remaining and Workspaces](https://github.com/wekan/wekan/pull/6268).
|
||||
Thanks to YosserDerbali.
|
||||
- [Add migration for v7.95 due dates](https://github.com/wekan/wekan/pull/6262).
|
||||
Thanks to Raawen-dev.
|
||||
- [Fix: include historical comments and activities in board exports](https://github.com/wekan/wekan/pull/6275).
|
||||
Thanks to KhaoulaMaleh.
|
||||
- [Fix Exporter: Attachments always empty in board JSON export](https://github.com/wekan/wekan/pull/6279).
|
||||
Thanks to kolaente.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.80 2026-04-10 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Try to fix GitHub Actions builds with custom newer bcrypt](https://github.com/wekan/wekan/commit/2ebefdd0bf1cf482548319e130baf2b633ba259b).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.79 2026-04-09 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Fix 8.78: WeKan build Error: Could not find rspack config. Using MongoDB Change Streams
|
||||
at start-wekan.sh start-wekan.bat bundle, docker-compose.yml and Snap Candidate](https://github.com/wekan/wekan/commit/2d4170a9bfc58b8e6504abf122aea505e55802ef).
|
||||
Thanks to nachocodoner and xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.78 2026-04-09 WeKan ® release
|
||||
|
||||
This release adds the the following updates:
|
||||
|
||||
- Upgraded to Meteor 3.5-beta.7 and Node.js 24.14.1. Now prefers MongoDB Change Streams at Snap Candidate and docker-compose.yml.
|
||||
[Part 1](https://github.com/wekan/wekan/commit/14f9ac39ad93db4f7c06721f1efd4c18e53cc5f8),
|
||||
[Part 2](https://github.com/wekan/wekan/commit/b1707b8691d0ba5f355e78e250765c8a7657c3d7).
|
||||
Thanks to Meteor developers.
|
||||
- [Enhance translations with new key:value pairs](https://github.com/wekan/wekan/pull/6259).
|
||||
Thanks to KhaoulaMaleh.
|
||||
- [Refine translations](https://github.com/wekan/wekan/pull/6261).
|
||||
Thanks to KhaoulaMaleh.
|
||||
- [Updated to Node.js 24.x at release scripts](https://github.com/wekan/wekan/commit/bdb92744854cc211866631746c63d748d4a93cfa).
|
||||
Thanks to xet7.
|
||||
- [Fix GitHub Actions builds](https://github.com/wekan/wekan/commit/bc88c0dfc2742154e94861201d239bc4b3c51cef).
|
||||
Thanks to xet7.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Fixed Card settings checkboxes](https://github.com/wekan/wekan/pull/6260).
|
||||
Thanks to KhaoulaMaleh.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.74 2026-04-08 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Fix can not save Card Data. Part 2](https://github.com/wekan/wekan/commit/0328e70d5f4a277722635e3fd9ea78312d1359cf).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.73 2026-04-07 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Fix Link to Windows release doesn't work](https://github.com/wekan/wekan/commit/9c695302565073b971a3521c0a94a380641cc436).
|
||||
Thanks to hmeunier95 and xet7.
|
||||
- [Fix 8.72 Bug: Can not save Card Date](https://github.com/wekan/wekan/commit/8da0f34ee6ca66884ab8a2dcdf1a724a0c9fcc81).
|
||||
Thanks to xet7.
|
||||
- [Removed exclude-archs from rebuild-wekan.sh, it is not necessary anymore](https://github.com/wekan/wekan/commit/028b404377651d34e334b048ecc960d3ff5b2eab).
|
||||
Thanks to xet7.
|
||||
- [Fix 8.72 Bug: LDAP login does not work. ReactiveCache is not defined](https://github.com/wekan/wekan/commit/bcbf4771ea88fb617ddc44650c8ac139b0cfc998).
|
||||
Thanks to poc-sm and xet7.
|
||||
- [Fix Error in choosing member or assignee in a card](https://github.com/wekan/wekan/commit/7f0c42cca555dd2dca04d3b6413c0080ea75e96e).
|
||||
Thanks to hmeunier95 and xet7.
|
||||
- [Fix Search All Boards result opened card missing Copy Card Link etc that can be used to open correct card](https://github.com/wekan/wekan/commit/304a007d078c04dac7de5074a856c4f0cc2c0aa7).
|
||||
Thanks bcook-konza and xet7.
|
||||
- [Fix Checklists add and Subtasks reorder. Fix Board Activity part 1](https://github.com/wekan/wekan/commit/08ebad0fe4a2b8a7b93d75a9a9c2317ce9374fea).
|
||||
Thanks bcook-konza and xet7.
|
||||
- [Fix Change list inside or card](https://github.com/wekan/wekan/commit/aea8c285c246b490ac259ceafe7d9f733681c20f).
|
||||
Thanks to mimZD and xet7.
|
||||
- [Fix board and card activities. Part 2](https://github.com/wekan/wekan/commit/c7408ad8d147f36cfdbb71089af688bef91c3ecf).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.72 2026-04-07 WeKan ® release
|
||||
|
||||
This release adds the following new features and fixes:
|
||||
|
||||
- [Fix Impersonate User. Show/Edit Avatar at Admin Panel/People/People](https://github.com/wekan/wekan/commit/3ac7c9057e1e53da9f285149ce832ad430b3bc30).
|
||||
Thanks to ahlgrimma, DnT1mmer, robbagithub, norrig and xet7.
|
||||
|
||||
and adds the following updates:
|
||||
|
||||
- [Bump actions/download-artifact from 4 to 8](https://github.com/wekan/wekan/pull/6247).
|
||||
Thanks to dependabot.
|
||||
- [Bump actions/upload-artifact from 4 to 7](https://github.com/wekan/wekan/pull/6248).
|
||||
Thanks to dependabot.
|
||||
- [Bump actions/cache from 4 to 5](https://github.com/wekan/wekan/pull/6249).
|
||||
Thanks to dependabot.
|
||||
- [Bump docker/login-action from 4.0.0 to 4.1.0](https://github.com/wekan/wekan/pull/6250).
|
||||
Thanks to dependabot.
|
||||
- [Updated release scripts](https://github.com/wekan/wekan/commit/87f592c67ffb1962ec8acb0d1676b8df6ac42a5d).
|
||||
Thanks to xet7.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Fix Admin Panel / Version not showing name of MongoDB storage engine and status of MongoDB Oplog enabled](https://github.com/wekan/wekan/commit/3b98f862bcda3e8a9b0d0131b91cdfa59986c2d8).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# 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
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Try to fix Docker and Snap](https://github.com/wekan/wekan/commit/03e0cfdc15c56ac0219f5e435034a1c0ad5006ae).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.51 2026-04-03 WeKan ® release
|
||||
|
||||
This release adds the following updates:
|
||||
|
||||
- [Updated release scripts](https://github.com/wekan/wekan/commit/4594711be41d1e9cf15b1f8bb070fcb36bf736ca).
|
||||
Thanks to xet7.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Fix Bug: WeKan v8.50 WRITABLE_PATH](https://github.com/wekan/wekan/commit/edc6b18b5f77320e966e56c888575bcb764096dc).
|
||||
Thanks to snowsky and xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.50 2026-04-03 WeKan ® release
|
||||
|
||||
This release adds the following updates:
|
||||
|
||||
- [Uncommented build steps. Not yet tested are required dependencies included](https://github.com/wekan/wekan/commit/145a17fee5dc9430de7a60100657566a4a69bc7b).
|
||||
Thanks to xet7.
|
||||
- [Updated npm package @wekanteam/exceljs](https://github.com/wekan/wekan/commit/6e8589b1f96b5f0c2ddec0831b238096ce610b1e).
|
||||
Thanks to xet7.
|
||||
- [Updated dependencies](https://github.com/wekan/wekan/commit/bf02c9a453e27edba1c08830eb4783b9dfc7bbc2).
|
||||
Thanks to developers of dependencies.
|
||||
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`.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Fix indentation for release-all.yml workflow](https://github.com/wekan/wekan/pull/6240).
|
||||
Thanks to snowsky.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.49 2026-03-31 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Fix: Missing module @meteorjs/reify/lib/runtime](https://github.com/wekan/wekan/pull/6237).
|
||||
Thanks to mzch and kovacs-andras.
|
||||
- [Fix docker-compose.yml](https://github.com/wekan/wekan/commit/d07fcceb6a884cf1ff0c9a2d36691af0304f36e7).
|
||||
Thanks to xet7.
|
||||
- [Try to fix Snap](https://github.com/wekan/wekan/commit/8b4676175caa4af36bf11567676f3c3f522f9512).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.48 2026-03-31 WeKan ® release
|
||||
|
||||
This release adds the following updates:
|
||||
|
||||
- Updated release scripts.
|
||||
[Part 1](https://github.com/wekan/wekan/commit/43601c5e3e95d6026f2e558f261c02a9578dcecd),
|
||||
[Part 2](https://github.com/wekan/wekan/commit/56377aaf4c5e92c1a03dc996b6c649ce17553280).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.47 2026-03-31 WeKan ® release
|
||||
|
||||
This release adds the following updates:
|
||||
|
||||
- [Updated attachments and avatar path to be at WRITABLE_PATH/files/attachments etc](https://github.com/wekan/wekan/commit/e58e99c2852dd81a040dcffc0f1f2798c4b8cf15).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.46 2026-03-31 WeKan ® release
|
||||
|
||||
This release adds the following updates:
|
||||
|
||||
- Updated release scripts.
|
||||
[Part 1](https://github.com/wekan/wekan/commit/6bc68ba57bf15339b80011d131a7da65124e071d),
|
||||
[Part 2](https://github.com/wekan/wekan/commit/ce52b8a0ab29805c562a2af0b79e30d970594e17).
|
||||
Thanks to xet7.
|
||||
- [Updated docker-compose.yml to change from FerretDB/PostgreSQL to MongoDB](https://github.com/wekan/wekan/commit/02b75824e5dc24c968959d5a64f846efe33dee4f).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.45 2026-03-31 WeKan ® release
|
||||
|
||||
This release adds the following updates:
|
||||
|
||||
- Updated release scripts.
|
||||
[Part 1](https://github.com/wekan/wekan/commit/4223c2a79f4c276ab1c9734a94314f1d1d1ce033),
|
||||
[Part 2](https://github.com/wekan/wekan/commit/6125822cf7244242832d1fe02f99150abb7350d0),
|
||||
[Part 3](https://github.com/wekan/wekan/commit/e90b2e384c168fbb4cee389d8af9b54a5bc57734),
|
||||
[Part 4](https://github.com/wekan/wekan/commit/29550cbd9335fc95e4f4ac399fe754ece8573450),
|
||||
[Part 5](https://github.com/wekan/wekan/commit/8349fb6b63097970d06af73af388b030761967bd),
|
||||
[Part 6](https://github.com/wekan/wekan/commit/f43b76c323c1f09cf1885251792b29229ef77d2b),
|
||||
[Part 7](https://github.com/wekan/wekan/commit/e90b2e384c168fbb4cee389d8af9b54a5bc57734).
|
||||
Thanks to xet7.
|
||||
- Updated GitHub Actions.
|
||||
[Part 1](https://github.com/wekan/wekan/commit/4b8cc0683e9dfdffb7ff7896f622afe8f908a7f5),
|
||||
[Part 2](https://github.com/wekan/wekan/commit/df067f01e894f43305ad36cebdf48a1bf55ff33a),
|
||||
[Part 3](https://github.com/wekan/wekan/commit/ec1e3835586bdc09d93d5049794e8657b460acef),
|
||||
[Part 4](https://github.com/wekan/wekan/commit/79853a2fb7efb738f2f10b6c2e9fef69def88c48),
|
||||
[Part 5](https://github.com/wekan/wekan/commit/9ae2842fa4bedbd4c132943703ef462cc353ab1a),
|
||||
[Part 6](https://github.com/wekan/wekan/commit/1a5e23617de98e6b65f78dfb25c233440f818d11),
|
||||
[Part 7](https://github.com/wekan/wekan/commit/c38fa1c272c32323d8a164dfcf34b898127e6b1d),
|
||||
[Part 8](https://github.com/wekan/wekan/commit/d8a2e06a95713e33e5676df38951dfd3f991ecb3),
|
||||
[Part 9](https://github.com/wekan/wekan/commit/e6ccbfd3b88299c52fbaad9f85fc3b438e3cdc89),
|
||||
[Part 10](https://github.com/wekan/wekan/commit/7666c6c0e1660b5aba300f4e465877bcf73d8066).
|
||||
Thanks to dependabot.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- Try to fix Snap.
|
||||
[Part 1](https://github.com/wekan/wekan/commit/e5c551f0092ccb71fafa3433bfd99911f9a2e9c0),
|
||||
[Part 2](https://github.com/wekan/wekan/commit/55ec0b5ff5594c10ebbc8cba74339de2ad0557a6),
|
||||
[Part 3](https://github.com/wekan/wekan/commit/fd58bb9e4dd0f825237a50043a171fc223d44101),
|
||||
[Part 4](https://github.com/wekan/wekan/commit/cdf1d3305bd738fe5357a5f3a9df2f7e6858d1d0),
|
||||
[Part 5](https://github.com/wekan/wekan/commit/2aa8ecfc39a6f971134784817b46ba9867bb402d),
|
||||
[Part 6](https://github.com/wekan/wekan/commit/ed718f083aa0c9f82e368a5badfe73393753a617),
|
||||
[Part 7](https://github.com/wekan/wekan/commit/5c4130311a063340bd89dff571fbf685cda7a3ba),
|
||||
[Part 8](https://github.com/wekan/wekan/commit/33267fa2e462fcc6cd2243ae1b5b39d59b03988f),
|
||||
[Part 9](https://github.com/wekan/wekan/commit/87916c20bf579e16e21fa3bd9ac7687019b277eb),
|
||||
[Part 10](https://github.com/wekan/wekan/commit/12c223d2260c9bd9547ae35a394869ef90e8bc83).
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v8.44 2026-03-30 WeKan ® release
|
||||
|
||||
|
||||
+6
-6
@@ -7,18 +7,17 @@ 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.44
|
||||
ARG VERSION=9.02
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
ENV BUILD_DEPS="apt-utils gnupg wget bzip2 g++ curl libarchive-tools build-essential git ca-certificates python3 unzip"
|
||||
|
||||
ENV \
|
||||
DEBUG=false \
|
||||
NODE_VERSION=v22.22.2 \
|
||||
METEOR_RELEASE=METEOR@3.4 \
|
||||
NODE_VERSION=v24.15.0 \
|
||||
METEOR_RELEASE=METEOR@3.5-beta.7 \
|
||||
USE_EDGE=false \
|
||||
METEOR_EDGE=1.5-beta.17 \
|
||||
NPM_VERSION=10.9.2 \
|
||||
NPM_VERSION=11.11.0 \
|
||||
SRC_PATH=./ \
|
||||
WITH_API=true \
|
||||
MONGO_OPLOG_URL="" \
|
||||
@@ -191,7 +190,7 @@ rm -f "node-${NODE_VERSION}-linux-${NODE_ARCH}.tar.gz" SHASUMS256.txt.asc
|
||||
ln -s "/usr/local/bin/node" "/usr/local/bin/nodejs"
|
||||
|
||||
# NPM configuration
|
||||
npm install -g npm@${NPM_VERSION} --production
|
||||
npm install -g npm@${NPM_VERSION}
|
||||
chown --recursive wekan:wekan /home/wekan/
|
||||
|
||||
# Temporary Tar swap for Meteor bundle
|
||||
@@ -204,6 +203,7 @@ cd /home/wekan/app
|
||||
wget "https://github.com/wekan/wekan/releases/download/v${VERSION}/wekan-${VERSION}-${WEKAN_ARCH}.zip"
|
||||
unzip "wekan-${VERSION}-${WEKAN_ARCH}.zip"
|
||||
rm "wekan-${VERSION}-${WEKAN_ARCH}.zip"
|
||||
npm install --prefix ./bundle/programs/server
|
||||
mv /home/wekan/app/bundle /build
|
||||
|
||||
# Restore original tar
|
||||
|
||||
@@ -47,12 +47,13 @@ See bottom of https://github.com/wekan/wekan/issues/3874
|
||||
## FAQ
|
||||
|
||||
**NOTE**:
|
||||
|
||||
- Please read the [FAQ](https://github.com/wekan/wekan/blob/main/docs/FAQ/FAQ.md) first
|
||||
- Please don't feed the [trolls](https://github.com/wekan/wekan/blob/main/docs/FAQ/FAQ.md#why-am-i-called-a-troll) and [spammers](https://github.com/wekan/wekan/blob/main/docs/FAQ/FAQ.md#why-am-i-called-a-spammer) that are mentioned in the FAQ :)
|
||||
|
||||
## About WeKan ®
|
||||
|
||||
WeKan ® is an completely [Open Source][open_source] and [Free software][free_software]
|
||||
WeKan ® is a completely [Open Source][open_source] and [Free software][free_software]
|
||||
collaborative kanban board application with MIT license.
|
||||
|
||||
Whether you’re maintaining a personal todo list, planning your holidays with some friends,
|
||||
@@ -76,15 +77,15 @@ that by providing one-click installation on various platforms.
|
||||
- 1 GB RAM minimum free for WeKan ®. Production server should have minimum total 4 GB RAM.
|
||||
For thousands of users, for example with [Docker](https://github.com/wekan/wekan/blob/main/docker-compose.yml): 3 frontend servers,
|
||||
each having 2 CPU and 2 wekan-app containers. One backend wekan-db server with many CPUs.
|
||||
- Enough disk space and alerts about low disk space. If you run out disk space, MongoDB database gets corrupted.
|
||||
- Enough disk space and alerts about low disk space. If you run out of disk space, MongoDB database gets corrupted.
|
||||
- SECURITY: Updating to newest WeKan ® version very often. Please check you do not have automatic updates of Sandstorm or Snap turned off.
|
||||
Old versions have security issues because of old versions Node.js etc. Only newest WeKan ® is supported.
|
||||
WeKan ® on Sandstorm is not usually affected by any Standalone WeKan ® (Snap/Docker/Source) security issues.
|
||||
- [Reporting all new bugs immediately](https://github.com/wekan/wekan/issues).
|
||||
New features and fixes are added to WeKan ® [many times a day](https://github.com/wekan/wekan/blob/main/CHANGELOG.md).
|
||||
- [Backups](https://github.com/wekan/wekan/blob/main/docs/Backup/Backup.md) of WeKan ® database once a day miminum.
|
||||
- [Backups](https://github.com/wekan/wekan/blob/main/docs/Backup/Backup.md) of WeKan ® database once a day minimum.
|
||||
Bugs, updates, users deleting list or card, harddrive full, harddrive crash etc can eat your data. There is no undo yet.
|
||||
Some bug can cause WeKan ® board to not load at all, requiring manual fixing of database content.
|
||||
Some bugs can cause WeKan ® board to not load at all, requiring manual fixing of database content.
|
||||
|
||||
## Roadmap and Demo
|
||||
|
||||
@@ -92,7 +93,7 @@ that by providing one-click installation on various platforms.
|
||||
|
||||
[Developer Documentation][dev_docs]
|
||||
|
||||
- There is many companies and individuals contributing code to WeKan ®, to add features and bugfixes
|
||||
- There are many companies and individuals contributing code to WeKan ®, to add features and bugfixes
|
||||
[many times a day](https://github.com/wekan/wekan/blob/main/CHANGELOG.md).
|
||||
- [Please add Add new Feature Requests and Bug Reports immediately](https://github.com/wekan/wekan/issues).
|
||||
- [Commercial Support](https://wekan.fi/commercial-support/).
|
||||
@@ -102,12 +103,75 @@ By working directly with WeKan ® you get the benefit of active maintenance and
|
||||
|
||||
## Getting Started with Development
|
||||
|
||||
The default branch uses [Meteor 2 with Node.js 14](https://wekan.fi/install/).
|
||||
The default branch uses Meteor 3.5-beta.7 with Node.js 24.x.
|
||||
See [CHANGELOG.md](https://github.com/wekan/wekan/blob/main/CHANGELOG.md) for the latest runtime updates.
|
||||
|
||||
To contribute, [create a fork](https://github.com/wekan/wekan/blob/main/docs/DeveloperDocs/Build-and-Create-Pull-Request.md#2-create-fork-of-httpsgithubcomwekanwekan-at-github-web-page) and run `./rebuild-wekan.sh` (or `./rebuild-wekan.bat` on Windows) as detailed [here](https://github.com/wekan/wekan/blob/main/docs/DeveloperDocs/Build-and-Create-Pull-Request.md#3-select-option-1-to-install-dependencies-and-then-enter). Once you're ready, please test your code and [submit a pull request (PR)](https://github.com/wekan/wekan/blob/main/docs/DeveloperDocs/Build-and-Create-Pull-Request.md#7-test).
|
||||
|
||||
Please refer to the [developer documentation](https://github.com/wekan/wekan/blob/main/docs/DeveloperDocs/Developer-Documentation.md) for more information.
|
||||
|
||||
## First-Time Setup for Development
|
||||
|
||||
### Prerequisites
|
||||
|
||||
Before building WeKan from source, ensure you have:
|
||||
|
||||
- **Git** - for cloning the repository
|
||||
- **Node.js 24.x** - WeKan requires Node.js 24.x
|
||||
- **Meteor** - the JavaScript framework WeKan is built with
|
||||
|
||||
### Installing Node.js 24.x
|
||||
|
||||
```bash
|
||||
# Using nvm (recommended)
|
||||
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
|
||||
source ~/.zshrc # or ~/.bashrc
|
||||
nvm install 24
|
||||
nvm use 24
|
||||
```
|
||||
|
||||
### Installing Meteor
|
||||
|
||||
```bash
|
||||
curl https://install.meteor.com/ | sh
|
||||
```
|
||||
|
||||
### Building WeKan
|
||||
|
||||
The `rebuild-wekan.sh` script guides you through a three-stage process:
|
||||
|
||||
1. **Install dependencies (Option 1)** - Downloads all required Meteor packages and npm modules
|
||||
2. **Build WeKan (Option 2)** - Compiles the application
|
||||
3. **Run WeKan (Option 3)** - Starts the development server at http://localhost:4000
|
||||
|
||||
```bash
|
||||
# Clone your fork
|
||||
git clone git@github.com:YOUR_USERNAME/wekan.git
|
||||
cd wekan
|
||||
|
||||
# Make the script executable
|
||||
chmod +x rebuild-wekan.sh
|
||||
|
||||
# Step 1: Install dependencies
|
||||
./rebuild-wekan.sh
|
||||
# Press 1 and Enter
|
||||
|
||||
# Step 2: Build WeKan (after dependencies complete)
|
||||
./rebuild-wekan.sh
|
||||
# Press 2 and Enter
|
||||
|
||||
# Step 3: Run WeKan in development mode
|
||||
./rebuild-wekan.sh
|
||||
# Press 3 and Enter
|
||||
```
|
||||
|
||||
|
||||
### WSL Users
|
||||
|
||||
WSL users can use Snap Candidate. See [install docs](https://wekan.fi/install/).
|
||||
|
||||
The development server will start at http://localhost:4000. Any changes you make to the source code will automatically trigger a rebuild and refresh your browser.
|
||||
|
||||
## Screenshot
|
||||
|
||||
[More screenshots at Features page](https://github.com/wekan/wekan/tree/main/docs/Features)
|
||||
|
||||
+61
-79
@@ -1,38 +1,21 @@
|
||||
## About money
|
||||
## About Money: No bounty
|
||||
|
||||
See [CONTRIBUTING](CONTRIBUTING.md)
|
||||
There is no bounty, like described at [CONTRIBUTING.md](CONTRIBUTING.md),
|
||||
because WeKan is NOT Big Tech. WeKan is FLOSS.
|
||||
|
||||
## Responsible Security Disclosure
|
||||
|
||||
1. To send email, if possible, use PGP key [security-at-wekan.fi.asc](security-at-wekan.fi.asc)
|
||||
2. Send info about security issue ONLY to security@wekan.fi . NOT TO ANYWHERE ELSE. NO CC, NO BCC.
|
||||
3. Wait for new WeKan release that fixes security issue to appear to top of
|
||||
1. Please email info about security issue to security@wekan.fi .
|
||||
If possible, include code for fixing security issue.
|
||||
Optional PGP key is at [security-at-wekan.fi.asc](security-at-wekan.fi.asc)
|
||||
2. Wait for new WeKan release that fixes security issue to appear to top of
|
||||
https://github.com/wekan/wekan/blob/main/CHANGELOG.md
|
||||
4. We will thank you by adding you to Hall of Fame: https://wekan.fi/hall-of-fame/
|
||||
5. All vulnerability details will be private to security@wekan.fi ,
|
||||
unless you help all WeKan platforms to have a way to upgrade, like sending
|
||||
database migrations code to security@wekan.fi or PRs to https://github.com/wekan/wekan/pulls .
|
||||
There is no benefit to Wordwide Security Community to have more details about vulnerabilities,
|
||||
if Worldwide Security Community does not help to make upgrades possible.
|
||||
6. If there some day becomes available a way to upgrade all WeKan platforms,
|
||||
this page will be updated to add permission for security researchers
|
||||
to request new GHSA or CVE ID and publish your vulnerability details at your blog, talks, etc,
|
||||
and send that info also to security@wekan.fi to be added to
|
||||
Hall of Fame: https://wekan.fi/hall-of-fame/ to get Upgrade Bonus Point Stars.
|
||||
In that case, it will become possible for security@wekan.fi to publish all
|
||||
remaining private security details, and publicly thank Worldwide Security Community.
|
||||
3. We will thank you by adding you to
|
||||
Hall the of Fame: https://wekan.fi/hall-of-fame/
|
||||
4. If you get CVE number assigned, please send it to security@wekan.fi, it will be added to
|
||||
Hall the of Fame: https://wekan.fi/hall-of-fame/
|
||||
|
||||
## Bonus Points
|
||||
|
||||
- If you include code for fixing security issue
|
||||
|
||||
## Losing Points
|
||||
|
||||
- If you ask about [bounty](CONTRIBUTING.md). There is no bounty. WeKan is NOT Big Tech. WeKan is FLOSS.
|
||||
- If you forget to include vulnerability details.
|
||||
- If you send info about security issue to somewhere else than security@wekan.fi
|
||||
|
||||
## How should reports be formatted?
|
||||
## How Should Reports Be Formatted?
|
||||
|
||||
```
|
||||
Name: %name
|
||||
@@ -57,15 +40,15 @@ added to the WeKan Hall of Fame https://wekan.fi/hall-of-fame/
|
||||
No public domains, because all those are donated to Wekan Open Source project,
|
||||
and we don't have any permissions to do security scans on those donated servers.
|
||||
|
||||
Please don't perform research that could impact other users. Secondly, please keep
|
||||
the reports short and succinct. If we fail to understand the logics of your bug, we will tell you.
|
||||
Please don't perform research that could impact other users. Second, please keep
|
||||
the reports short and succinct. If we fail to understand the logic of your bug, we will tell you.
|
||||
|
||||
You can [Install Wekan](https://github.com/wekan/wekan/releases) to your own computer
|
||||
You can [Install Wekan](https://wekan.fi/install/) on your own computer
|
||||
and scan it's vulnerabilities there.
|
||||
|
||||
## About Wekan versions
|
||||
## About Wekan Versions
|
||||
|
||||
There are only 2 versions of Wekan: Standalone Wekan, and Sandstorm Wekan.
|
||||
There are 2 versions of Wekan: Standalone Wekan, and Sandstorm Wekan.
|
||||
|
||||
### Standalone Wekan Security
|
||||
|
||||
@@ -74,11 +57,12 @@ like Snap and Docker have their own specific sandboxing etc features.
|
||||
|
||||
Standalone Wekan by default does not load any files from Internet, like fonts, CSS, etc.
|
||||
This also means all Standalone Wekan functionality works in offline local networks.
|
||||
WeKan is used at most countries of the world https://snapcraft.io/wekan
|
||||
and by by companies that have 30k users.
|
||||
WeKan is used in most countries of the world https://snapcraft.io/wekan
|
||||
and by companies that have 30k users.
|
||||
|
||||
- Wekan private board attachments are not accessible without logging in.
|
||||
- There is feature to set board public, so that board is visible without logging in in readonly mode, with realtime updates.
|
||||
- There is feature to set board public, so that board is visible without logging
|
||||
in readonly mode, with realtime updates.
|
||||
- Admin Panel has feature to disable all public boards, so all boards are private.
|
||||
|
||||
## SSL/TLS
|
||||
@@ -90,24 +74,25 @@ and by by companies that have 30k users.
|
||||
|
||||
## XSS
|
||||
|
||||
- Dompurify https://www.npmjs.com/package/dompurify
|
||||
- WeKan uses dompurify npm package to filter for XSS at fields like cards, as you can see from
|
||||
- DOMpurify https://www.npmjs.com/package/dompurify
|
||||
- WeKan uses DOMpurify npm package to filter for XSS at fields like cards, as you can see from
|
||||
[package.json](https://github.com/wekan/wekan/blob/main/package.json). Other used versions can be seen from
|
||||
[Meteor versions file](https://github.com/wekan/wekan/blob/main/.meteor/versions).
|
||||
- Forms can include markdown links, html, image tags etc like you see at https://wekan.github.io .
|
||||
- It's possible to add attachments to cards, and markdown/html links to files.
|
||||
- Dompurify cleans up viewed code, so Javascript in input fields does not execute
|
||||
- Dompurify cleans up viewed code, so JavaScript in input fields does not execute
|
||||
- https://wekan.github.io/hall-of-fame/fieldbleed/
|
||||
- Reaction in comment is now checked, that it does not have extra added code
|
||||
- https://wekan.github.io/hall-of-fame/reactionbleed/
|
||||
- https://github.com/wekan/wekan/blob/main/packages/markdown/src/template-integration.js#L76
|
||||
|
||||
## QA about PubSub
|
||||
## QA About PubSub
|
||||
|
||||
Q:
|
||||
|
||||
Hello,
|
||||
I have just seen the Meteor DevTools Evolved extension and was wondering if anyone had asked themselves the question of security.
|
||||
I have just seen the Meteor DevTools Evolved extension and was wondering if anyone
|
||||
had asked themselves the question of security.
|
||||
Insofar as all data is shown in the minimongo tab in plain text.
|
||||
How can data be hidden from this extension?
|
||||
|
||||
@@ -115,32 +100,36 @@ A:
|
||||
|
||||
## PubSub
|
||||
|
||||
- It is not security issue to show some text or image, that user has permission to see. It is a security issue, if browserside is some text or image that user should not see.
|
||||
- Meteor has browserside minimongo database, made with Javascript, updated with Publish/Subscribe, PubSub.
|
||||
- Publish/Subscribe means, that realtime web framework reads database changes stream, and then immediately updates webpage,
|
||||
like like dashboards, chat, kanban. That is the point in any realtime web framework in any programming language.
|
||||
- Yes, you should check with Meteor DevTools Evolved Chromium/Firefox extension that at minimongo is only text that user has permission to see.
|
||||
- Do checking as logged in user, and logged out user.
|
||||
- It is not a security issue to show text or images that the user has permission to see.
|
||||
It is a security issue, if browserside is some text or image that user should not see.
|
||||
- Meteor has browserside minimongo database, made with JavaScript, updated with Publish/Subscribe, PubSub.
|
||||
- Publish/Subscribe means, that realtime web framework reads database changes stream,
|
||||
and then immediately updates webpage, like dashboards, chat, kanban.
|
||||
That is the point of any realtime web framework in any programming language.
|
||||
- Yes, you should check with Meteor DevTools Evolved Chromium/Firefox extension that
|
||||
at minimongo is only text that user has permission to see.
|
||||
- Check as a logged-in user and as a logged-out user.
|
||||
- Check permissions and sanitize before allowing some change, because someone could modify content of input field,
|
||||
PubSub/websocket data (for example with Burp Suite Community Edition), etc.
|
||||
- If you have REST API, also check that only those that have login token, and have permission, can view or edit text
|
||||
- If you have a REST API, also check that only those who have a login token and permission can view or edit text.
|
||||
- You should not include any data user is not allowed to see. Not to webpage text, not to websockets/PubSub, etc.
|
||||
- Minimongo should not have password hashes PubSub https://wekan.github.io/hall-of-fame/userbleed/
|
||||
- PubSub uses Websockets, so you need those to be enabled at webserver like Caddy/Nginx/Apache etc, examples of settings
|
||||
- PubSub uses WebSockets, so you need those to be enabled on the webserver like Caddy/Nginx/Apache etc, examples of settings
|
||||
at right menu of https://github.com/wekan/wekan/wiki
|
||||
- Clientside https://github.com/wekan/wekan/tree/main/client/components subscribes to
|
||||
PubSub https://github.com/wekan/wekan/tree/main/server/publications or calls meteor methods at https://github.com/wekan/wekan/tree/main/models
|
||||
- Clientside https://github.com/wekan/wekan/tree/main/client/components subscribes to
|
||||
PubSub https://github.com/wekan/wekan/tree/main/server/publications or calls meteor methods
|
||||
at https://github.com/wekan/wekan/tree/main/models
|
||||
- For Admin:
|
||||
- You can have input field for password https://github.com/wekan/wekan/blob/main/client/components/cards/attachments.js#L303-L312
|
||||
- You can save password to database https://github.com/wekan/wekan/blob/main/client/components/cards/attachments.js#L303-L312
|
||||
- Check that only current user or Admin can change password https://github.com/wekan/wekan/blob/main/client/components/cards/attachments.js#L303-L312
|
||||
- Note that currentUser uses code like Meteor.user() in .js file
|
||||
- Do not have password hashes in PubSub https://github.com/wekan/wekan/blob/main/server/publications/users.js
|
||||
- Do not include password hashes in PubSub https://github.com/wekan/wekan/blob/main/server/publications/users.js
|
||||
- Only show Admin Panel to Admin https://github.com/wekan/wekan/blob/main/client/components/settings/settingBody.jade#L3
|
||||
- If there is a lot of data, use pagination https://github.com/wekan/wekan/blob/main/client/components/settings/peopleBody.js
|
||||
- Only have limited amount of data published in PubSub. Limit in MongoDB query in publications how much is published. Too much could make browser too slow.
|
||||
- Use Environment variables for any email etc passwords.
|
||||
- But what if you would like to remove minimongo? And only use Meteor methods for saving? In that case, you don't have realtime updates,
|
||||
- If there is a large amount of data, use pagination https://github.com/wekan/wekan/blob/main/client/components/settings/peopleBody.js
|
||||
- Only publish a limited amount of data in PubSub. Limit in MongoDB query in publications how much is published. Too much could make browser too slow.
|
||||
- Environment variables for email and other passwords.
|
||||
- But what if you would like to remove Minimongo and only use Meteor methods for saving? In that case, you don't have realtime updates,
|
||||
and you need to write much more code to load and save data yourself, handle any multi user data saving conflicts yourself,
|
||||
and many Meteor Atmospherejs.com PubSub using packages would not work anymore https://github.com/wekan/we
|
||||
|
||||
@@ -152,10 +141,10 @@ A:
|
||||
|
||||
## Permissions and Roles
|
||||
|
||||
- For any user permissions, it's best to use Meteor package package https://github.com/Meteor-Community-Packages/meteor-roles .
|
||||
- Currently WeKan has custom hardcoded permissions, WeKan does not yet use that meteor-roles package.
|
||||
- For any user permissions, it's best to use Meteor package https://github.com/Meteor-Community-Packages/meteor-roles .
|
||||
- Currently, WeKan has custom hardcoded permissions and does not yet use the meteor-roles package.
|
||||
- Using permissions at WeKan sidebar https://github.com/wekan/wekan/blob/main/client/components/sidebar/sidebar.js#L1854-L1875
|
||||
- List of roles https://github.com/wekan/wekan/wiki/REST-API-Role . Change at board or Admin Panel. Also Organizations/Teams.
|
||||
- List of roles: https://github.com/wekan/wekan/wiki/REST-API-Role . Change at board or Admin Panel. Also Organizations/Teams.
|
||||
- Worker role: https://github.com/wekan/wekan/issues/2788
|
||||
- Not implemented yet: Granular Roles https://github.com/wekan/wekan/issues/3022
|
||||
- Check is user logged in, with `if (Meteor.user()) {`
|
||||
@@ -164,8 +153,8 @@ A:
|
||||
|
||||
## Environment variables
|
||||
|
||||
- For any passwords, use environment variables, those are serverside
|
||||
- Do not copy environment variable to public variable that is visible browserside https://github.com/wekan/wekan/blob/main/server/max-size.js
|
||||
- For any passwords, use environment variables; those are serverside
|
||||
- Do not copy environment variables to public variables that are visible on the browserside https://github.com/wekan/wekan/blob/main/server/max-size.js
|
||||
|
||||
```
|
||||
Meteor.startup(() => {
|
||||
@@ -176,13 +165,13 @@ Meteor.startup(() => {
|
||||
```
|
||||
|
||||
- For serverside, you can set Meteor.settings.variablename, without text public
|
||||
- For WeKan kanban, there is feature for setting board public, it can be viewed by anyone, there is realtime updates. But
|
||||
- For WeKan kanban, there is a feature for setting a board to public; it can be viewed by anyone, with realtime updates. But
|
||||
- Some of those permissions are checked at users.js models at https://github.com/wekan/wekan/tree/main/models
|
||||
- Environment variables are used for email server passwords, etc, at all platforms https://github.com/wekan/wekan/commit/a781c0e7dcfdbe34c1483ee83cec12455b7026f7
|
||||
|
||||
## Escape HTML comment tags so that HTML comments are visible
|
||||
|
||||
- Someone reported, that it is problem that content of HTML comments in edit mode, are not visible at at view mode, so this makes HTML comments visible.
|
||||
- Someone reported that it was a problem that the content of HTML comments in edit mode was not visible in view mode, so this change makes HTML comments visible.
|
||||
- https://github.com/wekan/wekan/commit/167863d95711249e69bb3511175d73b34acbbdb3
|
||||
- https://wekan.github.io/hall-of-fame/invisiblebleed/
|
||||
|
||||
@@ -249,18 +238,16 @@ Meteor.startup(() => {
|
||||
|
||||
### Sandstorm Wekan Security
|
||||
|
||||
On Sandstorm platform using environment variable Standalone Wekan features like Admin Panel etc are
|
||||
turned off, because Sandstorm platform provides SSO for all apps running on Sandstorm.
|
||||
On the Sandstorm platform, Standalone WeKan features like the Admin Panel are turned off using environment variables, because Sandstorm platform provides SSO for all apps running on Sandstorm.
|
||||
|
||||
[Sandstorm](https://sandstorm.io) is separate Open Source platform that has been
|
||||
[Sandstorm](https://sandstorm.io) is a separate Open Source platform that has been
|
||||
[security audited](https://sandstorm.io/news/2017-03-02-security-review) and found bugs fixed.
|
||||
Sandstorm also has passwordless login, LDAP, SAML, Google etc auth options already.
|
||||
At Sandstorm code is read-only and signed by app maintainers, only grain content can be modified.
|
||||
Wekan at Sandstorm runs in sandboxed grain, it does not have access elsewhere without user-visible
|
||||
PowerBox request or opening randomly-generated API key URL.
|
||||
Sandstorm also has passwordless login, LDAP, SAML, Google, and other auth options already.
|
||||
On Sandstorm, code is read-only and signed by app maintainers; only grain content can be modified.
|
||||
WeKan on Sandstorm runs in a sandboxed grain; it does not have access elsewhere without a user-visible PowerBox request or opening a randomly-generated API key URL.
|
||||
Also read [Sandstorm Security Practices](https://docs.sandstorm.io/en/latest/using/security-practices/) and
|
||||
[Sandstorm Security non-events](https://docs.sandstorm.io/en/latest/using/security-non-events/).
|
||||
For Sandstorm specific security issues you can contact [kentonv](https://github.com/kentonv) by email.
|
||||
For Sandstorm specific security issues you can contact [kentonv](https://github.com/kentonv) by email.
|
||||
|
||||
## What Wekan bugs are eligible?
|
||||
|
||||
@@ -276,16 +263,11 @@ a security issue, we'd like to know about it, and also how to fix it:
|
||||
|
||||
## What Wekan bugs are NOT eligible?
|
||||
|
||||
Typical already known or "no impact" bugs such as:
|
||||
Typical already-known or 'no impact' bugs such as:
|
||||
|
||||
- [Wekan API old tokens not replaced correctly](https://github.com/wekan/wekan/issues/1437)
|
||||
- Missing Cookie flags on non-session cookies or 3rd party cookies
|
||||
- Logout CSRF
|
||||
- Social engineering
|
||||
- Denial of service
|
||||
- SSL BEAST/CRIME/etc. Wekan does not have SSL built-in, it uses Caddy/Nginx/Apache etc at front.
|
||||
Integrated Caddy support is updated often.
|
||||
- Email spoofing, SPF, DMARC & DKIM. Wekan does not include email server.
|
||||
- SSL BEAST/CRIME/etc. WeKan does not have SSL built-in; it uses Caddy/Nginx/Apache on the front end.
|
||||
|
||||
Wekan is Open Source with MIT license, and free to use also for commercial use.
|
||||
We welcome all fixes to improve security by email to security@wekan.fi
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
appId: wekan-public/apps/77b94f60-dec9-0136-304e-16ff53095928
|
||||
appVersion: "v8.44.0"
|
||||
appVersion: "v9.02.0"
|
||||
files:
|
||||
userUploads:
|
||||
- README.md
|
||||
|
||||
@@ -9,11 +9,11 @@ template(name="activities")
|
||||
+cardActivities
|
||||
|
||||
template(name="boardActivities")
|
||||
each activityData in currentBoard.activities
|
||||
each activityData in boardActivitiesList
|
||||
+activity(activity=activityData card=card mode=mode)
|
||||
|
||||
template(name="cardActivities")
|
||||
each activityData in activities
|
||||
each activityData in cardActivitiesList
|
||||
+activity(activity=activityData card=card mode=mode)
|
||||
|
||||
template(name="activity")
|
||||
|
||||
@@ -76,7 +76,9 @@ function _showActivities(data) {
|
||||
const currentCard = Utils.getCurrentCard();
|
||||
ret = currentCard.showActivities ?? false;
|
||||
} else if (mode === 'card') {
|
||||
ret = data?.card?.showActivities ?? false;
|
||||
// For card mode, get showActivities from data context or fallback to current card
|
||||
const card = data?.card || Utils.getCurrentCard();
|
||||
ret = card?.showActivities ?? false;
|
||||
} else {
|
||||
ret = Utils.getCurrentBoard().showActivities ?? false;
|
||||
}
|
||||
@@ -85,8 +87,31 @@ function _showActivities(data) {
|
||||
}
|
||||
|
||||
Template.activities.helpers({
|
||||
showActivities() {
|
||||
const data = Template.currentData();
|
||||
return _showActivities(data);
|
||||
},
|
||||
|
||||
activities() {
|
||||
return this.card.activities();
|
||||
const activities = this.card?.activities?.();
|
||||
return activities || [];
|
||||
},
|
||||
});
|
||||
|
||||
Template.boardActivities.helpers({
|
||||
boardActivitiesList() {
|
||||
const board = Utils.getCurrentBoard();
|
||||
const activities = board?.activities?.();
|
||||
return activities || [];
|
||||
},
|
||||
});
|
||||
|
||||
Template.cardActivities.helpers({
|
||||
cardActivitiesList() {
|
||||
const data = Template.currentData();
|
||||
const card = data?.card;
|
||||
const activities = card?.activities?.();
|
||||
return activities || [];
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -130,7 +130,7 @@ template(name="boardList")
|
||||
if BoardMultiSelection.isActive
|
||||
.materialCheckBox.multi-selection-checkbox.js-toggle-board-multi-selection(
|
||||
class="{{#if BoardMultiSelection.isSelected _id}}is-checked{{/if}}")
|
||||
span.board-handle(title="{{_ 'drag-board'}}")
|
||||
span.board-handle(title="{{boardWorkspaceDragHint}}")
|
||||
span.emoji-icon
|
||||
i.fa.fa-arrows
|
||||
|
||||
@@ -158,13 +158,13 @@ template(name="boardList")
|
||||
if BoardMultiSelection.isActive
|
||||
.materialCheckBox.multi-selection-checkbox.js-toggle-board-multi-selection(
|
||||
class="{{#if BoardMultiSelection.isSelected _id}}is-checked{{/if}}")
|
||||
span.board-handle(title="{{_ 'drag-board'}}")
|
||||
span.board-handle(title="{{boardWorkspaceDragHint}}")
|
||||
span.emoji-icon
|
||||
i.fa.fa-arrows
|
||||
|
||||
a.js-open-board(href="{{pathFor 'board' id=_id slug=slug}}")
|
||||
span.details
|
||||
span.board-list-item-name(title="{{_ 'board-drag-drop-reorder-or-click-open'}}")
|
||||
span.board-list-item-name(title="{{boardOpenAndMoveHint}}")
|
||||
+viewer
|
||||
= title
|
||||
unless currentSetting.hideBoardMemberList
|
||||
|
||||
@@ -539,6 +539,26 @@ Template.boardList.helpers({
|
||||
hasBoardsSelected() {
|
||||
return BoardMultiSelection.count() > 0;
|
||||
},
|
||||
boardWorkspaceDragHint() {
|
||||
const drag = TAPi18n.__('drag-board') || 'Drag board';
|
||||
const remaining = TAPi18n.__('allboards.remaining') || 'Remaining';
|
||||
const workspaces = TAPi18n.__('allboards.workspaces') || 'Workspaces';
|
||||
return `${drag}: ${remaining} <-> ${workspaces}`;
|
||||
},
|
||||
boardOpenAndMoveHint() {
|
||||
const remaining = TAPi18n.__('allboards.remaining') || 'Remaining';
|
||||
const workspaces = TAPi18n.__('allboards.workspaces') || 'Workspaces';
|
||||
return (
|
||||
TAPi18n.__(
|
||||
'board-open-and-move-between-remaining-and-workspaces',
|
||||
{
|
||||
remaining,
|
||||
workspaces,
|
||||
},
|
||||
) ||
|
||||
`Click board icon to open board. Drag board between ${remaining} and ${workspaces}.`
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
Template.workspaceTree.helpers({
|
||||
|
||||
@@ -48,7 +48,7 @@ Template.editCardReceivedDatePopup.helpers(datePickerHelpers());
|
||||
|
||||
Template.editCardReceivedDatePopup.events(datePickerEvents({
|
||||
storeDate(date) {
|
||||
this.datePicker.card.setReceived(formatDateTime(date));
|
||||
this.datePicker.card.setReceived(date);
|
||||
},
|
||||
deleteDate() {
|
||||
this.datePicker.card.unsetReceived();
|
||||
@@ -72,7 +72,7 @@ Template.editCardStartDatePopup.helpers(datePickerHelpers());
|
||||
|
||||
Template.editCardStartDatePopup.events(datePickerEvents({
|
||||
storeDate(date) {
|
||||
this.datePicker.card.setStart(formatDateTime(date));
|
||||
this.datePicker.card.setStart(date);
|
||||
},
|
||||
deleteDate() {
|
||||
this.datePicker.card.unsetStart();
|
||||
@@ -96,7 +96,7 @@ Template.editCardDueDatePopup.helpers(datePickerHelpers());
|
||||
|
||||
Template.editCardDueDatePopup.events(datePickerEvents({
|
||||
storeDate(date) {
|
||||
this.datePicker.card.setDue(formatDateTime(date));
|
||||
this.datePicker.card.setDue(date);
|
||||
},
|
||||
deleteDate() {
|
||||
this.datePicker.card.unsetDue();
|
||||
@@ -120,7 +120,7 @@ Template.editCardEndDatePopup.helpers(datePickerHelpers());
|
||||
|
||||
Template.editCardEndDatePopup.events(datePickerEvents({
|
||||
storeDate(date) {
|
||||
this.datePicker.card.setEnd(formatDateTime(date));
|
||||
this.datePicker.card.setEnd(date);
|
||||
},
|
||||
deleteDate() {
|
||||
this.datePicker.card.unsetEnd();
|
||||
|
||||
@@ -11,31 +11,30 @@ template(name="cardDetails")
|
||||
+editCardTitleForm
|
||||
else
|
||||
unless isMiniScreen
|
||||
unless isPopup
|
||||
span.card-collapse-toggle.js-card-collapse-toggle(title="{{_ 'collapse-card'}}")
|
||||
if cardCollapsed
|
||||
i.fa.fa-caret-right
|
||||
else
|
||||
i.fa.fa-caret-down
|
||||
a.close-card-details.js-close-card-details(title="{{_ 'close-card'}}")
|
||||
i.fa.fa-times-thin
|
||||
if cardMaximized
|
||||
a.fa.fa-window-minimize.minimize-card-details.js-minimize-card-details(title="{{_ 'minimize-card'}}")
|
||||
span.card-collapse-toggle.js-card-collapse-toggle(title="{{_ 'collapse-card'}}")
|
||||
if cardCollapsed
|
||||
i.fa.fa-caret-right
|
||||
else
|
||||
a.fa.fa-window-maximize.maximize-card-details.js-maximize-card-details(title="{{_ 'maximize-card'}}")
|
||||
a.card-details-menu.js-open-card-details-menu(title="{{_ 'cardDetailsActionsPopup-title'}}")
|
||||
i.fa.fa-bars
|
||||
a.card-copy-button.js-copy-link(
|
||||
id="cardURL_copy"
|
||||
title="{{_ 'copy-card-link-to-clipboard'}}"
|
||||
href="{{ originRelativeUrl }}"
|
||||
)
|
||||
span.emoji-icon
|
||||
i.fa.fa-link
|
||||
if canModifyCard
|
||||
span.card-drag-handle.js-card-drag-handle(title="Drag card")
|
||||
i.fa.fa-arrows
|
||||
span.copied-tooltip {{_ 'copied'}}
|
||||
i.fa.fa-caret-down
|
||||
a.close-card-details.js-close-card-details(title="{{_ 'close-card'}}")
|
||||
i.fa.fa-times-thin
|
||||
if cardMaximized
|
||||
a.fa.fa-window-minimize.minimize-card-details.js-minimize-card-details(title="{{_ 'minimize-card'}}")
|
||||
else
|
||||
a.fa.fa-window-maximize.maximize-card-details.js-maximize-card-details(title="{{_ 'maximize-card'}}")
|
||||
a.card-details-menu.js-open-card-details-menu(title="{{_ 'cardDetailsActionsPopup-title'}}")
|
||||
i.fa.fa-bars
|
||||
a.card-copy-button.js-copy-link(
|
||||
id="cardURL_copy"
|
||||
title="{{_ 'copy-card-link-to-clipboard'}}"
|
||||
href="{{ originRelativeUrl }}"
|
||||
)
|
||||
span.emoji-icon
|
||||
i.fa.fa-link
|
||||
if canModifyCard
|
||||
span.card-drag-handle.js-card-drag-handle(title="Drag card")
|
||||
i.fa.fa-arrows
|
||||
span.copied-tooltip {{_ 'copied'}}
|
||||
else
|
||||
a.close-card-details.js-close-card-details(title="{{_ 'close-card'}}")
|
||||
i.fa.fa-times-thin
|
||||
|
||||
@@ -207,22 +207,22 @@ Template.cardDetails.onRendered(function () {
|
||||
EscapeActions.executeUpTo('popup-close');
|
||||
},
|
||||
stop(evt, ui) {
|
||||
let prevChecklist = ui.item.prev('.js-subtasks').get(0);
|
||||
if (prevChecklist) {
|
||||
prevChecklist = Blaze.getData(prevChecklist).subtask;
|
||||
let prevSubtask = ui.item.prev('.js-subtasks').get(0);
|
||||
if (prevSubtask) {
|
||||
prevSubtask = Blaze.getData(prevSubtask).subtask;
|
||||
}
|
||||
let nextChecklist = ui.item.next('.js-subtasks').get(0);
|
||||
if (nextChecklist) {
|
||||
nextChecklist = Blaze.getData(nextChecklist).subtask;
|
||||
let nextSubtask = ui.item.next('.js-subtasks').get(0);
|
||||
if (nextSubtask) {
|
||||
nextSubtask = Blaze.getData(nextSubtask).subtask;
|
||||
}
|
||||
const sortIndex = calculateIndexData(prevChecklist, nextChecklist, 1);
|
||||
const sortIndex = calculateIndexData(prevSubtask, nextSubtask, 1);
|
||||
|
||||
$subtasksDom.sortable('cancel');
|
||||
const subtask = Blaze.getData(ui.item.get(0)).subtask;
|
||||
|
||||
Subtasks.update(subtask._id, {
|
||||
Cards.updateAsync(subtask._id, {
|
||||
$set: {
|
||||
subtaskSort: sortIndex.base,
|
||||
sort: sortIndex.base,
|
||||
},
|
||||
});
|
||||
},
|
||||
@@ -272,8 +272,8 @@ Template.cardDetails.helpers({
|
||||
},
|
||||
|
||||
showActivities() {
|
||||
const user = ReactiveCache.getCurrentUser();
|
||||
return user && user.hasShowActivities();
|
||||
const card = Template.currentData();
|
||||
return card && card.showActivities;
|
||||
},
|
||||
|
||||
cardCollapsed() {
|
||||
@@ -337,7 +337,12 @@ Template.cardDetails.helpers({
|
||||
},
|
||||
|
||||
isCurrentListId(listId) {
|
||||
const data = Template.currentData();
|
||||
// When called from within 'each currentBoard.lists' block, we need the card from parent context
|
||||
let data = Template.currentData();
|
||||
if (!data || typeof data.listId === 'undefined') {
|
||||
// Try parent context (for use within each loops)
|
||||
data = Template.parentData(1);
|
||||
}
|
||||
if (!data || typeof data.listId === 'undefined') return false;
|
||||
return data.listId == listId;
|
||||
},
|
||||
@@ -556,9 +561,8 @@ Template.cardDetails.events({
|
||||
}
|
||||
},
|
||||
async 'change .js-select-card-details-lists'(event, tpl) {
|
||||
const listId = event.target.value;
|
||||
let card = Template.currentData();
|
||||
const listSelect = tpl.$('.js-select-card-details-lists')[0];
|
||||
const listId = listSelect.options[listSelect.selectedIndex].value;
|
||||
|
||||
const minOrder = await card.getMinSort(listId, card.swimlaneId);
|
||||
await card.move(card.boardId, card.swimlaneId, listId, minOrder - 1);
|
||||
@@ -602,6 +606,10 @@ Template.cardDetails.events({
|
||||
const card = Template.currentData();
|
||||
await card.toggleHideCheckedChecklistItems();
|
||||
},
|
||||
async 'change #toggleShowActivitiesCard'() {
|
||||
const card = Template.currentData();
|
||||
await card.toggleShowActivities();
|
||||
},
|
||||
'click #toggleCustomFieldsGridButton'() {
|
||||
Meteor.call('toggleCustomFieldsGrid');
|
||||
},
|
||||
@@ -1096,14 +1104,21 @@ const filterMembers = (filterTerm) => {
|
||||
let members = currBoard.activeMembers();
|
||||
|
||||
if (filterTerm) {
|
||||
const searchTerm = filterTerm.toLowerCase();
|
||||
members = members
|
||||
.map(member => ({
|
||||
member,
|
||||
user: ReactiveCache.getUser(member.userId)
|
||||
}))
|
||||
.filter(({ user }) =>
|
||||
(user.profile.fullname !== undefined && user.profile.fullname.toLowerCase().indexOf(filterTerm.toLowerCase()) !== -1)
|
||||
|| user.profile.fullname === undefined && user.profile.username !== undefined && user.profile.username.toLowerCase().indexOf(filterTerm.toLowerCase()) !== -1)
|
||||
.filter(({ user }) => {
|
||||
// Check if user data is available
|
||||
if (!user || !user.profile) {
|
||||
return false;
|
||||
}
|
||||
const fullname = (user.profile.fullname || '').toLowerCase();
|
||||
const username = (user.username || '').toLowerCase();
|
||||
return fullname.indexOf(searchTerm) !== -1 || username.indexOf(searchTerm) !== -1;
|
||||
})
|
||||
.map(({ member }) => member);
|
||||
}
|
||||
return members;
|
||||
|
||||
@@ -223,7 +223,7 @@ Template.checklists.events({
|
||||
event.preventDefault();
|
||||
Template.currentData().card.toggleHideFinishedChecklist();
|
||||
},
|
||||
keydown(event) {
|
||||
'keydown textarea.js-add-checklist-item'(event) {
|
||||
//If user press enter key inside a form, submit it
|
||||
//Unless the user is also holding down the 'shift' key
|
||||
if (event.keyCode === 13 && !event.shiftKey) {
|
||||
|
||||
@@ -11,17 +11,21 @@ template(name="minicard")
|
||||
a.minicard-details-menu-with-handle.js-open-minicard-details-menu(title="{{_ 'cardDetailsActionsPopup-title'}}")
|
||||
i.fa.fa-bars
|
||||
.dates
|
||||
if getReceived
|
||||
.date
|
||||
+minicardReceivedDate
|
||||
if getStart
|
||||
.date
|
||||
+minicardStartDate
|
||||
if getDue
|
||||
.date
|
||||
+minicardDueDate
|
||||
if getEnd
|
||||
+minicardEndDate
|
||||
if showReceived
|
||||
if getReceived
|
||||
.date
|
||||
+minicardReceivedDate
|
||||
if showStart
|
||||
if getStart
|
||||
.date
|
||||
+minicardStartDate
|
||||
if showDue
|
||||
if getDue
|
||||
.date
|
||||
+minicardDueDate
|
||||
if showEnd
|
||||
if getEnd
|
||||
+minicardEndDate
|
||||
if getSpentTime
|
||||
.date
|
||||
+cardSpentTime
|
||||
@@ -68,19 +72,20 @@ template(name="minicard")
|
||||
span.linked-icon.linked-archived
|
||||
i.fa.fa-archive
|
||||
+viewer
|
||||
if currentBoard.allowsCardNumber
|
||||
if showCardNumber
|
||||
span.card-number
|
||||
| ##{getCardNumber}
|
||||
= getTitle
|
||||
if labels
|
||||
.minicard-labels(class="{{#if hiddenMinicardLabelText}}minicard-labels-no-text{{/if}}")
|
||||
each labels
|
||||
unless hiddenMinicardLabelText
|
||||
span.js-card-label.card-label(class="card-label-{{color}}" title=name)
|
||||
+viewer
|
||||
= name
|
||||
if hiddenMinicardLabelText
|
||||
.minicard-label(class="card-label-{{color}}" title="{{name}}")
|
||||
if showLabels
|
||||
if labels
|
||||
.minicard-labels(class="{{#if hiddenMinicardLabelText}}minicard-labels-no-text{{/if}}")
|
||||
each labels
|
||||
unless hiddenMinicardLabelText
|
||||
span.js-card-label.card-label(class="card-label-{{color}}" title=name)
|
||||
+viewer
|
||||
= name
|
||||
if hiddenMinicardLabelText
|
||||
.minicard-label(class="card-label-{{color}}" title="{{name}}")
|
||||
|
||||
.minicard-custom-fields
|
||||
each customFieldsWD
|
||||
@@ -179,12 +184,13 @@ template(name="minicard")
|
||||
span.badge-icon
|
||||
i.fa.fa-paperclip
|
||||
span.badge-text= attachments.length
|
||||
if allSubtasks.count
|
||||
.badge
|
||||
span.badge-icon
|
||||
i.fa.fa-globe
|
||||
span.badge-text.check-list-text {{subtasksFinishedCount}}/{{allSubtasksCount}}
|
||||
//{{subtasksFinishedCount}}/{{subtasksCount}} does not work because when a subtaks is archived, the count goes down
|
||||
if showSubtasks
|
||||
if allSubtasks.count
|
||||
.badge
|
||||
span.badge-icon
|
||||
i.fa.fa-globe
|
||||
span.badge-text.check-list-text {{subtasksFinishedCount}}/{{allSubtasksCount}}
|
||||
//{{subtasksFinishedCount}}/{{subtasksCount}} does not work because when a subtaks is archived, the count goes down
|
||||
if currentBoard.allowsCardSortingByNumber
|
||||
if currentBoard.allowsCardSortingByNumberOnMinicard
|
||||
.badge
|
||||
|
||||
@@ -50,32 +50,50 @@ Template.minicard.helpers({
|
||||
},
|
||||
|
||||
showMembers() {
|
||||
// cache "board" to reduce the mini-mongodb access
|
||||
const board = this.board();
|
||||
let ret = false;
|
||||
if (board) {
|
||||
ret =
|
||||
board.allowsMembers === null ||
|
||||
board.allowsMembers === undefined ||
|
||||
board.allowsMembers
|
||||
;
|
||||
ret = board.allowsMembersOnMinicard ?? false;
|
||||
}
|
||||
return ret;
|
||||
},
|
||||
|
||||
showAssignee() {
|
||||
// cache "board" to reduce the mini-mongodb access
|
||||
const board = this.board();
|
||||
let ret = false;
|
||||
if (board) {
|
||||
ret =
|
||||
board.allowsAssignee === null ||
|
||||
board.allowsAssignee === undefined ||
|
||||
board.allowsAssignee
|
||||
;
|
||||
ret = board.allowsAssigneeOnMinicard ?? false;
|
||||
}
|
||||
return ret;
|
||||
},
|
||||
showReceived() {
|
||||
const board = this.board();
|
||||
return board ? board.allowsReceivedDateOnMinicard : false;
|
||||
},
|
||||
showStart() {
|
||||
const board = this.board();
|
||||
return board ? board.allowsStartDateOnMinicard : false;
|
||||
},
|
||||
showDue() {
|
||||
const board = this.board();
|
||||
return board ? board.allowsDueDateOnMinicard : false;
|
||||
},
|
||||
showEnd() {
|
||||
const board = this.board();
|
||||
return board ? board.allowsEndDateOnMinicard : false;
|
||||
},
|
||||
showLabels() {
|
||||
const board = this.board();
|
||||
return board ? board.allowsLabelsOnMinicard : false;
|
||||
},
|
||||
showCardNumber() {
|
||||
const board = this.board();
|
||||
return board ? board.allowsCardNumberOnMinicard : false;
|
||||
},
|
||||
showSubtasks() {
|
||||
const board = this.board();
|
||||
return board ? board.allowsSubtasksOnMinicard : false;
|
||||
},
|
||||
|
||||
hiddenMinicardLabelText() {
|
||||
const currentUser = ReactiveCache.getCurrentUser();
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -15,7 +15,7 @@ textarea.js-edit-subtask-item {
|
||||
color: #8c8c8c;
|
||||
text-decoration: underline;
|
||||
word-wrap: break-word;
|
||||
float: right;
|
||||
flex-shrink: 0;
|
||||
padding-top: 6px;
|
||||
}
|
||||
.delete-text:hover,
|
||||
@@ -24,8 +24,13 @@ textarea.js-edit-subtask-item {
|
||||
.js-delete-subtask-item:hover {
|
||||
color: inherit;
|
||||
}
|
||||
.subtask-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
.subtask-title .checkbox {
|
||||
float: left;
|
||||
flex-shrink: 0;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
font-size: 18px;
|
||||
@@ -34,10 +39,12 @@ textarea.js-edit-subtask-item {
|
||||
.subtask-title .title {
|
||||
font-size: 18px;
|
||||
line-height: 25px;
|
||||
flex: 1;
|
||||
order: 1;
|
||||
}
|
||||
.subtask-title .subtasks-stat {
|
||||
margin: 0 0.5em;
|
||||
float: right;
|
||||
flex-shrink: 0;
|
||||
padding-top: 6px;
|
||||
}
|
||||
.subtask-title .subtasks-stat.is-finished {
|
||||
@@ -46,6 +53,9 @@ textarea.js-edit-subtask-item {
|
||||
.subtask-title .js-delete-subtask {
|
||||
margin: 0 0.5em;
|
||||
}
|
||||
.subtask-title .js-view-subtask {
|
||||
margin: 0 0.5em;
|
||||
}
|
||||
.js-confirm-subtask-delete {
|
||||
background-color: #f7f7f7;
|
||||
position: absolute;
|
||||
@@ -175,6 +185,7 @@ body.grey-icons-enabled .subtasks-item .check-box-unicode {
|
||||
display: inline-block;
|
||||
}
|
||||
.subtask-details-menu {
|
||||
float: right;
|
||||
flex-shrink: 0;
|
||||
padding: 6px 10px 6px 10px;
|
||||
order: 2;
|
||||
}
|
||||
@@ -4,7 +4,14 @@ import Cards from '/models/cards';
|
||||
import { Filter } from '/client/lib/filter';
|
||||
|
||||
Template.subtasks.events({
|
||||
'click .js-open-subtask-details-menu': Popup.open('subtaskActions'),
|
||||
'click .js-open-subtask-details-menu'(event) {
|
||||
// Close any existing popup first to avoid accumulating content
|
||||
if (Popup.isOpen()) {
|
||||
Popup.close();
|
||||
}
|
||||
// Now open the popup for this specific subtask
|
||||
Popup.open('subtaskActions').call(this, event);
|
||||
},
|
||||
async 'submit .js-add-subtask'(event, tpl) {
|
||||
event.preventDefault();
|
||||
const textarea = tpl.find('textarea.js-add-subtask-item');
|
||||
@@ -30,10 +37,12 @@ Template.subtasks.events({
|
||||
_id: card.swimlaneId,
|
||||
});
|
||||
//find the swimlane of the same name in the target board.
|
||||
const targetSwimlane = ReactiveCache.getSwimlane({
|
||||
boardId: targetBoard._id,
|
||||
title: parentSwimlane.title,
|
||||
});
|
||||
const targetSwimlane = parentSwimlane
|
||||
? ReactiveCache.getSwimlane({
|
||||
boardId: targetBoard._id,
|
||||
title: parentSwimlane.title,
|
||||
})
|
||||
: undefined;
|
||||
//If no swimlane with a matching title exists in the target board, fall back to the default swimlane.
|
||||
const swimlaneId =
|
||||
targetSwimlane === undefined
|
||||
|
||||
@@ -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;
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -177,7 +177,6 @@
|
||||
}
|
||||
#header-quick-access ul.header-quick-access-list {
|
||||
transition: opacity 0.2s;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
padding: 10px;
|
||||
margin: -10px;
|
||||
@@ -185,16 +184,18 @@
|
||||
min-width: 0; /* Allow shrinking below content size */
|
||||
display: flex; /* Use flexbox for better control */
|
||||
align-items: center;
|
||||
overflow-x: auto;
|
||||
scrollbar-color: white #2573a7;
|
||||
}
|
||||
|
||||
/* Hide scrollbar completely */
|
||||
#header-quick-access ul.header-quick-access-list::-webkit-scrollbar {
|
||||
display: none;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#header-quick-access ul.header-quick-access-list {
|
||||
-ms-overflow-style: none; /* IE and Edge */
|
||||
scrollbar-width: none; /* Firefox */
|
||||
-ms-overflow-style: thin; /* IE and Edge */
|
||||
scrollbar-width: thin; /* Firefox */
|
||||
}
|
||||
#header-quick-access ul.header-quick-access-list li {
|
||||
display: inline-block; /* Keep inline-block for proper spacing */
|
||||
|
||||
@@ -70,10 +70,6 @@ template(name="header")
|
||||
else
|
||||
li.current.empty(title="{{_ 'quick-access-description'}}")
|
||||
| {{_ 'quick-access-description'}}
|
||||
#header-new-board-icon
|
||||
// Next line is used only for spacing at header,
|
||||
// there is no visible clickable icon.
|
||||
#header-new-board-icon
|
||||
//
|
||||
Hide duplicate create board button,
|
||||
//
|
||||
|
||||
@@ -78,23 +78,32 @@
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
/* Allow dynamic max-height to override default constraint */
|
||||
/* Bounded height: flex column + clip so inline max-height cannot spill past the shell.
|
||||
Class pop-over--bounded matches popup.tpl.jade when max-height is set (more reliable
|
||||
than attribute substring matching on the style attribute alone). */
|
||||
.pop-over.pop-over--bounded,
|
||||
.pop-over[style*='max-height'] {
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.pop-over.pop-over--bounded .header,
|
||||
.pop-over[style*='max-height'] .header {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.pop-over.pop-over--bounded .content-wrapper,
|
||||
.pop-over[style*='max-height'] .content-wrapper {
|
||||
flex: 1 1 auto;
|
||||
/* 0% basis: use remaining space under header, scroll inside (not past white bg) */
|
||||
flex: 1 1 0%;
|
||||
min-height: 0;
|
||||
max-height: none;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
background: inherit;
|
||||
}
|
||||
.pop-over .content-container {
|
||||
width: 100%;
|
||||
@@ -103,6 +112,7 @@
|
||||
}
|
||||
|
||||
/* Allow dynamic max-height to override default constraint for content-container */
|
||||
.pop-over.pop-over--bounded .content-container,
|
||||
.pop-over[style*='max-height'] .content-container {
|
||||
max-height: none;
|
||||
}
|
||||
@@ -757,3 +767,124 @@ body.mobile-mode .pop-over .content-wrapper {
|
||||
overflow-y: auto !important;
|
||||
overflow-x: hidden !important;
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
FIX: List actions popup overflow (Issue #6221)
|
||||
Prevents menu from overflowing outside viewport
|
||||
============================================ */
|
||||
|
||||
/* General fix for all popups with many items */
|
||||
.pop-over .pop-over-list {
|
||||
max-height: 60vh;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
/* Specific fix for list actions menu */
|
||||
.pop-over[data-popup="listActionsPopup"] {
|
||||
max-height: 85vh !important;
|
||||
overflow-y: auto !important;
|
||||
}
|
||||
|
||||
.pop-over[data-popup="listActionsPopup"] .content-wrapper {
|
||||
max-height: calc(85vh - 50px) !important;
|
||||
overflow-y: auto !important;
|
||||
}
|
||||
|
||||
/* Prevent any popup from overflowing viewport */
|
||||
.pop-over {
|
||||
max-height: 90vh !important;
|
||||
display: flex !important;
|
||||
flex-direction: column !important;
|
||||
}
|
||||
|
||||
.pop-over .content-wrapper {
|
||||
flex: 1 1 auto !important;
|
||||
overflow-y: auto !important;
|
||||
min-height: 0 !important;
|
||||
}
|
||||
|
||||
.pop-over .content-container {
|
||||
flex: 1 1 auto !important;
|
||||
display: flex !important;
|
||||
flex-direction: column !important;
|
||||
min-height: 0 !important;
|
||||
}
|
||||
|
||||
.pop-over .content {
|
||||
flex: 1 1 auto !important;
|
||||
overflow-y: auto !important;
|
||||
min-height: 0 !important;
|
||||
}
|
||||
|
||||
/* Keep header fixed while content scrolls */
|
||||
.pop-over .header {
|
||||
flex-shrink: 0 !important;
|
||||
}
|
||||
|
||||
/* Mobile-specific adjustments */
|
||||
@media screen and (max-width: 800px) {
|
||||
.pop-over[data-popup="listActionsPopup"] {
|
||||
max-height: 100vh !important;
|
||||
}
|
||||
|
||||
.pop-over[data-popup="listActionsPopup"] .content-wrapper {
|
||||
max-height: calc(100vh - 48px) !important;
|
||||
}
|
||||
}
|
||||
/* STRONGER FIX - Override inline styles */
|
||||
.pop-over[style*="height"],
|
||||
.pop-over[style*="max-height"] {
|
||||
max-height: 80vh !important;
|
||||
height: auto !important;
|
||||
overflow-y: auto !important;
|
||||
}
|
||||
|
||||
.pop-over[style*="height"] .content-wrapper,
|
||||
.pop-over[style*="max-height"] .content-wrapper {
|
||||
max-height: calc(80vh - 60px) !important;
|
||||
height: auto !important;
|
||||
overflow-y: auto !important;
|
||||
}
|
||||
|
||||
/* Force list popups to have a max height and scroll */
|
||||
.pop-over .pop-over-list {
|
||||
max-height: 300px !important;
|
||||
overflow-y: auto !important;
|
||||
}
|
||||
|
||||
/* Make sure the popup doesn't grow too tall */
|
||||
.pop-over:has(.pop-over-list) {
|
||||
max-height: 400px !important;
|
||||
height: auto !important;
|
||||
}
|
||||
|
||||
/* For the list actions menu specifically */
|
||||
[data-popup="listActionsPopup"] .pop-over-list,
|
||||
.js-open-list-menu + .pop-over .pop-over-list {
|
||||
max-height: 350px !important;
|
||||
overflow-y: auto !important;
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
FIX: List actions popup overflow (Issue #6221)
|
||||
============================================ */
|
||||
|
||||
/* Force list popups to have a max height and scroll */
|
||||
.pop-over .pop-over-list {
|
||||
max-height: 300px !important;
|
||||
overflow-y: auto !important;
|
||||
}
|
||||
|
||||
/* Make sure the popup doesn't grow too tall */
|
||||
.pop-over:has(.pop-over-list) {
|
||||
max-height: 400px !important;
|
||||
height: auto !important;
|
||||
}
|
||||
|
||||
/* For the list actions menu specifically */
|
||||
[data-popup="listActionsPopup"] .pop-over-list,
|
||||
.js-open-list-menu + .pop-over .pop-over-list {
|
||||
max-height: 350px !important;
|
||||
overflow-y: auto !important;
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
class="{{#unless title}}miniprofile{{/unless}}"
|
||||
class=currentBoard.colorClass
|
||||
class="{{#unless title}}no-title{{/unless}}"
|
||||
class="{{#if offset.maxHeight}}pop-over--bounded{{/if}}"
|
||||
data-popup="{{popupName}}"
|
||||
style="left:{{offset.left}}px; top:{{offset.top}}px;{{#if offset.maxHeight}} max-height:{{offset.maxHeight}}px;{{/if}}")
|
||||
.header
|
||||
|
||||
@@ -37,7 +37,7 @@ template(name='statistics')
|
||||
td {{statistics.mongo.mongoStorageEngine}}
|
||||
tr
|
||||
th {{_ 'MongoDB_Oplog_enabled'}}
|
||||
td {{statistics.mongo.mongoOplogEnabled}}
|
||||
td {{formatBoolean statistics.mongo.mongoOplogEnabled}}
|
||||
tr
|
||||
th {{_ 'OS_Type'}}
|
||||
td {{statistics.os.type}}
|
||||
|
||||
@@ -47,4 +47,8 @@ Template.statistics.helpers({
|
||||
}
|
||||
return ret;
|
||||
},
|
||||
|
||||
formatBoolean(value) {
|
||||
return value ? TAPi18n.__('yes') : TAPi18n.__('no');
|
||||
},
|
||||
});
|
||||
@@ -311,3 +311,46 @@ table td:first-child {
|
||||
text-align: center;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
/* Avatar styling - removed people-avatar column */
|
||||
|
||||
/* Username column styling - displays avatar inline with username */
|
||||
.username a.js-edit-people-avatar {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
margin-right: 8px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.username a.js-edit-people-avatar:hover {
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.username .avatar {
|
||||
height: 30px;
|
||||
width: 30px;
|
||||
border-radius: 50%;
|
||||
display: inline-block;
|
||||
flex-shrink: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.username .avatar.avatar-initials {
|
||||
background-color: #dbdbdb;
|
||||
color: #444;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.username .avatar img.avatar-image {
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
@@ -114,7 +114,7 @@ template(name="orgGeneral")
|
||||
th {{_ 'shortName'}}
|
||||
th {{_ 'website'}}
|
||||
th {{_ 'createdAt'}}
|
||||
th {{_ 'active'}}
|
||||
th {{_ 'active-org'}}
|
||||
tbody
|
||||
tr
|
||||
each org in orgList
|
||||
@@ -137,7 +137,7 @@ template(name="teamGeneral")
|
||||
th {{_ 'shortName'}}
|
||||
th {{_ 'website'}}
|
||||
th {{_ 'createdAt'}}
|
||||
th {{_ 'active'}}
|
||||
th {{_ 'active-team'}}
|
||||
tbody
|
||||
tr
|
||||
each team in teamList
|
||||
@@ -160,7 +160,7 @@ template(name="peopleGeneral")
|
||||
th {{_ 'username'}}
|
||||
th {{_ 'email'}}
|
||||
th {{_ 'admin'}}
|
||||
th {{_ 'admin-people-active-status'}}
|
||||
th {{_ 'active-person'}}
|
||||
th {{_ 'accounts-lockout-status'}}
|
||||
th {{_ 'createdAt'}}
|
||||
th
|
||||
@@ -260,17 +260,38 @@ template(name="teamRow")
|
||||
template(name="peopleRow")
|
||||
tr
|
||||
td
|
||||
a.edit-user
|
||||
a.edit-user(data-user-id=userData._id)
|
||||
i.fa.fa-pencil-square-o
|
||||
| {{_ 'edit'}}
|
||||
a.more-settings-user
|
||||
a.more-settings-user(data-user-id=userData._id)
|
||||
| ⋯
|
||||
if userData.loginDisabled
|
||||
td.username <s>{{ userData.username }}</s>
|
||||
td.username
|
||||
a.js-edit-people-avatar(data-user-id=userData._id)
|
||||
if hasAvatarUrl
|
||||
.avatar
|
||||
img.avatar-image(src="{{userData.profile.avatarUrl}}", alt="{{userData.username}}", title="{{_ 'change-avatar'}}")
|
||||
else
|
||||
+userAvatarInitials(userId=userData._id)
|
||||
<s>{{ userData.username }}</s>
|
||||
else if isUserLocked
|
||||
td.username {{ userData.username }}
|
||||
td.username
|
||||
a.js-edit-people-avatar(data-user-id=userData._id)
|
||||
if hasAvatarUrl
|
||||
.avatar
|
||||
img.avatar-image(src="{{userData.profile.avatarUrl}}", alt="{{userData.username}}", title="{{_ 'change-avatar'}}")
|
||||
else
|
||||
+userAvatarInitials(userId=userData._id)
|
||||
| {{ userData.username }}
|
||||
else
|
||||
td.username {{ userData.username }}
|
||||
td.username
|
||||
a.js-edit-people-avatar(data-user-id=userData._id)
|
||||
if hasAvatarUrl
|
||||
.avatar
|
||||
img.avatar-image(src="{{userData.profile.avatarUrl}}", alt="{{userData.username}}", title="{{_ 'change-avatar'}}")
|
||||
else
|
||||
+userAvatarInitials(userId=userData._id)
|
||||
| {{ userData.username }}
|
||||
if userData.loginDisabled
|
||||
td <s>{{ userData.emails.[0].address }}</s>
|
||||
else
|
||||
@@ -333,7 +354,7 @@ template(name="editOrgPopup")
|
||||
| {{_ 'website'}}
|
||||
input.js-orgWebsite(type="text" value=org.orgWebsite)
|
||||
label
|
||||
| {{_ 'active'}}
|
||||
| {{_ 'active-org'}}
|
||||
select.select-active.js-org-isactive
|
||||
option(value="false") {{_ 'no'}}
|
||||
option(value="true" selected="{{org.orgIsActive}}") {{_ 'yes'}}
|
||||
@@ -359,7 +380,7 @@ template(name="editTeamPopup")
|
||||
| {{_ 'website'}}
|
||||
input.js-teamWebsite(type="text" value=team.teamWebsite)
|
||||
label
|
||||
| {{_ 'active'}}
|
||||
| {{_ 'active-team'}}
|
||||
select.select-active.js-team-isactive
|
||||
option(value="false") {{_ 'no'}}
|
||||
option(value="true" selected="{{team.teamIsActive}}") {{_ 'yes'}}
|
||||
@@ -406,7 +427,7 @@ template(name="editUserPopup")
|
||||
option(value="false") {{_ 'no'}}
|
||||
option(value="true" selected="{{userData.emails.[0].verified}}") {{_ 'yes'}}
|
||||
label
|
||||
| {{_ 'active'}}
|
||||
| {{_ 'active-person'}}
|
||||
select.select-active.js-profile-isactive
|
||||
option(value="false") {{_ 'yes'}}
|
||||
option(value="true" selected="{{user.loginDisabled}}") {{_ 'no'}}
|
||||
@@ -469,7 +490,7 @@ template(name="newOrgPopup")
|
||||
| {{_ 'website'}}
|
||||
input.js-orgWebsite(type="text" value="" required)
|
||||
label
|
||||
| {{_ 'active'}}
|
||||
| {{_ 'active-org'}}
|
||||
select.select-active.js-org-isactive
|
||||
option(value="false" selected="selected") {{_ 'no'}}
|
||||
option(value="true") {{_ 'yes'}}
|
||||
@@ -493,7 +514,7 @@ template(name="newTeamPopup")
|
||||
| {{_ 'website'}}
|
||||
input.js-teamWebsite(type="text" value="")
|
||||
label
|
||||
| {{_ 'active'}}
|
||||
| {{_ 'active-team'}}
|
||||
select.select-active.js-team-isactive
|
||||
option(value="false" selected="selected") {{_ 'no'}}
|
||||
option(value="true") {{_ 'yes'}}
|
||||
@@ -555,7 +576,7 @@ template(name="newUserPopup")
|
||||
option(value="false" selected="selected") {{_ 'no'}}
|
||||
option(value="true") {{_ 'yes'}}
|
||||
label
|
||||
| {{_ 'active'}}
|
||||
| {{_ 'active-person'}}
|
||||
select.select-active.js-profile-isactive
|
||||
option(value="false" selected="selected") {{_ 'yes'}}
|
||||
option(value="true") {{_ 'no'}}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { avatarUpdateCounter } from '/client/components/users/avatarUpdateCounter';
|
||||
import { InfiniteScrolling } from '/client/lib/infiniteScrolling';
|
||||
import LockoutSettings from '/models/lockoutSettings';
|
||||
import { FlowRouter } from 'meteor/ostrio:flow-router-extra';
|
||||
@@ -536,7 +537,39 @@ Template.teamRow.helpers({
|
||||
|
||||
Template.peopleRow.helpers({
|
||||
userData() {
|
||||
return this.user || ReactiveCache.getUser(this.userId);
|
||||
// Depend on global avatar update counter to reactively update when avatars change
|
||||
avatarUpdateCounter.get();
|
||||
// Get the user ID from either this._id or this.user._id
|
||||
let userId;
|
||||
if (this.user && this.user._id) {
|
||||
userId = this.user._id;
|
||||
} else if (this._id) {
|
||||
userId = this._id;
|
||||
}
|
||||
// Always fetch from ReactiveCache to ensure latest data
|
||||
if (userId) {
|
||||
return ReactiveCache.getUser(userId);
|
||||
}
|
||||
return this.user || this;
|
||||
},
|
||||
hasAvatarUrl() {
|
||||
// Depend on global avatar update counter to reactively update when avatars change
|
||||
avatarUpdateCounter.get();
|
||||
// Get the user ID from either this._id or this.user._id
|
||||
let userId;
|
||||
if (this.user && this.user._id) {
|
||||
userId = this.user._id;
|
||||
} else if (this._id) {
|
||||
userId = this._id;
|
||||
}
|
||||
let user;
|
||||
if (userId) {
|
||||
user = ReactiveCache.getUser(userId);
|
||||
} else {
|
||||
user = this.user || this;
|
||||
}
|
||||
if (!user || !user.profile) return false;
|
||||
return !!user.profile.avatarUrl;
|
||||
},
|
||||
isUserLocked() {
|
||||
const user = this.user || ReactiveCache.getUser(this.userId);
|
||||
@@ -726,8 +759,20 @@ Template.teamRow.events({
|
||||
});
|
||||
|
||||
Template.peopleRow.events({
|
||||
'click a.edit-user': Popup.open('editUser'),
|
||||
'click a.more-settings-user': Popup.open('settingsUser'),
|
||||
'click a.edit-user'(event) {
|
||||
// Get the user ID from the data attribute
|
||||
const userId = event.currentTarget.getAttribute('data-user-id');
|
||||
if (userId) {
|
||||
Popup.open('editUser').call({ userId: userId }, event);
|
||||
}
|
||||
},
|
||||
'click a.more-settings-user'(event) {
|
||||
// Get the user ID from the data attribute
|
||||
const userId = event.currentTarget.getAttribute('data-user-id');
|
||||
if (userId) {
|
||||
Popup.open('settingsUser').call({ userId: userId }, event);
|
||||
}
|
||||
},
|
||||
'click .selectUserChkBox': function(ev){
|
||||
if(ev.currentTarget){
|
||||
if(ev.currentTarget.checked){
|
||||
@@ -791,6 +836,18 @@ Template.peopleRow.events({
|
||||
// For now, we'll leave this as a no-op
|
||||
}
|
||||
},
|
||||
'click a.js-edit-people-avatar'(event) {
|
||||
// Extract the user ID from the data attribute
|
||||
const userId = event.currentTarget.getAttribute('data-user-id');
|
||||
if (userId) {
|
||||
// Get the user from cache to pass correct context
|
||||
const user = ReactiveCache.getUser(userId);
|
||||
if (user) {
|
||||
// Call Popup.open with the correct user data context
|
||||
Popup.open('adminChangeAvatar').call({ _id: userId, user: user }, event);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
Template.modifyTeamsUsers.helpers({
|
||||
@@ -1462,19 +1519,23 @@ Template.settingsTeamPopup.events({
|
||||
Template.settingsUserPopup.events({
|
||||
'click .impersonate-user'(event) {
|
||||
event.preventDefault();
|
||||
const userId = this.userId || this.user?._id;
|
||||
|
||||
Meteor.call('impersonate', this.userId, (err) => {
|
||||
Meteor.call('impersonate', userId, (err) => {
|
||||
if (!err) {
|
||||
// Meteor.connection.setUserId() triggers automatic cache invalidation
|
||||
// No need to manually invalidate - let Meteor handle the user data refresh
|
||||
Meteor.connection.setUserId(userId);
|
||||
FlowRouter.go('/');
|
||||
Meteor.connection.setUserId(this.userId);
|
||||
}
|
||||
});
|
||||
},
|
||||
'click #deleteButton'(event) {
|
||||
event.preventDefault();
|
||||
const userId = this.userId || this.user?._id;
|
||||
|
||||
// Use secure server method instead of direct client-side removal
|
||||
Meteor.call('removeUser', this.userId, (error, result) => {
|
||||
Meteor.call('removeUser', userId, (error, result) => {
|
||||
if (error) {
|
||||
if (process.env.DEBUG === 'true') {
|
||||
console.error('Error removing user:', error);
|
||||
@@ -1501,19 +1562,24 @@ Template.settingsUserPopup.events({
|
||||
|
||||
Template.settingsUserPopup.helpers({
|
||||
user() {
|
||||
return ReactiveCache.getUser(this.userId);
|
||||
const userId = this.userId || this.user?._id;
|
||||
return ReactiveCache.getUser(userId);
|
||||
},
|
||||
authentications() {
|
||||
return Template.instance().authenticationMethods.get();
|
||||
},
|
||||
isSelected(match) {
|
||||
const userId = Template.instance().data.userId;
|
||||
const selected = ReactiveCache.getUser(userId).authenticationMethod;
|
||||
const userId = Template.instance().data.userId || Template.instance().data.user?._id;
|
||||
const user = ReactiveCache.getUser(userId);
|
||||
if (!user) return false;
|
||||
const selected = user.authenticationMethod;
|
||||
return selected === match;
|
||||
},
|
||||
isLdap() {
|
||||
const userId = Template.instance().data.userId;
|
||||
const selected = ReactiveCache.getUser(userId).authenticationMethod;
|
||||
const userId = Template.instance().data.userId || Template.instance().data.user?._id;
|
||||
const user = ReactiveCache.getUser(userId);
|
||||
if (!user) return false;
|
||||
const selected = user.authenticationMethod;
|
||||
return selected === 'ldap';
|
||||
},
|
||||
errorMessage() {
|
||||
|
||||
@@ -177,8 +177,8 @@ template(name="boardCardSettingsPopup")
|
||||
a.flex.js-field-has-receiveddate(title="{{_ 'card-received'}}" class="{{#if allowsReceivedDate}}is-checked{{/if}}")
|
||||
i.fa(class="{{#if allowsReceivedDate}}fa-check{{else}}fa-square-o{{/if}}")
|
||||
.card-settings-column
|
||||
a.flex.js-field-has-receiveddate(title="{{_ 'card-received'}}" class="{{#if allowsReceivedDate}}is-checked{{/if}}")
|
||||
i.fa(class="{{#if allowsReceivedDate}}fa-check{{else}}fa-square-o{{/if}}")
|
||||
a.flex.js-field-has-receiveddate-on-minicard(title="{{_ 'card-received'}}" class="{{#if allowsReceivedDateOnMinicard}}is-checked{{/if}}")
|
||||
i.fa(class="{{#if allowsReceivedDateOnMinicard}}fa-check{{else}}fa-square-o{{/if}}")
|
||||
.card-settings-column
|
||||
span
|
||||
i.fa.fa-sign-in
|
||||
@@ -188,8 +188,8 @@ template(name="boardCardSettingsPopup")
|
||||
a.flex.js-field-has-startdate(title="{{_ 'card-start'}}" class="{{#if allowsStartDate}}is-checked{{/if}}")
|
||||
i.fa(class="{{#if allowsStartDate}}fa-check{{else}}fa-square-o{{/if}}")
|
||||
.card-settings-column
|
||||
a.flex.js-field-has-startdate(title="{{_ 'card-start'}}" class="{{#if allowsStartDate}}is-checked{{/if}}")
|
||||
i.fa(class="{{#if allowsStartDate}}fa-check{{else}}fa-square-o{{/if}}")
|
||||
a.flex.js-field-has-startdate-on-minicard(title="{{_ 'card-start'}}" class="{{#if allowsStartDateOnMinicard}}is-checked{{/if}}")
|
||||
i.fa(class="{{#if allowsStartDateOnMinicard}}fa-check{{else}}fa-square-o{{/if}}")
|
||||
.card-settings-column
|
||||
span
|
||||
i.fa.fa-hourglass
|
||||
@@ -199,8 +199,8 @@ template(name="boardCardSettingsPopup")
|
||||
a.flex.js-field-has-duedate(title="{{_ 'card-due'}}" class="{{#if allowsDueDate}}is-checked{{/if}}")
|
||||
i.fa(class="{{#if allowsDueDate}}fa-check{{else}}fa-square-o{{/if}}")
|
||||
.card-settings-column
|
||||
a.flex.js-field-has-duedate(title="{{_ 'card-due'}}" class="{{#if allowsDueDate}}is-checked{{/if}}")
|
||||
i.fa(class="{{#if allowsDueDate}}fa-check{{else}}fa-square-o{{/if}}")
|
||||
a.flex.js-field-has-duedate-on-minicard(title="{{_ 'card-due'}}" class="{{#if allowsDueDateOnMinicard}}is-checked{{/if}}")
|
||||
i.fa(class="{{#if allowsDueDateOnMinicard}}fa-check{{else}}fa-square-o{{/if}}")
|
||||
.card-settings-column
|
||||
span
|
||||
i.fa.fa-sign-in
|
||||
@@ -210,8 +210,8 @@ template(name="boardCardSettingsPopup")
|
||||
a.flex.js-field-has-enddate(title="{{_ 'card-end'}}" class="{{#if allowsEndDate}}is-checked{{/if}}")
|
||||
i.fa(class="{{#if allowsEndDate}}fa-check{{else}}fa-square-o{{/if}}")
|
||||
.card-settings-column
|
||||
a.flex.js-field-has-enddate(title="{{_ 'card-end'}}" class="{{#if allowsEndDate}}is-checked{{/if}}")
|
||||
i.fa(class="{{#if allowsEndDate}}fa-check{{else}}fa-square-o{{/if}}")
|
||||
a.flex.js-field-has-enddate-on-minicard(title="{{_ 'card-end'}}" class="{{#if allowsEndDateOnMinicard}}is-checked{{/if}}")
|
||||
i.fa(class="{{#if allowsEndDateOnMinicard}}fa-check{{else}}fa-square-o{{/if}}")
|
||||
.card-settings-column
|
||||
span
|
||||
i.fa.fa-clock-o
|
||||
@@ -221,8 +221,8 @@ template(name="boardCardSettingsPopup")
|
||||
a.flex.js-field-has-members(title="{{_ 'members'}}" class="{{#if allowsMembers}}is-checked{{/if}}")
|
||||
i.fa(class="{{#if allowsMembers}}fa-check{{else}}fa-square-o{{/if}}")
|
||||
.card-settings-column
|
||||
a.flex.js-field-has-members(title="{{_ 'members'}}" class="{{#if allowsMembers}}is-checked{{/if}}")
|
||||
i.fa(class="{{#if allowsMembers}}fa-check{{else}}fa-square-o{{/if}}")
|
||||
a.flex.js-field-has-members-on-minicard(title="{{_ 'members'}}" class="{{#if allowsMembersOnMinicard}}is-checked{{/if}}")
|
||||
i.fa(class="{{#if allowsMembersOnMinicard}}fa-check{{else}}fa-square-o{{/if}}")
|
||||
.card-settings-column
|
||||
span
|
||||
i.fa.fa-users
|
||||
@@ -252,8 +252,8 @@ template(name="boardCardSettingsPopup")
|
||||
a.flex.js-field-has-assignee(title="{{_ 'assignee'}}" class="{{#if allowsAssignee}}is-checked{{/if}}")
|
||||
i.fa(class="{{#if allowsAssignee}}fa-check{{else}}fa-square-o{{/if}}")
|
||||
.card-settings-column
|
||||
a.flex.js-field-has-assignee(title="{{_ 'assignee'}}" class="{{#if allowsAssignee}}is-checked{{/if}}")
|
||||
i.fa(class="{{#if allowsAssignee}}fa-check{{else}}fa-square-o{{/if}}")
|
||||
a.flex.js-field-has-assignee-on-minicard(title="{{_ 'assignee'}}" class="{{#if allowsAssigneeOnMinicard}}is-checked{{/if}}")
|
||||
i.fa(class="{{#if allowsAssigneeOnMinicard}}fa-check{{else}}fa-square-o{{/if}}")
|
||||
.card-settings-column
|
||||
span
|
||||
i.fa.fa-user
|
||||
@@ -263,8 +263,8 @@ template(name="boardCardSettingsPopup")
|
||||
a.flex.js-field-has-assigned-by(title="{{_ 'assigned-by'}}" class="{{#if allowsAssignedBy}}is-checked{{/if}}")
|
||||
i.fa(class="{{#if allowsAssignedBy}}fa-check{{else}}fa-square-o{{/if}}")
|
||||
.card-settings-column
|
||||
a.flex.js-field-has-assigned-by(title="{{_ 'assigned-by'}}" class="{{#if allowsAssignedBy}}is-checked{{/if}}")
|
||||
i.fa(class="{{#if allowsAssignedBy}}fa-check{{else}}fa-square-o{{/if}}")
|
||||
a.flex.js-field-has-assigned-by-on-minicard(title="{{_ 'assigned-by'}}" class="{{#if allowsAssignedByOnMinicard}}is-checked{{/if}}")
|
||||
i.fa(class="{{#if allowsAssignedByOnMinicard}}fa-check{{else}}fa-square-o{{/if}}")
|
||||
.card-settings-column
|
||||
span
|
||||
i.fa.fa-shopping-cart
|
||||
@@ -274,8 +274,8 @@ template(name="boardCardSettingsPopup")
|
||||
a.flex.js-field-has-requested-by(title="{{_ 'requested-by'}}" class="{{#if allowsRequestedBy}}is-checked{{/if}}")
|
||||
i.fa(class="{{#if allowsRequestedBy}}fa-check{{else}}fa-square-o{{/if}}")
|
||||
.card-settings-column
|
||||
a.flex.js-field-has-requested-by(title="{{_ 'requested-by'}}" class="{{#if allowsRequestedBy}}is-checked{{/if}}")
|
||||
i.fa(class="{{#if allowsRequestedBy}}fa-check{{else}}fa-square-o{{/if}}")
|
||||
a.flex.js-field-has-requested-by-on-minicard(title="{{_ 'requested-by'}}" class="{{#if allowsRequestedByOnMinicard}}is-checked{{/if}}")
|
||||
i.fa(class="{{#if allowsRequestedByOnMinicard}}fa-check{{else}}fa-square-o{{/if}}")
|
||||
.card-settings-column
|
||||
span
|
||||
i.fa.fa-user
|
||||
@@ -316,8 +316,8 @@ template(name="boardCardSettingsPopup")
|
||||
a.flex.js-field-has-labels(title="{{_ 'labels'}}" class="{{#if allowsLabels}}is-checked{{/if}}")
|
||||
i.fa(class="{{#if allowsLabels}}fa-check{{else}}fa-square-o{{/if}}")
|
||||
.card-settings-column
|
||||
a.flex.js-field-has-labels(title="{{_ 'labels'}}" class="{{#if allowsLabels}}is-checked{{/if}}")
|
||||
i.fa(class="{{#if allowsLabels}}fa-check{{else}}fa-square-o{{/if}}")
|
||||
a.flex.js-field-has-labels-on-minicard(title="{{_ 'labels'}}" class="{{#if allowsLabelsOnMinicard}}is-checked{{/if}}")
|
||||
i.fa(class="{{#if allowsLabelsOnMinicard}}fa-check{{else}}fa-square-o{{/if}}")
|
||||
.card-settings-column
|
||||
span
|
||||
i.fa.fa-tag
|
||||
@@ -337,8 +337,8 @@ template(name="boardCardSettingsPopup")
|
||||
a.flex.js-field-has-card-number(title="{{_ 'card'}} {{_ 'number'}}" class="{{#if allowsCardNumber}}is-checked{{/if}}")
|
||||
i.fa(class="{{#if allowsCardNumber}}fa-check{{else}}fa-square-o{{/if}}")
|
||||
.card-settings-column
|
||||
a.flex.js-field-has-card-number(title="{{_ 'card'}} {{_ 'number'}}" class="{{#if allowsCardNumber}}is-checked{{/if}}")
|
||||
i.fa(class="{{#if allowsCardNumber}}fa-check{{else}}fa-square-o{{/if}}")
|
||||
a.flex.js-field-has-card-number-on-minicard(title="{{_ 'card'}} {{_ 'number'}}" class="{{#if allowsCardNumberOnMinicard}}is-checked{{/if}}")
|
||||
i.fa(class="{{#if allowsCardNumberOnMinicard}}fa-check{{else}}fa-square-o{{/if}}")
|
||||
.card-settings-column
|
||||
span
|
||||
| #️⃣
|
||||
@@ -349,8 +349,8 @@ template(name="boardCardSettingsPopup")
|
||||
a.flex.js-field-has-description-title(title="{{_ 'description'}} {{_ 'title'}}" class="{{#if allowsDescriptionTitle}}is-checked{{/if}}")
|
||||
i.fa(class="{{#if allowsDescriptionTitle}}fa-check{{else}}fa-square-o{{/if}}")
|
||||
.card-settings-column
|
||||
a.flex.js-field-has-description-title(title="{{_ 'description'}} {{_ 'title'}}" class="{{#if allowsDescriptionTitle}}is-checked{{/if}}")
|
||||
i.fa(class="{{#if allowsDescriptionTitle}}fa-check{{else}}fa-square-o{{/if}}")
|
||||
a.flex.js-field-has-description-title-on-minicard(title="{{_ 'description'}} {{_ 'title'}}" class="{{#if allowsDescriptionTitleOnMinicard}}is-checked{{/if}}")
|
||||
i.fa(class="{{#if allowsDescriptionTitleOnMinicard}}fa-check{{else}}fa-square-o{{/if}}")
|
||||
.card-settings-column
|
||||
span
|
||||
i.fa.fa-file-text-o
|
||||
@@ -361,8 +361,8 @@ template(name="boardCardSettingsPopup")
|
||||
a.flex.js-field-has-description-text(title="{{_ 'description'}} {{_ 'custom-field-text'}}" class="{{#if allowsDescriptionText}}is-checked{{/if}}")
|
||||
i.fa(class="{{#if allowsDescriptionText}}fa-check{{else}}fa-square-o{{/if}}")
|
||||
.card-settings-column
|
||||
a.flex.js-field-has-description-text(title="{{_ 'description'}} {{_ 'custom-field-text'}}" class="{{#if allowsDescriptionText}}is-checked{{/if}}")
|
||||
i.fa(class="{{#if allowsDescriptionText}}fa-check{{else}}fa-square-o{{/if}}")
|
||||
a.flex.js-field-has-description-text-on-minicard(title="{{_ 'description'}} {{_ 'custom-field-text'}}" class="{{#if allowsDescriptionTextOnMinicard}}is-checked{{/if}}")
|
||||
i.fa(class="{{#if allowsDescriptionTextOnMinicard}}fa-check{{else}}fa-square-o{{/if}}")
|
||||
.card-settings-column
|
||||
span
|
||||
i.fa.fa-file-text-o
|
||||
@@ -383,8 +383,8 @@ template(name="boardCardSettingsPopup")
|
||||
a.flex.js-field-has-checklists(title="{{_ 'checklists'}}" class="{{#if allowsChecklists}}is-checked{{/if}}")
|
||||
i.fa(class="{{#if allowsChecklists}}fa-check{{else}}fa-square-o{{/if}}")
|
||||
.card-settings-column
|
||||
a.flex.js-field-has-checklists(title="{{_ 'checklists'}}" class="{{#if allowsChecklists}}is-checked{{/if}}")
|
||||
i.fa(class="{{#if allowsChecklists}}fa-check{{else}}fa-square-o{{/if}}")
|
||||
a.flex.js-field-has-checklists-on-minicard(title="{{_ 'checklists'}}" class="{{#if allowsChecklistsOnMinicard}}is-checked{{/if}}")
|
||||
i.fa(class="{{#if allowsChecklistsOnMinicard}}fa-check{{else}}fa-square-o{{/if}}")
|
||||
.card-settings-column
|
||||
span
|
||||
i.fa.fa-check
|
||||
@@ -394,8 +394,8 @@ template(name="boardCardSettingsPopup")
|
||||
a.flex.js-field-has-subtasks(title="{{_ 'subtasks'}}" class="{{#if allowsSubtasks}}is-checked{{/if}}")
|
||||
i.fa(class="{{#if allowsSubtasks}}fa-check{{else}}fa-square-o{{/if}}")
|
||||
.card-settings-column
|
||||
a.flex.js-field-has-subtasks(title="{{_ 'subtasks'}}" class="{{#if allowsSubtasks}}is-checked{{/if}}")
|
||||
i.fa(class="{{#if allowsSubtasks}}fa-check{{else}}fa-square-o{{/if}}")
|
||||
a.flex.js-field-has-subtasks-on-minicard(title="{{_ 'subtasks'}}" class="{{#if allowsSubtasksOnMinicard}}is-checked{{/if}}")
|
||||
i.fa(class="{{#if allowsSubtasksOnMinicard}}fa-check{{else}}fa-square-o{{/if}}")
|
||||
.card-settings-column
|
||||
span
|
||||
i.fa.fa-globe
|
||||
@@ -405,8 +405,8 @@ template(name="boardCardSettingsPopup")
|
||||
a.flex.js-field-has-attachments(title="{{_ 'attachments'}}" class="{{#if allowsAttachments}}is-checked{{/if}}")
|
||||
i.fa(class="{{#if allowsAttachments}}fa-check{{else}}fa-square-o{{/if}}")
|
||||
.card-settings-column
|
||||
a.flex.js-field-has-attachments(title="{{_ 'attachments'}}" class="{{#if allowsAttachments}}is-checked{{/if}}")
|
||||
i.fa(class="{{#if allowsAttachments}}fa-check{{else}}fa-square-o{{/if}}")
|
||||
a.flex.js-field-has-attachments-on-minicard(title="{{_ 'attachments'}}" class="{{#if allowsAttachmentsOnMinicard}}is-checked{{/if}}")
|
||||
i.fa(class="{{#if allowsAttachmentsOnMinicard}}fa-check{{else}}fa-square-o{{/if}}")
|
||||
.card-settings-column
|
||||
span
|
||||
i.fa.fa-paperclip
|
||||
|
||||
@@ -235,8 +235,8 @@ Template.homeSidebar.helpers({
|
||||
});
|
||||
|
||||
Template.homeSidebar.events({
|
||||
'click .js-toggle-show-activities'() {
|
||||
Utils.getCurrentBoard().toggleShowActivities();
|
||||
async 'click .js-toggle-show-activities'() {
|
||||
await Utils.getCurrentBoard().toggleShowActivities();
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1029,26 +1029,51 @@ Template.boardCardSettingsPopup.helpers({
|
||||
const currentBoard = ReactiveCache.getBoard(boardId);
|
||||
return currentBoard ? currentBoard.allowsReceivedDate : false;
|
||||
},
|
||||
allowsReceivedDateOnMinicard() {
|
||||
const boardId = Session.get('currentBoard');
|
||||
const currentBoard = ReactiveCache.getBoard(boardId);
|
||||
return currentBoard ? currentBoard.allowsReceivedDateOnMinicard : false;
|
||||
},
|
||||
allowsStartDate() {
|
||||
const boardId = Session.get('currentBoard');
|
||||
const currentBoard = ReactiveCache.getBoard(boardId);
|
||||
return currentBoard ? currentBoard.allowsStartDate : false;
|
||||
},
|
||||
allowsStartDateOnMinicard() {
|
||||
const boardId = Session.get('currentBoard');
|
||||
const currentBoard = ReactiveCache.getBoard(boardId);
|
||||
return currentBoard ? currentBoard.allowsStartDateOnMinicard : false;
|
||||
},
|
||||
allowsDueDate() {
|
||||
const boardId = Session.get('currentBoard');
|
||||
const currentBoard = ReactiveCache.getBoard(boardId);
|
||||
return currentBoard ? currentBoard.allowsDueDate : false;
|
||||
},
|
||||
allowsDueDateOnMinicard() {
|
||||
const boardId = Session.get('currentBoard');
|
||||
const currentBoard = ReactiveCache.getBoard(boardId);
|
||||
return currentBoard ? currentBoard.allowsDueDateOnMinicard : false;
|
||||
},
|
||||
allowsEndDate() {
|
||||
const boardId = Session.get('currentBoard');
|
||||
const currentBoard = ReactiveCache.getBoard(boardId);
|
||||
return currentBoard ? currentBoard.allowsEndDate : false;
|
||||
},
|
||||
allowsEndDateOnMinicard() {
|
||||
const boardId = Session.get('currentBoard');
|
||||
const currentBoard = ReactiveCache.getBoard(boardId);
|
||||
return currentBoard ? currentBoard.allowsEndDateOnMinicard : false;
|
||||
},
|
||||
allowsSubtasks() {
|
||||
const boardId = Session.get('currentBoard');
|
||||
const currentBoard = ReactiveCache.getBoard(boardId);
|
||||
return currentBoard ? currentBoard.allowsSubtasks : false;
|
||||
},
|
||||
allowsSubtasksOnMinicard() {
|
||||
const boardId = Session.get('currentBoard');
|
||||
const currentBoard = ReactiveCache.getBoard(boardId);
|
||||
return currentBoard ? currentBoard.allowsSubtasksOnMinicard : false;
|
||||
},
|
||||
allowsCreator() {
|
||||
const boardId = Session.get('currentBoard');
|
||||
const currentBoard = ReactiveCache.getBoard(boardId);
|
||||
@@ -1064,21 +1089,41 @@ Template.boardCardSettingsPopup.helpers({
|
||||
const currentBoard = ReactiveCache.getBoard(boardId);
|
||||
return currentBoard ? currentBoard.allowsMembers : false;
|
||||
},
|
||||
allowsMembersOnMinicard() {
|
||||
const boardId = Session.get('currentBoard');
|
||||
const currentBoard = ReactiveCache.getBoard(boardId);
|
||||
return currentBoard ? currentBoard.allowsMembersOnMinicard : false;
|
||||
},
|
||||
allowsAssignee() {
|
||||
const boardId = Session.get('currentBoard');
|
||||
const currentBoard = ReactiveCache.getBoard(boardId);
|
||||
return currentBoard ? currentBoard.allowsAssignee : false;
|
||||
},
|
||||
allowsAssigneeOnMinicard() {
|
||||
const boardId = Session.get('currentBoard');
|
||||
const currentBoard = ReactiveCache.getBoard(boardId);
|
||||
return currentBoard ? currentBoard.allowsAssigneeOnMinicard : false;
|
||||
},
|
||||
allowsAssignedBy() {
|
||||
const boardId = Session.get('currentBoard');
|
||||
const currentBoard = ReactiveCache.getBoard(boardId);
|
||||
return currentBoard ? currentBoard.allowsAssignedBy : false;
|
||||
},
|
||||
allowsAssignedByOnMinicard() {
|
||||
const boardId = Session.get('currentBoard');
|
||||
const currentBoard = ReactiveCache.getBoard(boardId);
|
||||
return currentBoard ? currentBoard.allowsAssignedByOnMinicard : false;
|
||||
},
|
||||
allowsRequestedBy() {
|
||||
const boardId = Session.get('currentBoard');
|
||||
const currentBoard = ReactiveCache.getBoard(boardId);
|
||||
return currentBoard ? currentBoard.allowsRequestedBy : false;
|
||||
},
|
||||
allowsRequestedByOnMinicard() {
|
||||
const boardId = Session.get('currentBoard');
|
||||
const currentBoard = ReactiveCache.getBoard(boardId);
|
||||
return currentBoard ? currentBoard.allowsRequestedByOnMinicard : false;
|
||||
},
|
||||
allowsCardSortingByNumber() {
|
||||
const boardId = Session.get('currentBoard');
|
||||
const currentBoard = ReactiveCache.getBoard(boardId);
|
||||
@@ -1094,6 +1139,11 @@ Template.boardCardSettingsPopup.helpers({
|
||||
const currentBoard = ReactiveCache.getBoard(boardId);
|
||||
return currentBoard ? currentBoard.allowsLabels : false;
|
||||
},
|
||||
allowsLabelsOnMinicard() {
|
||||
const boardId = Session.get('currentBoard');
|
||||
const currentBoard = ReactiveCache.getBoard(boardId);
|
||||
return currentBoard ? currentBoard.allowsLabelsOnMinicard : false;
|
||||
},
|
||||
allowsShowListsOnMinicard() {
|
||||
const boardId = Session.get('currentBoard');
|
||||
const currentBoard = ReactiveCache.getBoard(boardId);
|
||||
@@ -1104,11 +1154,21 @@ Template.boardCardSettingsPopup.helpers({
|
||||
const currentBoard = ReactiveCache.getBoard(boardId);
|
||||
return currentBoard ? currentBoard.allowsChecklists : false;
|
||||
},
|
||||
allowsChecklistsOnMinicard() {
|
||||
const boardId = Session.get('currentBoard');
|
||||
const currentBoard = ReactiveCache.getBoard(boardId);
|
||||
return currentBoard ? currentBoard.allowsChecklistsOnMinicard : false;
|
||||
},
|
||||
allowsAttachments() {
|
||||
const boardId = Session.get('currentBoard');
|
||||
const currentBoard = ReactiveCache.getBoard(boardId);
|
||||
return currentBoard ? currentBoard.allowsAttachments : false;
|
||||
},
|
||||
allowsAttachmentsOnMinicard() {
|
||||
const boardId = Session.get('currentBoard');
|
||||
const currentBoard = ReactiveCache.getBoard(boardId);
|
||||
return currentBoard ? currentBoard.allowsAttachmentsOnMinicard : false;
|
||||
},
|
||||
allowsComments() {
|
||||
const boardId = Session.get('currentBoard');
|
||||
const currentBoard = ReactiveCache.getBoard(boardId);
|
||||
@@ -1119,11 +1179,21 @@ Template.boardCardSettingsPopup.helpers({
|
||||
const currentBoard = ReactiveCache.getBoard(boardId);
|
||||
return currentBoard ? currentBoard.allowsCardNumber : false;
|
||||
},
|
||||
allowsCardNumberOnMinicard() {
|
||||
const boardId = Session.get('currentBoard');
|
||||
const currentBoard = ReactiveCache.getBoard(boardId);
|
||||
return currentBoard ? currentBoard.allowsCardNumberOnMinicard : false;
|
||||
},
|
||||
allowsDescriptionTitle() {
|
||||
const boardId = Session.get('currentBoard');
|
||||
const currentBoard = ReactiveCache.getBoard(boardId);
|
||||
return currentBoard ? currentBoard.allowsDescriptionTitle : false;
|
||||
},
|
||||
allowsDescriptionTitleOnMinicard() {
|
||||
const boardId = Session.get('currentBoard');
|
||||
const currentBoard = ReactiveCache.getBoard(boardId);
|
||||
return currentBoard ? currentBoard.allowsDescriptionTitleOnMinicard : false;
|
||||
},
|
||||
allowsDescriptionText() {
|
||||
const boardId = Session.get('currentBoard');
|
||||
const currentBoard = ReactiveCache.getBoard(boardId);
|
||||
@@ -1213,26 +1283,51 @@ Template.boardCardSettingsPopup.events({
|
||||
const newValue = !tpl.currentBoard.allowsReceivedDate;
|
||||
Boards.update(tpl.currentBoard._id, { $set: { allowsReceivedDate: newValue } });
|
||||
},
|
||||
'click .js-field-has-receiveddate-on-minicard'(evt, tpl) {
|
||||
evt.preventDefault();
|
||||
const newValue = !tpl.currentBoard.allowsReceivedDateOnMinicard;
|
||||
Boards.update(tpl.currentBoard._id, { $set: { allowsReceivedDateOnMinicard: newValue } });
|
||||
},
|
||||
'click .js-field-has-startdate'(evt, tpl) {
|
||||
evt.preventDefault();
|
||||
const newValue = !tpl.currentBoard.allowsStartDate;
|
||||
Boards.update(tpl.currentBoard._id, { $set: { allowsStartDate: newValue } });
|
||||
},
|
||||
'click .js-field-has-startdate-on-minicard'(evt, tpl) {
|
||||
evt.preventDefault();
|
||||
const newValue = !tpl.currentBoard.allowsStartDateOnMinicard;
|
||||
Boards.update(tpl.currentBoard._id, { $set: { allowsStartDateOnMinicard: newValue } });
|
||||
},
|
||||
'click .js-field-has-enddate'(evt, tpl) {
|
||||
evt.preventDefault();
|
||||
const newValue = !tpl.currentBoard.allowsEndDate;
|
||||
Boards.update(tpl.currentBoard._id, { $set: { allowsEndDate: newValue } });
|
||||
},
|
||||
'click .js-field-has-enddate-on-minicard'(evt, tpl) {
|
||||
evt.preventDefault();
|
||||
const newValue = !tpl.currentBoard.allowsEndDateOnMinicard;
|
||||
Boards.update(tpl.currentBoard._id, { $set: { allowsEndDateOnMinicard: newValue } });
|
||||
},
|
||||
'click .js-field-has-duedate'(evt, tpl) {
|
||||
evt.preventDefault();
|
||||
const newValue = !tpl.currentBoard.allowsDueDate;
|
||||
Boards.update(tpl.currentBoard._id, { $set: { allowsDueDate: newValue } });
|
||||
},
|
||||
'click .js-field-has-duedate-on-minicard'(evt, tpl) {
|
||||
evt.preventDefault();
|
||||
const newValue = !tpl.currentBoard.allowsDueDateOnMinicard;
|
||||
Boards.update(tpl.currentBoard._id, { $set: { allowsDueDateOnMinicard: newValue } });
|
||||
},
|
||||
'click .js-field-has-subtasks'(evt, tpl) {
|
||||
evt.preventDefault();
|
||||
const newValue = !tpl.currentBoard.allowsSubtasks;
|
||||
Boards.update(tpl.currentBoard._id, { $set: { allowsSubtasks: newValue } });
|
||||
},
|
||||
'click .js-field-has-subtasks-on-minicard'(evt, tpl) {
|
||||
evt.preventDefault();
|
||||
const newValue = !tpl.currentBoard.allowsSubtasksOnMinicard;
|
||||
Boards.update(tpl.currentBoard._id, { $set: { allowsSubtasksOnMinicard: newValue } });
|
||||
},
|
||||
'click .js-field-has-creator'(evt, tpl) {
|
||||
evt.preventDefault();
|
||||
const newValue = !tpl.currentBoard.allowsCreator;
|
||||
@@ -1248,21 +1343,41 @@ Template.boardCardSettingsPopup.events({
|
||||
const newValue = !tpl.currentBoard.allowsMembers;
|
||||
Boards.update(tpl.currentBoard._id, { $set: { allowsMembers: newValue } });
|
||||
},
|
||||
'click .js-field-has-members-on-minicard'(evt, tpl) {
|
||||
evt.preventDefault();
|
||||
const newValue = !tpl.currentBoard.allowsMembersOnMinicard;
|
||||
Boards.update(tpl.currentBoard._id, { $set: { allowsMembersOnMinicard: newValue } });
|
||||
},
|
||||
'click .js-field-has-assignee'(evt, tpl) {
|
||||
evt.preventDefault();
|
||||
const newValue = !tpl.currentBoard.allowsAssignee;
|
||||
Boards.update(tpl.currentBoard._id, { $set: { allowsAssignee: newValue } });
|
||||
},
|
||||
'click .js-field-has-assignee-on-minicard'(evt, tpl) {
|
||||
evt.preventDefault();
|
||||
const newValue = !tpl.currentBoard.allowsAssigneeOnMinicard;
|
||||
Boards.update(tpl.currentBoard._id, { $set: { allowsAssigneeOnMinicard: newValue } });
|
||||
},
|
||||
'click .js-field-has-assigned-by'(evt, tpl) {
|
||||
evt.preventDefault();
|
||||
const newValue = !tpl.currentBoard.allowsAssignedBy;
|
||||
Boards.update(tpl.currentBoard._id, { $set: { allowsAssignedBy: newValue } });
|
||||
},
|
||||
'click .js-field-has-assigned-by-on-minicard'(evt, tpl) {
|
||||
evt.preventDefault();
|
||||
const newValue = !tpl.currentBoard.allowsAssignedByOnMinicard;
|
||||
Boards.update(tpl.currentBoard._id, { $set: { allowsAssignedByOnMinicard: newValue } });
|
||||
},
|
||||
'click .js-field-has-requested-by'(evt, tpl) {
|
||||
evt.preventDefault();
|
||||
const newValue = !tpl.currentBoard.allowsRequestedBy;
|
||||
Boards.update(tpl.currentBoard._id, { $set: { allowsRequestedBy: newValue } });
|
||||
},
|
||||
'click .js-field-has-requested-by-on-minicard'(evt, tpl) {
|
||||
evt.preventDefault();
|
||||
const newValue = !tpl.currentBoard.allowsRequestedByOnMinicard;
|
||||
Boards.update(tpl.currentBoard._id, { $set: { allowsRequestedByOnMinicard: newValue } });
|
||||
},
|
||||
'click .js-field-has-card-sorting-by-number'(evt, tpl) {
|
||||
evt.preventDefault();
|
||||
const newValue = !tpl.currentBoard.allowsCardSortingByNumber;
|
||||
@@ -1278,6 +1393,11 @@ Template.boardCardSettingsPopup.events({
|
||||
const newValue = !tpl.currentBoard.allowsLabels;
|
||||
Boards.update(tpl.currentBoard._id, { $set: { allowsLabels: newValue } });
|
||||
},
|
||||
'click .js-field-has-labels-on-minicard'(evt, tpl) {
|
||||
evt.preventDefault();
|
||||
const newValue = !tpl.currentBoard.allowsLabelsOnMinicard;
|
||||
Boards.update(tpl.currentBoard._id, { $set: { allowsLabelsOnMinicard: newValue } });
|
||||
},
|
||||
'click .js-field-has-card-show-lists-on-minicard'(evt, tpl) {
|
||||
evt.preventDefault();
|
||||
tpl.currentBoard.allowsShowListsOnMinicard = !tpl.currentBoard
|
||||
@@ -1310,6 +1430,11 @@ Template.boardCardSettingsPopup.events({
|
||||
tpl.currentBoard.allowsDescriptionTitle,
|
||||
);
|
||||
},
|
||||
'click .js-field-has-description-title-on-minicard'(evt, tpl) {
|
||||
evt.preventDefault();
|
||||
const newValue = !tpl.currentBoard.allowsDescriptionTitleOnMinicard;
|
||||
Boards.update(tpl.currentBoard._id, { $set: { allowsDescriptionTitleOnMinicard: newValue } });
|
||||
},
|
||||
'click .js-field-has-card-number'(evt, tpl) {
|
||||
evt.preventDefault();
|
||||
tpl.currentBoard.allowsCardNumber = !tpl.currentBoard
|
||||
@@ -1326,6 +1451,11 @@ Template.boardCardSettingsPopup.events({
|
||||
tpl.currentBoard.allowsCardNumber,
|
||||
);
|
||||
},
|
||||
'click .js-field-has-card-number-on-minicard'(evt, tpl) {
|
||||
evt.preventDefault();
|
||||
const newValue = !tpl.currentBoard.allowsCardNumberOnMinicard;
|
||||
Boards.update(tpl.currentBoard._id, { $set: { allowsCardNumberOnMinicard: newValue } });
|
||||
},
|
||||
'click .js-field-has-description-text-on-minicard'(evt, tpl) {
|
||||
evt.preventDefault();
|
||||
tpl.currentBoard.allowsDescriptionTextOnMinicard = !tpl.currentBoard
|
||||
@@ -1374,6 +1504,11 @@ Template.boardCardSettingsPopup.events({
|
||||
tpl.currentBoard.allowsChecklists,
|
||||
);
|
||||
},
|
||||
'click .js-field-has-checklists-on-minicard'(evt, tpl) {
|
||||
evt.preventDefault();
|
||||
const newValue = !tpl.currentBoard.allowsChecklistsOnMinicard;
|
||||
Boards.update(tpl.currentBoard._id, { $set: { allowsChecklistsOnMinicard: newValue } });
|
||||
},
|
||||
'click .js-field-has-attachments'(evt, tpl) {
|
||||
evt.preventDefault();
|
||||
tpl.currentBoard.allowsAttachments = !tpl.currentBoard
|
||||
@@ -1390,6 +1525,11 @@ Template.boardCardSettingsPopup.events({
|
||||
tpl.currentBoard.allowsAttachments,
|
||||
);
|
||||
},
|
||||
'click .js-field-has-attachments-on-minicard'(evt, tpl) {
|
||||
evt.preventDefault();
|
||||
const newValue = !tpl.currentBoard.allowsAttachmentsOnMinicard;
|
||||
Boards.update(tpl.currentBoard._id, { $set: { allowsAttachmentsOnMinicard: newValue } });
|
||||
},
|
||||
'click .js-field-has-comments'(evt, tpl) {
|
||||
evt.preventDefault();
|
||||
tpl.currentBoard.allowsComments = !tpl.currentBoard.allowsComments;
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
import { ReactiveVar } from 'meteor/reactive-var';
|
||||
|
||||
// Reactive source for invalidating people row when avatars change
|
||||
export const avatarUpdateCounter = new ReactiveVar(0);
|
||||
@@ -70,11 +70,11 @@ template(name="changeAvatarPopup")
|
||||
each uploadedAvatars
|
||||
li: a.js-select-avatar
|
||||
.member
|
||||
img.avatar.avatar-image(src="{{link}}")
|
||||
img.avatar.avatar-image(src="{{avatarLink}}")
|
||||
if isSelected
|
||||
i.fa.fa-check
|
||||
p.sub-name
|
||||
a.js-delete-avatar {{_ 'delete'}}
|
||||
a.js-delete-avatar(data-avatar-id="{{_id}}") {{_ 'delete'}}
|
||||
| -
|
||||
= name
|
||||
li: a.js-select-initials
|
||||
@@ -100,6 +100,41 @@ template(name="deleteAvatarPopup")
|
||||
p {{_ 'delete-avatar-confirm'}}
|
||||
button.js-confirm.negate.full(type="submit") {{_ 'delete'}}
|
||||
|
||||
template(name="adminChangeAvatarPopup")
|
||||
.admin-change-avatar-header
|
||||
h3 {{_ 'change-avatar'}} - {{ username }}
|
||||
if error.get
|
||||
.warning {{_ error.get}}
|
||||
ul.pop-over-list
|
||||
each uploadedAvatars
|
||||
li: a.js-select-avatar
|
||||
.member
|
||||
img.avatar.avatar-image(src="{{avatarLink}}")
|
||||
if isSelected
|
||||
i.fa.fa-check
|
||||
p.sub-name
|
||||
a.js-delete-avatar(data-avatar-id="{{_id}}") {{_ 'delete'}}
|
||||
| -
|
||||
= name
|
||||
li: a.js-select-initials
|
||||
.member
|
||||
+userAvatarInitials(userData=userData)
|
||||
| {{_ 'initials' }}
|
||||
if noAvatarUrl
|
||||
i.fa.fa-check
|
||||
p.sub-name {{_ 'default-avatar'}}
|
||||
input.hide.js-upload-avatar-input(accept="image/*;capture=camera" type="file")
|
||||
if Meteor.settings.public.avatarsUploadMaxSize
|
||||
| {{_ 'max-avatar-filesize'}} {{Meteor.settings.public.avatarsUploadMaxSize}}
|
||||
br
|
||||
if Meteor.settings.public.avatarsUploadMimeTypes
|
||||
| {{_ 'allowed-avatar-filetypes'}} {{Meteor.settings.public.avatarsUploadMimeTypes}}
|
||||
br
|
||||
| {{_ 'invalid-file'}}
|
||||
button.full.js-upload-avatar
|
||||
i.fa.fa-upload
|
||||
| {{_ 'upload-avatar' }}
|
||||
|
||||
template(name="cardMemberPopup")
|
||||
.board-member-menu
|
||||
.mini-profile-info
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { ReactiveVar } from 'meteor/reactive-var';
|
||||
import { avatarUpdateCounter } from '/client/components/users/avatarUpdateCounter';
|
||||
import Avatars from '/models/avatars';
|
||||
import Presences from '/models/presences';
|
||||
import { Utils } from '/client/lib/utils';
|
||||
@@ -164,6 +166,7 @@ Template.boardTeamName.helpers({
|
||||
|
||||
Template.changeAvatarPopup.onCreated(function () {
|
||||
this.error = new ReactiveVar('');
|
||||
this.avatarUpdateCounter = new ReactiveVar(0); // Trigger to force helper re-evaluation
|
||||
Meteor.subscribe('my-avatars');
|
||||
});
|
||||
|
||||
@@ -172,16 +175,28 @@ Template.changeAvatarPopup.helpers({
|
||||
return Template.instance().error;
|
||||
},
|
||||
uploadedAvatars() {
|
||||
Template.instance().avatarUpdateCounter.get(); // Create dependency on update counter
|
||||
const ret = ReactiveCache.getAvatars({ userId: Meteor.userId() }, {}, true);
|
||||
return ret;
|
||||
},
|
||||
avatarLink() {
|
||||
if (this && typeof this.link === 'function') {
|
||||
return this.link();
|
||||
}
|
||||
return '';
|
||||
},
|
||||
isSelected() {
|
||||
Template.instance().avatarUpdateCounter.get(); // Create dependency on update counter
|
||||
const userProfile = ReactiveCache.getCurrentUser().profile;
|
||||
const avatarUrl = userProfile && userProfile.avatarUrl;
|
||||
const currentAvatarUrl = Template.currentData().link();
|
||||
return avatarUrl === currentAvatarUrl;
|
||||
const currentAvatarUrl = this.link && typeof this.link === 'function' ? this.link() : '';
|
||||
// Normalize URLs by removing query parameters for comparison
|
||||
// (they may be added for boardId but shouldn't affect selection comparison)
|
||||
const normalizeUrl = (url) => url ? url.split('?')[0] : '';
|
||||
return normalizeUrl(avatarUrl) === normalizeUrl(currentAvatarUrl);
|
||||
},
|
||||
noAvatarUrl() {
|
||||
Template.instance().avatarUpdateCounter.get(); // Create dependency on update counter
|
||||
const userProfile = ReactiveCache.getCurrentUser().profile;
|
||||
const avatarUrl = userProfile && userProfile.avatarUrl;
|
||||
return !avatarUrl;
|
||||
@@ -192,6 +207,14 @@ function changeAvatarSetAvatar(tpl, avatarUrl) {
|
||||
Meteor.call('setAvatarUrl', avatarUrl, (err) => {
|
||||
if (err) {
|
||||
tpl.error.set(err.reason || 'Error setting avatar');
|
||||
} else {
|
||||
// Trigger a re-evaluation of helpers to show updated avatar selection
|
||||
const counter = tpl.avatarUpdateCounter.get();
|
||||
tpl.avatarUpdateCounter.set(counter + 1);
|
||||
// Also increment global counter for admin people list updates
|
||||
avatarUpdateCounter.set(avatarUpdateCounter.get() + 1);
|
||||
// Clear input for next upload
|
||||
tpl.$('.js-upload-avatar-input').val('');
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -212,15 +235,25 @@ Template.changeAvatarPopup.events({
|
||||
uploader.on('error', (error, fileData) => {
|
||||
tpl.error.set(error.reason);
|
||||
});
|
||||
uploader.on('uploaded', (error, fileRef) => {
|
||||
if (!error) {
|
||||
// Trigger a re-evaluation of helpers to show new uploaded avatar
|
||||
const counter = tpl.avatarUpdateCounter.get();
|
||||
tpl.avatarUpdateCounter.set(counter + 1);
|
||||
// Also increment global counter for admin people list updates
|
||||
avatarUpdateCounter.set(avatarUpdateCounter.get() + 1);
|
||||
} else {
|
||||
tpl.error.set(error.reason);
|
||||
}
|
||||
});
|
||||
uploader.start();
|
||||
}
|
||||
},
|
||||
'click .js-select-avatar'(event, tpl) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
const data = Blaze.getData(event.currentTarget);
|
||||
if (data && typeof data.link === 'function') {
|
||||
const avatarUrl = data.link();
|
||||
if (this && typeof this.link === 'function') {
|
||||
const avatarUrl = this.link();
|
||||
changeAvatarSetAvatar(tpl, avatarUrl);
|
||||
}
|
||||
},
|
||||
@@ -229,10 +262,13 @@ Template.changeAvatarPopup.events({
|
||||
event.stopPropagation();
|
||||
changeAvatarSetAvatar(tpl, '');
|
||||
},
|
||||
'click .js-delete-avatar': Popup.afterConfirm('deleteAvatar', async function (event) {
|
||||
await Avatars.removeAsync(this._id);
|
||||
'click .js-delete-avatar': Popup.afterConfirm('deleteAvatar', async function() {
|
||||
// Inside the each loop, 'this' is the avatar object
|
||||
const avatarId = this._id;
|
||||
if (avatarId) {
|
||||
await Avatars.removeAsync(avatarId);
|
||||
}
|
||||
Popup.back();
|
||||
event.stopPropagation();
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -249,3 +285,146 @@ Template.cardMemberPopup.events({
|
||||
},
|
||||
'click .js-edit-profile': Popup.open('editProfile'),
|
||||
});
|
||||
|
||||
Template.adminChangeAvatarPopup.onCreated(function () {
|
||||
this.error = new ReactiveVar('');
|
||||
this.avatarUpdateCounter = new ReactiveVar(0);
|
||||
const userId = this.data._id || (this.data.user && this.data.user._id);
|
||||
this.targetUserId = userId;
|
||||
if (userId) {
|
||||
Meteor.subscribe('avatars-for-user', userId);
|
||||
}
|
||||
});
|
||||
|
||||
Template.adminChangeAvatarPopup.helpers({
|
||||
error() {
|
||||
return Template.instance().error;
|
||||
},
|
||||
userId() {
|
||||
const instance = Template.instance();
|
||||
return instance.targetUserId || (this._id || (this.user && this.user._id));
|
||||
},
|
||||
userData() {
|
||||
return this.user || this;
|
||||
},
|
||||
uploadedAvatars() {
|
||||
Template.instance().avatarUpdateCounter.get();
|
||||
const instance = Template.instance();
|
||||
const userId = instance.targetUserId || (this._id || (this.user && this.user._id));
|
||||
if (!userId) return [];
|
||||
const ret = ReactiveCache.getAvatars({ userId: userId }, {}, true);
|
||||
return ret;
|
||||
},
|
||||
avatarLink() {
|
||||
if (this && typeof this.link === 'function') {
|
||||
return this.link();
|
||||
}
|
||||
return '';
|
||||
},
|
||||
currentEditingUser() {
|
||||
Template.instance().avatarUpdateCounter.get();
|
||||
const instance = Template.instance();
|
||||
const userId = instance.targetUserId;
|
||||
if (!userId) return null;
|
||||
return ReactiveCache.getUser(userId);
|
||||
},
|
||||
isSelected() {
|
||||
Template.instance().avatarUpdateCounter.get();
|
||||
const instance = Template.instance();
|
||||
const userId = instance.targetUserId;
|
||||
if (!userId) return false;
|
||||
const user = ReactiveCache.getUser(userId);
|
||||
if (!user) return false;
|
||||
const userProfile = user.profile;
|
||||
const avatarUrl = userProfile && userProfile.avatarUrl;
|
||||
const currentAvatarUrl = this.link && typeof this.link === 'function' ? this.link() : '';
|
||||
const normalizeUrl = (url) => url ? url.split('?')[0] : '';
|
||||
return normalizeUrl(avatarUrl) === normalizeUrl(currentAvatarUrl);
|
||||
},
|
||||
noAvatarUrl() {
|
||||
Template.instance().avatarUpdateCounter.get();
|
||||
const instance = Template.instance();
|
||||
const userId = instance.targetUserId;
|
||||
if (!userId) return true;
|
||||
const user = ReactiveCache.getUser(userId);
|
||||
if (!user) return true;
|
||||
const userProfile = user.profile;
|
||||
const avatarUrl = userProfile && userProfile.avatarUrl;
|
||||
return !avatarUrl;
|
||||
},
|
||||
});
|
||||
|
||||
function adminChangeAvatarSetAvatar(tpl, avatarUrl) {
|
||||
const userId = tpl.targetUserId || (Template.currentData()._id || (Template.currentData().user && Template.currentData().user._id));
|
||||
if (!userId) {
|
||||
console.error('Cannot set avatar: no userId found');
|
||||
return;
|
||||
}
|
||||
Meteor.call('adminSetAvatarUrl', userId, avatarUrl, (err) => {
|
||||
if (err) {
|
||||
tpl.error.set(err.reason || 'Error setting avatar');
|
||||
} else {
|
||||
const counter = tpl.avatarUpdateCounter.get();
|
||||
tpl.avatarUpdateCounter.set(counter + 1);
|
||||
// Also increment global counter to update admin people list
|
||||
avatarUpdateCounter.set(avatarUpdateCounter.get() + 1);
|
||||
tpl.$('.js-upload-avatar-input').val('');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Template.adminChangeAvatarPopup.events({
|
||||
'click .js-upload-avatar'(event, tpl) {
|
||||
tpl.$('.js-upload-avatar-input').click();
|
||||
},
|
||||
async 'change .js-upload-avatar-input'(event, tpl) {
|
||||
if (event.currentTarget.files && event.currentTarget.files[0]) {
|
||||
const userId = tpl.targetUserId || (this._id || (this.user && this.user._id));
|
||||
const uploader = await Avatars.insertAsync(
|
||||
{
|
||||
file: event.currentTarget.files[0],
|
||||
chunkSize: 'dynamic',
|
||||
meta: {
|
||||
adminUploadForUserId: userId,
|
||||
},
|
||||
},
|
||||
false,
|
||||
);
|
||||
uploader.on('error', (error, fileData) => {
|
||||
tpl.error.set(error.reason);
|
||||
});
|
||||
uploader.on('uploaded', (error, fileRef) => {
|
||||
if (!error) {
|
||||
const counter = tpl.avatarUpdateCounter.get();
|
||||
tpl.avatarUpdateCounter.set(counter + 1);
|
||||
// Also increment global counter to update admin people list
|
||||
avatarUpdateCounter.set(avatarUpdateCounter.get() + 1);
|
||||
} else {
|
||||
tpl.error.set(error.reason);
|
||||
}
|
||||
});
|
||||
uploader.start();
|
||||
}
|
||||
},
|
||||
'click .js-select-avatar'(event, tpl) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
if (this && typeof this.link === 'function') {
|
||||
const avatarUrl = this.link();
|
||||
adminChangeAvatarSetAvatar(tpl, avatarUrl);
|
||||
}
|
||||
},
|
||||
'click .js-select-initials'(event, tpl) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
adminChangeAvatarSetAvatar(tpl, '');
|
||||
},
|
||||
'click .js-delete-avatar': Popup.afterConfirm('deleteAvatar', async function() {
|
||||
// Inside the each loop, 'this' is the avatar object
|
||||
const avatarId = this._id;
|
||||
if (avatarId) {
|
||||
await Avatars.removeAsync(avatarId);
|
||||
}
|
||||
Popup.back();
|
||||
}),
|
||||
});
|
||||
+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;
|
||||
}
|
||||
|
||||
|
||||
+373
-69
@@ -18,8 +18,9 @@ window.ExportHtml = Popup => {
|
||||
}
|
||||
};
|
||||
|
||||
const getPageHtmlString = () => {
|
||||
return `<!doctype html>${window.document.querySelector('html').outerHTML}`;
|
||||
const getPageHtmlString = (clonedElement = null) => {
|
||||
const element = clonedElement || window.document.querySelector('html');
|
||||
return `<!doctype html>${element.outerHTML}`;
|
||||
};
|
||||
|
||||
const removeAnchors = htmlString => {
|
||||
@@ -30,74 +31,161 @@ window.ExportHtml = Popup => {
|
||||
return replaceOpenAnchor.replace(new RegExp('</a', 'gim'), '</span');
|
||||
};
|
||||
|
||||
const ensureSidebarRemoved = () => {
|
||||
document.querySelector('.board-sidebar.sidebar').remove();
|
||||
const ensureSidebarRemoved = (element = null) => {
|
||||
const target = element || document;
|
||||
const sidebar = target.querySelector('.board-sidebar.sidebar');
|
||||
if (sidebar) {
|
||||
sidebar.remove();
|
||||
}
|
||||
};
|
||||
|
||||
const addJsonExportToZip = async (zip, boardSlug) => {
|
||||
const downloadJSONLink = document.querySelector('.download-json-link');
|
||||
const downloadJSONURL = downloadJSONLink.href;
|
||||
const response = await fetch(downloadJSONURL);
|
||||
const responseBody = await response.text();
|
||||
zip.file(`data/${boardSlug}.json`, responseBody);
|
||||
};
|
||||
|
||||
const closeSidebar = () => {
|
||||
document.querySelector('.board-header-btn.js-toggle-sidebar').click();
|
||||
};
|
||||
|
||||
const cleanBoardHtml = () => {
|
||||
Array.from(document.querySelectorAll('script')).forEach(elem =>
|
||||
const cleanBoardHtmlClone = (clonedElement) => {
|
||||
// Work on cloned element only, not live DOM
|
||||
Array.from(clonedElement.querySelectorAll('script')).forEach(elem =>
|
||||
elem.remove(),
|
||||
);
|
||||
Array.from(
|
||||
document.querySelectorAll('link:not([rel="stylesheet"])'),
|
||||
clonedElement.querySelectorAll('link:not([rel="stylesheet"])'),
|
||||
).forEach(elem => elem.remove());
|
||||
document.querySelector('#header-quick-access').remove();
|
||||
|
||||
const headerQuickAccess = clonedElement.querySelector('#header-quick-access');
|
||||
if (headerQuickAccess) headerQuickAccess.remove();
|
||||
|
||||
Array.from(
|
||||
document.querySelectorAll('#header-main-bar .board-header-btns'),
|
||||
clonedElement.querySelectorAll('#header-main-bar .board-header-btns'),
|
||||
).forEach(elem => elem.remove());
|
||||
Array.from(
|
||||
document.querySelectorAll('.js-pop-over, .pop-over'),
|
||||
clonedElement.querySelectorAll('.js-pop-over, .pop-over'),
|
||||
).forEach(elem => elem.remove());
|
||||
Array.from(document.querySelectorAll('.list-composer')).forEach(elem =>
|
||||
Array.from(clonedElement.querySelectorAll('.list-composer')).forEach(elem =>
|
||||
elem.remove(),
|
||||
);
|
||||
Array.from(
|
||||
document.querySelectorAll(
|
||||
clonedElement.querySelectorAll(
|
||||
'.list-composer,.js-card-composer, .js-add-card',
|
||||
),
|
||||
).forEach(elem => elem.remove());
|
||||
Array.from(document.querySelectorAll('[href]:not(link)')).forEach(elem =>
|
||||
|
||||
// Remove edit/action buttons from cards but keep card content
|
||||
Array.from(clonedElement.querySelectorAll('.js-edit, .js-delete, .js-open-card')).forEach(elem =>
|
||||
elem.remove(),
|
||||
);
|
||||
|
||||
// Keep card details structure for viewing - don't remove or hide
|
||||
// The interactive script will handle showing/hiding them
|
||||
|
||||
Array.from(clonedElement.querySelectorAll('[href]:not(link)')).forEach(elem =>
|
||||
elem.attributes.removeNamedItem('href'),
|
||||
);
|
||||
Array.from(document.querySelectorAll('[href]')).forEach(elem => {
|
||||
Array.from(clonedElement.querySelectorAll('[href]')).forEach(elem => {
|
||||
// eslint-disable-next-line no-self-assign
|
||||
elem.href = elem.href;
|
||||
// eslint-disable-next-line no-self-assign
|
||||
elem.src = elem.src;
|
||||
});
|
||||
Array.from(document.querySelectorAll('.is-editable')).forEach(elem => {
|
||||
Array.from(clonedElement.querySelectorAll('.is-editable')).forEach(elem => {
|
||||
elem.classList.remove('is-editable');
|
||||
});
|
||||
};
|
||||
|
||||
const addJsonExportToZip = async (zip, boardSlug, zipDirName) => {
|
||||
const downloadJSONLink = document.querySelector('.download-json-link');
|
||||
const downloadJSONURL = downloadJSONLink.href;
|
||||
const response = await fetch(downloadJSONURL);
|
||||
const responseBody = await response.text();
|
||||
zip.file(`${zipDirName}/data/${boardSlug}.json`, responseBody);
|
||||
};
|
||||
|
||||
const getBoardSlug = () => {
|
||||
// Use board ID from session instead of URL slug to keep filenames short
|
||||
const boardId = Session.get('currentBoard');
|
||||
if (boardId) {
|
||||
return boardId;
|
||||
}
|
||||
// Fallback to URL slug if session is not available
|
||||
return window.location.href.split('/').pop();
|
||||
};
|
||||
|
||||
const getBoardTitle = () => {
|
||||
// Extract from page header - most reliable method
|
||||
const headerTitle = document.querySelector('h1.header-board-menu');
|
||||
if (headerTitle && headerTitle.textContent) {
|
||||
const title = headerTitle.textContent.trim();
|
||||
// Filter out translation keys like "{{_ 'templates'}}"
|
||||
if (title && !title.includes('{{')) {
|
||||
return title;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: use board slug if header title extraction fails
|
||||
return getBoardSlug();
|
||||
};
|
||||
|
||||
const sanitizeFilename = (filename) => {
|
||||
// Remove or replace invalid filename characters
|
||||
// Keep alphanumeric, hyphens, underscores, and spaces
|
||||
return filename
|
||||
.replace(/[^a-zA-Z0-9\s\-_]/g, '') // Remove special chars
|
||||
.replace(/\s+/g, '-') // Replace spaces with hyphens
|
||||
.replace(/-+/g, '-') // Replace multiple hyphens with single
|
||||
.substring(0, 100) // Limit to 100 chars
|
||||
.trim();
|
||||
};
|
||||
|
||||
const getStylesheetList = () => {
|
||||
return Array.from(
|
||||
document.querySelectorAll('link[href][rel="stylesheet"]'),
|
||||
);
|
||||
};
|
||||
|
||||
const downloadStylesheets = async (stylesheets, zip) => {
|
||||
const getSrcAttached = () => {
|
||||
return Array.from(document.querySelectorAll('[src]'));
|
||||
};
|
||||
|
||||
const downloadStylesheets = async (stylesheets, zip, clonedHtmlElement, zipDirName) => {
|
||||
await asyncForEach(stylesheets, async elem => {
|
||||
const response = await fetch(elem.href);
|
||||
const responseBody = await response.text();
|
||||
let responseBody = await response.text();
|
||||
|
||||
const finalResponse = responseBody.replace(
|
||||
// Check if this is a Font Awesome CSS file
|
||||
const isFontAwesomeCSS = elem.href && (
|
||||
elem.href.includes('fontawesome') ||
|
||||
elem.href.includes('font-awesome') ||
|
||||
elem.href.includes('fa-') ||
|
||||
elem.href.includes('wekan-fontawesome')
|
||||
);
|
||||
|
||||
if (isFontAwesomeCSS) {
|
||||
// For Font Awesome: preserve @font-face but update paths to local files
|
||||
responseBody = responseBody.replace(
|
||||
/url\(["']?(?:\.\.\/)?webfonts\/([^"')]+)["']?\)/gi,
|
||||
'url("../webfonts/$1")'
|
||||
);
|
||||
// Also handle upstream package paths for Font Awesome
|
||||
responseBody = responseBody.replace(
|
||||
/url\(["']?[^"']*packages\/[^/]+\/upstream\/webfonts\/([^"')]+)["']?\)/gi,
|
||||
'url("../webfonts/$1")'
|
||||
);
|
||||
} else {
|
||||
// For non-Font-Awesome CSS: remove @font-face rules to eliminate external font dependencies
|
||||
responseBody = responseBody.replace(
|
||||
/@font-face\s*\{[^}]*\}/gi,
|
||||
''
|
||||
);
|
||||
|
||||
// Replace non-Font-Awesome font families with system fonts (sans-serif)
|
||||
// But preserve Font Awesome families
|
||||
responseBody = responseBody.replace(
|
||||
/font-family\s*:\s*[^;]*(?:Roboto|Lato|Open Sans)[^;]*;/gi,
|
||||
'font-family: sans-serif;'
|
||||
);
|
||||
}
|
||||
|
||||
// Fix relative paths for assets
|
||||
let finalResponse = responseBody;
|
||||
|
||||
// Replace upstream package paths
|
||||
finalResponse = finalResponse.replace(
|
||||
new RegExp('packages/[^/]+/upstream/', 'gim'),
|
||||
'../',
|
||||
);
|
||||
@@ -107,17 +195,20 @@ window.ExportHtml = Popup => {
|
||||
.pop()
|
||||
.split('?')
|
||||
.shift();
|
||||
const fileFullPath = `style/${filename}`;
|
||||
const fileFullPath = `${zipDirName}/style/${filename}`;
|
||||
zip.file(fileFullPath, finalResponse);
|
||||
elem.href = `../${fileFullPath}`;
|
||||
|
||||
// Update the cloned HTML element, not the live one
|
||||
if (clonedHtmlElement) {
|
||||
const clonedElements = clonedHtmlElement.querySelectorAll(`link[href="${elem.href}"]`);
|
||||
clonedElements.forEach(clonedElem => {
|
||||
clonedElem.href = `./style/${filename}`;
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const getSrcAttached = () => {
|
||||
return Array.from(document.querySelectorAll('[src]'));
|
||||
};
|
||||
|
||||
const downloadSrcAttached = async (elements, zip, boardSlug) => {
|
||||
const downloadSrcAttached = async (elements, zip, boardSlug, clonedHtmlElement, zipDirName) => {
|
||||
await asyncForEach(elements, async elem => {
|
||||
const response = await fetch(elem.src);
|
||||
const responseBody = await response.blob();
|
||||
@@ -126,9 +217,16 @@ window.ExportHtml = Popup => {
|
||||
.pop()
|
||||
.split('?')
|
||||
.shift();
|
||||
const fileFullPath = `${boardSlug}/${elem.tagName.toLowerCase()}/${filename}`;
|
||||
const fileFullPath = `${zipDirName}/${elem.tagName.toLowerCase()}/${filename}`;
|
||||
zip.file(fileFullPath, responseBody);
|
||||
elem.src = `./${elem.tagName.toLowerCase()}/${filename}`;
|
||||
|
||||
// Update the cloned HTML element, not the live one
|
||||
if (clonedHtmlElement) {
|
||||
const clonedElements = clonedHtmlElement.querySelectorAll(`[src="${elem.src}"]`);
|
||||
clonedElements.forEach(clonedElem => {
|
||||
clonedElem.src = `./${elem.tagName.toLowerCase()}/${filename}`;
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -156,7 +254,7 @@ window.ExportHtml = Popup => {
|
||||
};
|
||||
|
||||
const getWebFonts = () => {
|
||||
let fontUrls = [];
|
||||
let fonts = [];
|
||||
|
||||
for (let sheet of document.styleSheets) {
|
||||
// Get the base URL of the stylesheet
|
||||
@@ -169,10 +267,14 @@ window.ExportHtml = Popup => {
|
||||
let urlMatch = src.match(/url\(["']?(.+?)["']?\)/);
|
||||
if (urlMatch) {
|
||||
let fontUrl = urlMatch[1];
|
||||
let fontFamily = rule.style.getPropertyValue('font-family').replace(/["']/g, '');
|
||||
|
||||
// Resolve the URL relative to the stylesheet's base URL
|
||||
let resolvedUrl = new URL(fontUrl, baseUrl);
|
||||
fontUrls.push(resolvedUrl.href); // Using .href to get the absolute URL
|
||||
fonts.push({
|
||||
url: resolvedUrl.href,
|
||||
family: fontFamily
|
||||
}); // Using .href to get the absolute URL
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -181,25 +283,114 @@ window.ExportHtml = Popup => {
|
||||
}
|
||||
}
|
||||
|
||||
return fontUrls;
|
||||
return fonts;
|
||||
};
|
||||
|
||||
const downloadFonts = async(elements, zip) => {
|
||||
await asyncForEach(elements, async elem => {
|
||||
const downloadFonts = async(elements, zip, zipDirName) => {
|
||||
let fontIndex = 1;
|
||||
await asyncForEach(elements, async (fontObj, idx) => {
|
||||
const elem = fontObj.url;
|
||||
const fontFamily = fontObj.family || `font${fontIndex}`;
|
||||
|
||||
const response = await fetch(elem);
|
||||
const responseBody = await response.blob();
|
||||
const filename = elem.split('/')
|
||||
.pop()
|
||||
.split('?')
|
||||
.shift()
|
||||
.split('#')
|
||||
.shift();
|
||||
const fileFullPath = `webfonts/${filename}`;
|
||||
zip.file(fileFullPath, responseBody);
|
||||
|
||||
// Try to extract a better filename
|
||||
let filename = fontFamily.replace(/[^a-z0-9-]/gi, '').substring(0, 50) || `font${fontIndex++}`;
|
||||
|
||||
// If filename is empty after sanitization, use index
|
||||
if (!filename || filename.length === 0) {
|
||||
filename = `font${fontIndex++}`;
|
||||
}
|
||||
|
||||
// First, try to extract filename from URL path (for normal URLs)
|
||||
if (!elem.startsWith('data:')) {
|
||||
const pathname = new URL(elem).pathname;
|
||||
const urlFilename = pathname.split('/').pop().split('?')[0].split('#')[0];
|
||||
if (urlFilename && urlFilename.length > 0 && !urlFilename.match(/^[a-f0-9]+$/i)) {
|
||||
// Only use URL filename if it's not a hash
|
||||
filename = urlFilename;
|
||||
}
|
||||
}
|
||||
|
||||
// Detect format from content-type or file extension
|
||||
let extension = 'woff2';
|
||||
const contentType = response.headers.get('content-type');
|
||||
if (contentType) {
|
||||
if (contentType.includes('font/woff')) extension = 'woff';
|
||||
else if (contentType.includes('font/ttf')) extension = 'ttf';
|
||||
else if (contentType.includes('application/x-font-ttf')) extension = 'ttf';
|
||||
else if (contentType.includes('application/x-font-opentype')) extension = 'otf';
|
||||
}
|
||||
|
||||
// Ensure filename has extension
|
||||
if (!filename.includes('.')) {
|
||||
filename = `${filename}.${extension}`;
|
||||
}
|
||||
|
||||
const fileFullPath = `${zipDirName}/webfonts/${filename}`;
|
||||
zip.file(fileFullPath, responseBody);
|
||||
});
|
||||
}
|
||||
|
||||
const downloadCardCovers = async (elements, zip, boardSlug) => {
|
||||
const downloadFontAwesomeFonts = async (zip, zipDirName) => {
|
||||
// List of Font Awesome webfont files to include
|
||||
const fontAwesomeFiles = [
|
||||
'fa-solid-900.woff2',
|
||||
'fa-solid-900.ttf',
|
||||
'fa-brands-400.woff2',
|
||||
'fa-brands-400.ttf',
|
||||
'fa-regular-400.woff2',
|
||||
'fa-regular-400.ttf',
|
||||
'fa-v4compatibility.woff2',
|
||||
'fa-v4compatibility.ttf',
|
||||
];
|
||||
|
||||
try {
|
||||
await asyncForEach(fontAwesomeFiles, async (filename) => {
|
||||
try {
|
||||
// Try to fetch from the Meteor bundle webfont location
|
||||
const fontUrls = [
|
||||
`/packages/wekan-fontawesome/webfonts/${filename}`,
|
||||
`/webfonts/${filename}`,
|
||||
`./webfonts/${filename}`,
|
||||
`../packages/wekan-fontawesome/webfonts/${filename}`,
|
||||
];
|
||||
|
||||
let response = null;
|
||||
let fetchedUrl = null;
|
||||
|
||||
for (const url of fontUrls) {
|
||||
try {
|
||||
response = await fetch(url);
|
||||
if (response.ok) {
|
||||
fetchedUrl = url;
|
||||
break;
|
||||
}
|
||||
} catch (e) {
|
||||
// Try next URL
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (response && response.ok) {
|
||||
const responseBody = await response.blob();
|
||||
const fileFullPath = `${zipDirName}/webfonts/${filename}`;
|
||||
zip.file(fileFullPath, responseBody);
|
||||
console.log(`✓ Font Awesome font included: ${filename} from ${fetchedUrl}`);
|
||||
} else {
|
||||
console.log(`✗ Font Awesome font not found: ${filename}`);
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(`Error downloading Font Awesome font ${filename}:`, e);
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
console.log('Error in downloadFontAwesomeFonts:', e);
|
||||
}
|
||||
}
|
||||
|
||||
const downloadCardCovers = async (elements, zip, boardSlug, clonedHtmlElement, zipDirName) => {
|
||||
await asyncForEach(elements, async elem => {
|
||||
const response = await fetch(
|
||||
removeCssUrlSurround(elem.style['background-image']),
|
||||
@@ -212,18 +403,117 @@ window.ExportHtml = Popup => {
|
||||
.shift()
|
||||
.split('#')
|
||||
.shift();
|
||||
const fileFullPath = `${boardSlug}/covers/${filename}`;
|
||||
const fileFullPath = `${zipDirName}/covers/${filename}`;
|
||||
zip.file(fileFullPath, responseBody);
|
||||
elem.style = "background-image: url('" + `covers/${filename}` + "')";
|
||||
|
||||
// Update the cloned HTML element, not the live one
|
||||
if (clonedHtmlElement) {
|
||||
const bgImage = removeCssUrlSurround(elem.style['background-image']);
|
||||
const clonedElements = clonedHtmlElement.querySelectorAll('.minicard-cover');
|
||||
clonedElements.forEach(clonedElem => {
|
||||
if (removeCssUrlSurround(clonedElem.style['background-image']) === bgImage) {
|
||||
clonedElem.style.backgroundImage = `url('./covers/${filename}')`;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const addBoardHTMLToZip = (boardSlug, zip) => {
|
||||
ensureSidebarRemoved();
|
||||
const htmlOutputPath = `${boardSlug}/index.html`;
|
||||
const addBoardHTMLToZip = (boardSlug, zip, clonedElement, zipDirName) => {
|
||||
ensureSidebarRemoved(clonedElement);
|
||||
|
||||
// Get the HTML string
|
||||
let htmlString = removeAnchors(getPageHtmlString(clonedElement));
|
||||
|
||||
// Inject font styling with Font Awesome exception
|
||||
// Apply sans-serif to most elements, but preserve Font Awesome icon fonts
|
||||
const fontStyleTag = `<style>
|
||||
* { font-family: sans-serif !important; }
|
||||
body { font-family: sans-serif !important; }
|
||||
.fa, .fas, .far, .fab, .fa-solid, .fa-regular, .fa-brands, [class*="fa-"] {
|
||||
font-family: 'Font Awesome 6 Free', 'Font Awesome 6 Brands' !important;
|
||||
}
|
||||
</style>`;
|
||||
htmlString = htmlString.replace(
|
||||
/<\/head>/i,
|
||||
`${fontStyleTag}</head>`
|
||||
);
|
||||
|
||||
// Inject interactive script into the HTML before closing body tag
|
||||
const scriptContent = `
|
||||
// Make cards interactive in exported HTML
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
console.log('Initializing card interactions...');
|
||||
|
||||
// Create modal/popup for card details
|
||||
let modal = document.getElementById('card-details-modal');
|
||||
if (!modal) {
|
||||
modal = document.createElement('div');
|
||||
modal.id = 'card-details-modal';
|
||||
modal.style.cssText = 'display:none;position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);background:white;border:1px solid #ccc;border-radius:8px;padding:20px;max-width:600px;width:90%;max-height:80vh;overflow-y:auto;z-index:10000;box-shadow:0 4px 20px rgba(0,0,0,0.3);';
|
||||
document.body.appendChild(modal);
|
||||
}
|
||||
|
||||
// Add click handlers to cards to show/hide details
|
||||
const cards = document.querySelectorAll('.minicard');
|
||||
console.log('Found ' + cards.length + ' cards');
|
||||
|
||||
cards.forEach((card, idx) => {
|
||||
card.style.cursor = 'pointer';
|
||||
card.dataset.cardIndex = idx;
|
||||
|
||||
card.addEventListener('click', function(e) {
|
||||
// Ignore clicks on buttons or action elements
|
||||
if (e.target.closest('button, a, .js-') || e.target.closest('[role="button"]')) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
// Extract card title
|
||||
const title = this.querySelector('.card-title, .minicard-title, [class*="title"]');
|
||||
const titleText = title ? title.textContent.trim() : 'Card ' + this.dataset.cardIndex;
|
||||
|
||||
// Get all text content from the card
|
||||
const allText = this.textContent.trim();
|
||||
|
||||
// Show modal with card details
|
||||
modal.innerHTML = '<button style="position:absolute;top:10px;right:10px;padding:5px 10px;background:#f0f0f0;border:1px solid #ccc;border-radius:4px;cursor:pointer;">Close</button>';
|
||||
modal.querySelector('button').onclick = () => { modal.style.display = 'none'; document.body.style.overflow = 'auto'; };
|
||||
|
||||
const content = document.createElement('div');
|
||||
content.innerHTML = '<h2 style="margin-bottom:10px;">' + titleText + '</h2><hr style="margin:10px 0;"><div style="white-space:pre-wrap;word-wrap:break-word;font-family:sans-serif;font-size:13px;max-height:400px;overflow-y:auto;line-height:1.4;">' + allText + '</div><p style="color:#666;font-size:12px;margin-top:20px;"><em>Card #' + this.dataset.cardIndex + ' from exported board</em></p>';
|
||||
modal.appendChild(content);
|
||||
|
||||
modal.style.display = 'block';
|
||||
document.body.style.overflow = 'hidden';
|
||||
|
||||
console.log('Showing card details for card ' + this.dataset.cardIndex);
|
||||
});
|
||||
});
|
||||
|
||||
// Add style for cards
|
||||
if (!document.getElementById('card-open-styles')) {
|
||||
const style = document.createElement('style');
|
||||
style.id = 'card-open-styles';
|
||||
style.textContent = '* { font-family: sans-serif !important; } body { font-family: sans-serif !important; } .minicard { transition: all 0.3s ease; cursor: pointer; } .minicard:hover { box-shadow: 0 2px 8px rgba(0,0,0,0.15) !important; transform: translateY(-2px); }';
|
||||
document.head.appendChild(style);
|
||||
console.log('Added card styles and sans-serif font');
|
||||
}
|
||||
});
|
||||
`;
|
||||
|
||||
// Inject script before closing body tag
|
||||
htmlString = htmlString.replace(
|
||||
/<\/body>/i,
|
||||
`<script>${scriptContent}</script></body>`
|
||||
);
|
||||
|
||||
const htmlOutputPath = `${zipDirName}/index.html`;
|
||||
zip.file(
|
||||
htmlOutputPath,
|
||||
new Blob([removeAnchors(getPageHtmlString())], {
|
||||
new Blob([htmlString], {
|
||||
type: 'application/html',
|
||||
}),
|
||||
);
|
||||
@@ -232,21 +522,35 @@ window.ExportHtml = Popup => {
|
||||
return async () => {
|
||||
const zip = new JSZip();
|
||||
const boardSlug = getBoardSlug();
|
||||
const boardTitle = sanitizeFilename(getBoardTitle());
|
||||
const zipFilename = boardTitle || boardSlug;
|
||||
const zipDirName = zipFilename; // Directory name inside the ZIP
|
||||
|
||||
await addJsonExportToZip(zip, boardSlug);
|
||||
// Clone the HTML element to process for export without modifying live DOM
|
||||
const htmlElement = window.document.querySelector('html');
|
||||
const clonedHtmlElement = htmlElement.cloneNode(true);
|
||||
|
||||
await addJsonExportToZip(zip, boardSlug, zipDirName);
|
||||
Popup.back();
|
||||
closeSidebar();
|
||||
cleanBoardHtml();
|
||||
|
||||
await downloadStylesheets(getStylesheetList(), zip);
|
||||
await downloadSrcAttached(getSrcAttached(), zip, boardSlug);
|
||||
await downloadCardCovers(getCardCovers(), zip, boardSlug);
|
||||
await downloadFonts(getWebFonts(), zip);
|
||||
// Process the cloned element only
|
||||
cleanBoardHtmlClone(clonedHtmlElement);
|
||||
|
||||
addBoardHTMLToZip(boardSlug, zip);
|
||||
// Pass cloned element and zipDirName to all download functions so they update the clone, not the live DOM
|
||||
await downloadStylesheets(getStylesheetList(), zip, clonedHtmlElement, zipDirName);
|
||||
await downloadSrcAttached(getSrcAttached(), zip, boardSlug, clonedHtmlElement, zipDirName);
|
||||
await downloadCardCovers(getCardCovers(), zip, boardSlug, clonedHtmlElement, zipDirName);
|
||||
|
||||
// Download Font Awesome webfont files for icon support in exported HTML
|
||||
await downloadFontAwesomeFonts(zip, zipDirName);
|
||||
|
||||
// Note: General fonts are not exported to keep export lightweight
|
||||
// downloadFonts(getWebFonts(), zip, zipDirName); -- skipped
|
||||
|
||||
addBoardHTMLToZip(boardSlug, zip, clonedHtmlElement, zipDirName);
|
||||
|
||||
const content = await zip.generateAsync({ type: 'blob' });
|
||||
saveAs(content, `${boardSlug}.zip`);
|
||||
window.location.reload();
|
||||
saveAs(content, `${zipFilename}.zip`);
|
||||
// No page reload - impersonation session is preserved!
|
||||
};
|
||||
};
|
||||
+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(
|
||||
|
||||
+154
-116
@@ -108,54 +108,54 @@ services:
|
||||
#
|
||||
# If this is a fresh install, wekan-migrate exits instantly (nothing to migrate).
|
||||
#-------------------------------------------------------------------------------------
|
||||
|
||||
wekan-postgres:
|
||||
image: postgres:16-alpine
|
||||
container_name: wekan-postgres
|
||||
restart: always
|
||||
networks:
|
||||
- wekan-tier
|
||||
expose:
|
||||
- 5432
|
||||
environment:
|
||||
- POSTGRES_DB=wekan
|
||||
- POSTGRES_USER=wekan
|
||||
- POSTGRES_PASSWORD=wekan
|
||||
# Tune for a kanban workload (low connection count, moderate write rate)
|
||||
- POSTGRES_INITDB_ARGS=--encoding=UTF8 --locale=C
|
||||
volumes:
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
- wekan-postgres:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U wekan -d wekan"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
|
||||
wekan-ferretdb:
|
||||
image: ghcr.io/ferretdb/ferretdb:2
|
||||
container_name: wekan-ferretdb
|
||||
restart: always
|
||||
networks:
|
||||
- wekan-tier
|
||||
expose:
|
||||
- 27017
|
||||
environment:
|
||||
# FerretDB stores everything in PostgreSQL
|
||||
- FERRETDB_POSTGRESQL_URL=postgresql://wekan:wekan@wekan-postgres:5432/wekan
|
||||
# Emulate MongoDB replica-set for Meteor OpLog (real-time updates)
|
||||
- FERRETDB_REPLICATION_SET_NAME=rs0
|
||||
# Suppress verbose debug output
|
||||
- FERRETDB_LOG_LEVEL=warn
|
||||
depends_on:
|
||||
wekan-postgres:
|
||||
condition: service_healthy
|
||||
healthcheck:
|
||||
test: ["CMD", "ferretdb", "--version"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
|
||||
#
|
||||
#wekan-postgres:
|
||||
# image: postgres:16-alpine
|
||||
# container_name: wekan-postgres
|
||||
# restart: always
|
||||
# networks:
|
||||
# - wekan-tier
|
||||
# expose:
|
||||
# - 5432
|
||||
# environment:
|
||||
# - POSTGRES_DB=wekan
|
||||
# - POSTGRES_USER=wekan
|
||||
# - POSTGRES_PASSWORD=wekan
|
||||
# # Tune for a kanban workload (low connection count, moderate write rate)
|
||||
# - POSTGRES_INITDB_ARGS=--encoding=UTF8 --locale=C
|
||||
# volumes:
|
||||
# - /etc/localtime:/etc/localtime:ro
|
||||
# - wekan-postgres:/var/lib/postgresql/data
|
||||
# healthcheck:
|
||||
# test: ["CMD-SHELL", "pg_isready -U wekan -d wekan"]
|
||||
# interval: 5s
|
||||
# timeout: 5s
|
||||
# retries: 10
|
||||
#
|
||||
#wekan-ferretdb:
|
||||
# image: ghcr.io/ferretdb/ferretdb:2
|
||||
# container_name: wekan-ferretdb
|
||||
# restart: always
|
||||
# networks:
|
||||
# - wekan-tier
|
||||
# expose:
|
||||
# - 27017
|
||||
# environment:
|
||||
# # FerretDB stores everything in PostgreSQL
|
||||
# - FERRETDB_POSTGRESQL_URL=postgresql://wekan:wekan@wekan-postgres:5432/wekan
|
||||
# # Emulate MongoDB replica-set for Meteor OpLog (real-time updates)
|
||||
# - FERRETDB_REPLICATION_SET_NAME=rs0
|
||||
# # Suppress verbose debug output
|
||||
# - FERRETDB_LOG_LEVEL=warn
|
||||
# depends_on:
|
||||
# wekan-postgres:
|
||||
# condition: service_healthy
|
||||
# healthcheck:
|
||||
# test: ["CMD", "ferretdb", "--version"]
|
||||
# interval: 5s
|
||||
# timeout: 5s
|
||||
# retries: 10
|
||||
#
|
||||
#-------------------------------------------------------------------------------------
|
||||
# ==== MIGRATION SERVICE ====
|
||||
# Runs once, before WeKan starts. Exits 0 on success, 1 on fatal error.
|
||||
@@ -170,71 +170,98 @@ services:
|
||||
# mongodb://192.168.1.10:27017/wekan
|
||||
# Leave it unset or empty to skip migration.
|
||||
#-------------------------------------------------------------------------------------
|
||||
wekan-migrate:
|
||||
image: node:22.22.2-slim
|
||||
container_name: wekan-migrate
|
||||
restart: "no"
|
||||
networks:
|
||||
- wekan-tier
|
||||
working_dir: /migrate
|
||||
# Install the mongodb driver then run the migration script.
|
||||
# npm ci is used if package-lock.json exists; npm install otherwise.
|
||||
command: >
|
||||
sh -c "
|
||||
cd /migrate &&
|
||||
npm install --omit=dev --prefer-offline 2>/dev/null || npm install --omit=dev &&
|
||||
node migrate-mongodb-to-ferretdb.mjs
|
||||
"
|
||||
environment:
|
||||
# ---- Source (old MongoDB) ----
|
||||
# Set to your old MongoDB URL to trigger data migration.
|
||||
# Leave empty for a fresh install (migration is skipped automatically).
|
||||
- SOURCE_MONGO_URL=
|
||||
#- SOURCE_MONGO_URL=mongodb://wekandb:27017/wekan
|
||||
|
||||
# ---- Target (FerretDB) ----
|
||||
- TARGET_MONGO_URL=mongodb://wekan-ferretdb:27017/wekan
|
||||
|
||||
# ---- File storage ----
|
||||
# Must match the WRITABLE_PATH used by the wekan service.
|
||||
- WRITABLE_PATH=/data
|
||||
|
||||
# ---- Progress dashboard ----
|
||||
# Browse to http://localhost:8080/ while migration runs.
|
||||
- MIGRATION_PORT=8080
|
||||
|
||||
# ---- Tuning (optional) ----
|
||||
#- BATCH_SIZE=200
|
||||
#- DRY_RUN=true # Log only, no writes — useful for testing
|
||||
#- FORCE_MIGRATE=true # Re-run even if already marked complete
|
||||
ports:
|
||||
- 8080:8080
|
||||
depends_on:
|
||||
wekan-ferretdb:
|
||||
condition: service_healthy
|
||||
volumes:
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
- wekan-files:/data:rw
|
||||
- ./releases:/migrate:ro
|
||||
#wekan-migrate:
|
||||
# image: node:24.15.0-slim
|
||||
# container_name: wekan-migrate
|
||||
# restart: "no"
|
||||
# networks:
|
||||
# - wekan-tier
|
||||
# working_dir: /migrate
|
||||
# # Install the mongodb driver then run the migration script.
|
||||
# # npm ci is used if package-lock.json exists; npm install otherwise.
|
||||
# command: >
|
||||
# sh -c "
|
||||
# cd /migrate &&
|
||||
# npm install --omit=dev --prefer-offline 2>/dev/null || npm install --omit=dev &&
|
||||
# node migrate-mongodb-to-ferretdb.mjs
|
||||
# "
|
||||
# environment:
|
||||
# # ---- Source (old MongoDB) ----
|
||||
# # Set to your old MongoDB URL to trigger data migration.
|
||||
# # Leave empty for a fresh install (migration is skipped automatically).
|
||||
# - SOURCE_MONGO_URL=
|
||||
# #- SOURCE_MONGO_URL=mongodb://wekandb:27017/wekan
|
||||
#
|
||||
# # ---- Target (FerretDB) ----
|
||||
# - TARGET_MONGO_URL=mongodb://wekan-ferretdb:27017/wekan
|
||||
#
|
||||
# # ---- File storage ----
|
||||
# # Must match the WRITABLE_PATH used by the wekan service.
|
||||
# - WRITABLE_PATH=/data
|
||||
#
|
||||
# # ---- Progress dashboard ----
|
||||
# # Browse to http://localhost:8080/ while migration runs.
|
||||
# - MIGRATION_PORT=8080
|
||||
#
|
||||
# # ---- Tuning (optional) ----
|
||||
# #- BATCH_SIZE=200
|
||||
# #- DRY_RUN=true # Log only, no writes — useful for testing
|
||||
# #- FORCE_MIGRATE=true # Re-run even if already marked complete
|
||||
# ports:
|
||||
# - 8080:8080
|
||||
# depends_on:
|
||||
# wekan-ferretdb:
|
||||
# condition: service_healthy
|
||||
# volumes:
|
||||
# - /etc/localtime:/etc/localtime:ro
|
||||
# - wekan-files:/data:rw
|
||||
# - ./releases:/migrate:ro
|
||||
|
||||
#-------------------------------------------------------------------------------------
|
||||
# ==== LEGACY MONGODB (commented out) ====
|
||||
# Uncomment to keep old MongoDB running alongside FerretDB during migration.
|
||||
# After migration is verified, remove this block entirely.
|
||||
#-------------------------------------------------------------------------------------
|
||||
#wekandb:
|
||||
# image: mongo:7
|
||||
# container_name: wekan-db
|
||||
# restart: always
|
||||
# command: mongod --logpath /dev/null --oplogSize 128 --quiet
|
||||
# networks:
|
||||
# - wekan-tier
|
||||
# expose:
|
||||
# - 27017
|
||||
# volumes:
|
||||
# - /etc/localtime:/etc/localtime:ro
|
||||
# - wekan-db:/data/db
|
||||
# - wekan-db-dump:/dump
|
||||
wekandb:
|
||||
image: mongo:7
|
||||
container_name: wekan-db
|
||||
restart: always
|
||||
#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 --bind_ip_all --quiet &
|
||||
until mongosh --host 127.0.0.1 --quiet --eval "
|
||||
try {
|
||||
const status = rs.status();
|
||||
quit(status.ok === 1 ? 0 : 1);
|
||||
} catch (e) {
|
||||
if (
|
||||
e.codeName === \"NotYetInitialized\" ||
|
||||
e.message.includes(\"no replset config has been received\") ||
|
||||
e.message.includes(\"not yet initialized\")
|
||||
) {
|
||||
rs.initiate({
|
||||
_id: \"rs0\",
|
||||
members: [{ _id: 0, host: \"wekandb:27017\" }]
|
||||
});
|
||||
quit(1);
|
||||
}
|
||||
quit(1);
|
||||
}
|
||||
" >/dev/null 2>&1; do
|
||||
sleep 2
|
||||
done
|
||||
wait
|
||||
'
|
||||
networks:
|
||||
- wekan-tier
|
||||
expose:
|
||||
- 27017
|
||||
volumes:
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
- wekan-db:/data/db
|
||||
- wekan-db-dump:/dump
|
||||
|
||||
wekan:
|
||||
#-------------------------------------------------------------------------------------
|
||||
@@ -281,6 +308,15 @@ services:
|
||||
# remove port mapping if you use nginx reverse proxy, port 8080 is already exposed to wekan-tier network
|
||||
- 80:8080
|
||||
environment:
|
||||
#-------------------- USING MONGODB CHANGE STREAMS WITH REPLICA SETS AT CURRENT DATABASE --------------------
|
||||
# If you would not like to use Change Streams and replica set for improving speed, change to use polling:
|
||||
#- METEOR_REACTIVITY_ORDER=polling
|
||||
# https://forums.meteor.com/t/meteor-3-5-beta-change-streams-performance-improvements/64461#change-streams-setup-3
|
||||
# https://github.com/meteor/meteor/blob/release-3.5/v3-docs/docs/performance/change-streams-observer-driver.md#choosing-the-reactivity-driver-order
|
||||
# Use oplog,polling to fix performance until changeStreams is fixed at next release of Meteor 3.5 Beta:
|
||||
# https://github.com/wekan/wekan/issues/6307#issuecomment-4299349231
|
||||
# Later change to: METEOR_REACTIVITY_ORDER=changeStreams,oplog,polling
|
||||
- METEOR_REACTIVITY_ORDER=oplog,polling
|
||||
#-----------------------------------------------------------------
|
||||
# ==== WRITEABLE PATH FOR FILE UPLOADS ====
|
||||
- WRITABLE_PATH=/data
|
||||
@@ -295,7 +331,8 @@ services:
|
||||
#- S3_SECRET_FILE=/run/secrets/s3_secret
|
||||
#-----------------------------------------------------------------
|
||||
# ==== MONGO_URL — points to FerretDB (MongoDB-compatible) ====
|
||||
- MONGO_URL=mongodb://wekan-ferretdb:27017/wekan
|
||||
#- MONGO_URL=mongodb://wekan-ferretdb:27017/wekan
|
||||
- MONGO_URL=mongodb://wekandb:27017/wekan
|
||||
#- MONGO_PASSWORD_FILE=/run/secrets/mongo_password
|
||||
#---------------------------------------------------------------
|
||||
# ==== ROOT_URL SETTING ====
|
||||
@@ -345,7 +382,8 @@ services:
|
||||
# See: https://blog.meteor.com/tuning-meteor-mongo-livedata-for-scalability-13fe9deb8908
|
||||
# FerretDB emulates OpLog via --replication-set-name=rs0.
|
||||
# HIGHLY RECOMMENDED — enables real-time DDP updates (sub-100ms latency).
|
||||
- MONGO_OPLOG_URL=mongodb://wekan-ferretdb:27017/local?replicaSet=rs0
|
||||
#- MONGO_OPLOG_URL=mongodb://wekan-ferretdb:27017/local?replicaSet=rs0
|
||||
- MONGO_OPLOG_URL=mongodb://wekandb:27017/local?replicaSet=rs0
|
||||
#---------------------------------------------------------------
|
||||
# ==== OPTIONAL: KADIRA PERFORMANCE MONITORING FOR METEOR ====
|
||||
# https://github.com/edemaine/kadira-compose
|
||||
@@ -853,11 +891,11 @@ services:
|
||||
# Wait spinner to use
|
||||
# - WAIT_SPINNER=Bounce
|
||||
#---------------------------------------------------------------------
|
||||
depends_on:
|
||||
wekan-migrate:
|
||||
condition: service_completed_successfully
|
||||
wekan-ferretdb:
|
||||
condition: service_healthy
|
||||
#depends_on:
|
||||
# wekan-migrate:
|
||||
# condition: service_completed_successfully
|
||||
# wekan-ferretdb:
|
||||
# condition: service_healthy
|
||||
volumes:
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
- wekan-files:/data:rw
|
||||
@@ -921,8 +959,8 @@ services:
|
||||
volumes:
|
||||
wekan-files:
|
||||
driver: local
|
||||
wekan-postgres:
|
||||
driver: local
|
||||
#wekan-postgres:
|
||||
# driver: local
|
||||
# Legacy MongoDB volumes — kept so existing data survives until migration is done.
|
||||
# Remove once migration is verified and old MongoDB is decommissioned.
|
||||
wekan-db:
|
||||
|
||||
@@ -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:
|
||||
```
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
# History of Schema Migration Systems
|
||||
|
||||
1. At `server/migrations.js` was changes to database schema, but making modifications to thousands
|
||||
of cards did take many hours, it is too much time.
|
||||
2. There was Admin Panel options to migrate attachments from MongoDB GridFS to filesystem, but that could
|
||||
cause WeKan to become unresponsive, it did take too much resources.
|
||||
3. There was separate migration script to change database schema, but it was incomplete, some data was not migrated.
|
||||
4. Migrations were moved to opening of board, but that caused opening board to take too much time
|
||||
5. Migrations were moved to Right Sidebar/Board Settings/Migrations, but there was complains that
|
||||
it is too much try to get users to learn using those migrations, and it could take
|
||||
many hours for migrations to run at big board. Also, there was Responsible Security Disclosure
|
||||
that Board Admins have too much rights to change board structure so much, so migrations were moved
|
||||
to Admin Panel to be used only by Admins.
|
||||
6. At Admin Panel/Cron, migrations did not show progress of migrations well enough, it looked like no
|
||||
migrations were happening, migrations did take too much time, and WeKan did slow down while migrations
|
||||
were in progress, as was seen at increased CPU and RAM usage.
|
||||
7. Migrations were commented out, so that they would not slow down WeKan anymore.
|
||||
8. WeKan was migrated to Meteor 3.x.
|
||||
9. Someone added datetime migrations, to convert previous date strings to Date Objects, that PR was merged,
|
||||
but questions still is, does it cause too much slowdown. It should have been changed to detect and show
|
||||
any current date, detecting is it a string or Date Object.
|
||||
10. There was added code, that could show all Swimlanes/Lists/Cards without migrations, showing both
|
||||
previous Shared Lists and newest Per-Swimlane Lists, and also orphaned Swimlanes/Lists/Cards.
|
||||
But there was bug that something still disappeared when moving. It remains to be seen,
|
||||
can there continue to be showing all data without migrations, can that code be made to work,
|
||||
or is it really necessary to reintroduce migrations that take too much time.
|
||||
|
||||
How should migrations work?
|
||||
|
||||
a) Separate migrations script, that would be run before starting WeKan?
|
||||
b) Reading any database structure and showing data, without needing to migrate any data?
|
||||
c) Migrating while WeKan is running, that could cause slowdown?
|
||||
d) Some other way?
|
||||
@@ -1,3 +1,20 @@
|
||||
## From xet7, WeKan at s390x
|
||||
|
||||
- https://www.openmainframeproject.org/blog/2020/11/20/wekan-open-source-kanban-on-s390x
|
||||
|
||||
[xet7](https://github.com/xet7), as maintainer of [WeKan](https://wekan.fi), got access
|
||||
to mainframe at IBM LinuxOne Community Cloud.
|
||||
Access to those servers is monitored, it's running on a real mainframe.
|
||||
|
||||
Previously xet7 had ssh access. At 2023-09 xet7 got web console access,
|
||||
and IBM bumped quota to 2 VMs with 8 GB of memory, 200 GB disk and 4 CPUs each.
|
||||
At web console it is possible to create and remove VMs, and select distro
|
||||
like RHEL/SUSE/Ubuntu. xet7 did do-release-upgrade to upgrade newest Ubuntu.
|
||||
|
||||
## Download
|
||||
|
||||
- https://github.com/wekan/wekan/releases
|
||||
|
||||
## About s390x
|
||||
|
||||
- Dave's Garage at 2023-10: Why Do Mainframes Still Exist? What's Inside One? 40TB, 200+ Cores, AI, and more! https://www.youtube.com/watch?v=ouAG4vXFORc
|
||||
@@ -106,22 +123,12 @@ Transfer/sec: 70.23MB
|
||||
Ported by others, not xet7:
|
||||
- PostreSQL https://news.ycombinator.com/item?id=38398305
|
||||
|
||||
|
||||
## From xet7, WeKan at s390x
|
||||
|
||||
- https://www.openmainframeproject.org/blog/2020/11/20/wekan-open-source-kanban-on-s390x
|
||||
|
||||
[xet7](https://github.com/xet7), as maintainer of [WeKan](https://wekan.fi), got access to mainframe at IBM LinuxOne Community Cloud. Access to those servers is monitored, it's running on a real mainframe.
|
||||
|
||||
Previously xet7 had ssh access. At 2023-09 xet7 got web console access, and IBM bumped quota to 2 VMs with 8 GB of memory, 200 GB disk and 4 CPUs each. At web console it is possible to create and remove VMs, and select distro like RHEL/SUSE/Ubuntu. xet7 did do-release-upgrade to upgrade newest Ubuntu 23.10.
|
||||
|
||||
## Download
|
||||
|
||||
- wekan-VERSION-s390x.zip at https://releases.wekan.team/s390x/
|
||||
|
||||
## Installing MongoDB for s390x
|
||||
|
||||
This Snap package https://snapcraft.io/juju-db , created by Canonical, has MongoDB for various CPU architectures . It is internal package for Canonical's Juju service https://jaas.ai . Snap repo at https://github.com/juju/juju-db-snap and copy at https://github.com/wekan/mongodb-snap
|
||||
This Snap package https://snapcraft.io/juju-db , created by Canonical,
|
||||
has MongoDB for various CPU architectures .
|
||||
It is internal package for Canonical's Juju service https://jaas.ai .
|
||||
Snap repo at https://github.com/juju/juju-db-snap and copy at https://github.com/wekan/mongodb-snap
|
||||
|
||||
Install Snap for your distro https://snapcraft.io/docs/installing-snapd
|
||||
|
||||
|
||||
@@ -10,9 +10,8 @@ This is without container (without Docker or Snap).
|
||||
|
||||
Right click and download files 1-4:
|
||||
|
||||
1. [wekan-8.44-amd64-windows.zip](https://github.com/wekan/wekan/releases/download/v8.44/wekan-8.44-amd64-windows.zip)
|
||||
|
||||
2. [node.exe](https://nodejs.org/dist/latest-v22.x/win-x64/node.exe)
|
||||
1. [wekan-9.02-win64.zip](https://github.com/wekan/wekan/releases/download/v9.02/wekan-9.02-win64.zip)
|
||||
2. [node.exe](https://nodejs.org/dist/latest-v24.x/win-x64/node.exe)
|
||||
|
||||
3. [mongodb-windows-x86_64-7.0.31-signed.msi](https://fastdl.mongodb.org/windows/mongodb-windows-x86_64-7.0.31-signed.msi)
|
||||
|
||||
@@ -22,7 +21,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.44-amd64-windows.zip` , inside it is directory `bundle`, to it copy other files:
|
||||
7. Unzip `wekan-9.02-win64.zip` , inside it is directory `bundle`, to it copy other files:
|
||||
|
||||
```
|
||||
bundle (directory)
|
||||
|
||||
@@ -189,6 +189,7 @@
|
||||
"board-private-info": "This board will be <strong>private</strong>.",
|
||||
"board-public-info": "This board will be <strong>public</strong>.",
|
||||
"board-drag-drop-reorder-or-click-open": "Drag and drop to reorder board icons. Click board icon to open board.",
|
||||
"board-open-and-move-between-remaining-and-workspaces": "Click board icon to open board. Drag board between __remaining__ and __workspaces__.",
|
||||
"boardChangeColorPopup-title": "Change Board Background",
|
||||
"boardChangeBackgroundImagePopup-title": "Change Background Image",
|
||||
"allBoardsChangeColorPopup-title": "Change color",
|
||||
@@ -345,7 +346,7 @@
|
||||
"unset-color": "Unset",
|
||||
"comments": "Comments",
|
||||
"comment": "Comment",
|
||||
"comment-placeholder": "Write Comment",
|
||||
"comment-placeholder": "",
|
||||
"comment-only": "Comment only",
|
||||
"comment-only-desc": "Can comment on cards only.",
|
||||
"comment-assigned-only": "Only Assigned Comment",
|
||||
@@ -808,6 +809,9 @@
|
||||
"modifiedAt": "Modified at",
|
||||
"verified": "Verified",
|
||||
"active": "Active",
|
||||
"active-team": "Active Team",
|
||||
"active-org": "Active Organization",
|
||||
"active-person": "Active Person",
|
||||
"card-received": "Received",
|
||||
"card-received-on": "Received on",
|
||||
"card-end": "End",
|
||||
@@ -1572,7 +1576,6 @@
|
||||
"run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?",
|
||||
"run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?",
|
||||
"restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore",
|
||||
|
||||
"migration-progress-title": "Board Migration in Progress",
|
||||
"migration-progress-overall": "Overall Progress",
|
||||
"migration-progress-current-step": "Current Step",
|
||||
@@ -1582,7 +1585,6 @@
|
||||
"steps": "steps",
|
||||
"view": "View",
|
||||
"has-swimlanes": "Has Swimlanes",
|
||||
|
||||
"step-analyze-board-structure": "Analyze Board Structure",
|
||||
"step-fix-orphaned-cards": "Fix Orphaned Cards",
|
||||
"step-convert-shared-lists": "Convert Shared Lists",
|
||||
@@ -1729,4 +1731,4 @@
|
||||
"logout": "Logout",
|
||||
"server": "Server",
|
||||
"protocol": "Protocol"
|
||||
}
|
||||
}
|
||||
@@ -189,6 +189,7 @@
|
||||
"board-private-info": "This board will be <strong>private</strong>.",
|
||||
"board-public-info": "This board will be <strong>public</strong>.",
|
||||
"board-drag-drop-reorder-or-click-open": "Drag and drop to reorder board icons. Click board icon to open board.",
|
||||
"board-open-and-move-between-remaining-and-workspaces": "Click board icon to open board. Drag board between __remaining__ and __workspaces__.",
|
||||
"boardChangeColorPopup-title": "Change Board Background",
|
||||
"boardChangeBackgroundImagePopup-title": "Change Background Image",
|
||||
"allBoardsChangeColorPopup-title": "Change color",
|
||||
@@ -345,7 +346,7 @@
|
||||
"unset-color": "Unset",
|
||||
"comments": "Comments",
|
||||
"comment": "Comment",
|
||||
"comment-placeholder": "Write Comment",
|
||||
"comment-placeholder": "",
|
||||
"comment-only": "Comment only",
|
||||
"comment-only-desc": "Can comment on cards only.",
|
||||
"comment-assigned-only": "Only Assigned Comment",
|
||||
@@ -808,6 +809,9 @@
|
||||
"modifiedAt": "Modified at",
|
||||
"verified": "Verified",
|
||||
"active": "Active",
|
||||
"active-team": "Active Team",
|
||||
"active-org": "Active Organization",
|
||||
"active-person": "Active Person",
|
||||
"card-received": "Received",
|
||||
"card-received-on": "Received on",
|
||||
"card-end": "End",
|
||||
@@ -1572,7 +1576,6 @@
|
||||
"run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?",
|
||||
"run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?",
|
||||
"restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore",
|
||||
|
||||
"migration-progress-title": "Board Migration in Progress",
|
||||
"migration-progress-overall": "Overall Progress",
|
||||
"migration-progress-current-step": "Current Step",
|
||||
@@ -1582,7 +1585,6 @@
|
||||
"steps": "steps",
|
||||
"view": "View",
|
||||
"has-swimlanes": "Has Swimlanes",
|
||||
|
||||
"step-analyze-board-structure": "Analyze Board Structure",
|
||||
"step-fix-orphaned-cards": "Fix Orphaned Cards",
|
||||
"step-convert-shared-lists": "Convert Shared Lists",
|
||||
@@ -1729,4 +1731,4 @@
|
||||
"logout": "Logout",
|
||||
"server": "Server",
|
||||
"protocol": "Protocol"
|
||||
}
|
||||
}
|
||||
@@ -189,6 +189,7 @@
|
||||
"board-private-info": "This board will be <strong>private</strong>.",
|
||||
"board-public-info": "This board will be <strong>public</strong>.",
|
||||
"board-drag-drop-reorder-or-click-open": "Drag and drop to reorder board icons. Click board icon to open board.",
|
||||
"board-open-and-move-between-remaining-and-workspaces": "Click board icon to open board. Drag board between __remaining__ and __workspaces__.",
|
||||
"boardChangeColorPopup-title": "Change Board Background",
|
||||
"boardChangeBackgroundImagePopup-title": "Change Background Image",
|
||||
"allBoardsChangeColorPopup-title": "Change color",
|
||||
@@ -345,7 +346,7 @@
|
||||
"unset-color": "Unset",
|
||||
"comments": "Comments",
|
||||
"comment": "Comment",
|
||||
"comment-placeholder": "Write Comment",
|
||||
"comment-placeholder": "",
|
||||
"comment-only": "Comment only",
|
||||
"comment-only-desc": "Can comment on cards only.",
|
||||
"comment-assigned-only": "Only Assigned Comment",
|
||||
@@ -808,6 +809,9 @@
|
||||
"modifiedAt": "Modified at",
|
||||
"verified": "Verified",
|
||||
"active": "Active",
|
||||
"active-team": "Active Team",
|
||||
"active-org": "Active Organization",
|
||||
"active-person": "Active Person",
|
||||
"card-received": "Received",
|
||||
"card-received-on": "Received on",
|
||||
"card-end": "End",
|
||||
@@ -1572,7 +1576,6 @@
|
||||
"run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?",
|
||||
"run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?",
|
||||
"restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore",
|
||||
|
||||
"migration-progress-title": "Board Migration in Progress",
|
||||
"migration-progress-overall": "Overall Progress",
|
||||
"migration-progress-current-step": "Current Step",
|
||||
@@ -1582,7 +1585,6 @@
|
||||
"steps": "steps",
|
||||
"view": "View",
|
||||
"has-swimlanes": "Has Swimlanes",
|
||||
|
||||
"step-analyze-board-structure": "Analyze Board Structure",
|
||||
"step-fix-orphaned-cards": "Fix Orphaned Cards",
|
||||
"step-convert-shared-lists": "Convert Shared Lists",
|
||||
@@ -1729,4 +1731,4 @@
|
||||
"logout": "Logout",
|
||||
"server": "Server",
|
||||
"protocol": "Protocol"
|
||||
}
|
||||
}
|
||||
@@ -189,6 +189,7 @@
|
||||
"board-private-info": "This board will be <strong>private</strong>.",
|
||||
"board-public-info": "This board will be <strong>public</strong>.",
|
||||
"board-drag-drop-reorder-or-click-open": "Drag and drop to reorder board icons. Click board icon to open board.",
|
||||
"board-open-and-move-between-remaining-and-workspaces": "Click board icon to open board. Drag board between __remaining__ and __workspaces__.",
|
||||
"boardChangeColorPopup-title": "Change Board Background",
|
||||
"boardChangeBackgroundImagePopup-title": "Change Background Image",
|
||||
"allBoardsChangeColorPopup-title": "Change color",
|
||||
@@ -345,7 +346,7 @@
|
||||
"unset-color": "Unset",
|
||||
"comments": "Comments",
|
||||
"comment": "Comment",
|
||||
"comment-placeholder": "Write Comment",
|
||||
"comment-placeholder": "",
|
||||
"comment-only": "Comment only",
|
||||
"comment-only-desc": "Can comment on cards only.",
|
||||
"comment-assigned-only": "Only Assigned Comment",
|
||||
@@ -808,6 +809,9 @@
|
||||
"modifiedAt": "Modified at",
|
||||
"verified": "Verified",
|
||||
"active": "Active",
|
||||
"active-team": "Active Team",
|
||||
"active-org": "Active Organization",
|
||||
"active-person": "Active Person",
|
||||
"card-received": "Received",
|
||||
"card-received-on": "Received on",
|
||||
"card-end": "End",
|
||||
@@ -1572,7 +1576,6 @@
|
||||
"run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?",
|
||||
"run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?",
|
||||
"restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore",
|
||||
|
||||
"migration-progress-title": "Board Migration in Progress",
|
||||
"migration-progress-overall": "Overall Progress",
|
||||
"migration-progress-current-step": "Current Step",
|
||||
@@ -1582,7 +1585,6 @@
|
||||
"steps": "steps",
|
||||
"view": "View",
|
||||
"has-swimlanes": "Has Swimlanes",
|
||||
|
||||
"step-analyze-board-structure": "Analyze Board Structure",
|
||||
"step-fix-orphaned-cards": "Fix Orphaned Cards",
|
||||
"step-convert-shared-lists": "Convert Shared Lists",
|
||||
@@ -1729,4 +1731,4 @@
|
||||
"logout": "Logout",
|
||||
"server": "Server",
|
||||
"protocol": "Protocol"
|
||||
}
|
||||
}
|
||||
@@ -189,6 +189,7 @@
|
||||
"board-private-info": "This board will be <strong>private</strong>.",
|
||||
"board-public-info": "This board will be <strong>public</strong>.",
|
||||
"board-drag-drop-reorder-or-click-open": "Drag and drop to reorder board icons. Click board icon to open board.",
|
||||
"board-open-and-move-between-remaining-and-workspaces": "Click board icon to open board. Drag board between __remaining__ and __workspaces__.",
|
||||
"boardChangeColorPopup-title": "Change Board Background",
|
||||
"boardChangeBackgroundImagePopup-title": "Change Background Image",
|
||||
"allBoardsChangeColorPopup-title": "Change color",
|
||||
@@ -345,7 +346,7 @@
|
||||
"unset-color": "Unset",
|
||||
"comments": "Comments",
|
||||
"comment": "Comment",
|
||||
"comment-placeholder": "Write Comment",
|
||||
"comment-placeholder": "",
|
||||
"comment-only": "Comment only",
|
||||
"comment-only-desc": "Can comment on cards only.",
|
||||
"comment-assigned-only": "Only Assigned Comment",
|
||||
@@ -808,6 +809,9 @@
|
||||
"modifiedAt": "Modified at",
|
||||
"verified": "Verified",
|
||||
"active": "Active",
|
||||
"active-team": "Active Team",
|
||||
"active-org": "Active Organization",
|
||||
"active-person": "Active Person",
|
||||
"card-received": "Received",
|
||||
"card-received-on": "Received on",
|
||||
"card-end": "End",
|
||||
@@ -1572,7 +1576,6 @@
|
||||
"run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?",
|
||||
"run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?",
|
||||
"restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore",
|
||||
|
||||
"migration-progress-title": "Board Migration in Progress",
|
||||
"migration-progress-overall": "Overall Progress",
|
||||
"migration-progress-current-step": "Current Step",
|
||||
@@ -1582,7 +1585,6 @@
|
||||
"steps": "steps",
|
||||
"view": "View",
|
||||
"has-swimlanes": "Has Swimlanes",
|
||||
|
||||
"step-analyze-board-structure": "Analyze Board Structure",
|
||||
"step-fix-orphaned-cards": "Fix Orphaned Cards",
|
||||
"step-convert-shared-lists": "Convert Shared Lists",
|
||||
@@ -1729,4 +1731,4 @@
|
||||
"logout": "Logout",
|
||||
"server": "Server",
|
||||
"protocol": "Protocol"
|
||||
}
|
||||
}
|
||||
@@ -189,6 +189,7 @@
|
||||
"board-private-info": "سوف تصبح هذه اللوحة <strong>خاصة</strong>",
|
||||
"board-public-info": "سوف تصبح هذه اللوحة <strong>عامّة</strong>.",
|
||||
"board-drag-drop-reorder-or-click-open": "Drag and drop to reorder board icons. Click board icon to open board.",
|
||||
"board-open-and-move-between-remaining-and-workspaces": "Click board icon to open board. Drag board between __remaining__ and __workspaces__.",
|
||||
"boardChangeColorPopup-title": "تعديل خلفية الشاشة",
|
||||
"boardChangeBackgroundImagePopup-title": "تغيير صورة الخلفية",
|
||||
"allBoardsChangeColorPopup-title": "تغيير اللومr",
|
||||
@@ -345,7 +346,7 @@
|
||||
"unset-color": "غير محدد",
|
||||
"comments": "تعليقات",
|
||||
"comment": "تعليق",
|
||||
"comment-placeholder": "أكتب تعليق",
|
||||
"comment-placeholder": "",
|
||||
"comment-only": "التعليق فقط",
|
||||
"comment-only-desc": "يمكن التعليق على بطاقات فقط.",
|
||||
"comment-assigned-only": "Only Assigned Comment",
|
||||
@@ -808,6 +809,9 @@
|
||||
"modifiedAt": "Modified at",
|
||||
"verified": "Verified",
|
||||
"active": "نشط",
|
||||
"active-team": "Active Team",
|
||||
"active-org": "Active Organization",
|
||||
"active-person": "Active Person",
|
||||
"card-received": "Received",
|
||||
"card-received-on": "Received on",
|
||||
"card-end": "End",
|
||||
@@ -1395,7 +1399,7 @@
|
||||
"accessibility": "Accessibility",
|
||||
"accessibility-page-enabled": "تم تمكين صفحة إمكانية الوصول",
|
||||
"accessibility-info-not-added-yet": "Accessibility info has not been added yet",
|
||||
"accessibility-title": "Accessibility title",
|
||||
"accessibility-title": "عنوان إمكانية الوصول",
|
||||
"accessibility-content": "محتوى إمكانية الوصول",
|
||||
"accounts-lockout-settings": "Brute Force Protection Settings",
|
||||
"accounts-lockout-info": "These settings control how login attempts are protected against brute force attacks.",
|
||||
@@ -1572,7 +1576,6 @@
|
||||
"run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?",
|
||||
"run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?",
|
||||
"restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore",
|
||||
|
||||
"migration-progress-title": "Board Migration in Progress",
|
||||
"migration-progress-overall": "Overall Progress",
|
||||
"migration-progress-current-step": "Current Step",
|
||||
@@ -1582,7 +1585,6 @@
|
||||
"steps": "steps",
|
||||
"view": "View",
|
||||
"has-swimlanes": "Has Swimlanes",
|
||||
|
||||
"step-analyze-board-structure": "Analyze Board Structure",
|
||||
"step-fix-orphaned-cards": "Fix Orphaned Cards",
|
||||
"step-convert-shared-lists": "Convert Shared Lists",
|
||||
@@ -1729,4 +1731,4 @@
|
||||
"logout": "Logout",
|
||||
"server": "Server",
|
||||
"protocol": "Protocol"
|
||||
}
|
||||
}
|
||||
@@ -189,6 +189,7 @@
|
||||
"board-private-info": "This board will be <strong>private</strong>.",
|
||||
"board-public-info": "This board will be <strong>public</strong>.",
|
||||
"board-drag-drop-reorder-or-click-open": "Drag and drop to reorder board icons. Click board icon to open board.",
|
||||
"board-open-and-move-between-remaining-and-workspaces": "Click board icon to open board. Drag board between __remaining__ and __workspaces__.",
|
||||
"boardChangeColorPopup-title": "Change Board Background",
|
||||
"boardChangeBackgroundImagePopup-title": "Change Background Image",
|
||||
"allBoardsChangeColorPopup-title": "Change color",
|
||||
@@ -345,7 +346,7 @@
|
||||
"unset-color": "Unset",
|
||||
"comments": "Comments",
|
||||
"comment": "Comment",
|
||||
"comment-placeholder": "Write Comment",
|
||||
"comment-placeholder": "",
|
||||
"comment-only": "Comment only",
|
||||
"comment-only-desc": "Can comment on cards only.",
|
||||
"comment-assigned-only": "Only Assigned Comment",
|
||||
@@ -808,6 +809,9 @@
|
||||
"modifiedAt": "Modified at",
|
||||
"verified": "Verified",
|
||||
"active": "Active",
|
||||
"active-team": "Active Team",
|
||||
"active-org": "Active Organization",
|
||||
"active-person": "Active Person",
|
||||
"card-received": "Received",
|
||||
"card-received-on": "Received on",
|
||||
"card-end": "End",
|
||||
@@ -1572,7 +1576,6 @@
|
||||
"run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?",
|
||||
"run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?",
|
||||
"restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore",
|
||||
|
||||
"migration-progress-title": "Board Migration in Progress",
|
||||
"migration-progress-overall": "Overall Progress",
|
||||
"migration-progress-current-step": "Current Step",
|
||||
@@ -1582,7 +1585,6 @@
|
||||
"steps": "steps",
|
||||
"view": "View",
|
||||
"has-swimlanes": "Has Swimlanes",
|
||||
|
||||
"step-analyze-board-structure": "Analyze Board Structure",
|
||||
"step-fix-orphaned-cards": "Fix Orphaned Cards",
|
||||
"step-convert-shared-lists": "Convert Shared Lists",
|
||||
@@ -1729,4 +1731,4 @@
|
||||
"logout": "Logout",
|
||||
"server": "Server",
|
||||
"protocol": "Protocol"
|
||||
}
|
||||
}
|
||||
@@ -189,6 +189,7 @@
|
||||
"board-private-info": "This board will be <strong>private</strong>.",
|
||||
"board-public-info": "This board will be <strong>public</strong>.",
|
||||
"board-drag-drop-reorder-or-click-open": "Drag and drop to reorder board icons. Click board icon to open board.",
|
||||
"board-open-and-move-between-remaining-and-workspaces": "Click board icon to open board. Drag board between __remaining__ and __workspaces__.",
|
||||
"boardChangeColorPopup-title": "Change Board Background",
|
||||
"boardChangeBackgroundImagePopup-title": "Change Background Image",
|
||||
"allBoardsChangeColorPopup-title": "Change color",
|
||||
@@ -345,7 +346,7 @@
|
||||
"unset-color": "Unset",
|
||||
"comments": "Comments",
|
||||
"comment": "Comment",
|
||||
"comment-placeholder": "Write Comment",
|
||||
"comment-placeholder": "",
|
||||
"comment-only": "Comment only",
|
||||
"comment-only-desc": "Can comment on cards only.",
|
||||
"comment-assigned-only": "Only Assigned Comment",
|
||||
@@ -808,6 +809,9 @@
|
||||
"modifiedAt": "Modified at",
|
||||
"verified": "Verified",
|
||||
"active": "Active",
|
||||
"active-team": "Active Team",
|
||||
"active-org": "Active Organization",
|
||||
"active-person": "Active Person",
|
||||
"card-received": "Received",
|
||||
"card-received-on": "Received on",
|
||||
"card-end": "End",
|
||||
@@ -1572,7 +1576,6 @@
|
||||
"run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?",
|
||||
"run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?",
|
||||
"restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore",
|
||||
|
||||
"migration-progress-title": "Board Migration in Progress",
|
||||
"migration-progress-overall": "Overall Progress",
|
||||
"migration-progress-current-step": "Current Step",
|
||||
@@ -1582,7 +1585,6 @@
|
||||
"steps": "steps",
|
||||
"view": "View",
|
||||
"has-swimlanes": "Has Swimlanes",
|
||||
|
||||
"step-analyze-board-structure": "Analyze Board Structure",
|
||||
"step-fix-orphaned-cards": "Fix Orphaned Cards",
|
||||
"step-convert-shared-lists": "Convert Shared Lists",
|
||||
@@ -1729,4 +1731,4 @@
|
||||
"logout": "Logout",
|
||||
"server": "Server",
|
||||
"protocol": "Protocol"
|
||||
}
|
||||
}
|
||||
@@ -189,6 +189,7 @@
|
||||
"board-private-info": "This board will be <strong>private</strong>.",
|
||||
"board-public-info": "This board will be <strong>public</strong>.",
|
||||
"board-drag-drop-reorder-or-click-open": "Drag and drop to reorder board icons. Click board icon to open board.",
|
||||
"board-open-and-move-between-remaining-and-workspaces": "Click board icon to open board. Drag board between __remaining__ and __workspaces__.",
|
||||
"boardChangeColorPopup-title": "Change Board Background",
|
||||
"boardChangeBackgroundImagePopup-title": "Change Background Image",
|
||||
"allBoardsChangeColorPopup-title": "Change color",
|
||||
@@ -345,7 +346,7 @@
|
||||
"unset-color": "Unset",
|
||||
"comments": "Comments",
|
||||
"comment": "Comment",
|
||||
"comment-placeholder": "Write Comment",
|
||||
"comment-placeholder": "",
|
||||
"comment-only": "Comment only",
|
||||
"comment-only-desc": "Can comment on cards only.",
|
||||
"comment-assigned-only": "Only Assigned Comment",
|
||||
@@ -808,6 +809,9 @@
|
||||
"modifiedAt": "Modified at",
|
||||
"verified": "Verified",
|
||||
"active": "Active",
|
||||
"active-team": "Active Team",
|
||||
"active-org": "Active Organization",
|
||||
"active-person": "Active Person",
|
||||
"card-received": "Received",
|
||||
"card-received-on": "Received on",
|
||||
"card-end": "End",
|
||||
@@ -1572,7 +1576,6 @@
|
||||
"run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?",
|
||||
"run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?",
|
||||
"restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore",
|
||||
|
||||
"migration-progress-title": "Board Migration in Progress",
|
||||
"migration-progress-overall": "Overall Progress",
|
||||
"migration-progress-current-step": "Current Step",
|
||||
@@ -1582,7 +1585,6 @@
|
||||
"steps": "steps",
|
||||
"view": "View",
|
||||
"has-swimlanes": "Has Swimlanes",
|
||||
|
||||
"step-analyze-board-structure": "Analyze Board Structure",
|
||||
"step-fix-orphaned-cards": "Fix Orphaned Cards",
|
||||
"step-convert-shared-lists": "Convert Shared Lists",
|
||||
@@ -1729,4 +1731,4 @@
|
||||
"logout": "Logout",
|
||||
"server": "Server",
|
||||
"protocol": "Protocol"
|
||||
}
|
||||
}
|
||||
@@ -189,6 +189,7 @@
|
||||
"board-private-info": "This board will be <strong>private</strong>.",
|
||||
"board-public-info": "This board will be <strong>public</strong>.",
|
||||
"board-drag-drop-reorder-or-click-open": "Drag and drop to reorder board icons. Click board icon to open board.",
|
||||
"board-open-and-move-between-remaining-and-workspaces": "Click board icon to open board. Drag board between __remaining__ and __workspaces__.",
|
||||
"boardChangeColorPopup-title": "Change Board Background",
|
||||
"boardChangeBackgroundImagePopup-title": "Change Background Image",
|
||||
"allBoardsChangeColorPopup-title": "Change color",
|
||||
@@ -345,7 +346,7 @@
|
||||
"unset-color": "Unset",
|
||||
"comments": "Comments",
|
||||
"comment": "Comment",
|
||||
"comment-placeholder": "Write Comment",
|
||||
"comment-placeholder": "",
|
||||
"comment-only": "Comment only",
|
||||
"comment-only-desc": "Can comment on cards only.",
|
||||
"comment-assigned-only": "Only Assigned Comment",
|
||||
@@ -808,6 +809,9 @@
|
||||
"modifiedAt": "Modified at",
|
||||
"verified": "Verified",
|
||||
"active": "Active",
|
||||
"active-team": "Active Team",
|
||||
"active-org": "Active Organization",
|
||||
"active-person": "Active Person",
|
||||
"card-received": "Received",
|
||||
"card-received-on": "Received on",
|
||||
"card-end": "End",
|
||||
@@ -1572,7 +1576,6 @@
|
||||
"run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?",
|
||||
"run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?",
|
||||
"restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore",
|
||||
|
||||
"migration-progress-title": "Board Migration in Progress",
|
||||
"migration-progress-overall": "Overall Progress",
|
||||
"migration-progress-current-step": "Current Step",
|
||||
@@ -1582,7 +1585,6 @@
|
||||
"steps": "steps",
|
||||
"view": "View",
|
||||
"has-swimlanes": "Has Swimlanes",
|
||||
|
||||
"step-analyze-board-structure": "Analyze Board Structure",
|
||||
"step-fix-orphaned-cards": "Fix Orphaned Cards",
|
||||
"step-convert-shared-lists": "Convert Shared Lists",
|
||||
@@ -1729,4 +1731,4 @@
|
||||
"logout": "Logout",
|
||||
"server": "Server",
|
||||
"protocol": "Protocol"
|
||||
}
|
||||
}
|
||||
@@ -189,6 +189,7 @@
|
||||
"board-private-info": "This board will be <strong>private</strong>.",
|
||||
"board-public-info": "This board will be <strong>public</strong>.",
|
||||
"board-drag-drop-reorder-or-click-open": "Drag and drop to reorder board icons. Click board icon to open board.",
|
||||
"board-open-and-move-between-remaining-and-workspaces": "Click board icon to open board. Drag board between __remaining__ and __workspaces__.",
|
||||
"boardChangeColorPopup-title": "Change Board Background",
|
||||
"boardChangeBackgroundImagePopup-title": "Change Background Image",
|
||||
"allBoardsChangeColorPopup-title": "Change color",
|
||||
@@ -345,7 +346,7 @@
|
||||
"unset-color": "Unset",
|
||||
"comments": "Comments",
|
||||
"comment": "Comment",
|
||||
"comment-placeholder": "Write Comment",
|
||||
"comment-placeholder": "",
|
||||
"comment-only": "Comment only",
|
||||
"comment-only-desc": "Can comment on cards only.",
|
||||
"comment-assigned-only": "Only Assigned Comment",
|
||||
@@ -808,6 +809,9 @@
|
||||
"modifiedAt": "Modified at",
|
||||
"verified": "Verified",
|
||||
"active": "Active",
|
||||
"active-team": "Active Team",
|
||||
"active-org": "Active Organization",
|
||||
"active-person": "Active Person",
|
||||
"card-received": "Received",
|
||||
"card-received-on": "Received on",
|
||||
"card-end": "End",
|
||||
@@ -1572,7 +1576,6 @@
|
||||
"run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?",
|
||||
"run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?",
|
||||
"restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore",
|
||||
|
||||
"migration-progress-title": "Board Migration in Progress",
|
||||
"migration-progress-overall": "Overall Progress",
|
||||
"migration-progress-current-step": "Current Step",
|
||||
@@ -1582,7 +1585,6 @@
|
||||
"steps": "steps",
|
||||
"view": "View",
|
||||
"has-swimlanes": "Has Swimlanes",
|
||||
|
||||
"step-analyze-board-structure": "Analyze Board Structure",
|
||||
"step-fix-orphaned-cards": "Fix Orphaned Cards",
|
||||
"step-convert-shared-lists": "Convert Shared Lists",
|
||||
@@ -1729,4 +1731,4 @@
|
||||
"logout": "Logout",
|
||||
"server": "Server",
|
||||
"protocol": "Protocol"
|
||||
}
|
||||
}
|
||||
@@ -189,6 +189,7 @@
|
||||
"board-private-info": "Това табло ще бъде <strong>лично</strong>",
|
||||
"board-public-info": "Това табло ще бъде <strong>публично</strong>",
|
||||
"board-drag-drop-reorder-or-click-open": "Drag and drop to reorder board icons. Click board icon to open board.",
|
||||
"board-open-and-move-between-remaining-and-workspaces": "Click board icon to open board. Drag board between __remaining__ and __workspaces__.",
|
||||
"boardChangeColorPopup-title": "Променете фона на таблото",
|
||||
"boardChangeBackgroundImagePopup-title": "Change Background Image",
|
||||
"allBoardsChangeColorPopup-title": "Промени цвета",
|
||||
@@ -345,7 +346,7 @@
|
||||
"unset-color": "Премахни",
|
||||
"comments": "Comments",
|
||||
"comment": "Коментирай",
|
||||
"comment-placeholder": "Напиши коментар",
|
||||
"comment-placeholder": "",
|
||||
"comment-only": "Само коментар",
|
||||
"comment-only-desc": "Може да коментира само в карти.",
|
||||
"comment-assigned-only": "Only Assigned Comment",
|
||||
@@ -808,6 +809,9 @@
|
||||
"modifiedAt": "Modified at",
|
||||
"verified": "Потвърден",
|
||||
"active": "Активен",
|
||||
"active-team": "Active Team",
|
||||
"active-org": "Active Organization",
|
||||
"active-person": "Active Person",
|
||||
"card-received": "Получена",
|
||||
"card-received-on": "Получена на",
|
||||
"card-end": "Завършена",
|
||||
@@ -1572,7 +1576,6 @@
|
||||
"run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?",
|
||||
"run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?",
|
||||
"restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore",
|
||||
|
||||
"migration-progress-title": "Board Migration in Progress",
|
||||
"migration-progress-overall": "Overall Progress",
|
||||
"migration-progress-current-step": "Current Step",
|
||||
@@ -1582,7 +1585,6 @@
|
||||
"steps": "steps",
|
||||
"view": "View",
|
||||
"has-swimlanes": "Has Swimlanes",
|
||||
|
||||
"step-analyze-board-structure": "Analyze Board Structure",
|
||||
"step-fix-orphaned-cards": "Fix Orphaned Cards",
|
||||
"step-convert-shared-lists": "Convert Shared Lists",
|
||||
@@ -1729,4 +1731,4 @@
|
||||
"logout": "Logout",
|
||||
"server": "Server",
|
||||
"protocol": "Protocol"
|
||||
}
|
||||
}
|
||||
@@ -189,6 +189,7 @@
|
||||
"board-private-info": "This board will be <strong>private</strong>.",
|
||||
"board-public-info": "This board will be <strong>public</strong>.",
|
||||
"board-drag-drop-reorder-or-click-open": "Drag and drop to reorder board icons. Click board icon to open board.",
|
||||
"board-open-and-move-between-remaining-and-workspaces": "Click board icon to open board. Drag board between __remaining__ and __workspaces__.",
|
||||
"boardChangeColorPopup-title": "Change Board Background",
|
||||
"boardChangeBackgroundImagePopup-title": "Change Background Image",
|
||||
"allBoardsChangeColorPopup-title": "Kemmañ al liv",
|
||||
@@ -345,7 +346,7 @@
|
||||
"unset-color": "Unset",
|
||||
"comments": "Comments",
|
||||
"comment": "Comment",
|
||||
"comment-placeholder": "Write Comment",
|
||||
"comment-placeholder": "",
|
||||
"comment-only": "Comment only",
|
||||
"comment-only-desc": "Can comment on cards only.",
|
||||
"comment-assigned-only": "Only Assigned Comment",
|
||||
@@ -808,6 +809,9 @@
|
||||
"modifiedAt": "Modified at",
|
||||
"verified": "Verified",
|
||||
"active": "Active",
|
||||
"active-team": "Active Team",
|
||||
"active-org": "Active Organization",
|
||||
"active-person": "Active Person",
|
||||
"card-received": "Received",
|
||||
"card-received-on": "Received on",
|
||||
"card-end": "End",
|
||||
@@ -1572,7 +1576,6 @@
|
||||
"run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?",
|
||||
"run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?",
|
||||
"restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore",
|
||||
|
||||
"migration-progress-title": "Board Migration in Progress",
|
||||
"migration-progress-overall": "Overall Progress",
|
||||
"migration-progress-current-step": "Current Step",
|
||||
@@ -1582,7 +1585,6 @@
|
||||
"steps": "steps",
|
||||
"view": "View",
|
||||
"has-swimlanes": "Has Swimlanes",
|
||||
|
||||
"step-analyze-board-structure": "Analyze Board Structure",
|
||||
"step-fix-orphaned-cards": "Fix Orphaned Cards",
|
||||
"step-convert-shared-lists": "Convert Shared Lists",
|
||||
@@ -1729,4 +1731,4 @@
|
||||
"logout": "Logout",
|
||||
"server": "Server",
|
||||
"protocol": "Protocol"
|
||||
}
|
||||
}
|
||||
@@ -189,6 +189,7 @@
|
||||
"board-private-info": "Aquest tauler serà <strong> privat.",
|
||||
"board-public-info": "Aquest tauler serà <strong> públic.",
|
||||
"board-drag-drop-reorder-or-click-open": "Arrossegueu i deixeu anar per reordenar les icones del tauler. Feu clic a la icona del tauler per obrir el tauler.",
|
||||
"board-open-and-move-between-remaining-and-workspaces": "Click board icon to open board. Drag board between __remaining__ and __workspaces__.",
|
||||
"boardChangeColorPopup-title": "Canvia fons del tauler",
|
||||
"boardChangeBackgroundImagePopup-title": "Change Background Image",
|
||||
"allBoardsChangeColorPopup-title": "Canvia el color",
|
||||
@@ -345,7 +346,7 @@
|
||||
"unset-color": "Desactivat",
|
||||
"comments": "Comments",
|
||||
"comment": "Comentari",
|
||||
"comment-placeholder": "Escriu un comentari",
|
||||
"comment-placeholder": "",
|
||||
"comment-only": "Només comentaris",
|
||||
"comment-only-desc": "Només pots fer comentaris a les fitxes",
|
||||
"comment-assigned-only": "Only Assigned Comment",
|
||||
@@ -808,6 +809,9 @@
|
||||
"modifiedAt": "Modificat a",
|
||||
"verified": "Verificat",
|
||||
"active": "Actiu",
|
||||
"active-team": "Active Team",
|
||||
"active-org": "Active Organization",
|
||||
"active-person": "Active Person",
|
||||
"card-received": "Rebut",
|
||||
"card-received-on": "Rebut el",
|
||||
"card-end": "Final",
|
||||
@@ -1572,7 +1576,6 @@
|
||||
"run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?",
|
||||
"run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?",
|
||||
"restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore",
|
||||
|
||||
"migration-progress-title": "Board Migration in Progress",
|
||||
"migration-progress-overall": "Overall Progress",
|
||||
"migration-progress-current-step": "Current Step",
|
||||
@@ -1582,7 +1585,6 @@
|
||||
"steps": "steps",
|
||||
"view": "View",
|
||||
"has-swimlanes": "Has Swimlanes",
|
||||
|
||||
"step-analyze-board-structure": "Analyze Board Structure",
|
||||
"step-fix-orphaned-cards": "Fix Orphaned Cards",
|
||||
"step-convert-shared-lists": "Convert Shared Lists",
|
||||
@@ -1729,4 +1731,4 @@
|
||||
"logout": "Logout",
|
||||
"server": "Server",
|
||||
"protocol": "Protocol"
|
||||
}
|
||||
}
|
||||
@@ -189,6 +189,7 @@
|
||||
"board-private-info": "This board will be <strong>private</strong>.",
|
||||
"board-public-info": "This board will be <strong>public</strong>.",
|
||||
"board-drag-drop-reorder-or-click-open": "Drag and drop to reorder board icons. Click board icon to open board.",
|
||||
"board-open-and-move-between-remaining-and-workspaces": "Click board icon to open board. Drag board between __remaining__ and __workspaces__.",
|
||||
"boardChangeColorPopup-title": "Change Board Background",
|
||||
"boardChangeBackgroundImagePopup-title": "Change Background Image",
|
||||
"allBoardsChangeColorPopup-title": "Change color",
|
||||
@@ -345,7 +346,7 @@
|
||||
"unset-color": "Unset",
|
||||
"comments": "Comments",
|
||||
"comment": "Comment",
|
||||
"comment-placeholder": "Write Comment",
|
||||
"comment-placeholder": "",
|
||||
"comment-only": "Comment only",
|
||||
"comment-only-desc": "Can comment on cards only.",
|
||||
"comment-assigned-only": "Only Assigned Comment",
|
||||
@@ -808,6 +809,9 @@
|
||||
"modifiedAt": "Modified at",
|
||||
"verified": "Verified",
|
||||
"active": "Active",
|
||||
"active-team": "Active Team",
|
||||
"active-org": "Active Organization",
|
||||
"active-person": "Active Person",
|
||||
"card-received": "Received",
|
||||
"card-received-on": "Received on",
|
||||
"card-end": "End",
|
||||
@@ -1572,7 +1576,6 @@
|
||||
"run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?",
|
||||
"run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?",
|
||||
"restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore",
|
||||
|
||||
"migration-progress-title": "Board Migration in Progress",
|
||||
"migration-progress-overall": "Overall Progress",
|
||||
"migration-progress-current-step": "Current Step",
|
||||
@@ -1582,7 +1585,6 @@
|
||||
"steps": "steps",
|
||||
"view": "View",
|
||||
"has-swimlanes": "Has Swimlanes",
|
||||
|
||||
"step-analyze-board-structure": "Analyze Board Structure",
|
||||
"step-fix-orphaned-cards": "Fix Orphaned Cards",
|
||||
"step-convert-shared-lists": "Convert Shared Lists",
|
||||
@@ -1729,4 +1731,4 @@
|
||||
"logout": "Logout",
|
||||
"server": "Server",
|
||||
"protocol": "Protocol"
|
||||
}
|
||||
}
|
||||
@@ -189,6 +189,7 @@
|
||||
"board-private-info": "This board will be <strong>private</strong>.",
|
||||
"board-public-info": "This board will be <strong>public</strong>.",
|
||||
"board-drag-drop-reorder-or-click-open": "Drag and drop to reorder board icons. Click board icon to open board.",
|
||||
"board-open-and-move-between-remaining-and-workspaces": "Click board icon to open board. Drag board between __remaining__ and __workspaces__.",
|
||||
"boardChangeColorPopup-title": "Change Board Background",
|
||||
"boardChangeBackgroundImagePopup-title": "Change Background Image",
|
||||
"allBoardsChangeColorPopup-title": "Change color",
|
||||
@@ -345,7 +346,7 @@
|
||||
"unset-color": "Unset",
|
||||
"comments": "Comments",
|
||||
"comment": "Comment",
|
||||
"comment-placeholder": "Write Comment",
|
||||
"comment-placeholder": "",
|
||||
"comment-only": "Comment only",
|
||||
"comment-only-desc": "Can comment on cards only.",
|
||||
"comment-assigned-only": "Only Assigned Comment",
|
||||
@@ -808,6 +809,9 @@
|
||||
"modifiedAt": "Modified at",
|
||||
"verified": "Verified",
|
||||
"active": "Active",
|
||||
"active-team": "Active Team",
|
||||
"active-org": "Active Organization",
|
||||
"active-person": "Active Person",
|
||||
"card-received": "Received",
|
||||
"card-received-on": "Received on",
|
||||
"card-end": "End",
|
||||
@@ -1572,7 +1576,6 @@
|
||||
"run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?",
|
||||
"run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?",
|
||||
"restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore",
|
||||
|
||||
"migration-progress-title": "Board Migration in Progress",
|
||||
"migration-progress-overall": "Overall Progress",
|
||||
"migration-progress-current-step": "Current Step",
|
||||
@@ -1582,7 +1585,6 @@
|
||||
"steps": "steps",
|
||||
"view": "View",
|
||||
"has-swimlanes": "Has Swimlanes",
|
||||
|
||||
"step-analyze-board-structure": "Analyze Board Structure",
|
||||
"step-fix-orphaned-cards": "Fix Orphaned Cards",
|
||||
"step-convert-shared-lists": "Convert Shared Lists",
|
||||
@@ -1729,4 +1731,4 @@
|
||||
"logout": "Logout",
|
||||
"server": "Server",
|
||||
"protocol": "Protocol"
|
||||
}
|
||||
}
|
||||
@@ -189,6 +189,7 @@
|
||||
"board-private-info": "This board will be <strong>private</strong>.",
|
||||
"board-public-info": "This board will be <strong>public</strong>.",
|
||||
"board-drag-drop-reorder-or-click-open": "Drag and drop to reorder board icons. Click board icon to open board.",
|
||||
"board-open-and-move-between-remaining-and-workspaces": "Click board icon to open board. Drag board between __remaining__ and __workspaces__.",
|
||||
"boardChangeColorPopup-title": "Change Board Background",
|
||||
"boardChangeBackgroundImagePopup-title": "Change Background Image",
|
||||
"allBoardsChangeColorPopup-title": "Change color",
|
||||
@@ -345,7 +346,7 @@
|
||||
"unset-color": "Unset",
|
||||
"comments": "Comments",
|
||||
"comment": "Comment",
|
||||
"comment-placeholder": "Write Comment",
|
||||
"comment-placeholder": "",
|
||||
"comment-only": "Comment only",
|
||||
"comment-only-desc": "Can comment on cards only.",
|
||||
"comment-assigned-only": "Only Assigned Comment",
|
||||
@@ -808,6 +809,9 @@
|
||||
"modifiedAt": "Modified at",
|
||||
"verified": "Verified",
|
||||
"active": "Active",
|
||||
"active-team": "Active Team",
|
||||
"active-org": "Active Organization",
|
||||
"active-person": "Active Person",
|
||||
"card-received": "Received",
|
||||
"card-received-on": "Received on",
|
||||
"card-end": "End",
|
||||
@@ -1572,7 +1576,6 @@
|
||||
"run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?",
|
||||
"run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?",
|
||||
"restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore",
|
||||
|
||||
"migration-progress-title": "Board Migration in Progress",
|
||||
"migration-progress-overall": "Overall Progress",
|
||||
"migration-progress-current-step": "Current Step",
|
||||
@@ -1582,7 +1585,6 @@
|
||||
"steps": "steps",
|
||||
"view": "View",
|
||||
"has-swimlanes": "Has Swimlanes",
|
||||
|
||||
"step-analyze-board-structure": "Analyze Board Structure",
|
||||
"step-fix-orphaned-cards": "Fix Orphaned Cards",
|
||||
"step-convert-shared-lists": "Convert Shared Lists",
|
||||
@@ -1729,4 +1731,4 @@
|
||||
"logout": "Logout",
|
||||
"server": "Server",
|
||||
"protocol": "Protocol"
|
||||
}
|
||||
}
|
||||
@@ -189,6 +189,7 @@
|
||||
"board-private-info": "Toto tablo bude <strong>soukromé</strong>.",
|
||||
"board-public-info": "Toto tablo bude <strong>veřejné</strong>.",
|
||||
"board-drag-drop-reorder-or-click-open": "Přetažením změníte pořadí ikon tabel. Kliknutím otevřete tablo.",
|
||||
"board-open-and-move-between-remaining-and-workspaces": "Click board icon to open board. Drag board between __remaining__ and __workspaces__.",
|
||||
"boardChangeColorPopup-title": "Změnit pozadí tabla",
|
||||
"boardChangeBackgroundImagePopup-title": "Change Background Image",
|
||||
"allBoardsChangeColorPopup-title": "Změnit barvu",
|
||||
@@ -345,7 +346,7 @@
|
||||
"unset-color": "Nenastaveno",
|
||||
"comments": "Comments",
|
||||
"comment": "Komentář",
|
||||
"comment-placeholder": "Text komentáře",
|
||||
"comment-placeholder": "",
|
||||
"comment-only": "Pouze komentáře",
|
||||
"comment-only-desc": "Může přidávat komentáře pouze do karet.",
|
||||
"comment-assigned-only": "Only Assigned Comment",
|
||||
@@ -808,6 +809,9 @@
|
||||
"modifiedAt": "Modifikováno",
|
||||
"verified": "Ověřen",
|
||||
"active": "Aktivní",
|
||||
"active-team": "Active Team",
|
||||
"active-org": "Active Organization",
|
||||
"active-person": "Active Person",
|
||||
"card-received": "Přijato",
|
||||
"card-received-on": "Přijaté v",
|
||||
"card-end": "Konec",
|
||||
@@ -1572,7 +1576,6 @@
|
||||
"run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?",
|
||||
"run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?",
|
||||
"restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore",
|
||||
|
||||
"migration-progress-title": "Board Migration in Progress",
|
||||
"migration-progress-overall": "Overall Progress",
|
||||
"migration-progress-current-step": "Current Step",
|
||||
@@ -1582,7 +1585,6 @@
|
||||
"steps": "steps",
|
||||
"view": "View",
|
||||
"has-swimlanes": "Has Swimlanes",
|
||||
|
||||
"step-analyze-board-structure": "Analyze Board Structure",
|
||||
"step-fix-orphaned-cards": "Fix Orphaned Cards",
|
||||
"step-convert-shared-lists": "Convert Shared Lists",
|
||||
@@ -1729,4 +1731,4 @@
|
||||
"logout": "Logout",
|
||||
"server": "Server",
|
||||
"protocol": "Protocol"
|
||||
}
|
||||
}
|
||||
@@ -189,6 +189,7 @@
|
||||
"board-private-info": "Toto tablo bude <strong>soukromé</strong>.",
|
||||
"board-public-info": "Toto tablo bude <strong>veřejné</strong>.",
|
||||
"board-drag-drop-reorder-or-click-open": "Přetažením změníte pořadí ikon tabel. Kliknutím otevřete tablo.",
|
||||
"board-open-and-move-between-remaining-and-workspaces": "Click board icon to open board. Drag board between __remaining__ and __workspaces__.",
|
||||
"boardChangeColorPopup-title": "Změnit pozadí tabla",
|
||||
"boardChangeBackgroundImagePopup-title": "Změnit obrázek na pozadí",
|
||||
"allBoardsChangeColorPopup-title": "Změnit barvu",
|
||||
@@ -345,7 +346,7 @@
|
||||
"unset-color": "Nenastaveno",
|
||||
"comments": "Comments",
|
||||
"comment": "Komentář",
|
||||
"comment-placeholder": "Text komentáře",
|
||||
"comment-placeholder": "",
|
||||
"comment-only": "Pouze komentáře",
|
||||
"comment-only-desc": "Může přidávat komentáře pouze do karet.",
|
||||
"comment-assigned-only": "Only Assigned Comment",
|
||||
@@ -808,6 +809,9 @@
|
||||
"modifiedAt": "Modifikováno",
|
||||
"verified": "Ověřen",
|
||||
"active": "Aktivní",
|
||||
"active-team": "Active Team",
|
||||
"active-org": "Active Organization",
|
||||
"active-person": "Active Person",
|
||||
"card-received": "Přijato",
|
||||
"card-received-on": "Přijaté v",
|
||||
"card-end": "Konec",
|
||||
@@ -1572,7 +1576,6 @@
|
||||
"run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?",
|
||||
"run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?",
|
||||
"restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore",
|
||||
|
||||
"migration-progress-title": "Board Migration in Progress",
|
||||
"migration-progress-overall": "Overall Progress",
|
||||
"migration-progress-current-step": "Current Step",
|
||||
@@ -1582,7 +1585,6 @@
|
||||
"steps": "steps",
|
||||
"view": "View",
|
||||
"has-swimlanes": "Has Swimlanes",
|
||||
|
||||
"step-analyze-board-structure": "Analyze Board Structure",
|
||||
"step-fix-orphaned-cards": "Fix Orphaned Cards",
|
||||
"step-convert-shared-lists": "Convert Shared Lists",
|
||||
@@ -1729,4 +1731,4 @@
|
||||
"logout": "Logout",
|
||||
"server": "Server",
|
||||
"protocol": "Protocol"
|
||||
}
|
||||
}
|
||||
@@ -189,6 +189,7 @@
|
||||
"board-private-info": "This board will be <strong>private</strong>.",
|
||||
"board-public-info": "This board will be <strong>public</strong>.",
|
||||
"board-drag-drop-reorder-or-click-open": "Drag and drop to reorder board icons. Click board icon to open board.",
|
||||
"board-open-and-move-between-remaining-and-workspaces": "Click board icon to open board. Drag board between __remaining__ and __workspaces__.",
|
||||
"boardChangeColorPopup-title": "Change Board Background",
|
||||
"boardChangeBackgroundImagePopup-title": "Change Background Image",
|
||||
"allBoardsChangeColorPopup-title": "Change color",
|
||||
@@ -345,7 +346,7 @@
|
||||
"unset-color": "Unset",
|
||||
"comments": "Comments",
|
||||
"comment": "Comment",
|
||||
"comment-placeholder": "Write Comment",
|
||||
"comment-placeholder": "",
|
||||
"comment-only": "Comment only",
|
||||
"comment-only-desc": "Can comment on cards only.",
|
||||
"comment-assigned-only": "Only Assigned Comment",
|
||||
@@ -808,6 +809,9 @@
|
||||
"modifiedAt": "Modified at",
|
||||
"verified": "Verified",
|
||||
"active": "Active",
|
||||
"active-team": "Active Team",
|
||||
"active-org": "Active Organization",
|
||||
"active-person": "Active Person",
|
||||
"card-received": "Received",
|
||||
"card-received-on": "Received on",
|
||||
"card-end": "End",
|
||||
@@ -1572,7 +1576,6 @@
|
||||
"run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?",
|
||||
"run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?",
|
||||
"restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore",
|
||||
|
||||
"migration-progress-title": "Board Migration in Progress",
|
||||
"migration-progress-overall": "Overall Progress",
|
||||
"migration-progress-current-step": "Current Step",
|
||||
@@ -1582,7 +1585,6 @@
|
||||
"steps": "steps",
|
||||
"view": "View",
|
||||
"has-swimlanes": "Has Swimlanes",
|
||||
|
||||
"step-analyze-board-structure": "Analyze Board Structure",
|
||||
"step-fix-orphaned-cards": "Fix Orphaned Cards",
|
||||
"step-convert-shared-lists": "Convert Shared Lists",
|
||||
@@ -1729,4 +1731,4 @@
|
||||
"logout": "Logout",
|
||||
"server": "Server",
|
||||
"protocol": "Protocol"
|
||||
}
|
||||
}
|
||||
@@ -189,6 +189,7 @@
|
||||
"board-private-info": "This board will be <strong>private</strong>.",
|
||||
"board-public-info": "This board will be <strong>public</strong>.",
|
||||
"board-drag-drop-reorder-or-click-open": "Drag and drop to reorder board icons. Click board icon to open board.",
|
||||
"board-open-and-move-between-remaining-and-workspaces": "Click board icon to open board. Drag board between __remaining__ and __workspaces__.",
|
||||
"boardChangeColorPopup-title": "Change Board Background",
|
||||
"boardChangeBackgroundImagePopup-title": "Change Background Image",
|
||||
"allBoardsChangeColorPopup-title": "Change color",
|
||||
@@ -345,7 +346,7 @@
|
||||
"unset-color": "Unset",
|
||||
"comments": "Comments",
|
||||
"comment": "Comment",
|
||||
"comment-placeholder": "Write Comment",
|
||||
"comment-placeholder": "",
|
||||
"comment-only": "Comment only",
|
||||
"comment-only-desc": "Can comment on cards only.",
|
||||
"comment-assigned-only": "Only Assigned Comment",
|
||||
@@ -808,6 +809,9 @@
|
||||
"modifiedAt": "Modified at",
|
||||
"verified": "Verified",
|
||||
"active": "Active",
|
||||
"active-team": "Active Team",
|
||||
"active-org": "Active Organization",
|
||||
"active-person": "Active Person",
|
||||
"card-received": "Received",
|
||||
"card-received-on": "Received on",
|
||||
"card-end": "End",
|
||||
@@ -1572,7 +1576,6 @@
|
||||
"run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?",
|
||||
"run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?",
|
||||
"restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore",
|
||||
|
||||
"migration-progress-title": "Board Migration in Progress",
|
||||
"migration-progress-overall": "Overall Progress",
|
||||
"migration-progress-current-step": "Current Step",
|
||||
@@ -1582,7 +1585,6 @@
|
||||
"steps": "steps",
|
||||
"view": "View",
|
||||
"has-swimlanes": "Has Swimlanes",
|
||||
|
||||
"step-analyze-board-structure": "Analyze Board Structure",
|
||||
"step-fix-orphaned-cards": "Fix Orphaned Cards",
|
||||
"step-convert-shared-lists": "Convert Shared Lists",
|
||||
@@ -1729,4 +1731,4 @@
|
||||
"logout": "Logout",
|
||||
"server": "Server",
|
||||
"protocol": "Protocol"
|
||||
}
|
||||
}
|
||||
@@ -189,6 +189,7 @@
|
||||
"board-private-info": "Denne tavle vil være <strong>privat</strong>.",
|
||||
"board-public-info": "Denne tavle vil være <strong>offentlig</strong>.",
|
||||
"board-drag-drop-reorder-or-click-open": "Drag and drop to reorder board icons. Click board icon to open board.",
|
||||
"board-open-and-move-between-remaining-and-workspaces": "Click board icon to open board. Drag board between __remaining__ and __workspaces__.",
|
||||
"boardChangeColorPopup-title": "Skift tavlens baggrund",
|
||||
"boardChangeBackgroundImagePopup-title": "Skift baggrundsbillede",
|
||||
"allBoardsChangeColorPopup-title": "Skift farve",
|
||||
@@ -345,7 +346,7 @@
|
||||
"unset-color": "Nulstil",
|
||||
"comments": "Comments",
|
||||
"comment": "Kommentér",
|
||||
"comment-placeholder": "Skriv kommentar",
|
||||
"comment-placeholder": "",
|
||||
"comment-only": "Kun kommentarer",
|
||||
"comment-only-desc": "Kan kun kommentere på kort.",
|
||||
"comment-assigned-only": "Only Assigned Comment",
|
||||
@@ -808,6 +809,9 @@
|
||||
"modifiedAt": "Modified at",
|
||||
"verified": "Verificeret",
|
||||
"active": "Aktiv",
|
||||
"active-team": "Active Team",
|
||||
"active-org": "Active Organization",
|
||||
"active-person": "Active Person",
|
||||
"card-received": "Modtaget",
|
||||
"card-received-on": "Modtaget per",
|
||||
"card-end": "Slut",
|
||||
@@ -1572,7 +1576,6 @@
|
||||
"run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?",
|
||||
"run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?",
|
||||
"restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore",
|
||||
|
||||
"migration-progress-title": "Board Migration in Progress",
|
||||
"migration-progress-overall": "Overall Progress",
|
||||
"migration-progress-current-step": "Current Step",
|
||||
@@ -1582,7 +1585,6 @@
|
||||
"steps": "steps",
|
||||
"view": "View",
|
||||
"has-swimlanes": "Has Swimlanes",
|
||||
|
||||
"step-analyze-board-structure": "Analyze Board Structure",
|
||||
"step-fix-orphaned-cards": "Fix Orphaned Cards",
|
||||
"step-convert-shared-lists": "Convert Shared Lists",
|
||||
@@ -1729,4 +1731,4 @@
|
||||
"logout": "Logout",
|
||||
"server": "Server",
|
||||
"protocol": "Protocol"
|
||||
}
|
||||
}
|
||||
@@ -189,6 +189,7 @@
|
||||
"board-private-info": "Dieses Board wird <strong>privat</strong> sein.",
|
||||
"board-public-info": "Dieses Board wird <strong>öffentlich</strong> sein.",
|
||||
"board-drag-drop-reorder-or-click-open": "Benutze Drag-and-Drop, um Board-Icons neu anzuordnen. Klicke auf ein Board-Icon, um das Board zu öffnen.",
|
||||
"board-open-and-move-between-remaining-and-workspaces": "Click board icon to open board. Drag board between __remaining__ and __workspaces__.",
|
||||
"boardChangeColorPopup-title": "Farbe des Boards ändern",
|
||||
"boardChangeBackgroundImagePopup-title": "Change Background Image",
|
||||
"allBoardsChangeColorPopup-title": "Farbe ändern",
|
||||
@@ -345,7 +346,7 @@
|
||||
"unset-color": "Nicht festgelegt",
|
||||
"comments": "Comments",
|
||||
"comment": "Kommentar",
|
||||
"comment-placeholder": "Kommentar schreiben",
|
||||
"comment-placeholder": "",
|
||||
"comment-only": "Nur Kommentare",
|
||||
"comment-only-desc": "Kann Karten nur kommentieren.",
|
||||
"comment-assigned-only": "Only Assigned Comment",
|
||||
@@ -808,6 +809,9 @@
|
||||
"modifiedAt": "Geändert am",
|
||||
"verified": "Geprüft",
|
||||
"active": "Aktiv",
|
||||
"active-team": "Active Team",
|
||||
"active-org": "Active Organization",
|
||||
"active-person": "Active Person",
|
||||
"card-received": "Empfangen",
|
||||
"card-received-on": "Empfangen am",
|
||||
"card-end": "Ende",
|
||||
@@ -1572,7 +1576,6 @@
|
||||
"run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?",
|
||||
"run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?",
|
||||
"restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore",
|
||||
|
||||
"migration-progress-title": "Board Migration in Progress",
|
||||
"migration-progress-overall": "Overall Progress",
|
||||
"migration-progress-current-step": "Current Step",
|
||||
@@ -1582,7 +1585,6 @@
|
||||
"steps": "steps",
|
||||
"view": "View",
|
||||
"has-swimlanes": "Has Swimlanes",
|
||||
|
||||
"step-analyze-board-structure": "Analyze Board Structure",
|
||||
"step-fix-orphaned-cards": "Fix Orphaned Cards",
|
||||
"step-convert-shared-lists": "Convert Shared Lists",
|
||||
@@ -1729,4 +1731,4 @@
|
||||
"logout": "Logout",
|
||||
"server": "Server",
|
||||
"protocol": "Protocol"
|
||||
}
|
||||
}
|
||||
@@ -189,6 +189,7 @@
|
||||
"board-private-info": "Dieses Board wird <strong>privat</strong> sein.",
|
||||
"board-public-info": "Dieses Board wird <strong>öffentlich zugänglich</strong> sein.",
|
||||
"board-drag-drop-reorder-or-click-open": "Ziehen und Fallenlassen um die Board-Icons neu anzuordnen. Ein Klick auf das Board-Icon öffnet das zugehörige Board.",
|
||||
"board-open-and-move-between-remaining-and-workspaces": "Click board icon to open board. Drag board between __remaining__ and __workspaces__.",
|
||||
"boardChangeColorPopup-title": "Farbe des Boards ändern",
|
||||
"boardChangeBackgroundImagePopup-title": "Change Background Image",
|
||||
"allBoardsChangeColorPopup-title": "Farbe ändern",
|
||||
@@ -345,7 +346,7 @@
|
||||
"unset-color": "Nicht festgelegt",
|
||||
"comments": "Comments",
|
||||
"comment": "Kommentar speichern",
|
||||
"comment-placeholder": "Kommentar schreiben",
|
||||
"comment-placeholder": "",
|
||||
"comment-only": "Nur Kommentare",
|
||||
"comment-only-desc": "Kann Karten nur kommentieren.",
|
||||
"comment-assigned-only": "Only Assigned Comment",
|
||||
@@ -808,6 +809,9 @@
|
||||
"modifiedAt": "Geändert am",
|
||||
"verified": "Geprüft",
|
||||
"active": "Aktiv",
|
||||
"active-team": "Active Team",
|
||||
"active-org": "Active Organization",
|
||||
"active-person": "Active Person",
|
||||
"card-received": "Empfangen",
|
||||
"card-received-on": "Empfangen am",
|
||||
"card-end": "Ende",
|
||||
@@ -1572,7 +1576,6 @@
|
||||
"run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?",
|
||||
"run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?",
|
||||
"restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore",
|
||||
|
||||
"migration-progress-title": "Board Migration in Progress",
|
||||
"migration-progress-overall": "Overall Progress",
|
||||
"migration-progress-current-step": "Current Step",
|
||||
@@ -1582,7 +1585,6 @@
|
||||
"steps": "steps",
|
||||
"view": "View",
|
||||
"has-swimlanes": "Has Swimlanes",
|
||||
|
||||
"step-analyze-board-structure": "Analyze Board Structure",
|
||||
"step-fix-orphaned-cards": "Fix Orphaned Cards",
|
||||
"step-convert-shared-lists": "Convert Shared Lists",
|
||||
@@ -1729,4 +1731,4 @@
|
||||
"logout": "Logout",
|
||||
"server": "Server",
|
||||
"protocol": "Protocol"
|
||||
}
|
||||
}
|
||||
@@ -78,21 +78,21 @@
|
||||
"activity-deleteComment": "löschte Kommentar %s",
|
||||
"activity-receivedDate": "hat Empfangsdatum zu %s geändert auf %s",
|
||||
"activity-startDate": "hat Startdatum zu %s geändert auf %s",
|
||||
"allboards.starred": "Starred",
|
||||
"allboards.starred": "Markiert",
|
||||
"allboards.templates": "Vorlagen",
|
||||
"allboards.remaining": "Remaining",
|
||||
"allboards.workspaces": "Workspaces",
|
||||
"allboards.add-workspace": "Add Workspace",
|
||||
"allboards.add-workspace-prompt": "Workspace name",
|
||||
"allboards.add-subworkspace": "Add Subworkspace",
|
||||
"allboards.add-subworkspace-prompt": "Subworkspace name",
|
||||
"allboards.edit-workspace": "Edit workspace",
|
||||
"allboards.edit-workspace-name": "Workspace name",
|
||||
"allboards.edit-workspace-icon": "Workspace icon (markdown)",
|
||||
"allboards.remaining": "Verbleibend",
|
||||
"allboards.workspaces": "Arbeitsplatz",
|
||||
"allboards.add-workspace": "Arbeitsplatz hinzufügen",
|
||||
"allboards.add-workspace-prompt": "Name des Arbeitsplatzes",
|
||||
"allboards.add-subworkspace": "Teilarbeitsplatz hinzufügen",
|
||||
"allboards.add-subworkspace-prompt": "Name des Teilarbeitsplatz",
|
||||
"allboards.edit-workspace": "Arbeitsplatz ändern",
|
||||
"allboards.edit-workspace-name": "Name des Arbeitsplatzes",
|
||||
"allboards.edit-workspace-icon": "Arbeitsplatzsymbol (markdown)",
|
||||
"allboards.workspace-menu": "Workspace menu",
|
||||
"workspace-settings": "Workspace Settings",
|
||||
"workspaceActionsPopup-title": "Workspace Settings",
|
||||
"allboards.workspace-color": "Color",
|
||||
"workspace-settings": "Arbeitsplatz-Einstellungen",
|
||||
"workspaceActionsPopup-title": "Arbeitsplatz-Einstellungen",
|
||||
"allboards.workspace-color": "Farbe",
|
||||
"allboards.delete-workspace-confirm": "Are you sure you want to delete this workspace?",
|
||||
"allboards.delete-workspace-confirm-check": "Confirm workspace deletion",
|
||||
"multi-selection-active": "Click checkboxes to select boards",
|
||||
@@ -189,6 +189,7 @@
|
||||
"board-private-info": "Dieses Board wird <strong>privat</strong> sein.",
|
||||
"board-public-info": "Dieses Board wird <strong>öffentlich</strong> sein.",
|
||||
"board-drag-drop-reorder-or-click-open": "Benutze Drag-and-Drop, um Board-Icons neu anzuordnen. Klicke auf ein Board-Icon, um das Board zu öffnen.",
|
||||
"board-open-and-move-between-remaining-and-workspaces": "Click board icon to open board. Drag board between __remaining__ and __workspaces__.",
|
||||
"boardChangeColorPopup-title": "Farbe des Boards ändern",
|
||||
"boardChangeBackgroundImagePopup-title": "Hintergrundbild ändern",
|
||||
"allBoardsChangeColorPopup-title": "Farbe ändern",
|
||||
@@ -215,8 +216,8 @@
|
||||
"board-view-gantt": "Gantt",
|
||||
"board-view-lists": "Listen",
|
||||
"bucket-example": "Like \"Bucket List\" for example",
|
||||
"calendar-previous-month-label": "Previous Month",
|
||||
"calendar-next-month-label": "Next Month",
|
||||
"calendar-previous-month-label": "Letzter Monat",
|
||||
"calendar-next-month-label": "Nächster Monat",
|
||||
"cancel": "Abbrechen",
|
||||
"card-archived": "Diese Karte wurde ins Archiv verschoben",
|
||||
"board-archived": "Dieses Board wurde ins Archiv verschoben.",
|
||||
@@ -228,7 +229,7 @@
|
||||
"card-archive-suggest-cancel": "Sie können die Karte später aus dem Archiv wiederherstellen.",
|
||||
"list-archive-pop": "List will not be visible on the board after archiving.",
|
||||
"list-archive-suggest": "You can later restore the list from the Archive in Board Settings.",
|
||||
"listArchivePopup-title": "Archive List?",
|
||||
"listArchivePopup-title": "Liste archivieren?",
|
||||
"swimlane-archive-pop": "Swimlane will not be visible on the board after archiving.",
|
||||
"swimlane-archive-suggest": "You can later restore the swimlane from the Archive in Board Settings.",
|
||||
"swimlaneArchivePopup-title": "Archive Swimlane?",
|
||||
@@ -345,7 +346,7 @@
|
||||
"unset-color": "Nicht festgelegt",
|
||||
"comments": "Kommentare",
|
||||
"comment": "Kommentar speichern",
|
||||
"comment-placeholder": "Kommentar schreiben",
|
||||
"comment-placeholder": "",
|
||||
"comment-only": "Nur Kommentare",
|
||||
"comment-only-desc": "Kann Karten nur kommentieren.",
|
||||
"comment-assigned-only": "Only Assigned Comment",
|
||||
@@ -372,7 +373,7 @@
|
||||
"linkCardPopup-title": "Karte verknüpfen",
|
||||
"searchElementPopup-title": "Suche",
|
||||
"copyCardPopup-title": "Karte kopieren",
|
||||
"copyListPopup-title": "Copy List",
|
||||
"copyListPopup-title": "Liste kopieren",
|
||||
"copyManyCardsPopup-title": "Kopiere die Vorlage zu mehreren Karten",
|
||||
"copyManyCardsPopup-instructions": "Titel und Beschreibungen der Zielkarten im folgenden JSON-Format",
|
||||
"copyManyCardsPopup-format": "[ {\"title\": \"Titel der ersten Karte\", \"description\":\"Beschreibung der ersten Karte\"}, {\"title\":\"Titel der zweiten Karte\",\"description\":\"Beschreibung der zweiten Karte\"},{\"title\":\"Titel der letzten Karte\",\"description\":\"Beschreibung der letzten Karte\"} ]",
|
||||
@@ -399,9 +400,9 @@
|
||||
"custom-fields": "Benutzerdefinierte Felder",
|
||||
"date": "Datum",
|
||||
"date-format": "Date Format",
|
||||
"date-format-yyyy-mm-dd": "YYYY-MM-DD",
|
||||
"date-format-dd-mm-yyyy": "DD-MM-YYYY",
|
||||
"date-format-mm-dd-yyyy": "MM-DD-YYYY",
|
||||
"date-format-yyyy-mm-dd": "JJJJ-MM-TT",
|
||||
"date-format-dd-mm-yyyy": "TT-MM-JJJJ",
|
||||
"date-format-mm-dd-yyyy": "MM-TT-JJJJ",
|
||||
"decline": "Ablehnen",
|
||||
"default-avatar": "Standard Profilbild",
|
||||
"delete": "Löschen",
|
||||
@@ -427,7 +428,7 @@
|
||||
"editNotificationPopup-title": "Benachrichtigung ändern",
|
||||
"editProfilePopup-title": "Profil ändern",
|
||||
"email": "E-Mail",
|
||||
"email-address": "Email Address",
|
||||
"email-address": "E-Mail Adresse",
|
||||
"email-enrollAccount-subject": "Ihr Benutzerkonto auf __siteName__ wurde erstellt",
|
||||
"email-enrollAccount-text": "Hallo __user__,\n\num den Dienst nutzen zu können, klicken Sie bitte auf folgenden Link:\n\n__url__\n\nDanke.",
|
||||
"email-fail": "Senden der E-Mail fehlgeschlagen",
|
||||
@@ -475,10 +476,10 @@
|
||||
"export-card-field-people": "People (Creator, Owner, Members, Assignees)",
|
||||
"export-card-field-board-info": "Board Info (Board, List, Swimlane)",
|
||||
"export-card-field-dates": "Dates (Created, Received, Start, Due, End)",
|
||||
"export-card-attachment-filename": "Filename",
|
||||
"export-card-attachment-filename": "Dateiname",
|
||||
"export-card-attachment-size": "Größe",
|
||||
"export-card-attachment-type": "Typ",
|
||||
"export-card-attachment-uploaded-by": "Uploaded By",
|
||||
"export-card-attachment-uploaded-by": "Hochgeladen von",
|
||||
"export-card-attachment-uploaded-at": "Uploaded At",
|
||||
"export-card-attachment-image-previews": "Image Previews",
|
||||
"export-card-excel-no-disk-space": "Cannot export to Excel: not enough free disk space",
|
||||
@@ -808,6 +809,9 @@
|
||||
"modifiedAt": "Geändert am",
|
||||
"verified": "Geprüft",
|
||||
"active": "Aktiv",
|
||||
"active-team": "Active Team",
|
||||
"active-org": "Active Organization",
|
||||
"active-person": "Active Person",
|
||||
"card-received": "Empfangen",
|
||||
"card-received-on": "Empfangen am",
|
||||
"card-end": "Ende",
|
||||
@@ -1090,9 +1094,9 @@
|
||||
"my-cards": "Meine Karten",
|
||||
"card": "Karte",
|
||||
"today": "Today",
|
||||
"day": "Day",
|
||||
"week": "Week",
|
||||
"month": "Month",
|
||||
"day": "Tag",
|
||||
"week": "Woche",
|
||||
"month": "Monat",
|
||||
"list": "Liste",
|
||||
"board": "Board",
|
||||
"context-separator": "/",
|
||||
@@ -1153,7 +1157,7 @@
|
||||
"operator-debug": "Debug",
|
||||
"operator-org": "Organisation",
|
||||
"operator-team": "Team",
|
||||
"operator-title": "title",
|
||||
"operator-title": "Titel",
|
||||
"operator-description": "Beschreibung",
|
||||
"operator-customfield": "customfield",
|
||||
"operator-attachment-text": "Anhang",
|
||||
@@ -1460,7 +1464,7 @@
|
||||
"cron-error-time": "Zeit",
|
||||
"cron-error-message": "Error Message",
|
||||
"cron-error-details": "Details",
|
||||
"cron-clear-errors": "Clear All Errors",
|
||||
"cron-clear-errors": "Alle Fehlermeldungen löschen",
|
||||
"cron-retry-failed": "Retry Failed Migrations",
|
||||
"cron-resume-paused": "Resume Paused Migrations",
|
||||
"cron-errors-cleared": "All errors cleared successfully",
|
||||
@@ -1473,7 +1477,7 @@
|
||||
"filesystem-path-description": "Base path for file storage",
|
||||
"gridfs-enabled": "GridFS Enabled",
|
||||
"gridfs-enabled-description": "Use MongoDB GridFS for file storage",
|
||||
"all-migrations": "All Migrations",
|
||||
"all-migrations": "Alle Migrations",
|
||||
"select-migration": "Select Migration",
|
||||
"start": "Start",
|
||||
"pause": "Pause",
|
||||
@@ -1486,7 +1490,7 @@
|
||||
"migration-progress": "Migration Progress",
|
||||
"migration-start-failed": "Failed to start migrations",
|
||||
"migration-started": "Migrations started successfully",
|
||||
"migration-not-needed": "No migration needed",
|
||||
"migration-not-needed": "Keine Migration notwendig",
|
||||
"migration-status": "Migration Status",
|
||||
"migration-stop-confirm": "Are you sure you want to stop all migrations?",
|
||||
"migration-stop-failed": "Failed to stop migrations",
|
||||
@@ -1540,13 +1544,13 @@
|
||||
"card-show-lists-on-minicard": "Show Lists on Minicard",
|
||||
"comprehensive-board-migration": "Comprehensive Board Migration",
|
||||
"comprehensive-board-migration-description": "Performs comprehensive checks and fixes for board data integrity, including list ordering, card positions, and swimlane structure.",
|
||||
"delete-duplicate-empty-lists-migration": "Delete Duplicate Empty Lists",
|
||||
"delete-duplicate-empty-lists-migration": "Lösche doppelte leere Listen",
|
||||
"delete-duplicate-empty-lists-migration-description": "Safely deletes empty duplicate lists. Only removes lists that have no cards AND have another list with the same title that contains cards.",
|
||||
"lost-cards": "Lost Cards",
|
||||
"lost-cards-list": "Restored Items",
|
||||
"restore-lost-cards-migration": "Restore Lost Cards",
|
||||
"restore-lost-cards-migration-description": "Finds and restores cards and lists with missing swimlaneId or listId. Creates a 'Lost Cards' swimlane to make all lost items visible again.",
|
||||
"restore-all-archived-migration": "Restore All Archived",
|
||||
"restore-all-archived-migration": "Alles Archivierte wiederherstellen",
|
||||
"restore-all-archived-migration-description": "Restores all archived swimlanes, lists, and cards. Automatically fixes any missing swimlaneId or listId to make items visible.",
|
||||
"fix-missing-lists-migration": "Fix Missing Lists",
|
||||
"fix-missing-lists-migration-description": "Detects and repairs missing or corrupted lists in the board structure.",
|
||||
@@ -1556,33 +1560,31 @@
|
||||
"fix-all-file-urls-migration-description": "Updates all file attachment URLs on this board to use the correct storage backend and fixes broken file references.",
|
||||
"migration-needed": "Migration Needed",
|
||||
"migration-complete": "Abgeschlossen",
|
||||
"migration-running": "Running...",
|
||||
"migration-successful": "Migration completed successfully",
|
||||
"migration-failed": "Migration failed",
|
||||
"migrations": "Migrations",
|
||||
"migration-running": "Läuft...",
|
||||
"migration-successful": "Migration erfolgreich abgeschlossen",
|
||||
"migration-failed": "Migration fehlgeschlagen",
|
||||
"migrations": "Migrationen",
|
||||
"migrations-admin-only": "Only board administrators can run migrations",
|
||||
"migrations-description": "Run data integrity checks and repairs for this board. Each migration can be executed individually.",
|
||||
"no-issues-found": "No issues found",
|
||||
"run-migration": "Run Migration",
|
||||
"run-comprehensive-migration-confirm": "This will perform a comprehensive migration to check and fix board data integrity. This may take a few moments. Continue?",
|
||||
"run-delete-duplicate-empty-lists-migration-confirm": "This will first convert any shared lists to per-swimlane lists, then delete empty lists that have a duplicate list with the same title containing cards. Only truly redundant empty lists will be removed. Continue?",
|
||||
"run-comprehensive-migration-confirm": "Dadurch wird eine umfassende Migration durchgeführt, um die Integrität der Board-Daten zu überprüfen und gegebenenfalls zu korrigieren. Dies kann einen Moment dauern. Möchten Sie fortfahren?",
|
||||
"run-delete-duplicate-empty-lists-migration-confirm": "Dadurch werden zunächst alle gemeinsam genutzten Listen in Listen pro Swimlane umgewandelt und anschließend leere Listen gelöscht, für die es eine doppelte Liste mit demselben Titel gibt, die Karten enthält. Es werden nur wirklich überflüssige leere Listen entfernt. Möchten Sie fortfahren?",
|
||||
"run-restore-lost-cards-migration-confirm": "This will create a 'Lost Cards' swimlane and restore all cards and lists with missing swimlaneId or listId. This only affects non-archived items. Continue?",
|
||||
"run-restore-all-archived-migration-confirm": "This will restore ALL archived swimlanes, lists, and cards, making them visible again. Any items with missing IDs will be automatically fixed. This cannot be easily undone. Continue?",
|
||||
"run-fix-missing-lists-migration-confirm": "This will detect and repair missing or corrupted lists in the board structure. Continue?",
|
||||
"run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?",
|
||||
"run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?",
|
||||
"restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore",
|
||||
|
||||
"migration-progress-title": "Board Migration in Progress",
|
||||
"migration-progress-overall": "Overall Progress",
|
||||
"migration-progress-current-step": "Current Step",
|
||||
"migration-progress-current-step": "Aktueller Schritt",
|
||||
"migration-progress-status": "Status",
|
||||
"migration-progress-details": "Details",
|
||||
"migration-progress-note": "Please wait while we migrate your board to the latest structure...",
|
||||
"steps": "steps",
|
||||
"view": "View",
|
||||
"steps": "Schritte",
|
||||
"view": "Ansicht",
|
||||
"has-swimlanes": "Has Swimlanes",
|
||||
|
||||
"step-analyze-board-structure": "Analyze Board Structure",
|
||||
"step-fix-orphaned-cards": "Fix Orphaned Cards",
|
||||
"step-convert-shared-lists": "Convert Shared Lists",
|
||||
@@ -1594,11 +1596,11 @@
|
||||
"step-create-missing-lists": "Create Missing Lists",
|
||||
"step-update-cards": "Update Cards",
|
||||
"step-finalize": "Finalize",
|
||||
"step-delete-duplicate-empty-lists": "Delete Duplicate Empty Lists",
|
||||
"step-delete-duplicate-empty-lists": "Lösche doppelte leere Listen",
|
||||
"step-ensure-lost-cards-swimlane": "Ensure Lost Cards Swimlane",
|
||||
"step-restore-lists": "Restore Lists",
|
||||
"step-restore-cards": "Restore Cards",
|
||||
"step-restore-swimlanes": "Restore Swimlanes",
|
||||
"step-restore-lists": "Listen wiederherstellen",
|
||||
"step-restore-cards": "Karten wiederherstellen",
|
||||
"step-restore-swimlanes": "Swimlanes wiederherstellen",
|
||||
"step-fix-missing-ids": "Fix Missing IDs",
|
||||
"step-scan-users": "Checking board member avatars",
|
||||
"step-scan-files": "Checking board file attachments",
|
||||
@@ -1697,10 +1699,10 @@
|
||||
"unmigrated-boards": "Unmigrated Boards",
|
||||
"weight": "Gewicht",
|
||||
"cron": "Zeitplan",
|
||||
"current-step": "Current Step",
|
||||
"current-step": "Aktueller Schritt",
|
||||
"otp": "OTP Code",
|
||||
"create-account": "Create Account",
|
||||
"already-account": "Already have an account? Sign in",
|
||||
"create-account": "Konto erstellen",
|
||||
"already-account": "Hast du schon ein Konto? Anmelden",
|
||||
"available-repositories": "Available Repositories",
|
||||
"repositories": "Repositories",
|
||||
"repository": "Repository",
|
||||
@@ -1712,21 +1714,21 @@
|
||||
"upload-repository": "Upload/Update Repository",
|
||||
"api-endpoints": "API Endpoints",
|
||||
"sign-in-to-upload": "Sign In to upload repositories",
|
||||
"account-locked": "Account is temporarily locked due to too many failed login attempts. Please try again later.",
|
||||
"account-locked": "Das Konto wurde aufgrund zu vieler fehlgeschlagener Anmeldeversuche vorübergehend gesperrt. Bitte versuche es später erneut.",
|
||||
"otp-required": "OTP code required",
|
||||
"invalid-credentials": "Invalid username or password",
|
||||
"username-password-required": "Username and password are required",
|
||||
"password-mismatch": "Passwords do not match",
|
||||
"username-too-short": "Username must be at least 3 characters",
|
||||
"user-exists": "User already exists",
|
||||
"invalid-credentials": "Ungültiger Benutzername oder Passwort",
|
||||
"username-password-required": "Benutzername und Passwort sind erforderlich",
|
||||
"password-mismatch": "Die Passwörter stimmen nicht überein",
|
||||
"username-too-short": "Der Benutzername muss mindestens 3 Zeichen lang sein",
|
||||
"user-exists": "Der Benutzer existiert bereits",
|
||||
"account-created": "Account created! You can now sign in.",
|
||||
"account-creation-failed": "Failed to create account",
|
||||
"login": "Login",
|
||||
"confirm": "Bestätigen",
|
||||
"error": "Error",
|
||||
"file": "File",
|
||||
"error": "Fehler",
|
||||
"file": "Datei",
|
||||
"log": "Log",
|
||||
"logout": "Logout",
|
||||
"server": "Server",
|
||||
"protocol": "Protocol"
|
||||
}
|
||||
"protocol": "Protokoll"
|
||||
}
|
||||
@@ -189,6 +189,7 @@
|
||||
"board-private-info": "Dieses Board wird <strong>privat</strong> sein.",
|
||||
"board-public-info": "Dieses Board wird <strong>öffentlich</strong> sein.",
|
||||
"board-drag-drop-reorder-or-click-open": "Benutze Drag-and-Drop, um Board-Icons neu anzuordnen. Klicke auf ein Board-Icon, um das Board zu öffnen.",
|
||||
"board-open-and-move-between-remaining-and-workspaces": "Click board icon to open board. Drag board between __remaining__ and __workspaces__.",
|
||||
"boardChangeColorPopup-title": "Farbe des Boards ändern",
|
||||
"boardChangeBackgroundImagePopup-title": "Hintergrundbild ändern",
|
||||
"allBoardsChangeColorPopup-title": "Farbe ändern",
|
||||
@@ -345,7 +346,7 @@
|
||||
"unset-color": "Nicht festgelegt",
|
||||
"comments": "Kommentare",
|
||||
"comment": "Kommentar speichern",
|
||||
"comment-placeholder": "Kommentar schreiben",
|
||||
"comment-placeholder": "",
|
||||
"comment-only": "Nur Kommentare",
|
||||
"comment-only-desc": "Kann Karten nur kommentieren.",
|
||||
"comment-assigned-only": "Nur zugewiesener Kommentar",
|
||||
@@ -808,6 +809,9 @@
|
||||
"modifiedAt": "Geändert am",
|
||||
"verified": "Geprüft",
|
||||
"active": "Aktiv",
|
||||
"active-team": "Active Team",
|
||||
"active-org": "Active Organization",
|
||||
"active-person": "Active Person",
|
||||
"card-received": "Empfangen",
|
||||
"card-received-on": "Empfangen am",
|
||||
"card-end": "Ende",
|
||||
@@ -1572,7 +1576,6 @@
|
||||
"run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?",
|
||||
"run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?",
|
||||
"restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore",
|
||||
|
||||
"migration-progress-title": "Board Migration in Progress",
|
||||
"migration-progress-overall": "Gesamtfortschritt",
|
||||
"migration-progress-current-step": "Current Step",
|
||||
@@ -1582,7 +1585,6 @@
|
||||
"steps": "steps",
|
||||
"view": "View",
|
||||
"has-swimlanes": "Has Swimlanes",
|
||||
|
||||
"step-analyze-board-structure": "Analyze Board Structure",
|
||||
"step-fix-orphaned-cards": "Fix Orphaned Cards",
|
||||
"step-convert-shared-lists": "Convert Shared Lists",
|
||||
@@ -1729,4 +1731,4 @@
|
||||
"logout": "Logout",
|
||||
"server": "Server",
|
||||
"protocol": "Protocol"
|
||||
}
|
||||
}
|
||||
@@ -189,6 +189,7 @@
|
||||
"board-private-info": "Αυτός ο πίνακας θα είναι <strong>κρυφός</strong>.",
|
||||
"board-public-info": "Αυτός ο πίνακας θα είναι <strong>δημόσιος</strong>.",
|
||||
"board-drag-drop-reorder-or-click-open": "Drag and drop to reorder board icons. Click board icon to open board.",
|
||||
"board-open-and-move-between-remaining-and-workspaces": "Click board icon to open board. Drag board between __remaining__ and __workspaces__.",
|
||||
"boardChangeColorPopup-title": "Αλλαγή Φόντου Πίνακα",
|
||||
"boardChangeBackgroundImagePopup-title": "Change Background Image",
|
||||
"allBoardsChangeColorPopup-title": "Αλλαγή χρώματος",
|
||||
@@ -345,7 +346,7 @@
|
||||
"unset-color": "Unset",
|
||||
"comments": "Comments",
|
||||
"comment": "Σχόλιο",
|
||||
"comment-placeholder": "Συγγραφή Σχολίου",
|
||||
"comment-placeholder": "",
|
||||
"comment-only": "Μόνο σχόλιο",
|
||||
"comment-only-desc": "Μπορεί μόνο να σχολιάζει σε κάρτες.",
|
||||
"comment-assigned-only": "Only Assigned Comment",
|
||||
@@ -808,6 +809,9 @@
|
||||
"modifiedAt": "Modified at",
|
||||
"verified": "Επιβεβαιώθηκε",
|
||||
"active": "Ενεργό",
|
||||
"active-team": "Active Team",
|
||||
"active-org": "Active Organization",
|
||||
"active-person": "Active Person",
|
||||
"card-received": "Ελήφθη",
|
||||
"card-received-on": "Ελήφθη στις",
|
||||
"card-end": "Τέλος",
|
||||
@@ -1572,7 +1576,6 @@
|
||||
"run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?",
|
||||
"run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?",
|
||||
"restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore",
|
||||
|
||||
"migration-progress-title": "Board Migration in Progress",
|
||||
"migration-progress-overall": "Overall Progress",
|
||||
"migration-progress-current-step": "Current Step",
|
||||
@@ -1582,7 +1585,6 @@
|
||||
"steps": "steps",
|
||||
"view": "View",
|
||||
"has-swimlanes": "Has Swimlanes",
|
||||
|
||||
"step-analyze-board-structure": "Analyze Board Structure",
|
||||
"step-fix-orphaned-cards": "Fix Orphaned Cards",
|
||||
"step-convert-shared-lists": "Convert Shared Lists",
|
||||
@@ -1729,4 +1731,4 @@
|
||||
"logout": "Logout",
|
||||
"server": "Server",
|
||||
"protocol": "Protocol"
|
||||
}
|
||||
}
|
||||
@@ -189,6 +189,7 @@
|
||||
"board-private-info": "Αυτός ο πίνακας θα είναι <strong>κρυφός</strong>.",
|
||||
"board-public-info": "Αυτός ο πίνακας θα είναι <strong>δημόσιος</strong>.",
|
||||
"board-drag-drop-reorder-or-click-open": "Drag and drop to reorder board icons. Click board icon to open board.",
|
||||
"board-open-and-move-between-remaining-and-workspaces": "Click board icon to open board. Drag board between __remaining__ and __workspaces__.",
|
||||
"boardChangeColorPopup-title": "Αλλαγή Φόντου Πίνακα",
|
||||
"boardChangeBackgroundImagePopup-title": "Change Background Image",
|
||||
"allBoardsChangeColorPopup-title": "Αλλαγή χρώματος",
|
||||
@@ -345,7 +346,7 @@
|
||||
"unset-color": "Unset",
|
||||
"comments": "Comments",
|
||||
"comment": "Σχόλιο",
|
||||
"comment-placeholder": "Συγγραφή Σχολίου",
|
||||
"comment-placeholder": "",
|
||||
"comment-only": "Μόνο σχόλιο",
|
||||
"comment-only-desc": "Μπορεί μόνο να σχολιάζει σε κάρτες.",
|
||||
"comment-assigned-only": "Only Assigned Comment",
|
||||
@@ -808,6 +809,9 @@
|
||||
"modifiedAt": "Modified at",
|
||||
"verified": "Επιβεβαιώθηκε",
|
||||
"active": "Ενεργό",
|
||||
"active-team": "Active Team",
|
||||
"active-org": "Active Organization",
|
||||
"active-person": "Active Person",
|
||||
"card-received": "Ελήφθη",
|
||||
"card-received-on": "Ελήφθη στις",
|
||||
"card-end": "Τέλος",
|
||||
@@ -1572,7 +1576,6 @@
|
||||
"run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?",
|
||||
"run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?",
|
||||
"restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore",
|
||||
|
||||
"migration-progress-title": "Board Migration in Progress",
|
||||
"migration-progress-overall": "Overall Progress",
|
||||
"migration-progress-current-step": "Current Step",
|
||||
@@ -1582,7 +1585,6 @@
|
||||
"steps": "steps",
|
||||
"view": "View",
|
||||
"has-swimlanes": "Has Swimlanes",
|
||||
|
||||
"step-analyze-board-structure": "Analyze Board Structure",
|
||||
"step-fix-orphaned-cards": "Fix Orphaned Cards",
|
||||
"step-convert-shared-lists": "Convert Shared Lists",
|
||||
@@ -1729,4 +1731,4 @@
|
||||
"logout": "Logout",
|
||||
"server": "Server",
|
||||
"protocol": "Protocol"
|
||||
}
|
||||
}
|
||||
@@ -189,6 +189,7 @@
|
||||
"board-private-info": "This board will be <strong>private</strong>.",
|
||||
"board-public-info": "This board will be <strong>public</strong>.",
|
||||
"board-drag-drop-reorder-or-click-open": "Drag and drop to reorder board icons. Click board icon to open board.",
|
||||
"board-open-and-move-between-remaining-and-workspaces": "Click board icon to open board. Drag board between __remaining__ and __workspaces__.",
|
||||
"boardChangeColorPopup-title": "Change Board Background",
|
||||
"boardChangeBackgroundImagePopup-title": "Change Background Image",
|
||||
"allBoardsChangeColorPopup-title": "Change color",
|
||||
@@ -345,7 +346,7 @@
|
||||
"unset-color": "Unset",
|
||||
"comments": "Comments",
|
||||
"comment": "Comment",
|
||||
"comment-placeholder": "Write Comment",
|
||||
"comment-placeholder": "",
|
||||
"comment-only": "Comment only",
|
||||
"comment-only-desc": "Can comment on cards only.",
|
||||
"comment-assigned-only": "Only Assigned Comment",
|
||||
@@ -808,6 +809,9 @@
|
||||
"modifiedAt": "Modified at",
|
||||
"verified": "Verified",
|
||||
"active": "Active",
|
||||
"active-team": "Active Team",
|
||||
"active-org": "Active Organization",
|
||||
"active-person": "Active Person",
|
||||
"card-received": "Received",
|
||||
"card-received-on": "Received on",
|
||||
"card-end": "End",
|
||||
@@ -1572,7 +1576,6 @@
|
||||
"run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?",
|
||||
"run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?",
|
||||
"restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore",
|
||||
|
||||
"migration-progress-title": "Board Migration in Progress",
|
||||
"migration-progress-overall": "Overall Progress",
|
||||
"migration-progress-current-step": "Current Step",
|
||||
@@ -1582,7 +1585,6 @@
|
||||
"steps": "steps",
|
||||
"view": "View",
|
||||
"has-swimlanes": "Has Swimlanes",
|
||||
|
||||
"step-analyze-board-structure": "Analyze Board Structure",
|
||||
"step-fix-orphaned-cards": "Fix Orphaned Cards",
|
||||
"step-convert-shared-lists": "Convert Shared Lists",
|
||||
@@ -1729,4 +1731,4 @@
|
||||
"logout": "Logout",
|
||||
"server": "Server",
|
||||
"protocol": "Protocol"
|
||||
}
|
||||
}
|
||||
@@ -189,6 +189,7 @@
|
||||
"board-private-info": "This board will be <strong>private</strong>.",
|
||||
"board-public-info": "This board will be <strong>public</strong>.",
|
||||
"board-drag-drop-reorder-or-click-open": "Drag and drop to reorder board icons. Click board icon to open board.",
|
||||
"board-open-and-move-between-remaining-and-workspaces": "Click board icon to open board. Drag board between __remaining__ and __workspaces__.",
|
||||
"boardChangeColorPopup-title": "Change Board Background",
|
||||
"boardChangeBackgroundImagePopup-title": "Change Background Image",
|
||||
"allBoardsChangeColorPopup-title": "Change color",
|
||||
@@ -345,7 +346,7 @@
|
||||
"unset-color": "Unset",
|
||||
"comments": "Comments",
|
||||
"comment": "Comment",
|
||||
"comment-placeholder": "Write Comment",
|
||||
"comment-placeholder": "",
|
||||
"comment-only": "Comment only",
|
||||
"comment-only-desc": "Can comment on cards only.",
|
||||
"comment-assigned-only": "Only Assigned Comment",
|
||||
@@ -808,6 +809,9 @@
|
||||
"modifiedAt": "Modified at",
|
||||
"verified": "Verified",
|
||||
"active": "Active",
|
||||
"active-team": "Active Team",
|
||||
"active-org": "Active Organization",
|
||||
"active-person": "Active Person",
|
||||
"card-received": "Received",
|
||||
"card-received-on": "Received on",
|
||||
"card-end": "End",
|
||||
@@ -1572,7 +1576,6 @@
|
||||
"run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?",
|
||||
"run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?",
|
||||
"restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore",
|
||||
|
||||
"migration-progress-title": "Board Migration in Progress",
|
||||
"migration-progress-overall": "Overall Progress",
|
||||
"migration-progress-current-step": "Current Step",
|
||||
@@ -1582,7 +1585,6 @@
|
||||
"steps": "steps",
|
||||
"view": "View",
|
||||
"has-swimlanes": "Has Swimlanes",
|
||||
|
||||
"step-analyze-board-structure": "Analyze Board Structure",
|
||||
"step-fix-orphaned-cards": "Fix Orphaned Cards",
|
||||
"step-convert-shared-lists": "Convert Shared Lists",
|
||||
@@ -1729,4 +1731,4 @@
|
||||
"logout": "Logout",
|
||||
"server": "Server",
|
||||
"protocol": "Protocol"
|
||||
}
|
||||
}
|
||||
@@ -189,6 +189,7 @@
|
||||
"board-private-info": "This board will be <strong>private</strong>.",
|
||||
"board-public-info": "This board will be <strong>public</strong>.",
|
||||
"board-drag-drop-reorder-or-click-open": "Drag and drop to reorder board icons. Click board icon to open board.",
|
||||
"board-open-and-move-between-remaining-and-workspaces": "Click board icon to open board. Drag board between __remaining__ and __workspaces__.",
|
||||
"boardChangeColorPopup-title": "Change Board Background",
|
||||
"boardChangeBackgroundImagePopup-title": "Change Background Image",
|
||||
"allBoardsChangeColorPopup-title": "Change color",
|
||||
@@ -345,7 +346,7 @@
|
||||
"unset-color": "Unset",
|
||||
"comments": "Comments",
|
||||
"comment": "Comment",
|
||||
"comment-placeholder": "Write Comment",
|
||||
"comment-placeholder": "",
|
||||
"comment-only": "Comment only",
|
||||
"comment-only-desc": "Can comment on cards only.",
|
||||
"comment-assigned-only": "Only Assigned Comment",
|
||||
@@ -808,6 +809,9 @@
|
||||
"modifiedAt": "Modified at",
|
||||
"verified": "Verified",
|
||||
"active": "Active",
|
||||
"active-team": "Active Team",
|
||||
"active-org": "Active Organization",
|
||||
"active-person": "Active Person",
|
||||
"card-received": "Received",
|
||||
"card-received-on": "Received on",
|
||||
"card-end": "End",
|
||||
@@ -1572,7 +1576,6 @@
|
||||
"run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?",
|
||||
"run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?",
|
||||
"restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore",
|
||||
|
||||
"migration-progress-title": "Board Migration in Progress",
|
||||
"migration-progress-overall": "Overall Progress",
|
||||
"migration-progress-current-step": "Current Step",
|
||||
@@ -1582,7 +1585,6 @@
|
||||
"steps": "steps",
|
||||
"view": "View",
|
||||
"has-swimlanes": "Has Swimlanes",
|
||||
|
||||
"step-analyze-board-structure": "Analyze Board Structure",
|
||||
"step-fix-orphaned-cards": "Fix Orphaned Cards",
|
||||
"step-convert-shared-lists": "Convert Shared Lists",
|
||||
@@ -1729,4 +1731,4 @@
|
||||
"logout": "Logout",
|
||||
"server": "Server",
|
||||
"protocol": "Protocol"
|
||||
}
|
||||
}
|
||||
@@ -189,6 +189,7 @@
|
||||
"board-private-info": "This board will be <strong>private</strong>.",
|
||||
"board-public-info": "This board will be <strong>public</strong>.",
|
||||
"board-drag-drop-reorder-or-click-open": "Drag and drop to reorder board icons. Click board icon to open board.",
|
||||
"board-open-and-move-between-remaining-and-workspaces": "Click board icon to open board. Drag board between __remaining__ and __workspaces__.",
|
||||
"boardChangeColorPopup-title": "Change Board Background",
|
||||
"boardChangeBackgroundImagePopup-title": "Change Background Image",
|
||||
"allBoardsChangeColorPopup-title": "Change color",
|
||||
@@ -345,7 +346,7 @@
|
||||
"unset-color": "Unset",
|
||||
"comments": "Comments",
|
||||
"comment": "Comment",
|
||||
"comment-placeholder": "Write Comment",
|
||||
"comment-placeholder": "",
|
||||
"comment-only": "Comment only",
|
||||
"comment-only-desc": "Can comment on cards only.",
|
||||
"comment-assigned-only": "Only Assigned Comment",
|
||||
@@ -808,6 +809,9 @@
|
||||
"modifiedAt": "Modified at",
|
||||
"verified": "Verified",
|
||||
"active": "Active",
|
||||
"active-team": "Active Team",
|
||||
"active-org": "Active Organization",
|
||||
"active-person": "Active Person",
|
||||
"card-received": "Received",
|
||||
"card-received-on": "Received on",
|
||||
"card-end": "End",
|
||||
@@ -1572,7 +1576,6 @@
|
||||
"run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?",
|
||||
"run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?",
|
||||
"restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore",
|
||||
|
||||
"migration-progress-title": "Board Migration in Progress",
|
||||
"migration-progress-overall": "Overall Progress",
|
||||
"migration-progress-current-step": "Current Step",
|
||||
@@ -1582,7 +1585,6 @@
|
||||
"steps": "steps",
|
||||
"view": "View",
|
||||
"has-swimlanes": "Has Swimlanes",
|
||||
|
||||
"step-analyze-board-structure": "Analyze Board Structure",
|
||||
"step-fix-orphaned-cards": "Fix Orphaned Cards",
|
||||
"step-convert-shared-lists": "Convert Shared Lists",
|
||||
@@ -1729,4 +1731,4 @@
|
||||
"logout": "Logout",
|
||||
"server": "Server",
|
||||
"protocol": "Protocol"
|
||||
}
|
||||
}
|
||||
@@ -189,6 +189,7 @@
|
||||
"board-private-info": "This board will be <strong>private</strong>.",
|
||||
"board-public-info": "This board will be <strong>public</strong>.",
|
||||
"board-drag-drop-reorder-or-click-open": "Drag and drop to reorder board icons. Click board icon to open board.",
|
||||
"board-open-and-move-between-remaining-and-workspaces": "Click board icon to open board. Drag board between __remaining__ and __workspaces__.",
|
||||
"boardChangeColorPopup-title": "Change Board Background",
|
||||
"boardChangeBackgroundImagePopup-title": "Change Background Image",
|
||||
"allBoardsChangeColorPopup-title": "Change color",
|
||||
@@ -345,7 +346,7 @@
|
||||
"unset-color": "Unset",
|
||||
"comments": "Comments",
|
||||
"comment": "Comment",
|
||||
"comment-placeholder": "Write Comment",
|
||||
"comment-placeholder": "",
|
||||
"comment-only": "Comment only",
|
||||
"comment-only-desc": "Can comment on cards only.",
|
||||
"comment-assigned-only": "Only Assigned Comment",
|
||||
@@ -808,6 +809,9 @@
|
||||
"modifiedAt": "Modified at",
|
||||
"verified": "Verified",
|
||||
"active": "Active",
|
||||
"active-team": "Active Team",
|
||||
"active-org": "Active Organization",
|
||||
"active-person": "Active Person",
|
||||
"card-received": "Received",
|
||||
"card-received-on": "Received on",
|
||||
"card-end": "End",
|
||||
@@ -1572,7 +1576,6 @@
|
||||
"run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?",
|
||||
"run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?",
|
||||
"restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore",
|
||||
|
||||
"migration-progress-title": "Board Migration in Progress",
|
||||
"migration-progress-overall": "Overall Progress",
|
||||
"migration-progress-current-step": "Current Step",
|
||||
@@ -1582,7 +1585,6 @@
|
||||
"steps": "steps",
|
||||
"view": "View",
|
||||
"has-swimlanes": "Has Swimlanes",
|
||||
|
||||
"step-analyze-board-structure": "Analyze Board Structure",
|
||||
"step-fix-orphaned-cards": "Fix Orphaned Cards",
|
||||
"step-convert-shared-lists": "Convert Shared Lists",
|
||||
@@ -1729,4 +1731,4 @@
|
||||
"logout": "Logout",
|
||||
"server": "Server",
|
||||
"protocol": "Protocol"
|
||||
}
|
||||
}
|
||||
@@ -189,6 +189,7 @@
|
||||
"board-private-info": "This board will be <strong>private</strong>.",
|
||||
"board-public-info": "This board will be <strong>public</strong>.",
|
||||
"board-drag-drop-reorder-or-click-open": "Drag and drop to reorder board icons. Click board icon to open board.",
|
||||
"board-open-and-move-between-remaining-and-workspaces": "Click board icon to open board. Drag board between __remaining__ and __workspaces__.",
|
||||
"boardChangeColorPopup-title": "Change Board Background",
|
||||
"boardChangeBackgroundImagePopup-title": "Change Background Image",
|
||||
"allBoardsChangeColorPopup-title": "Change color",
|
||||
@@ -345,7 +346,7 @@
|
||||
"unset-color": "Unset",
|
||||
"comments": "Comments",
|
||||
"comment": "Comment",
|
||||
"comment-placeholder": "Write Comment",
|
||||
"comment-placeholder": "",
|
||||
"comment-only": "Comment only",
|
||||
"comment-only-desc": "Can comment on cards only.",
|
||||
"comment-assigned-only": "Only Assigned Comment",
|
||||
@@ -808,6 +809,9 @@
|
||||
"modifiedAt": "Modified at",
|
||||
"verified": "Verified",
|
||||
"active": "Active",
|
||||
"active-team": "Active Team",
|
||||
"active-org": "Active Organization",
|
||||
"active-person": "Active Person",
|
||||
"card-received": "Received",
|
||||
"card-received-on": "Received on",
|
||||
"card-end": "End",
|
||||
@@ -1572,7 +1576,6 @@
|
||||
"run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?",
|
||||
"run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?",
|
||||
"restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore",
|
||||
|
||||
"migration-progress-title": "Board Migration in Progress",
|
||||
"migration-progress-overall": "Overall Progress",
|
||||
"migration-progress-current-step": "Current Step",
|
||||
@@ -1582,7 +1585,6 @@
|
||||
"steps": "steps",
|
||||
"view": "View",
|
||||
"has-swimlanes": "Has Swimlanes",
|
||||
|
||||
"step-analyze-board-structure": "Analyze Board Structure",
|
||||
"step-fix-orphaned-cards": "Fix Orphaned Cards",
|
||||
"step-convert-shared-lists": "Convert Shared Lists",
|
||||
@@ -1729,4 +1731,4 @@
|
||||
"logout": "Logout",
|
||||
"server": "Server",
|
||||
"protocol": "Protocol"
|
||||
}
|
||||
}
|
||||
@@ -189,6 +189,7 @@
|
||||
"board-private-info": "This board will be <strong>private</strong>.",
|
||||
"board-public-info": "This board will be <strong>public</strong>.",
|
||||
"board-drag-drop-reorder-or-click-open": "Drag and drop to reorder board icons. Click board icon to open board.",
|
||||
"board-open-and-move-between-remaining-and-workspaces": "Click board icon to open board. Drag board between __remaining__ and __workspaces__.",
|
||||
"boardChangeColorPopup-title": "Change Board Background",
|
||||
"boardChangeBackgroundImagePopup-title": "Change Background Image",
|
||||
"allBoardsChangeColorPopup-title": "Change color",
|
||||
@@ -345,7 +346,7 @@
|
||||
"unset-color": "Unset",
|
||||
"comments": "Comments",
|
||||
"comment": "Comment",
|
||||
"comment-placeholder": "Write Comment",
|
||||
"comment-placeholder": "",
|
||||
"comment-only": "Comment only",
|
||||
"comment-only-desc": "Can comment on cards only.",
|
||||
"comment-assigned-only": "Only Assigned Comment",
|
||||
@@ -808,6 +809,9 @@
|
||||
"modifiedAt": "Modified at",
|
||||
"verified": "Verified",
|
||||
"active": "Active",
|
||||
"active-team": "Active Team",
|
||||
"active-org": "Active Organization",
|
||||
"active-person": "Active Person",
|
||||
"card-received": "Received",
|
||||
"card-received-on": "Received on",
|
||||
"card-end": "End",
|
||||
@@ -1572,7 +1576,6 @@
|
||||
"run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?",
|
||||
"run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?",
|
||||
"restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore",
|
||||
|
||||
"migration-progress-title": "Board Migration in Progress",
|
||||
"migration-progress-overall": "Overall Progress",
|
||||
"migration-progress-current-step": "Current Step",
|
||||
@@ -1582,7 +1585,6 @@
|
||||
"steps": "steps",
|
||||
"view": "View",
|
||||
"has-swimlanes": "Has Swimlanes",
|
||||
|
||||
"step-analyze-board-structure": "Analyze Board Structure",
|
||||
"step-fix-orphaned-cards": "Fix Orphaned Cards",
|
||||
"step-convert-shared-lists": "Convert Shared Lists",
|
||||
@@ -1729,4 +1731,4 @@
|
||||
"logout": "Logout",
|
||||
"server": "Server",
|
||||
"protocol": "Protocol"
|
||||
}
|
||||
}
|
||||
@@ -189,6 +189,7 @@
|
||||
"board-private-info": "This board will be <strong>private</strong>.",
|
||||
"board-public-info": "This board will be <strong>public</strong>.",
|
||||
"board-drag-drop-reorder-or-click-open": "Drag and drop to reorder board icons. Click board icon to open board.",
|
||||
"board-open-and-move-between-remaining-and-workspaces": "Click board icon to open board. Drag board between __remaining__ and __workspaces__.",
|
||||
"boardChangeColorPopup-title": "Change Board Background",
|
||||
"boardChangeBackgroundImagePopup-title": "Change Background Image",
|
||||
"allBoardsChangeColorPopup-title": "Change color",
|
||||
@@ -345,7 +346,7 @@
|
||||
"unset-color": "Unset",
|
||||
"comments": "Comments",
|
||||
"comment": "Comment",
|
||||
"comment-placeholder": "Write Comment",
|
||||
"comment-placeholder": "",
|
||||
"comment-only": "Comment only",
|
||||
"comment-only-desc": "Can comment on cards only.",
|
||||
"comment-assigned-only": "Only Assigned Comment",
|
||||
@@ -808,6 +809,9 @@
|
||||
"modifiedAt": "Modified at",
|
||||
"verified": "Verified",
|
||||
"active": "Active",
|
||||
"active-team": "Active Team",
|
||||
"active-org": "Active Organization",
|
||||
"active-person": "Active Person",
|
||||
"card-received": "Received",
|
||||
"card-received-on": "Received on",
|
||||
"card-end": "End",
|
||||
@@ -1572,7 +1576,6 @@
|
||||
"run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?",
|
||||
"run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?",
|
||||
"restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore",
|
||||
|
||||
"migration-progress-title": "Board Migration in Progress",
|
||||
"migration-progress-overall": "Overall Progress",
|
||||
"migration-progress-current-step": "Current Step",
|
||||
@@ -1582,7 +1585,6 @@
|
||||
"steps": "steps",
|
||||
"view": "View",
|
||||
"has-swimlanes": "Has Swimlanes",
|
||||
|
||||
"step-analyze-board-structure": "Analyze Board Structure",
|
||||
"step-fix-orphaned-cards": "Fix Orphaned Cards",
|
||||
"step-convert-shared-lists": "Convert Shared Lists",
|
||||
@@ -1729,4 +1731,4 @@
|
||||
"logout": "Logout",
|
||||
"server": "Server",
|
||||
"protocol": "Protocol"
|
||||
}
|
||||
}
|
||||
@@ -189,6 +189,7 @@
|
||||
"board-private-info": "This board will be <strong>private</strong>.",
|
||||
"board-public-info": "This board will be <strong>public</strong>.",
|
||||
"board-drag-drop-reorder-or-click-open": "Drag and drop to reorder board icons. Click board icon to open board.",
|
||||
"board-open-and-move-between-remaining-and-workspaces": "Click board icon to open board. Drag board between __remaining__ and __workspaces__.",
|
||||
"boardChangeColorPopup-title": "Change Board Background",
|
||||
"boardChangeBackgroundImagePopup-title": "Change Background Image",
|
||||
"allBoardsChangeColorPopup-title": "Change color",
|
||||
@@ -345,7 +346,7 @@
|
||||
"unset-color": "Unset",
|
||||
"comments": "Comments",
|
||||
"comment": "Comment",
|
||||
"comment-placeholder": "Write Comment",
|
||||
"comment-placeholder": "",
|
||||
"comment-only": "Comment only",
|
||||
"comment-only-desc": "Can comment on cards only.",
|
||||
"comment-assigned-only": "Only Assigned Comment",
|
||||
@@ -808,6 +809,9 @@
|
||||
"modifiedAt": "Modified at",
|
||||
"verified": "Verified",
|
||||
"active": "Active",
|
||||
"active-team": "Active Team",
|
||||
"active-org": "Active Organization",
|
||||
"active-person": "Active Person",
|
||||
"card-received": "Received",
|
||||
"card-received-on": "Received on",
|
||||
"card-end": "End",
|
||||
@@ -1572,7 +1576,6 @@
|
||||
"run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?",
|
||||
"run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?",
|
||||
"restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore",
|
||||
|
||||
"migration-progress-title": "Board Migration in Progress",
|
||||
"migration-progress-overall": "Overall Progress",
|
||||
"migration-progress-current-step": "Current Step",
|
||||
@@ -1582,7 +1585,6 @@
|
||||
"steps": "steps",
|
||||
"view": "View",
|
||||
"has-swimlanes": "Has Swimlanes",
|
||||
|
||||
"step-analyze-board-structure": "Analyze Board Structure",
|
||||
"step-fix-orphaned-cards": "Fix Orphaned Cards",
|
||||
"step-convert-shared-lists": "Convert Shared Lists",
|
||||
@@ -1729,4 +1731,4 @@
|
||||
"logout": "Logout",
|
||||
"server": "Server",
|
||||
"protocol": "Protocol"
|
||||
}
|
||||
}
|
||||
@@ -189,6 +189,7 @@
|
||||
"board-private-info": "This board will be <strong>private</strong>.",
|
||||
"board-public-info": "This board will be <strong>public</strong>.",
|
||||
"board-drag-drop-reorder-or-click-open": "Drag and drop to reorder board icons. Click board icon to open board.",
|
||||
"board-open-and-move-between-remaining-and-workspaces": "Click board icon to open board. Drag board between __remaining__ and __workspaces__.",
|
||||
"boardChangeColorPopup-title": "Change Board Background",
|
||||
"boardChangeBackgroundImagePopup-title": "Change Background Image",
|
||||
"allBoardsChangeColorPopup-title": "Change color",
|
||||
@@ -345,7 +346,7 @@
|
||||
"unset-color": "Unset",
|
||||
"comments": "Comments",
|
||||
"comment": "Comment",
|
||||
"comment-placeholder": "Write Comment",
|
||||
"comment-placeholder": "",
|
||||
"comment-only": "Comment only",
|
||||
"comment-only-desc": "Can comment on cards only.",
|
||||
"comment-assigned-only": "Only Assigned Comment",
|
||||
@@ -808,6 +809,9 @@
|
||||
"modifiedAt": "Modified at",
|
||||
"verified": "Verified",
|
||||
"active": "Active",
|
||||
"active-team": "Active Team",
|
||||
"active-org": "Active Organization",
|
||||
"active-person": "Active Person",
|
||||
"card-received": "Received",
|
||||
"card-received-on": "Received on",
|
||||
"card-end": "End",
|
||||
@@ -1572,7 +1576,6 @@
|
||||
"run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?",
|
||||
"run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?",
|
||||
"restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore",
|
||||
|
||||
"migration-progress-title": "Board Migration in Progress",
|
||||
"migration-progress-overall": "Overall Progress",
|
||||
"migration-progress-current-step": "Current Step",
|
||||
@@ -1582,7 +1585,6 @@
|
||||
"steps": "steps",
|
||||
"view": "View",
|
||||
"has-swimlanes": "Has Swimlanes",
|
||||
|
||||
"step-analyze-board-structure": "Analyze Board Structure",
|
||||
"step-fix-orphaned-cards": "Fix Orphaned Cards",
|
||||
"step-convert-shared-lists": "Convert Shared Lists",
|
||||
@@ -1729,4 +1731,4 @@
|
||||
"logout": "Logout",
|
||||
"server": "Server",
|
||||
"protocol": "Protocol"
|
||||
}
|
||||
}
|
||||
@@ -189,6 +189,7 @@
|
||||
"board-private-info": "This board will be <strong>private</strong>.",
|
||||
"board-public-info": "This board will be <strong>public</strong>.",
|
||||
"board-drag-drop-reorder-or-click-open": "Drag and drop to reorder board icons. Click board icon to open board.",
|
||||
"board-open-and-move-between-remaining-and-workspaces": "Click board icon to open board. Drag board between __remaining__ and __workspaces__.",
|
||||
"boardChangeColorPopup-title": "Change Board Background",
|
||||
"boardChangeBackgroundImagePopup-title": "Change Background Image",
|
||||
"allBoardsChangeColorPopup-title": "Change color",
|
||||
@@ -345,7 +346,7 @@
|
||||
"unset-color": "Unset",
|
||||
"comments": "Comments",
|
||||
"comment": "Comment",
|
||||
"comment-placeholder": "Write Comment",
|
||||
"comment-placeholder": "",
|
||||
"comment-only": "Comment only",
|
||||
"comment-only-desc": "Can comment on cards only.",
|
||||
"comment-assigned-only": "Only Assigned Comment",
|
||||
@@ -808,6 +809,9 @@
|
||||
"modifiedAt": "Modified at",
|
||||
"verified": "Verified",
|
||||
"active": "Active",
|
||||
"active-team": "Active Team",
|
||||
"active-org": "Active Organization",
|
||||
"active-person": "Active Person",
|
||||
"card-received": "Received",
|
||||
"card-received-on": "Received on",
|
||||
"card-end": "End",
|
||||
@@ -1572,7 +1576,6 @@
|
||||
"run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?",
|
||||
"run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?",
|
||||
"restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore",
|
||||
|
||||
"migration-progress-title": "Board Migration in Progress",
|
||||
"migration-progress-overall": "Overall Progress",
|
||||
"migration-progress-current-step": "Current Step",
|
||||
@@ -1582,7 +1585,6 @@
|
||||
"steps": "steps",
|
||||
"view": "View",
|
||||
"has-swimlanes": "Has Swimlanes",
|
||||
|
||||
"step-analyze-board-structure": "Analyze Board Structure",
|
||||
"step-fix-orphaned-cards": "Fix Orphaned Cards",
|
||||
"step-convert-shared-lists": "Convert Shared Lists",
|
||||
@@ -1729,4 +1731,4 @@
|
||||
"logout": "Logout",
|
||||
"server": "Server",
|
||||
"protocol": "Protocol"
|
||||
}
|
||||
}
|
||||
@@ -189,6 +189,7 @@
|
||||
"board-private-info": "This board will be <strong>private</strong>.",
|
||||
"board-public-info": "This board will be <strong>public</strong>.",
|
||||
"board-drag-drop-reorder-or-click-open": "Drag and drop to reorder board icons. Click board icon to open board.",
|
||||
"board-open-and-move-between-remaining-and-workspaces": "Click board icon to open board. Drag board between __remaining__ and __workspaces__.",
|
||||
"boardChangeColorPopup-title": "Change Board Background",
|
||||
"boardChangeBackgroundImagePopup-title": "Change Background Image",
|
||||
"allBoardsChangeColorPopup-title": "Change color",
|
||||
@@ -345,7 +346,7 @@
|
||||
"unset-color": "Unset",
|
||||
"comments": "Comments",
|
||||
"comment": "Comment",
|
||||
"comment-placeholder": "Write Comment",
|
||||
"comment-placeholder": "",
|
||||
"comment-only": "Comment only",
|
||||
"comment-only-desc": "Can comment on cards only.",
|
||||
"comment-assigned-only": "Only Assigned Comment",
|
||||
@@ -808,6 +809,9 @@
|
||||
"modifiedAt": "Modified at",
|
||||
"verified": "Verified",
|
||||
"active": "Active",
|
||||
"active-team": "Active Team",
|
||||
"active-org": "Active Organization",
|
||||
"active-person": "Active Person",
|
||||
"card-received": "Received",
|
||||
"card-received-on": "Received on",
|
||||
"card-end": "End",
|
||||
@@ -1572,7 +1576,6 @@
|
||||
"run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?",
|
||||
"run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?",
|
||||
"restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore",
|
||||
|
||||
"migration-progress-title": "Board Migration in Progress",
|
||||
"migration-progress-overall": "Overall Progress",
|
||||
"migration-progress-current-step": "Current Step",
|
||||
@@ -1582,7 +1585,6 @@
|
||||
"steps": "steps",
|
||||
"view": "View",
|
||||
"has-swimlanes": "Has Swimlanes",
|
||||
|
||||
"step-analyze-board-structure": "Analyze Board Structure",
|
||||
"step-fix-orphaned-cards": "Fix Orphaned Cards",
|
||||
"step-convert-shared-lists": "Convert Shared Lists",
|
||||
@@ -1729,4 +1731,4 @@
|
||||
"logout": "Logout",
|
||||
"server": "Server",
|
||||
"protocol": "Protocol"
|
||||
}
|
||||
}
|
||||
@@ -189,6 +189,7 @@
|
||||
"board-private-info": "This board will be <strong>private</strong>.",
|
||||
"board-public-info": "This board will be <strong>public</strong>.",
|
||||
"board-drag-drop-reorder-or-click-open": "Drag and drop to reorder board icons. Click board icon to open board.",
|
||||
"board-open-and-move-between-remaining-and-workspaces": "Click board icon to open board. Drag board between __remaining__ and __workspaces__.",
|
||||
"boardChangeColorPopup-title": "Change Board Background",
|
||||
"boardChangeBackgroundImagePopup-title": "Change Background Image",
|
||||
"allBoardsChangeColorPopup-title": "Ŝanĝi koloron",
|
||||
@@ -345,7 +346,7 @@
|
||||
"unset-color": "Unset",
|
||||
"comments": "Komentoj",
|
||||
"comment": "Komento",
|
||||
"comment-placeholder": "Write Comment",
|
||||
"comment-placeholder": "",
|
||||
"comment-only": "Comment only",
|
||||
"comment-only-desc": "Can comment on cards only.",
|
||||
"comment-assigned-only": "Only Assigned Comment",
|
||||
@@ -808,6 +809,9 @@
|
||||
"modifiedAt": "Modified at",
|
||||
"verified": "Verified",
|
||||
"active": "Active",
|
||||
"active-team": "Active Team",
|
||||
"active-org": "Active Organization",
|
||||
"active-person": "Active Person",
|
||||
"card-received": "Received",
|
||||
"card-received-on": "Received on",
|
||||
"card-end": "End",
|
||||
@@ -1572,7 +1576,6 @@
|
||||
"run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?",
|
||||
"run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?",
|
||||
"restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore",
|
||||
|
||||
"migration-progress-title": "Board Migration in Progress",
|
||||
"migration-progress-overall": "Overall Progress",
|
||||
"migration-progress-current-step": "Current Step",
|
||||
@@ -1582,7 +1585,6 @@
|
||||
"steps": "steps",
|
||||
"view": "View",
|
||||
"has-swimlanes": "Has Swimlanes",
|
||||
|
||||
"step-analyze-board-structure": "Analyze Board Structure",
|
||||
"step-fix-orphaned-cards": "Fix Orphaned Cards",
|
||||
"step-convert-shared-lists": "Convert Shared Lists",
|
||||
@@ -1729,4 +1731,4 @@
|
||||
"logout": "Logout",
|
||||
"server": "Server",
|
||||
"protocol": "Protocol"
|
||||
}
|
||||
}
|
||||
@@ -189,6 +189,7 @@
|
||||
"board-private-info": "Este tablero va a ser <strong>privado</strong>.",
|
||||
"board-public-info": "Este tablero va a ser <strong>público</strong>.",
|
||||
"board-drag-drop-reorder-or-click-open": "Drag and drop to reorder board icons. Click board icon to open board.",
|
||||
"board-open-and-move-between-remaining-and-workspaces": "Click board icon to open board. Drag board between __remaining__ and __workspaces__.",
|
||||
"boardChangeColorPopup-title": "Cambiar Fondo del Tablero",
|
||||
"boardChangeBackgroundImagePopup-title": "Change Background Image",
|
||||
"allBoardsChangeColorPopup-title": "Cambiar color",
|
||||
@@ -345,7 +346,7 @@
|
||||
"unset-color": "Deseleccionado",
|
||||
"comments": "Comments",
|
||||
"comment": "Comentario",
|
||||
"comment-placeholder": "Comentar",
|
||||
"comment-placeholder": "",
|
||||
"comment-only": "Comentar solamente",
|
||||
"comment-only-desc": "Puede comentar en tarjetas solamente.",
|
||||
"comment-assigned-only": "Only Assigned Comment",
|
||||
@@ -808,6 +809,9 @@
|
||||
"modifiedAt": "Modified at",
|
||||
"verified": "Verificado",
|
||||
"active": "Activo",
|
||||
"active-team": "Active Team",
|
||||
"active-org": "Active Organization",
|
||||
"active-person": "Active Person",
|
||||
"card-received": "Recibido",
|
||||
"card-received-on": "Recibido en",
|
||||
"card-end": "Termino",
|
||||
@@ -1572,7 +1576,6 @@
|
||||
"run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?",
|
||||
"run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?",
|
||||
"restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore",
|
||||
|
||||
"migration-progress-title": "Board Migration in Progress",
|
||||
"migration-progress-overall": "Overall Progress",
|
||||
"migration-progress-current-step": "Current Step",
|
||||
@@ -1582,7 +1585,6 @@
|
||||
"steps": "steps",
|
||||
"view": "View",
|
||||
"has-swimlanes": "Has Swimlanes",
|
||||
|
||||
"step-analyze-board-structure": "Analyze Board Structure",
|
||||
"step-fix-orphaned-cards": "Fix Orphaned Cards",
|
||||
"step-convert-shared-lists": "Convert Shared Lists",
|
||||
@@ -1729,4 +1731,4 @@
|
||||
"logout": "Logout",
|
||||
"server": "Server",
|
||||
"protocol": "Protocol"
|
||||
}
|
||||
}
|
||||
@@ -189,6 +189,7 @@
|
||||
"board-private-info": "Este tablero será <strong>privado</strong>.",
|
||||
"board-public-info": "Este tablero será <strong>público</strong>.",
|
||||
"board-drag-drop-reorder-or-click-open": "Drag and drop to reorder board icons. Click board icon to open board.",
|
||||
"board-open-and-move-between-remaining-and-workspaces": "Click board icon to open board. Drag board between __remaining__ and __workspaces__.",
|
||||
"boardChangeColorPopup-title": "Cambiar el fondo del tablero",
|
||||
"boardChangeBackgroundImagePopup-title": "Change Background Image",
|
||||
"allBoardsChangeColorPopup-title": "Cambiar el color",
|
||||
@@ -345,7 +346,7 @@
|
||||
"unset-color": "Desmarcar",
|
||||
"comments": "Comments",
|
||||
"comment": "Comentar",
|
||||
"comment-placeholder": "Escribir comentario",
|
||||
"comment-placeholder": "",
|
||||
"comment-only": "Sólo comentarios",
|
||||
"comment-only-desc": "Solo puedes comentar en las tarjetas.",
|
||||
"comment-assigned-only": "Only Assigned Comment",
|
||||
@@ -808,6 +809,9 @@
|
||||
"modifiedAt": "Modified at",
|
||||
"verified": "Verificado",
|
||||
"active": "Activo",
|
||||
"active-team": "Active Team",
|
||||
"active-org": "Active Organization",
|
||||
"active-person": "Active Person",
|
||||
"card-received": "Recibido",
|
||||
"card-received-on": "Recibido el",
|
||||
"card-end": "Finalizado",
|
||||
@@ -1572,7 +1576,6 @@
|
||||
"run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?",
|
||||
"run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?",
|
||||
"restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore",
|
||||
|
||||
"migration-progress-title": "Board Migration in Progress",
|
||||
"migration-progress-overall": "Overall Progress",
|
||||
"migration-progress-current-step": "Current Step",
|
||||
@@ -1582,7 +1585,6 @@
|
||||
"steps": "steps",
|
||||
"view": "View",
|
||||
"has-swimlanes": "Has Swimlanes",
|
||||
|
||||
"step-analyze-board-structure": "Analyze Board Structure",
|
||||
"step-fix-orphaned-cards": "Fix Orphaned Cards",
|
||||
"step-convert-shared-lists": "Convert Shared Lists",
|
||||
@@ -1729,4 +1731,4 @@
|
||||
"logout": "Logout",
|
||||
"server": "Server",
|
||||
"protocol": "Protocol"
|
||||
}
|
||||
}
|
||||
@@ -189,6 +189,7 @@
|
||||
"board-private-info": "This board will be <strong>private</strong>.",
|
||||
"board-public-info": "This board will be <strong>public</strong>.",
|
||||
"board-drag-drop-reorder-or-click-open": "Drag and drop to reorder board icons. Click board icon to open board.",
|
||||
"board-open-and-move-between-remaining-and-workspaces": "Click board icon to open board. Drag board between __remaining__ and __workspaces__.",
|
||||
"boardChangeColorPopup-title": "Change Board Background",
|
||||
"boardChangeBackgroundImagePopup-title": "Change Background Image",
|
||||
"allBoardsChangeColorPopup-title": "Change color",
|
||||
@@ -345,7 +346,7 @@
|
||||
"unset-color": "Unset",
|
||||
"comments": "Comments",
|
||||
"comment": "Comment",
|
||||
"comment-placeholder": "Write Comment",
|
||||
"comment-placeholder": "",
|
||||
"comment-only": "Comment only",
|
||||
"comment-only-desc": "Can comment on cards only.",
|
||||
"comment-assigned-only": "Only Assigned Comment",
|
||||
@@ -808,6 +809,9 @@
|
||||
"modifiedAt": "Modified at",
|
||||
"verified": "Verified",
|
||||
"active": "Active",
|
||||
"active-team": "Active Team",
|
||||
"active-org": "Active Organization",
|
||||
"active-person": "Active Person",
|
||||
"card-received": "Received",
|
||||
"card-received-on": "Received on",
|
||||
"card-end": "End",
|
||||
@@ -1572,7 +1576,6 @@
|
||||
"run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?",
|
||||
"run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?",
|
||||
"restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore",
|
||||
|
||||
"migration-progress-title": "Board Migration in Progress",
|
||||
"migration-progress-overall": "Overall Progress",
|
||||
"migration-progress-current-step": "Current Step",
|
||||
@@ -1582,7 +1585,6 @@
|
||||
"steps": "steps",
|
||||
"view": "View",
|
||||
"has-swimlanes": "Has Swimlanes",
|
||||
|
||||
"step-analyze-board-structure": "Analyze Board Structure",
|
||||
"step-fix-orphaned-cards": "Fix Orphaned Cards",
|
||||
"step-convert-shared-lists": "Convert Shared Lists",
|
||||
@@ -1729,4 +1731,4 @@
|
||||
"logout": "Logout",
|
||||
"server": "Server",
|
||||
"protocol": "Protocol"
|
||||
}
|
||||
}
|
||||
@@ -189,6 +189,7 @@
|
||||
"board-private-info": "This board will be <strong>private</strong>.",
|
||||
"board-public-info": "This board will be <strong>public</strong>.",
|
||||
"board-drag-drop-reorder-or-click-open": "Drag and drop to reorder board icons. Click board icon to open board.",
|
||||
"board-open-and-move-between-remaining-and-workspaces": "Click board icon to open board. Drag board between __remaining__ and __workspaces__.",
|
||||
"boardChangeColorPopup-title": "Change Board Background",
|
||||
"boardChangeBackgroundImagePopup-title": "Change Background Image",
|
||||
"allBoardsChangeColorPopup-title": "Change color",
|
||||
@@ -345,7 +346,7 @@
|
||||
"unset-color": "Unset",
|
||||
"comments": "Comments",
|
||||
"comment": "Comment",
|
||||
"comment-placeholder": "Write Comment",
|
||||
"comment-placeholder": "",
|
||||
"comment-only": "Comment only",
|
||||
"comment-only-desc": "Can comment on cards only.",
|
||||
"comment-assigned-only": "Only Assigned Comment",
|
||||
@@ -808,6 +809,9 @@
|
||||
"modifiedAt": "Modified at",
|
||||
"verified": "Verified",
|
||||
"active": "Active",
|
||||
"active-team": "Active Team",
|
||||
"active-org": "Active Organization",
|
||||
"active-person": "Active Person",
|
||||
"card-received": "Received",
|
||||
"card-received-on": "Received on",
|
||||
"card-end": "End",
|
||||
@@ -1572,7 +1576,6 @@
|
||||
"run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?",
|
||||
"run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?",
|
||||
"restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore",
|
||||
|
||||
"migration-progress-title": "Board Migration in Progress",
|
||||
"migration-progress-overall": "Overall Progress",
|
||||
"migration-progress-current-step": "Current Step",
|
||||
@@ -1582,7 +1585,6 @@
|
||||
"steps": "steps",
|
||||
"view": "View",
|
||||
"has-swimlanes": "Has Swimlanes",
|
||||
|
||||
"step-analyze-board-structure": "Analyze Board Structure",
|
||||
"step-fix-orphaned-cards": "Fix Orphaned Cards",
|
||||
"step-convert-shared-lists": "Convert Shared Lists",
|
||||
@@ -1729,4 +1731,4 @@
|
||||
"logout": "Logout",
|
||||
"server": "Server",
|
||||
"protocol": "Protocol"
|
||||
}
|
||||
}
|
||||
@@ -189,6 +189,7 @@
|
||||
"board-private-info": "Este tablero será <strong>privado</strong>.",
|
||||
"board-public-info": "Este tablero será <strong>público</strong>.",
|
||||
"board-drag-drop-reorder-or-click-open": "Drag and drop to reorder board icons. Click board icon to open board.",
|
||||
"board-open-and-move-between-remaining-and-workspaces": "Click board icon to open board. Drag board between __remaining__ and __workspaces__.",
|
||||
"boardChangeColorPopup-title": "Cambiar el fondo del tablero",
|
||||
"boardChangeBackgroundImagePopup-title": "Change Background Image",
|
||||
"allBoardsChangeColorPopup-title": "Cambiar el color",
|
||||
@@ -345,7 +346,7 @@
|
||||
"unset-color": "Desmarcar",
|
||||
"comments": "Comments",
|
||||
"comment": "Comentar",
|
||||
"comment-placeholder": "Escribir comentario",
|
||||
"comment-placeholder": "",
|
||||
"comment-only": "Sólo comentarios",
|
||||
"comment-only-desc": "Sólo puede comentar en las tarjetas.",
|
||||
"comment-assigned-only": "Only Assigned Comment",
|
||||
@@ -808,6 +809,9 @@
|
||||
"modifiedAt": "Modified at",
|
||||
"verified": "Verificado",
|
||||
"active": "Activo",
|
||||
"active-team": "Active Team",
|
||||
"active-org": "Active Organization",
|
||||
"active-person": "Active Person",
|
||||
"card-received": "Recibido",
|
||||
"card-received-on": "Recibido el",
|
||||
"card-end": "Finalizado",
|
||||
@@ -1572,7 +1576,6 @@
|
||||
"run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?",
|
||||
"run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?",
|
||||
"restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore",
|
||||
|
||||
"migration-progress-title": "Board Migration in Progress",
|
||||
"migration-progress-overall": "Overall Progress",
|
||||
"migration-progress-current-step": "Current Step",
|
||||
@@ -1582,7 +1585,6 @@
|
||||
"steps": "steps",
|
||||
"view": "View",
|
||||
"has-swimlanes": "Has Swimlanes",
|
||||
|
||||
"step-analyze-board-structure": "Analyze Board Structure",
|
||||
"step-fix-orphaned-cards": "Fix Orphaned Cards",
|
||||
"step-convert-shared-lists": "Convert Shared Lists",
|
||||
@@ -1729,4 +1731,4 @@
|
||||
"logout": "Logout",
|
||||
"server": "Server",
|
||||
"protocol": "Protocol"
|
||||
}
|
||||
}
|
||||
@@ -189,6 +189,7 @@
|
||||
"board-private-info": "This board will be <strong>private</strong>.",
|
||||
"board-public-info": "This board will be <strong>public</strong>.",
|
||||
"board-drag-drop-reorder-or-click-open": "Drag and drop to reorder board icons. Click board icon to open board.",
|
||||
"board-open-and-move-between-remaining-and-workspaces": "Click board icon to open board. Drag board between __remaining__ and __workspaces__.",
|
||||
"boardChangeColorPopup-title": "Change Board Background",
|
||||
"boardChangeBackgroundImagePopup-title": "Change Background Image",
|
||||
"allBoardsChangeColorPopup-title": "Change color",
|
||||
@@ -345,7 +346,7 @@
|
||||
"unset-color": "Unset",
|
||||
"comments": "Comments",
|
||||
"comment": "Comment",
|
||||
"comment-placeholder": "Write Comment",
|
||||
"comment-placeholder": "",
|
||||
"comment-only": "Comment only",
|
||||
"comment-only-desc": "Can comment on cards only.",
|
||||
"comment-assigned-only": "Only Assigned Comment",
|
||||
@@ -808,6 +809,9 @@
|
||||
"modifiedAt": "Modified at",
|
||||
"verified": "Verified",
|
||||
"active": "Active",
|
||||
"active-team": "Active Team",
|
||||
"active-org": "Active Organization",
|
||||
"active-person": "Active Person",
|
||||
"card-received": "Received",
|
||||
"card-received-on": "Received on",
|
||||
"card-end": "End",
|
||||
@@ -1572,7 +1576,6 @@
|
||||
"run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?",
|
||||
"run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?",
|
||||
"restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore",
|
||||
|
||||
"migration-progress-title": "Board Migration in Progress",
|
||||
"migration-progress-overall": "Overall Progress",
|
||||
"migration-progress-current-step": "Current Step",
|
||||
@@ -1582,7 +1585,6 @@
|
||||
"steps": "steps",
|
||||
"view": "View",
|
||||
"has-swimlanes": "Has Swimlanes",
|
||||
|
||||
"step-analyze-board-structure": "Analyze Board Structure",
|
||||
"step-fix-orphaned-cards": "Fix Orphaned Cards",
|
||||
"step-convert-shared-lists": "Convert Shared Lists",
|
||||
@@ -1729,4 +1731,4 @@
|
||||
"logout": "Logout",
|
||||
"server": "Server",
|
||||
"protocol": "Protocol"
|
||||
}
|
||||
}
|
||||
@@ -189,6 +189,7 @@
|
||||
"board-private-info": "Este tablero será <strong>privado</strong>.",
|
||||
"board-public-info": "Este tablero será <strong>público</strong>.",
|
||||
"board-drag-drop-reorder-or-click-open": "Arrastra y suelta para reordenar los iconos del tablero. Click en el icono del tablero para abrirlo",
|
||||
"board-open-and-move-between-remaining-and-workspaces": "Click board icon to open board. Drag board between __remaining__ and __workspaces__.",
|
||||
"boardChangeColorPopup-title": "Cambiar el fondo del tablero",
|
||||
"boardChangeBackgroundImagePopup-title": "Cambiar imagen de fondo",
|
||||
"allBoardsChangeColorPopup-title": "Cambiar el color",
|
||||
@@ -345,7 +346,7 @@
|
||||
"unset-color": "Desmarcar",
|
||||
"comments": "Comentarios",
|
||||
"comment": "Comentar",
|
||||
"comment-placeholder": "Escribir comentario",
|
||||
"comment-placeholder": "",
|
||||
"comment-only": "Sólo comentarios",
|
||||
"comment-only-desc": "Solo puedes comentar en las tarjetas.",
|
||||
"comment-assigned-only": "Only Assigned Comment",
|
||||
@@ -808,6 +809,9 @@
|
||||
"modifiedAt": "Modified at",
|
||||
"verified": "Verificado",
|
||||
"active": "Activo",
|
||||
"active-team": "Active Team",
|
||||
"active-org": "Active Organization",
|
||||
"active-person": "Active Person",
|
||||
"card-received": "Recibido",
|
||||
"card-received-on": "Recibido el",
|
||||
"card-end": "Finalizado",
|
||||
@@ -1572,7 +1576,6 @@
|
||||
"run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?",
|
||||
"run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?",
|
||||
"restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore",
|
||||
|
||||
"migration-progress-title": "Board Migration in Progress",
|
||||
"migration-progress-overall": "Overall Progress",
|
||||
"migration-progress-current-step": "Current Step",
|
||||
@@ -1582,7 +1585,6 @@
|
||||
"steps": "steps",
|
||||
"view": "View",
|
||||
"has-swimlanes": "Has Swimlanes",
|
||||
|
||||
"step-analyze-board-structure": "Analyze Board Structure",
|
||||
"step-fix-orphaned-cards": "Fix Orphaned Cards",
|
||||
"step-convert-shared-lists": "Convert Shared Lists",
|
||||
@@ -1729,4 +1731,4 @@
|
||||
"logout": "Logout",
|
||||
"server": "Server",
|
||||
"protocol": "Protocol"
|
||||
}
|
||||
}
|
||||
@@ -189,6 +189,7 @@
|
||||
"board-private-info": "This board will be <strong>private</strong>.",
|
||||
"board-public-info": "This board will be <strong>public</strong>.",
|
||||
"board-drag-drop-reorder-or-click-open": "Drag and drop to reorder board icons. Click board icon to open board.",
|
||||
"board-open-and-move-between-remaining-and-workspaces": "Click board icon to open board. Drag board between __remaining__ and __workspaces__.",
|
||||
"boardChangeColorPopup-title": "Change Board Background",
|
||||
"boardChangeBackgroundImagePopup-title": "Change Background Image",
|
||||
"allBoardsChangeColorPopup-title": "Change color",
|
||||
@@ -345,7 +346,7 @@
|
||||
"unset-color": "Unset",
|
||||
"comments": "Comments",
|
||||
"comment": "Comment",
|
||||
"comment-placeholder": "Write Comment",
|
||||
"comment-placeholder": "",
|
||||
"comment-only": "Comment only",
|
||||
"comment-only-desc": "Can comment on cards only.",
|
||||
"comment-assigned-only": "Only Assigned Comment",
|
||||
@@ -808,6 +809,9 @@
|
||||
"modifiedAt": "Modified at",
|
||||
"verified": "Verified",
|
||||
"active": "Active",
|
||||
"active-team": "Active Team",
|
||||
"active-org": "Active Organization",
|
||||
"active-person": "Active Person",
|
||||
"card-received": "Received",
|
||||
"card-received-on": "Received on",
|
||||
"card-end": "End",
|
||||
@@ -1572,7 +1576,6 @@
|
||||
"run-fix-avatar-urls-migration-confirm": "This will update avatar URLs for board members to use the correct storage backend. Continue?",
|
||||
"run-fix-all-file-urls-migration-confirm": "This will update all file attachment URLs on this board to use the correct storage backend. Continue?",
|
||||
"restore-lost-cards-nothing-to-restore": "No lost swimlanes, lists, or cards to restore",
|
||||
|
||||
"migration-progress-title": "Board Migration in Progress",
|
||||
"migration-progress-overall": "Overall Progress",
|
||||
"migration-progress-current-step": "Current Step",
|
||||
@@ -1582,7 +1585,6 @@
|
||||
"steps": "steps",
|
||||
"view": "View",
|
||||
"has-swimlanes": "Has Swimlanes",
|
||||
|
||||
"step-analyze-board-structure": "Analyze Board Structure",
|
||||
"step-fix-orphaned-cards": "Fix Orphaned Cards",
|
||||
"step-convert-shared-lists": "Convert Shared Lists",
|
||||
@@ -1729,4 +1731,4 @@
|
||||
"logout": "Logout",
|
||||
"server": "Server",
|
||||
"protocol": "Protocol"
|
||||
}
|
||||
}
|
||||
Loaded 100 of 249 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user