mirror of
https://github.com/wekan/wekan.git
synced 2026-11-08 11:25:19 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c87da21587 | ||
|
|
6c8e4e88b3 | ||
|
|
2d3d6d6ca7 | ||
|
|
5b23954be8 | ||
|
|
f368c1a2ac | ||
|
|
4c02cf5585 | ||
|
|
9a9e81f15a | ||
|
|
aa76ae81b1 | ||
|
|
8d0de427ef | ||
|
|
f3f6032160 | ||
|
|
639214574c | ||
|
|
7b84c74359 | ||
|
|
807fc5ea89 | ||
|
|
1993d7d3c8 | ||
|
|
ae46562308 | ||
|
|
f48b2c03e2 | ||
|
|
3f9b81bcbc | ||
|
|
484eae7362 | ||
|
|
3f80161607 | ||
|
|
bf047d53c8 | ||
|
|
c623718db1 | ||
|
|
4b89394087 | ||
|
|
5269d0ba5c | ||
|
|
3b6b601085 | ||
|
|
fcc3951f40 | ||
|
|
418ea838bc | ||
|
|
09a525ae83 | ||
|
|
68dbbd8b47 | ||
|
|
1cef5ede9a | ||
|
|
71992ef546 | ||
|
|
80f5518724 | ||
|
|
097ad9160a | ||
|
|
6420819cfa | ||
|
|
184e1713d3 | ||
|
|
0c5cb99b7c | ||
|
|
b6d0be0f45 | ||
|
|
3ebc38cb40 | ||
|
|
b4ebe48d7b | ||
|
|
09ce64ecf6 | ||
|
|
8456170d45 | ||
|
|
b1e7b1e538 | ||
|
|
dac8d1da2f | ||
|
|
c452a2defd | ||
|
|
c8393f3f53 | ||
|
|
be558257cd | ||
|
|
7fc1f35bed | ||
|
|
a442959dda | ||
|
|
b6d003089c | ||
|
|
fc1e089d38 | ||
|
|
35b44a1f8b | ||
|
|
a434bb4bd5 | ||
|
|
292ffb8906 | ||
|
|
1a2ec06332 | ||
|
|
2c7a016327 | ||
|
|
18da0d2618 | ||
|
|
c0a5c2b7c9 | ||
|
|
01f691ba3d | ||
|
|
8248892e33 | ||
|
|
7b8c377099 | ||
|
|
e1c6221f22 | ||
|
|
7f5408947b | ||
|
|
061593c5ee | ||
|
|
5fe2192962 | ||
|
|
132a644848 | ||
|
|
5852351d30 | ||
|
|
a475afd3d3 | ||
|
|
4763c94604 | ||
|
|
539c678199 | ||
|
|
d0dc7dff98 | ||
|
|
71ba0c2dcd | ||
|
|
909496fb8b | ||
|
|
562fa02718 | ||
|
|
fd67a510f8 | ||
|
|
aed26c6771 | ||
|
|
ed0d7a2bad | ||
|
|
5a947b6959 | ||
|
|
01c36852da | ||
|
|
afcb9353ee | ||
|
|
1d9222eb81 | ||
|
|
4588fb8b3d | ||
|
|
fd3a381cd6 | ||
|
|
5091c3883a | ||
|
|
de7770f211 | ||
|
|
dcc6c8fe5d | ||
|
|
3170b70f51 | ||
|
|
664b8fde6f | ||
|
|
cf0c347b2e | ||
|
|
bf1f7aea47 | ||
|
|
d077948115 | ||
|
|
35dd10b89f | ||
|
|
cf000d000a | ||
|
|
5ec9f3ae5b | ||
|
|
f342d54d18 | ||
|
|
d9e4cd57cb | ||
|
|
3d9ee1f9fc | ||
|
|
8bb7b9ba62 | ||
|
|
c892540f43 | ||
|
|
08f41037f3 | ||
|
|
4e9be22f95 | ||
|
|
74dfacd76e | ||
|
|
058c74e9c8 | ||
|
|
e596805194 |
No files matched your search
@@ -10,7 +10,13 @@ name: Release all missing
|
||||
# those six without running the whole thing again, version bump and all.
|
||||
#
|
||||
# This finishes a release that already exists. It never bumps a version, never
|
||||
# tags, never touches Docker, snap, the website or the charts.
|
||||
# tags, and never touches Docker, snap or the website.
|
||||
#
|
||||
# It DOES publish the Helm chart, because that is a thing a release can be
|
||||
# missing like any other: the chart entry is written once, during the release it
|
||||
# belongs to, so a release whose charts job did not run leaves a hole that the
|
||||
# next release never goes back for - v10.80 is one of those, and it was not
|
||||
# alone. See the charts job at the end.
|
||||
#
|
||||
# WHAT IT CAN BUILD, and why that is not everything. Only build-amd64 runs
|
||||
# Meteor; every other bundle WeKan ships is that same bundle repacked. This job
|
||||
@@ -279,9 +285,107 @@ jobs:
|
||||
publish: true
|
||||
only: ${{ needs.plan.outputs.flatpak }}
|
||||
|
||||
|
||||
# ─── The Helm chart, for a release that never got one ───────────────────────
|
||||
#
|
||||
# Everything else here rebuilds a missing BUNDLE; this publishes a missing
|
||||
# CHART, which goes missing the same way and for the same reason. A chart is
|
||||
# written once, by release-charts.sh, during the release it belongs to, so a
|
||||
# release whose charts job did not run has no chart and nothing ever goes back
|
||||
# for it. That is not rare - 146 of the packages already on gh-pages had no
|
||||
# index entry, and v10.80 has no package at all, because a cancelled
|
||||
# build-mac-x64 cancelled its run before the charts job started.
|
||||
#
|
||||
# It is the one part of this workflow that PUSHES to another repository, so it
|
||||
# is guarded twice: it does nothing unless a token that can push to
|
||||
# wekan/charts is configured, and nothing if the chart for this version is
|
||||
# already published. Re-publishing an existing version would re-tar the package
|
||||
# and change the digest of a chart people have already pulled.
|
||||
charts:
|
||||
name: Helm chart
|
||||
needs: plan
|
||||
if: ${{ always() && needs.plan.outputs.version != '' }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Is a chart already published for this version?
|
||||
id: check
|
||||
env:
|
||||
V: ${{ needs.plan.outputs.version }}
|
||||
REPO_TOKEN: ${{ secrets.WEKAN_REPO_TOKEN }}
|
||||
run: |
|
||||
set -uo pipefail
|
||||
if [ -z "${REPO_TOKEN:-}" ]; then
|
||||
echo "::warning::No WEKAN_REPO_TOKEN, so the Helm chart cannot be published. Add a token that can push to wekan/charts to have this finish the chart too."
|
||||
echo "skip=true" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
# The published index is the authority on what exists, not this
|
||||
# checkout. An entry's own version is at EXACTLY four spaces; the
|
||||
# mongodb subchart's version sits deeper and would match a loose grep.
|
||||
curl -fsSL --retry 3 -o index.yaml https://wekan.github.io/charts/index.yaml || {
|
||||
echo "::warning::Could not read the published chart index; not touching the charts repo."
|
||||
echo "skip=true" >> "$GITHUB_OUTPUT"; exit 0; }
|
||||
# -F, a FIXED string: the dots in a version are regex wildcards
|
||||
# otherwise, so "10.80" would also match a line reading 10x80. -x so it
|
||||
# is the whole line, and the four-space indent is what makes it an
|
||||
# entry's own version rather than the mongodb subchart's, which sits
|
||||
# deeper.
|
||||
if grep -qxF " version: ${V}.0" index.yaml; then
|
||||
echo "::notice::v$V already has a published Helm chart (${V}.0); nothing to do."
|
||||
echo "skip=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "v$V has no published chart; publishing ${V}.0."
|
||||
echo "skip=false" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
- name: Checkout wekan (for releases/release-charts.sh)
|
||||
if: steps.check.outputs.skip != 'true'
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
path: wekan
|
||||
|
||||
- name: Checkout wekan/charts (main + gh-pages)
|
||||
if: steps.check.outputs.skip != 'true'
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
repository: wekan/charts
|
||||
token: ${{ secrets.WEKAN_REPO_TOKEN }}
|
||||
fetch-depth: 0
|
||||
path: charts
|
||||
|
||||
- name: Install Helm
|
||||
if: steps.check.outputs.skip != 'true'
|
||||
uses: azure/setup-helm@v5
|
||||
|
||||
- name: Publish the chart for this release
|
||||
if: steps.check.outputs.skip != 'true'
|
||||
env:
|
||||
CHARTS_DIR: ${{ github.workspace }}/charts
|
||||
run: |
|
||||
set -euo pipefail
|
||||
cd charts
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
git fetch origin '+refs/heads/*:refs/remotes/origin/*'
|
||||
git branch --track gh-pages origin/gh-pages 2>/dev/null || true
|
||||
git checkout main
|
||||
cd ..
|
||||
./wekan/releases/release-charts.sh "${{ needs.plan.outputs.version }}"
|
||||
|
||||
- name: Job result
|
||||
if: always()
|
||||
run: |
|
||||
case "${{ job.status }}" in
|
||||
success) mark='OK ' ;;
|
||||
failure) mark='FAILED ' ;;
|
||||
cancelled) mark='CANCELLED' ;;
|
||||
*) mark='${{ job.status }}' ;;
|
||||
esac
|
||||
echo "$mark charts" >> "$GITHUB_STEP_SUMMARY"
|
||||
|
||||
done:
|
||||
name: what is still missing
|
||||
needs: [plan, extra-arches, appimage, flatpak]
|
||||
needs: [plan, extra-arches, appimage, flatpak, charts]
|
||||
if: ${{ always() }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
@@ -39,7 +39,8 @@ name: Release All Platforms
|
||||
# not compiled here) and embeds it
|
||||
# - release: creates the GitHub Release with the newest CHANGELOG.md notes and
|
||||
# uploads the core wekan-<version>-{amd64,arm64}.zip bundles
|
||||
# - build-win64 / build-mac-arm64 / build-extra-arches: built AFTER release, each
|
||||
# - build-win64 / build-win-arm64 / build-mac-arm64 / build-extra-arches: built
|
||||
# AFTER release, each
|
||||
# rebuilds the amd64 bundle's native modules for its platform (Windows,
|
||||
# macOS arm64, and QEMU-emulated ppc64le/s390x/riscv64) and attaches
|
||||
# its .zip to the Release. Windows/macOS strip the Linux FerretDB back
|
||||
@@ -409,6 +410,17 @@ jobs:
|
||||
# is actually on the registries. If `docker` fails, this job is skipped.
|
||||
charts:
|
||||
needs: docker
|
||||
# `always()` so that a CANCELLATION somewhere else in the run cannot skip
|
||||
# this job. It is not defensive dressing: in v10.80 the release itself, the
|
||||
# image and every bundle were published, and then charts, ucs and nextcloud
|
||||
# were all skipped the moment `docker` finished - because build-mac-x64 was
|
||||
# queued on a retired runner label and had to be cancelled by hand, and a
|
||||
# cancelled job cancels the RUN, which skips every job that has not started.
|
||||
# A job whose `if` is `always()` still runs while a run is cancelling, so the
|
||||
# chart is published for a release that IS on the registries. The guard is
|
||||
# then explicit about the only condition that ever mattered: docker SUCCEEDED
|
||||
# - the chart points at the image that job pushes, so it must exist first.
|
||||
if: ${{ always() && needs.docker.result == 'success' }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# First step on purpose: a missing secret is then ONE named line at the top of
|
||||
@@ -474,6 +486,21 @@ jobs:
|
||||
run: |
|
||||
./wekan/releases/release-charts.sh "${{ inputs.new_version }}"
|
||||
|
||||
# What the index does NOT have, reported every release rather than
|
||||
# discovered years later. A chart entry is written once, during the release
|
||||
# it belongs to, so a release whose charts job did not run leaves a hole
|
||||
# that nothing ever fills - v10.80's, when a cancelled build-mac-x64
|
||||
# cancelled the run, is one of many. This is a PLAN ONLY: it reads the
|
||||
# releases API, the live index and ghcr, writes nothing, and prints which
|
||||
# releases have a chart, which are missing one that could be built, and
|
||||
# which are omitted because they have no container image for a chart to
|
||||
# point at. Filling them in is `backfill-charts.sh --apply --push`, run by
|
||||
# hand: rewriting a published Helm index is not a side effect of a release.
|
||||
- name: Report which releases the chart index is missing
|
||||
continue-on-error: true
|
||||
run: |
|
||||
./wekan/releases/backfill-charts.sh | tee -a "$GITHUB_STEP_SUMMARY"
|
||||
|
||||
# Always, as the last step: the run summary then answers "what worked and what
|
||||
# did not" for the whole release at a glance, instead of eighteen job logs. A
|
||||
# step that failed has already printed an ::error:: saying why; this names the
|
||||
@@ -623,21 +650,40 @@ jobs:
|
||||
cat "wekan-${VERSION}-amd64.zip.sha256sum"
|
||||
# Where this bundle's binaries came from, for the release notes.
|
||||
#
|
||||
# $GITHUB_WORKSPACE, not a relative path: this step ran `cd .build`
|
||||
# above, so `mkdir -p provenance` made .build/provenance while the
|
||||
# upload-artifact below looks at provenance/ from the workspace root.
|
||||
# It found nothing - "No files were found with the provided path:
|
||||
# provenance/" - and amd64, the platform most people download, was the
|
||||
# one bundle missing from the v10.77 release-notes table. Every other
|
||||
# build job records from the workspace root, which is why only this one
|
||||
# was affected.
|
||||
# EVERY path here is absolute, because this step ran `cd .build` above
|
||||
# and NOTHING relative means what it looks like it means from inside
|
||||
# it. Both halves of that bit:
|
||||
#
|
||||
# The SCRIPT. `bash releases/record-provenance.sh` resolves against
|
||||
# .build/, which has no releases/ - so it was
|
||||
# bash: releases/record-provenance.sh: No such file or directory
|
||||
# every single run, and the `|| true` on the end swallowed it. amd64
|
||||
# had therefore never recorded anything, and the only visible symptom
|
||||
# was its absence from the release-notes table.
|
||||
#
|
||||
# The OUTPUT. `mkdir -p provenance` makes .build/provenance, while
|
||||
# the upload-artifact below looks at provenance/ from the workspace
|
||||
# root - "No files were found with the provided path: provenance/".
|
||||
#
|
||||
# Every other build job records from the workspace root, which is why
|
||||
# only this one was affected by either.
|
||||
#
|
||||
# The `|| true` stays on the record calls: a release note must not fail
|
||||
# a build that produced a good bundle. It is exactly what hid this for
|
||||
# so long, so the absolute paths are what make it honest rather than
|
||||
# the error handling.
|
||||
mkdir -p "$GITHUB_WORKSPACE/provenance"
|
||||
PROVENANCE_FILE="$GITHUB_WORKSPACE/provenance/amd64.tsv" bash releases/record-provenance.sh \
|
||||
PROVENANCE_FILE="$GITHUB_WORKSPACE/provenance/amd64.tsv" bash "$GITHUB_WORKSPACE/releases/record-provenance.sh" \
|
||||
'amd64' 'Node.js' "${NODE_FROM:-}" "${NODE_FULL:-$NODE_VERSION}" \
|
||||
"${NODE_URL:-}" \
|
||||
"${NODE_SHA256:-}" || true
|
||||
FERRET_TAG="$(bash releases/ferretdb-latest-tag.sh)"
|
||||
PROVENANCE_FILE="$GITHUB_WORKSPACE/provenance/amd64.tsv" bash releases/record-provenance.sh \
|
||||
# ...and `|| true` here too, for the same reason: this is an
|
||||
# ASSIGNMENT, so under `set -e` a missing script ends the step with
|
||||
# exit 127 - which is what this line did on v10.78 before the path was
|
||||
# made absolute, failing the whole amd64 build after the zip was
|
||||
# already built and checksummed.
|
||||
FERRET_TAG="$(bash "$GITHUB_WORKSPACE/releases/ferretdb-latest-tag.sh" || true)"
|
||||
PROVENANCE_FILE="$GITHUB_WORKSPACE/provenance/amd64.tsv" bash "$GITHUB_WORKSPACE/releases/record-provenance.sh" \
|
||||
'amd64' 'FerretDB' 'wekan/FerretDB' "${FERRET_TAG:-latest}" \
|
||||
'https://github.com/wekan/FerretDB/releases/latest/download/ferretdb-amd64' \
|
||||
"${FERRET_SHA:-}" || true
|
||||
@@ -842,7 +888,7 @@ jobs:
|
||||
'arm64' 'Node.js' "${NODE_FROM:-}" "${NODE_FULL:-$NODE_VERSION}" \
|
||||
"${NODE_URL:-}" \
|
||||
"${NODE_SHA256:-}" || true
|
||||
FERRET_TAG="$(bash releases/ferretdb-latest-tag.sh)"
|
||||
FERRET_TAG="$(bash releases/ferretdb-latest-tag.sh || true)"
|
||||
PROVENANCE_FILE=provenance/arm64.tsv bash releases/record-provenance.sh \
|
||||
'arm64' 'FerretDB' 'wekan/FerretDB' "${FERRET_TAG:-latest}" \
|
||||
'https://github.com/wekan/FerretDB/releases/latest/download/ferretdb-arm64' \
|
||||
@@ -1230,7 +1276,7 @@ jobs:
|
||||
"${node_url:-}" \
|
||||
"${node_sha256:-}" || true
|
||||
if [ -s bundle/ferretdb.exe ]; then
|
||||
FERRET_TAG="$(bash src/releases/ferretdb-latest-tag.sh)"
|
||||
FERRET_TAG="$(bash src/releases/ferretdb-latest-tag.sh || true)"
|
||||
PROVENANCE_FILE=provenance/win64.tsv bash src/releases/record-provenance.sh \
|
||||
'win64' 'FerretDB' 'wekan/FerretDB' "${FERRET_TAG:-latest}" \
|
||||
'https://github.com/wekan/FerretDB/releases/latest/download/ferretdb-win64.exe' \
|
||||
@@ -1380,6 +1426,353 @@ jobs:
|
||||
echo "::error::build-win64 FAILED. The ::error:: line in this job's log, above, says which step and why."
|
||||
fi
|
||||
|
||||
# Build win32 (32-bit Windows) bundle.
|
||||
#
|
||||
# BEST-EFFORT, like mac-x64 and the exotic Linux arches: nodejs.org has no
|
||||
# 32-bit Windows Node 24 at all (upstream removed the build in Node 23) and
|
||||
# unofficial-builds has none either, so this bundle's node.exe can only come
|
||||
# from wekan/node-patches. Until node-win32.exe is published there the preflight
|
||||
# SKIPS this job (a warning, not a red failure); it returns on its own the
|
||||
# release after it appears.
|
||||
#
|
||||
# The runner is 64-bit and the bundle is 32-bit. There is NO 32-bit Windows
|
||||
# Node 24 to install (that is the whole reason the fork exists), so setup-node
|
||||
# runs the runner's normal x64 Node to DRIVE the build, and the native modules
|
||||
# (bcrypt) are cross-compiled to ia32 by passing npm_config_arch=ia32 in the
|
||||
# rebuild step below - node-gyp then fetches the ia32 headers and builds Win32
|
||||
# binaries. The shipped node.exe is the fork's 32-bit node-win32.exe.
|
||||
# Windows on ARM. Every binary this bundle needs is published: nodejs.org
|
||||
# builds node-<version>-win-arm64.zip itself, wekan/FerretDB publishes
|
||||
# ferretdb-win-arm64.exe and wekan/mongo-tools-patches publishes the tools
|
||||
# as -win-arm64.exe - so this is a bundle WeKan could always have shipped
|
||||
# and simply did not.
|
||||
#
|
||||
# It builds on the x64 Windows runner, like win32 does: the Meteor bundle is
|
||||
# JavaScript, the native modules are installed with --ignore-scripts and are
|
||||
# not compiled for the runner's architecture either way, and the only
|
||||
# architecture-specific things in the zip are the three binaries above,
|
||||
# which are downloaded rather than built.
|
||||
build-win-arm64:
|
||||
needs: [prepare, build-amd64, release]
|
||||
runs-on: windows-latest
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
VERSION: ${{ needs.prepare.outputs.version }}
|
||||
steps:
|
||||
# Checked out into src/ so start-wekan.bat and snapcraft.yaml (which pins
|
||||
# the MongoDB tools/mongosh versions) are available; the downloaded bundle
|
||||
# is extracted alongside it in the workspace root.
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
ref: refs/tags/v${{ needs.prepare.outputs.version }}
|
||||
path: src
|
||||
|
||||
- uses: actions/setup-node@v7
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
|
||||
# Which Node.js this platform gets - and whether it is built at all.
|
||||
#
|
||||
# WeKan takes its Node.js from official nodejs.org, then
|
||||
# unofficial-builds.nodejs.org, then wekan/node-patches
|
||||
# (releases/resolve-node-source.sh is the one place that order lives).
|
||||
# When NO source has one for this CPU the platform is simply NOT BUILT
|
||||
# this release: every step below is gated on skip, and it comes back by
|
||||
# itself the first run after a Node.js for it is published anywhere.
|
||||
- name: Preflight - resolve this platform's Node.js
|
||||
id: preflight
|
||||
shell: bash
|
||||
run: |
|
||||
set -uo pipefail
|
||||
out="$(bash src/releases/resolve-node-source.sh 'win-arm64' "$NODE_VERSION")" || true
|
||||
if printf '%s\n' "$out" | grep -q '^node_found=true$'; then
|
||||
printf '%s\n' "$out" | grep -E '^node_(full|from|url|kind|member|sha256)=' >> "$GITHUB_OUTPUT"
|
||||
echo "skip=false" >> "$GITHUB_OUTPUT"
|
||||
printf '%s\n' "$out" | grep -E '^node_(full|from|url)='
|
||||
else
|
||||
echo "::warning::win-arm64 is not built this time. No Node.js for it at nodejs.org, unofficial-builds.nodejs.org or wekan/node-patches; it returns by itself when one is published."
|
||||
echo "skip=true" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
- name: Install 7-zip
|
||||
if: steps.preflight.outputs.skip != 'true'
|
||||
run: choco install -y 7zip
|
||||
|
||||
- name: Download amd64 bundle
|
||||
if: steps.preflight.outputs.skip != 'true'
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: bundle-amd64
|
||||
|
||||
- name: Fix bcrypt for Node.js 24
|
||||
if: steps.preflight.outputs.skip != 'true'
|
||||
shell: bash
|
||||
run: |
|
||||
7z x wekan-${VERSION}-amd64.zip
|
||||
# Drop the Linux node + FerretDB binaries + MongoDB Database Tools + POSIX
|
||||
# launcher inherited from the amd64 base bundle; the Windows node.exe,
|
||||
# ferretdb.exe, *.exe tools and start-wekan.bat are added in later steps.
|
||||
rm -f bundle/node bundle/ferretdb bundle/.ferretdb-default bundle/start-wekan.sh
|
||||
rm -f bundle/bsondump bundle/mongodump bundle/mongoexport bundle/mongofiles \
|
||||
bundle/mongoimport bundle/mongorestore bundle/mongostat bundle/mongotop
|
||||
# Linux-only cpu-exec + qemu-user (#6458) make no sense on Windows.
|
||||
rm -f bundle/cpu-exec bundle/qemu-x86_64
|
||||
# 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
|
||||
if: steps.preflight.outputs.skip != 'true'
|
||||
shell: bash
|
||||
run: |
|
||||
cd bundle/programs/server
|
||||
rm -rf node_modules
|
||||
npm install
|
||||
|
||||
- name: Check the binaries the win-arm64 bundle needs exist
|
||||
if: steps.preflight.outputs.skip != 'true'
|
||||
# bash, not the Windows default shell: this is a bash script (`set -euo
|
||||
# pipefail`, a bash script call). Without it PowerShell runs the body and
|
||||
# dies on `set -euo pipefail` with "A parameter cannot be found that
|
||||
# matches parameter name 'euo'".
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# This job checks the repo out into src/ (see the checkout step above),
|
||||
# so the script lives at src/releases/, not the workspace root - the
|
||||
# same path the start-wekan.bat copy below uses.
|
||||
bash src/releases/require-binaries.sh 'win-arm64 bundle' \
|
||||
'https://github.com/wekan/FerretDB/releases/latest/download/ferretdb-win-arm64.exe'
|
||||
|
||||
- name: Add MongoDB Database Tools to the bundle
|
||||
if: steps.preflight.outputs.skip != 'true'
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# MongoDB Database Tools (Windows) built by wekan/mongo-tools-patches (pure Go),
|
||||
# one <tool>-win-arm64.exe per tool from that repo's newest release — no
|
||||
# mongodb.com dependency. No mongosh: WeKan no longer bundles the MongoDB
|
||||
# Shell; scripted DB access uses the bundled Node.js 24 + `mongodb` driver.
|
||||
# (The Windows launcher, start-wekan.bat, is added by the FerretDB embed
|
||||
# step below from releases/ferretdb/start-wekan.bat.)
|
||||
BASE="https://github.com/wekan/mongo-tools-patches/releases/latest/download"
|
||||
for tool in bsondump mongodump mongoexport mongofiles mongoimport mongorestore mongostat mongotop; do
|
||||
curl -fL --retry 5 --retry-delay 10 -o "bundle/${tool}.exe" "${BASE}/${tool}-win-arm64.exe"
|
||||
done
|
||||
|
||||
echo "=== bundle contents ==="
|
||||
ls -1 bundle/
|
||||
|
||||
- name: Embed Node.js, FerretDB (win-arm64) and launcher into the bundle
|
||||
if: steps.preflight.outputs.skip != 'true'
|
||||
shell: bash
|
||||
# Make the Windows .zip self-contained: bundle node.exe (from the runner's
|
||||
# win-arm64 Node 24), ferretdb.exe (downloaded per-arch from the newest
|
||||
# wekan/FerretDB release) and start-wekan.bat. FerretDB embedding is
|
||||
# tolerant: if the win-arm64 asset is missing the bundle stays MongoDB-only
|
||||
# (start-wekan.bat then won't find ferretdb.exe).
|
||||
run: |
|
||||
# Bundled Node.js: download the pinned Node ${NODE_VERSION} win-arm64
|
||||
# node.exe from nodejs.org and VERIFY it, rather than copying the
|
||||
# runner's unchecksummed node. Exports NODE_FULL/NODE_SHA256 for
|
||||
# provenance.
|
||||
# Capture node_full/node_sha256 in THIS shell (provenance is recorded in
|
||||
# the same step, and $GITHUB_ENV only reaches later steps); a failed
|
||||
# download/verify stops the build here rather than at the later guard.
|
||||
node_meta="$(bash src/releases/embed-verified-node.sh bundle/node.exe node-win-arm64.exe "$NODE_VERSION")" \
|
||||
|| { echo "::error::Verified Node.js embed failed for win-arm64."; exit 1; }
|
||||
eval "$node_meta"
|
||||
# Bundled FerretDB (win-arm64): download this arch's binary and verify it
|
||||
# against the .sha256sum wekan/FerretDB publishes beside it.
|
||||
FERRET_URL="https://github.com/wekan/FerretDB/releases/latest/download/ferretdb-win-arm64.exe"
|
||||
if curl -fSL --retry 5 --retry-delay 10 -o bundle/ferretdb.exe "$FERRET_URL"; then
|
||||
echo "Embedded FerretDB win-arm64 -> bundle/ferretdb.exe"
|
||||
if curl -fsSL "${FERRET_URL}.sha256sum" -o /tmp/ferretdb.sha256sum 2>/dev/null; then
|
||||
FERRET_SHA="$(awk '{print $1; exit}' /tmp/ferretdb.sha256sum)"
|
||||
GOT="$(sha256sum bundle/ferretdb.exe | cut -d' ' -f1)"
|
||||
if [ "$GOT" != "$FERRET_SHA" ]; then
|
||||
echo "::error::FerretDB win-arm64 does not match its published SHA256 (published $FERRET_SHA, got $GOT)."
|
||||
exit 1
|
||||
fi
|
||||
echo "FerretDB SHA256 verified: $GOT"
|
||||
echo "FERRET_SHA=$FERRET_SHA" >> "$GITHUB_ENV"
|
||||
else
|
||||
echo "::warning::wekan/FerretDB publishes no checksum for ferretdb-win-arm64.exe on this release, so it is unverified."
|
||||
fi
|
||||
else
|
||||
rm -f bundle/ferretdb.exe
|
||||
echo "No win-arm64 FerretDB asset in the release; Windows bundle stays MongoDB-only."
|
||||
fi
|
||||
# Self-contained Windows launcher (defaults to FerretDB SQLite).
|
||||
cp src/releases/ferretdb/start-wekan.bat bundle/
|
||||
# Where this bundle's binaries came from, for the release notes.
|
||||
mkdir -p provenance
|
||||
PROVENANCE_FILE=provenance/win-arm64.tsv bash src/releases/record-provenance.sh \
|
||||
'win-arm64' 'Node.js' "${node_from:-}" "${node_full:-$NODE_VERSION}" \
|
||||
"${node_url:-}" \
|
||||
"${node_sha256:-}" || true
|
||||
if [ -s bundle/ferretdb.exe ]; then
|
||||
FERRET_TAG="$(bash src/releases/ferretdb-latest-tag.sh || true)"
|
||||
PROVENANCE_FILE=provenance/win-arm64.tsv bash src/releases/record-provenance.sh \
|
||||
'win-arm64' 'FerretDB' 'wekan/FerretDB' "${FERRET_TAG:-latest}" \
|
||||
'https://github.com/wekan/FerretDB/releases/latest/download/ferretdb-win-arm64.exe' \
|
||||
"${FERRET_SHA:-}" || true
|
||||
fi
|
||||
# Check what goes IN, before anything is archived. This is the honest place
|
||||
# for it: whether the zip can hold a startable bundle is decided here, in a
|
||||
# plain directory, with no archive-listing format in the way.
|
||||
for want in main.js node.exe start-wekan.bat; do
|
||||
if [ ! -s "bundle/$want" ]; then
|
||||
echo "::error::bundle/$want is missing or empty, so the win-arm64 zip cannot start WeKan. The bundle comes from the build job; the lines above say what was copied in."
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
echo "bundle/ has main.js, node.exe and start-wekan.bat:"
|
||||
ls -la bundle
|
||||
|
||||
- name: Create win-arm64 zip
|
||||
if: steps.preflight.outputs.skip != 'true'
|
||||
shell: cmd
|
||||
run: 7z a wekan-%VERSION%-win-arm64.zip bundle
|
||||
|
||||
- name: Verify the win-arm64 zip
|
||||
if: steps.preflight.outputs.skip != 'true'
|
||||
shell: bash
|
||||
run: |
|
||||
# Same question as on the other platforms, asked in bash because the zip
|
||||
# itself is made with 7-Zip under cmd: does this zip actually carry a
|
||||
# startable bundle, or only a name that looks like one?
|
||||
zip="wekan-${VERSION}-win-arm64.zip"
|
||||
if [ ! -f "$zip" ]; then
|
||||
echo "::error::$zip was not created - 7z failed above, or the bundle directory was missing."
|
||||
exit 1
|
||||
fi
|
||||
# A checksum beside the bundle, so a download can be checked.
|
||||
sha256sum "$zip" > "${zip}.sha256sum"
|
||||
cat "${zip}.sha256sum"
|
||||
bytes=$(wc -c < "$zip")
|
||||
if [ "$bytes" -lt 10000000 ]; then
|
||||
echo "::error::$zip is only $bytes bytes; a whole bundle is tens of megabytes. The bundle directory was empty or partial when it was zipped."
|
||||
exit 1
|
||||
fi
|
||||
# Integrity: `7z t` reads every entry and fails on a truncated or corrupt
|
||||
# archive. Together with the check on bundle/ before zipping, that is what
|
||||
# actually decides whether this zip is startable.
|
||||
if ! 7z t "$zip" > 7z-test.log 2>&1; then
|
||||
echo "::error::$zip did not pass 7z t - the archive is corrupt or truncated."
|
||||
tail -n 30 7z-test.log
|
||||
exit 1
|
||||
fi
|
||||
echo "7z t: archive is intact."
|
||||
# The listing is EVIDENCE, printed, not a hidden verdict. v10.48 failed the
|
||||
# release because `grep` found neither "bundle\main.js" nor "bundle/main.js"
|
||||
# in `7z l -ba` output that nothing ever printed, so a bad zip and a bad
|
||||
# grep looked exactly alike. Now the listing shows itself, and a missing
|
||||
# match is a WARNING: bundle/main.js was verified to exist before zipping
|
||||
# and the archive passed its integrity test, so a zero count here says
|
||||
# something about 7-Zip's output format, not about the bundle.
|
||||
# Through a FILE, never a pipe. `cmd | head`/`cmd | grep -q` ends the
|
||||
# reader early, the writer gets SIGPIPE, and with `set -o pipefail` (which
|
||||
# GitHub's bash uses) the pipeline's status becomes 141 - so under `set -e`
|
||||
# a MATCH fails the step. That is what "has no bundle/main.js" was in
|
||||
# v10.48, and what exit code 141 was in v10.49: the file was there both
|
||||
# times, and the listing below proves it (`bundle\main.js`, five lines in).
|
||||
7z l -ba "$zip" > zip-listing.txt 2>/dev/null || true
|
||||
entries="$(wc -l < zip-listing.txt)"
|
||||
echo "7z l -ba listed $entries entries; the first five:"
|
||||
head -5 zip-listing.txt || true
|
||||
for want in main.js node.exe; do
|
||||
n="$(grep -F -c -e "bundle\\$want" -e "bundle/$want" zip-listing.txt || true)"
|
||||
echo " entries matching bundle/$want: $n"
|
||||
if [ "${n:-0}" -eq 0 ]; then
|
||||
echo "::warning::$zip listing shows no bundle/$want, but bundle/$want existed before zipping and the archive passed 7z t. Compare the five listing lines above with what is being searched for."
|
||||
fi
|
||||
done
|
||||
echo "OK: $zip is $((bytes/1024/1024)) MiB, intact, and was built from a bundle that had main.js and node.exe."
|
||||
|
||||
- uses: actions/upload-artifact@v7
|
||||
if: steps.preflight.outputs.skip != 'true'
|
||||
with:
|
||||
name: bundle-win-arm64
|
||||
path: wekan-${{ needs.prepare.outputs.version }}-win-arm64.zip
|
||||
retention-days: 1
|
||||
|
||||
- name: Upload win-arm64 provenance
|
||||
if: steps.preflight.outputs.skip != 'true'
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: provenance-win-arm64
|
||||
path: provenance/
|
||||
if-no-files-found: ignore
|
||||
retention-days: 1
|
||||
|
||||
- name: Attach win-arm64 bundle to the GitHub Release
|
||||
if: steps.preflight.outputs.skip != 'true'
|
||||
shell: bash
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
# The repo is checked out into src/, so the workspace root is not a git
|
||||
# repository; set GH_REPO so `gh` targets wekan/wekan without relying on
|
||||
# git remote detection (else: "fatal: not a git repository").
|
||||
GH_REPO: ${{ github.repository }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
asset="wekan-${VERSION}-win-arm64.zip"
|
||||
if [ ! -f "$asset" ]; then
|
||||
echo "::error::$asset does not exist, so there is nothing to attach. The step that builds it failed, or produced a different name."
|
||||
exit 1
|
||||
fi
|
||||
# The checksum goes up with it, so a download can be checked. It is
|
||||
# built beside the zip by the step above; older jobs that do not make
|
||||
# one still upload cleanly.
|
||||
up=("$asset")
|
||||
[ -f "${asset}.sha256sum" ] && up+=("${asset}.sha256sum")
|
||||
if ! gh release upload "v${VERSION}" "${up[@]}" --clobber; then
|
||||
echo "::error::Could not attach $asset to release v${VERSION}: the release must exist first (the release job), and GITHUB_TOKEN must be allowed to write releases here."
|
||||
exit 1
|
||||
fi
|
||||
# Confirm from the OTHER side. An upload that reports success but leaves no
|
||||
# asset behind is the failure nobody notices until a download 404s.
|
||||
gh release view "v${VERSION}" --json assets --jq '.assets[].name' > release-assets.txt
|
||||
if ! grep -qxF "$(basename "$asset")" release-assets.txt; then
|
||||
echo "::error::$asset is not listed in release v${VERSION} although the upload reported success. Re-run this job."
|
||||
exit 1
|
||||
fi
|
||||
echo "OK: $(basename "$asset") is attached to release v${VERSION} ($(($(wc -c < "$asset")/1024/1024)) MiB)."
|
||||
|
||||
# Always, as the last step: the run summary then answers "what worked and what
|
||||
# did not" for the whole release at a glance, instead of eighteen job logs. A
|
||||
# step that failed has already printed an ::error:: saying why; this names the
|
||||
# job it was in.
|
||||
- name: Job result
|
||||
if: always()
|
||||
# bash explicitly: this same step runs on the Windows and macOS runners too,
|
||||
# where the default shell is PowerShell / not necessarily this bash.
|
||||
shell: bash
|
||||
run: |
|
||||
case "${{ job.status }}" in
|
||||
success) mark='OK ' ;;
|
||||
failure) mark='FAILED ' ;;
|
||||
cancelled) mark='CANCELLED' ;;
|
||||
*) mark='${{ job.status }}' ;;
|
||||
esac
|
||||
echo "$mark build-win-arm64"
|
||||
echo "$mark build-win-arm64" >> "$GITHUB_STEP_SUMMARY"
|
||||
if [ "${{ job.status }}" = "failure" ]; then
|
||||
echo "::error::build-win-arm64 FAILED. The ::error:: line in this job's log, above, says which step and why."
|
||||
fi
|
||||
|
||||
# Build win32 (32-bit Windows) bundle.
|
||||
#
|
||||
# BEST-EFFORT, like mac-x64 and the exotic Linux arches: nodejs.org has no
|
||||
@@ -1573,7 +1966,7 @@ jobs:
|
||||
"${node_url:-}" \
|
||||
"${node_sha256:-}" || true
|
||||
if [ -s bundle/ferretdb.exe ]; then
|
||||
FERRET_TAG="$(bash src/releases/ferretdb-latest-tag.sh)"
|
||||
FERRET_TAG="$(bash src/releases/ferretdb-latest-tag.sh || true)"
|
||||
PROVENANCE_FILE=provenance/win32.tsv bash src/releases/record-provenance.sh \
|
||||
'win32' 'FerretDB' 'wekan/FerretDB' "${FERRET_TAG:-latest}" \
|
||||
'https://github.com/wekan/FerretDB/releases/latest/download/ferretdb-win32.exe' \
|
||||
@@ -1818,7 +2211,7 @@ jobs:
|
||||
"${node_url:-}" \
|
||||
"${node_sha256:-}" || true
|
||||
if [ -s bundle/ferretdb ]; then
|
||||
FERRET_TAG="$(bash releases/ferretdb-latest-tag.sh)"
|
||||
FERRET_TAG="$(bash releases/ferretdb-latest-tag.sh || true)"
|
||||
PROVENANCE_FILE=provenance/mac-arm64.tsv bash releases/record-provenance.sh \
|
||||
'mac-arm64' 'FerretDB' 'wekan/FerretDB' "${FERRET_TAG:-latest}" \
|
||||
'https://github.com/wekan/FerretDB/releases/latest/download/ferretdb-mac-arm64' \
|
||||
@@ -1947,7 +2340,18 @@ jobs:
|
||||
# failing red, and returns on its own if a Node.js for it appears again.
|
||||
build-mac-x64:
|
||||
needs: [prepare, build-amd64, release]
|
||||
runs-on: macos-13 # macos-13 runners are Intel (x86_64); macos-14+ are arm64
|
||||
# Intel (x86_64) macOS. It was `macos-13`, and GitHub RETIRED that image -
|
||||
# actions/runner-images publishes macos-14, macos-15 and macos-26 only, and
|
||||
# macos-13 is gone from the hosted-runner table. A retired label does not
|
||||
# fail: the job QUEUES FOREVER waiting for a runner that will never come, so
|
||||
# every release since then had a build-mac-x64 sitting there for hours until
|
||||
# it was cancelled by hand - and cancelling it cancelled the RUN, which is
|
||||
# what skipped the charts, ucs and nextcloud jobs (they had not started yet).
|
||||
# No release has ever carried a wekan-<version>-mac-x64.zip because of it.
|
||||
# Intel macOS is still offered, under new labels: macos-15-intel and
|
||||
# macos-26-intel (macos-14/15/26 without the suffix are Apple Silicon). This
|
||||
# is the same label .tools/TSC already builds its Intel Mac on.
|
||||
runs-on: macos-15-intel
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
VERSION: ${{ needs.prepare.outputs.version }}
|
||||
@@ -2071,7 +2475,7 @@ jobs:
|
||||
"${node_url:-}" \
|
||||
"${node_sha256:-}" || true
|
||||
if [ -s bundle/ferretdb ]; then
|
||||
FERRET_TAG="$(bash releases/ferretdb-latest-tag.sh)"
|
||||
FERRET_TAG="$(bash releases/ferretdb-latest-tag.sh || true)"
|
||||
PROVENANCE_FILE=provenance/mac-x64.tsv bash releases/record-provenance.sh \
|
||||
'mac-x64' 'FerretDB' 'wekan/FerretDB' "${FERRET_TAG:-latest}" \
|
||||
'https://github.com/wekan/FerretDB/releases/latest/download/ferretdb-mac-amd64' \
|
||||
@@ -2255,6 +2659,38 @@ jobs:
|
||||
node_arch: x86
|
||||
ferretdb_arch: i386
|
||||
optional: true
|
||||
# ARMv6: Raspberry Pi 1 and Zero. It takes wekan/node-patches'
|
||||
# node-armv6 (nobody else publishes an ARMv6 Node - nodejs.org dropped
|
||||
# it after Node 11), and FerretDB and the MongoDB tools build a GOARM=6
|
||||
# armv6 of their own. Their armel is GOARM=5 and WOULD run on these
|
||||
# boards, but in software floating point, so it is not used here.
|
||||
#
|
||||
# The CONTAINER is linux/arm/v7, not linux/arm/v6, and that is not a
|
||||
# typo. DEBIAN HAS NO ARMv6 PORT: debian:trixie publishes arm/v5 and
|
||||
# arm/v7 only, and because containerd treats a lower ARM variant as
|
||||
# compatible, asking it for linux/arm/v6 silently handed back arm/v5 -
|
||||
# Debian armel, ARMv5 SOFT-float. node-armv6 is HARD-float, so it could
|
||||
# not start there and the job died on
|
||||
# qemu-arm: Could not open '/lib/ld-linux-armhf.so.3'
|
||||
# after the whole apt install (v10.80). Debian's arm/v7 IS armhf: the
|
||||
# same hard-float ABI and the same loader, so node-armv6 runs in it.
|
||||
#
|
||||
# Nothing ARMv7 reaches the bundle. What the container does is run
|
||||
# `npm install`, and that install compiles NOTHING - it is npm-rebuild
|
||||
# over pure-JavaScript packages ("rebuilt dependencies successfully",
|
||||
# no node-gyp, no CXX). Every binary in the bundle is downloaded already
|
||||
# built FOR ARMv6: node-armv6, ferretdb-armv6 and the armv6 MongoDB
|
||||
# tools. The container only has to be a userland this arch's node can
|
||||
# RUN in, and armhf is exactly that. The one thing that would have been
|
||||
# the container's own CPU is the bundled qemu-user, and that is why
|
||||
# SAME_ARCH_CONTAINER is false below.
|
||||
- arch: armv6
|
||||
platform: linux/arm/v7
|
||||
image: debian:trixie
|
||||
node_arch: armv6
|
||||
ferretdb_arch: armv6
|
||||
same_arch_container: false
|
||||
optional: true
|
||||
- arch: armhf
|
||||
platform: linux/arm/v7
|
||||
image: debian:trixie
|
||||
@@ -2399,6 +2835,7 @@ jobs:
|
||||
-e NODE_SHA256="$NODE_SHA256" \
|
||||
-e ARCH='${{ matrix.arch }}' \
|
||||
-e NODE_ARCH='${{ matrix.node_arch }}' \
|
||||
-e SAME_ARCH_CONTAINER='${{ matrix.same_arch_container }}' \
|
||||
-v "$(pwd)/bundle:/bundle" \
|
||||
-v "$(pwd)/releases:/releases:ro" \
|
||||
-w /bundle/programs/server \
|
||||
@@ -2436,7 +2873,7 @@ jobs:
|
||||
else
|
||||
echo "::warning::wekan/FerretDB publishes no checksum for ferretdb-${{ matrix.ferretdb_arch }} on this release, so it is unverified."
|
||||
fi
|
||||
FERRET_TAG="$(bash releases/ferretdb-latest-tag.sh)"
|
||||
FERRET_TAG="$(bash releases/ferretdb-latest-tag.sh || true)"
|
||||
bash releases/record-provenance.sh '${{ matrix.arch }}' 'FerretDB' \
|
||||
'wekan/FerretDB' "${FERRET_TAG:-latest}" "$FERRET_URL" "$FERRET_SHA"
|
||||
# Overwrite the inherited amd64 MongoDB Database Tools with this arch's ones.
|
||||
@@ -2858,11 +3295,37 @@ jobs:
|
||||
base="https://github.com/wekan/wekan/releases/download/v${VERSION}"
|
||||
have() { curl -fsSL -o /dev/null -I --retry 3 --retry-delay 5 "$1"; }
|
||||
# docker platform : the wekan bundle arch the Dockerfile downloads for it.
|
||||
# linux/arm/v6 and linux/arm/v7 are BOTH TARGETARCH=arm and differ only in
|
||||
# TARGETVARIANT, which is why the Dockerfile's arch case reads the variant.
|
||||
req="linux/amd64:amd64 linux/arm64:arm64"
|
||||
opt="linux/ppc64le:ppc64le linux/s390x:s390x linux/riscv64:riscv64 linux/386:i386 linux/arm/v7:armhf"
|
||||
opt="linux/ppc64le:ppc64le linux/s390x:s390x linux/riscv64:riscv64 linux/386:i386 linux/arm/v6:armv6 linux/arm/v7:armhf"
|
||||
|
||||
# A bundle on the release is not enough: the BASE IMAGE has to publish the
|
||||
# platform too, and for 32-bit ARM that is not a clean failure when it does
|
||||
# not. containerd treats a LOWER arm variant as compatible, so a
|
||||
# linux/arm/v6 request against a base that has arm/v5 and arm/v7 silently
|
||||
# resolves to arm/v5 - Debian armel, SOFT-float - and the hard-float
|
||||
# node-armv6 inside the armv6 bundle cannot run on that userland. Ask the
|
||||
# base once, and treat a platform it does not publish exactly like a bundle
|
||||
# that did not land. The base is read out of the Dockerfile so there is no
|
||||
# second copy of its name here. arm64 is recorded as arm64/v8, which
|
||||
# everyone writes as linux/arm64, so the implied /v8 is normalised away -
|
||||
# the same normalisation the push-verify does below.
|
||||
base_image="$(awk '/^FROM /{print $2; exit}' Dockerfile)"
|
||||
base_plats="$(docker buildx imagetools inspect "$base_image" \
|
||||
--format '{{range .Manifest.Manifests}}{{.Platform.OS}}/{{.Platform.Architecture}}{{if .Platform.Variant}}/{{.Platform.Variant}}{{end}} {{end}}' \
|
||||
| sed 's#/v8 # #g')" || {
|
||||
echo "::error::Cannot read the platform list of the base image ${base_image}."; exit 1; }
|
||||
echo "Base image ${base_image} publishes: ${base_plats}"
|
||||
base_has() { case " $base_plats " in *" $1 "*) return 0 ;; *) return 1 ;; esac; }
|
||||
|
||||
platforms=""; want=""; arches=""
|
||||
for pair in $req; do
|
||||
p="${pair%%:*}"; a="${pair#*:}"
|
||||
if ! base_has "$p"; then
|
||||
echo "::error::The base image ${base_image} does not publish $p, so the image cannot be built for it - and it is a CORE platform."
|
||||
exit 1
|
||||
fi
|
||||
if have "${base}/wekan-${VERSION}-${a}.zip"; then
|
||||
platforms="${platforms:+$platforms,}$p"; want="${want:+$want }$p"; arches="${arches:+$arches }$a"
|
||||
else
|
||||
@@ -2872,6 +3335,10 @@ jobs:
|
||||
done
|
||||
for pair in $opt; do
|
||||
p="${pair%%:*}"; a="${pair#*:}"
|
||||
if ! base_has "$p"; then
|
||||
echo "::warning::$p is dropped from the image: the base image ${base_image} publishes no $p, and a request for it would resolve to a lower-variant base the ${a} bundle cannot run on. The ${a} bundle zip is unaffected."
|
||||
continue
|
||||
fi
|
||||
if have "${base}/wekan-${VERSION}-${a}.zip"; then
|
||||
platforms="${platforms},$p"; want="${want} $p"; arches="${arches} $a"
|
||||
echo "including $p (wekan-${VERSION}-${a}.zip present)"
|
||||
@@ -3579,7 +4046,18 @@ jobs:
|
||||
# usually transient, so the three attempts above cover a one-off.
|
||||
# (The large-history push that also broke these builds is fixed
|
||||
# separately, by flattening the repo before the push.)
|
||||
echo "::error::If the build ended as 'Stopped' with no artifact: the Launchpad project https://launchpad.net/xet7-craft-remote-build should be MIT / X/Expat (it is set now) - re-set it only if it shows 'None specified'. Otherwise Launchpad cancelled the build as it ran (often an OOM in the Meteor npm install, or a transient build-farm reset - the printed build log ends mid-step); re-run, and if it persists on this arch open a Launchpad question. Builds: https://launchpad.net/~xet7/+snaps" >&2
|
||||
# THE BUILD LOG IS PRINTED ABOVE AND IT SAYS WHY. Read it before
|
||||
# believing any guess in this message - the guess has been wrong. For
|
||||
# four releases this line said "often an OOM in the Meteor npm install,
|
||||
# or a transient build-farm reset", and every one of the four
|
||||
# architectures was in fact failing on one deterministic line:
|
||||
# Failed to copy '.../parts/mongo42/install/mongo42':
|
||||
# no such file or directory
|
||||
# a `stage:` filter naming a path that an amd64/arm64-only part does not
|
||||
# produce anywhere else. Nothing transient about it, and "re-run" was
|
||||
# the one thing that could not help. So these are named as the things to
|
||||
# LOOK FOR in the log above, not as what probably happened.
|
||||
echo "::error::snap-launchpad ${{ matrix.arch }}: the Launchpad build log is printed above - read it first; it names the part and the line that failed. Common causes, in the order they are worth checking: (1) a 'Failed to copy .../parts/<part>/install/<path>' - a stage:/prime: filter naming something the part did not produce on THIS architecture, which is deterministic and will not pass on a re-run; (2) an npm/network error inside a part's override-build, which is transient and is retried; (3) 'Stopped' with no artifact and no error - then check that https://launchpad.net/xet7-craft-remote-build still has a licence set (MIT / X/Expat), and otherwise Launchpad ended the build itself. Builds: https://launchpad.net/~xet7/+snaps" >&2
|
||||
# A wrong or expired LP_CREDENTIALS makes Launchpad answer 401/403, which
|
||||
# reads as an ordinary build failure unless the log is checked. But the
|
||||
# pattern must be SPECIFIC: a bare `401`/`403` matches any three digits in
|
||||
@@ -3651,11 +4129,42 @@ jobs:
|
||||
fi
|
||||
# base: core24 allows publishing to stable and candidate (core26 does not).
|
||||
for f in "${snaps[@]}"; do
|
||||
echo "Uploading $f to the Snap Store (stable,candidate,beta,edge)..."
|
||||
if ! snapcraft upload --release=stable,candidate,beta,edge "$f"; then
|
||||
echo "::error::The Snap Store refused the upload of $f. The snapcraft line above says which: 'is not a valid file' means the build produced nothing usable; 'Credentials could not be parsed' means SNAP_AUTH is not a readable exported login; 401/403 means it lacks the ACL for this snap name. The last two are fixed by re-exporting for all three names: snapcraft export-login --snaps wekan,wekan-ondra,wekan-gantt-gpl --acls package_access,package_push,package_release,package_update snap-auth.txt"
|
||||
# RETRIED, because the upload can fail for a reason that has nothing
|
||||
# to do with the snap. The store accepts the file, scans it, and can
|
||||
# then answer:
|
||||
# Status: error while processing
|
||||
# Issues while processing snap:
|
||||
# - binary_sha3_384: Error checking upload uniqueness.
|
||||
# which is the store failing its OWN duplicate check on the digest
|
||||
# it just computed - a server-side hiccup, not a bad snap. It hit
|
||||
# riscv64, ppc64el and s390x in the same v10.78 run, each after a
|
||||
# Launchpad build that had succeeded, so three good snaps were lost
|
||||
# to it at once. Re-uploading the identical file is what fixes it.
|
||||
up_attempts=3
|
||||
uploaded=0
|
||||
for u in $(seq 1 "$up_attempts"); do
|
||||
echo "Uploading $f to the Snap Store (stable,candidate,beta,edge), attempt $u/$up_attempts..."
|
||||
if snapcraft upload --release=stable,candidate,beta,edge "$f" 2>&1 | tee /tmp/snap-upload.log; then
|
||||
uploaded=1
|
||||
break
|
||||
fi
|
||||
# Only the store's own processing errors are worth retrying. A
|
||||
# rejected file, or credentials the store will not accept, will be
|
||||
# rejected exactly the same way three times - and retrying those
|
||||
# only buries the message that says what to fix.
|
||||
if grep -qiE 'Error checking upload uniqueness|error while processing|502 Bad Gateway|503 Service|504 Gateway|Timeout|Connection (reset|aborted)' /tmp/snap-upload.log; then
|
||||
if [ "$u" -lt "$up_attempts" ]; then
|
||||
echo "::warning::The Snap Store failed while PROCESSING $f (not a problem with the snap). Retrying in $((u * 30))s."
|
||||
sleep $((u * 30))
|
||||
continue
|
||||
fi
|
||||
echo "::error::The Snap Store failed while processing $f on every one of $up_attempts attempts. This is the store's own upload-uniqueness/processing check failing on a snap it accepted - the file itself built and downloaded fine, so re-running this job later usually publishes it unchanged. Nothing in this repository needs to change." >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "::error::The Snap Store refused the upload of $f. The snapcraft line above says which: 'is not a valid file' means the build produced nothing usable; 'Credentials could not be parsed' means SNAP_AUTH is not a readable exported login; 401/403 means it lacks the ACL for this snap name. The last two are fixed by re-exporting for all three names: snapcraft export-login --snaps wekan,wekan-ondra,wekan-gantt-gpl --acls package_access,package_push,package_release,package_update snap-auth.txt" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
[ "$uploaded" -eq 1 ] || exit 1
|
||||
done
|
||||
|
||||
- name: Attach the ${{ matrix.arch }} snap to the GitHub Release
|
||||
@@ -3921,8 +4430,13 @@ jobs:
|
||||
ucs:
|
||||
# ENABLED. `continue-on-error: true` below means a failure here can never
|
||||
# fail the release or hold up another job - the point of running it is to
|
||||
# SEE what it reports. Disable again with `if: ${{ false }}`.
|
||||
# SEE what it reports. Disable again by replacing the `if` below with
|
||||
# `if: ${{ false }}`.
|
||||
needs: [prepare, release, docker]
|
||||
# always(), for the same reason as the charts job above: a cancellation
|
||||
# elsewhere in the run skips every job that has not started yet, and in
|
||||
# v10.80 that silently dropped this one along with charts.
|
||||
if: ${{ always() && needs.prepare.result == 'success' && needs.release.result == 'success' && needs.docker.result == 'success' }}
|
||||
continue-on-error: true
|
||||
timeout-minutes: 45
|
||||
runs-on: ubuntu-latest
|
||||
@@ -4016,8 +4530,13 @@ jobs:
|
||||
nextcloud:
|
||||
# ENABLED. `continue-on-error: true` below means a failure here can never
|
||||
# fail the release or hold up another job - the point of running it is to
|
||||
# SEE what it reports. Disable again with `if: ${{ false }}`.
|
||||
# SEE what it reports. Disable again by replacing the `if` below with
|
||||
# `if: ${{ false }}`.
|
||||
needs: [prepare, release, docker]
|
||||
# always(), for the same reason as the charts job above: a cancellation
|
||||
# elsewhere in the run skips every job that has not started yet, and in
|
||||
# v10.80 that silently dropped this one along with charts.
|
||||
if: ${{ always() && needs.prepare.result == 'success' && needs.release.result == 'success' && needs.docker.result == 'success' }}
|
||||
continue-on-error: true
|
||||
timeout-minutes: 60
|
||||
runs-on: ubuntu-latest
|
||||
@@ -4143,6 +4662,7 @@ jobs:
|
||||
- build-amd64
|
||||
- build-arm64
|
||||
- build-win64
|
||||
- build-win-arm64
|
||||
- build-win32
|
||||
- build-mac-arm64
|
||||
- build-mac-x64
|
||||
|
||||
@@ -2,7 +2,35 @@
|
||||
|
||||
Codex reads this file at the repo root before doing work here. Follow it.
|
||||
|
||||
## First: are you the maintainer or a contributor?
|
||||
## First: who maintains this, and who is committing?
|
||||
|
||||
**WeKan, the `wekan/` repositories cloned under `.tools/`, and
|
||||
[Secretchronicles/TSC](https://github.com/Secretchronicles/TSC) are all maintained by
|
||||
Lauri Ojansivu (xet7) `<x@xet7.org>`** — [wekan/wekan](https://github.com/wekan/wekan),
|
||||
[wekan/FerretDB](https://github.com/wekan/FerretDB),
|
||||
[wekan/node-patches](https://github.com/wekan/node-patches),
|
||||
[wekan/mongo-tools-patches](https://github.com/wekan/mongo-tools-patches) and TSC,
|
||||
which is under the **Secretchronicles** organisation rather than **wekan** and is his
|
||||
all the same — his GitHub profile, [xet7](https://github.com/xet7), says exactly that:
|
||||
*"WeKan and TSC maintainer"*. Work done on the maintainer's behalf is committed as
|
||||
**`Lauri Ojansivu <x@xet7.org>`** — that author, in every one of those repositories,
|
||||
every time. Two rules follow from it and neither has an exception:
|
||||
|
||||
- **Never attribute a commit to an AI.** No `Co-Authored-By:` trailer, no "Generated
|
||||
with", no assistant or model name — not in the commit message, not in a pull-request
|
||||
body, not in the CHANGELOG. [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) is where this
|
||||
comes from: *"For pull requests, mention only those participants that are
|
||||
**human**."* A `Thanks to ... and xet7 !` line credits people — the issue reporter
|
||||
and xet7 — never a tool.
|
||||
- **If the git identity is missing or wrong in one of these checkouts, set it; do not
|
||||
commit under something else.** The `.tools/` clones are made by `build.sh` inside
|
||||
this checkout and can come up with no `user.name`/`user.email` of their own, which
|
||||
would silently author a commit as whatever the machine's default is:
|
||||
|
||||
```
|
||||
git -C .tools/<repo> config user.name 'Lauri Ojansivu'
|
||||
git -C .tools/<repo> config user.email 'x@xet7.org'
|
||||
```
|
||||
|
||||
Check the current git identity before committing or releasing:
|
||||
|
||||
@@ -10,16 +38,25 @@ Check the current git identity before committing or releasing:
|
||||
git config user.name && git config user.email
|
||||
```
|
||||
|
||||
- **Maintainer mode** — ONLY when the identity is exactly
|
||||
`Lauri Ojansivu <x@xet7.org>` (name `Lauri Ojansivu`, email `x@xet7.org`). Then, and
|
||||
only then: commit **directly to the current branch** as `Lauri Ojansivu <x@xet7.org>`
|
||||
with no AI trailer and no pull request, and the **publishing / release steps** below
|
||||
are available.
|
||||
- **Contributor mode** — any other git identity. Then: do **not** commit directly to
|
||||
the branch and do **not** run any release/publishing step. Make changes on a branch
|
||||
and open a **pull request** for the maintainer to review. The "commit as Lauri
|
||||
Ojansivu", "commit directly", and all release instructions below are **maintainer-only
|
||||
and do not apply to you**.
|
||||
- **Maintainer mode** — the identity is `Lauri Ojansivu <x@xet7.org>` (name
|
||||
`Lauri Ojansivu`, email `x@xet7.org`), or it is unset in a checkout of one of the
|
||||
repositories above, which means it is to be SET to that as above rather than worked
|
||||
around. Then: commit **directly to the current branch** as
|
||||
`Lauri Ojansivu <x@xet7.org>` with no AI trailer and no pull request, and the
|
||||
**publishing / release steps** below are available.
|
||||
- **Contributor mode** — the identity is somebody ELSE, in a fork or a clone of your
|
||||
own. Then: do **not** commit directly to the branch and do **not** run any
|
||||
release/publishing step. Make changes on a branch and open a **pull request** for
|
||||
the maintainer to review, and keep that pull request free of AI attribution too.
|
||||
The "commit as Lauri Ojansivu", "commit directly", and all release instructions
|
||||
below are **maintainer-only and do not apply to you**.
|
||||
|
||||
Maintainer mode covers TSC as well: commit directly to its `devel` branch, no pull
|
||||
request, same author and no AI attribution. What it does NOT bring along is WeKan's
|
||||
house style — TSC keeps its own **GNU ChangeLog** `CHANGELOG` and its own release
|
||||
process, because a project is read on its own terms (see the CHANGELOG section below).
|
||||
The one repository under `.tools/` that is somebody else's is `sandstorm-io/sandstorm`,
|
||||
cloned for reference only.
|
||||
|
||||
Everything below marked as maintainer-specific (committing directly, the exact commit
|
||||
author, and the entire "Making a release" / publishing flow) applies only in maintainer
|
||||
@@ -121,21 +158,75 @@ pushed to Transifex as if it were human.
|
||||
"Co-Authored-By" or any other AI trailer, directly to the `main` branch of WeKan and
|
||||
the `main-v1` branch of the FerretDB fork. **Do not make pull requests.** (Contributors
|
||||
do the opposite: work on a branch and open a pull request — see the top section.)
|
||||
- Lauri Ojansivu (xet7) maintains WeKan (https://wekan.fi) and the FerretDB v1 fork.
|
||||
This is the same rule as the top section, restated where the release work is: one
|
||||
author, `Lauri Ojansivu <x@xet7.org>`, and no AI attribution anywhere.
|
||||
- Lauri Ojansivu (xet7) maintains WeKan (https://wekan.fi), the FerretDB v1 fork, and
|
||||
the two patch repositories under `.tools/` — node-patches and mongo-tools-patches.
|
||||
- Directory structure:
|
||||
- `wekan` — this repo (https://github.com/wekan/wekan); see
|
||||
`docs/DeveloperDocs/Directory-Structure.md`; `CHANGELOG.md` at root.
|
||||
- `../w/wekan.fi` — the WeKan website.
|
||||
- `FerretDB` subdirectory (when present) — https://github.com/wekan/FerretDB, its own
|
||||
`CHANGELOG.md`. FerretDB `.go` files must contain **no** application-specific names
|
||||
(say "the client" / "a Meteor 3 driver" / a bare `#NNNN`); its `CHANGELOG.md` may
|
||||
use `wekan/wekan#NNNN`.
|
||||
- `sandstorm` subdirectory (when present) — https://github.com/sandstorm-io/sandstorm.
|
||||
- `.tools/` — everything that is NOT part of this repository but is needed to
|
||||
build, test and release it, in ONE directory that `.gitignore` and
|
||||
`.meteorignore` already exclude (each used to need its own ignore entry at
|
||||
the repo root), so nothing in it can reach a commit or a Meteor rebuild. Two
|
||||
different kinds of thing live there, and the difference matters:
|
||||
|
||||
**Companion git repositories.** Separate repositories with their own history,
|
||||
branches, changelog and release flow — a commit here is never a commit there.
|
||||
`build.sh`'s `ensure_tool_repo` clones one on demand (SSH first, HTTPS
|
||||
second), so a fresh checkout needs no manual setup:
|
||||
|
||||
| Path | Repository | Branch | What it is |
|
||||
| --- | --- | --- | --- |
|
||||
| `.tools/FerretDB` | wekan/FerretDB | `main-v1` | the FerretDB v1 fork WeKan ships as its default database |
|
||||
| `.tools/node-patches` | wekan/node-patches | `main` | patches to upstream Node.js; builds the `node-<platform>` binaries the bundles, the Docker image and the snap embed |
|
||||
| `.tools/mongo-tools-patches` | wekan/mongo-tools-patches | `main` | patches to the MongoDB Database Tools; builds `<tool>-<arch>` |
|
||||
| `.tools/TSC` | Secretchronicles/TSC | `devel` | the game xet7 also maintains — same author and maintainer mode, its own GNU ChangeLog and release process |
|
||||
| `.tools/sandstorm` | sandstorm-io/sandstorm | — | upstream Sandstorm, when present — somebody else's project, cloned for reference |
|
||||
|
||||
**Unpacked toolchains and caches.** Downloads, not repositories — put there by
|
||||
the sandbox instructions in `docs/Security/Sandboxes/vscode/README.md`, deleted
|
||||
and re-fetched freely, never committed anywhere:
|
||||
`node-v<version>-linux-<arch>/` (the Node.js the test suites are run with),
|
||||
`go/` with `gopath/`, `gomodcache/` and `gocache/` (FerretDB's Go builds),
|
||||
`.meteor/` when `HOME` is pointed at `.tools`, and the `TSC*` AppImage.
|
||||
- **Do NOT add a `CLAUDE.md` or an `AGENTS.md` to any repository under
|
||||
`.tools/`.** node-patches and mongo-tools-patches each had a pair and they were
|
||||
REMOVED on purpose: the rules are the same for every one of these repositories,
|
||||
and a second copy of a rule drifts from the first. THIS file, and its `AGENTS.md`
|
||||
twin beside it, are where they live for all of them. Something true of only one
|
||||
of those repositories goes in that repository's own `README.md` or `docs/`,
|
||||
never in a new instruction file — and if you find one there, remove it rather
|
||||
than updating it.
|
||||
- `.tools/FerretDB` specifics — FerretDB `.go` files must contain **no**
|
||||
application-specific names (say "the client" / "a Meteor 3 driver" / a bare
|
||||
`#NNNN`); its `CHANGELOG.md` may use `wekan/wekan#NNNN`.
|
||||
|
||||
### CHANGELOG
|
||||
|
||||
- **Every repository writes its changelog in the format that repository's own file
|
||||
already uses.** Open its changelog, read the entries above the place you are
|
||||
adding one, and match them — never import another project's shape into it. The
|
||||
five that come up here:
|
||||
|
||||
| Repository | File | Format |
|
||||
| --- | --- | --- |
|
||||
| `wekan/wekan` | `CHANGELOG.md` | the WeKan format this section describes: `# Platforms`, `# TODO Later`, then `# v<MAJOR>.<MINOR> YYYY-MM-DD WeKan ® release` sections of `<details>` entries whose `<summary>` links the commit |
|
||||
| `wekan/node-patches` | `CHANGELOG.md` | the same WeKan format, with `# Upcoming node-patches release` |
|
||||
| `wekan/mongo-tools-patches` | `CHANGELOG.md` | the same WeKan format, with `# Upcoming mongo-tools-patches release` |
|
||||
| `wekan/FerretDB` | `CHANGELOG.md` | **upstream FerretDB's** format, not WeKan's: `## [v1.48.0](tag URL) (YYYY-MM-DD)` and `### New Features 🎉` / `### Fixed 🐛` / `### Other Changes 🤖` bullets ending `by @xet7. Thanks to xet7.` |
|
||||
| `Secretchronicles/TSC` | `CHANGELOG` (no extension) | **GNU ChangeLog** format: a `YYYY-MM-DD Name <email>` header line, then TAB-indented `* Version …` / `* Fix: …` / `* Misc: …` entries, wrapped and continued with further tabs, each ending `(by Name)` |
|
||||
|
||||
The reason is the reader, not consistency for its own sake: a FerretDB release is
|
||||
read beside upstream FerretDB's releases, and a TSC entry beside a decade of GNU
|
||||
ChangeLog entries. A WeKan-shaped `<details>` block in either would be the odd one
|
||||
out and would break the tooling that parses them. When this file and the file being
|
||||
edited disagree, **the file being edited wins** — and everything below in this
|
||||
section is about the WeKan format specifically.
|
||||
- During development, add entries under a new `# Upcoming WeKan ® release` section above
|
||||
the newest release (FerretDB uses `## Upcoming FerretDB release`). Do **not** hand-edit
|
||||
the newest release (FerretDB uses `## Upcoming FerretDB release`; the patch repos use
|
||||
`# Upcoming <repo> release`). Do **not** hand-edit
|
||||
`package.json` or any other version reference — the release workflow bumps those.
|
||||
- **The file's shape, top to bottom** — keep it exactly as it is now:
|
||||
1. `# Platforms` — the line `Newest WeKan at these platforms:` and the Install /
|
||||
@@ -342,7 +433,7 @@ All publishing / release steps below are maintainer-only. Contributors never run
|
||||
version reference, then the release jobs tag `v<new>` and publish the GitHub Release).
|
||||
An explicit `oldversion newversion` pair still overrides. Adding entries under Upcoming
|
||||
is the only hand step.
|
||||
- FerretDB: run `./build.sh release-ferretdb` from the `FerretDB` subdirectory (no
|
||||
- FerretDB: run `./build.sh release-ferretdb` from `.tools/FerretDB` (no
|
||||
version). It renames `## Upcoming FerretDB release` to the next version with the
|
||||
correct git-tag link, commits + tags + pushes, then triggers `release-all.yml` (which
|
||||
in turn triggers `docker.yml` for the multi-arch image). It refuses to re-release an
|
||||
|
||||
+1868
-4
File diff suppressed because it is too large.
Load diff
@@ -2,7 +2,35 @@
|
||||
|
||||
Claude Code reads this file at the repo root before doing work here. Follow it.
|
||||
|
||||
## First: are you the maintainer or a contributor?
|
||||
## First: who maintains this, and who is committing?
|
||||
|
||||
**WeKan, the `wekan/` repositories cloned under `.tools/`, and
|
||||
[Secretchronicles/TSC](https://github.com/Secretchronicles/TSC) are all maintained by
|
||||
Lauri Ojansivu (xet7) `<x@xet7.org>`** — [wekan/wekan](https://github.com/wekan/wekan),
|
||||
[wekan/FerretDB](https://github.com/wekan/FerretDB),
|
||||
[wekan/node-patches](https://github.com/wekan/node-patches),
|
||||
[wekan/mongo-tools-patches](https://github.com/wekan/mongo-tools-patches) and TSC,
|
||||
which is under the **Secretchronicles** organisation rather than **wekan** and is his
|
||||
all the same — his GitHub profile, [xet7](https://github.com/xet7), says exactly that:
|
||||
*"WeKan and TSC maintainer"*. Work done on the maintainer's behalf is committed as
|
||||
**`Lauri Ojansivu <x@xet7.org>`** — that author, in every one of those repositories,
|
||||
every time. Two rules follow from it and neither has an exception:
|
||||
|
||||
- **Never attribute a commit to an AI.** No `Co-Authored-By:` trailer, no "Generated
|
||||
with", no assistant or model name — not in the commit message, not in a pull-request
|
||||
body, not in the CHANGELOG. [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) is where this
|
||||
comes from: *"For pull requests, mention only those participants that are
|
||||
**human**."* A `Thanks to ... and xet7 !` line credits people — the issue reporter
|
||||
and xet7 — never a tool.
|
||||
- **If the git identity is missing or wrong in one of these checkouts, set it; do not
|
||||
commit under something else.** The `.tools/` clones are made by `build.sh` inside
|
||||
this checkout and can come up with no `user.name`/`user.email` of their own, which
|
||||
would silently author a commit as whatever the machine's default is:
|
||||
|
||||
```
|
||||
git -C .tools/<repo> config user.name 'Lauri Ojansivu'
|
||||
git -C .tools/<repo> config user.email 'x@xet7.org'
|
||||
```
|
||||
|
||||
Check the current git identity before committing or releasing:
|
||||
|
||||
@@ -10,16 +38,25 @@ Check the current git identity before committing or releasing:
|
||||
git config user.name && git config user.email
|
||||
```
|
||||
|
||||
- **Maintainer mode** — ONLY when the identity is exactly
|
||||
`Lauri Ojansivu <x@xet7.org>` (name `Lauri Ojansivu`, email `x@xet7.org`). Then, and
|
||||
only then: commit **directly to the current branch** as `Lauri Ojansivu <x@xet7.org>`
|
||||
with no AI trailer and no pull request, and the **publishing / release steps** below
|
||||
are available.
|
||||
- **Contributor mode** — any other git identity. Then: do **not** commit directly to
|
||||
the branch and do **not** run any release/publishing step. Make changes on a branch
|
||||
and open a **pull request** for the maintainer to review. The "commit as Lauri
|
||||
Ojansivu", "commit directly", and all release instructions below are **maintainer-only
|
||||
and do not apply to you**.
|
||||
- **Maintainer mode** — the identity is `Lauri Ojansivu <x@xet7.org>` (name
|
||||
`Lauri Ojansivu`, email `x@xet7.org`), or it is unset in a checkout of one of the
|
||||
repositories above, which means it is to be SET to that as above rather than worked
|
||||
around. Then: commit **directly to the current branch** as
|
||||
`Lauri Ojansivu <x@xet7.org>` with no AI trailer and no pull request, and the
|
||||
**publishing / release steps** below are available.
|
||||
- **Contributor mode** — the identity is somebody ELSE, in a fork or a clone of your
|
||||
own. Then: do **not** commit directly to the branch and do **not** run any
|
||||
release/publishing step. Make changes on a branch and open a **pull request** for
|
||||
the maintainer to review, and keep that pull request free of AI attribution too.
|
||||
The "commit as Lauri Ojansivu", "commit directly", and all release instructions
|
||||
below are **maintainer-only and do not apply to you**.
|
||||
|
||||
Maintainer mode covers TSC as well: commit directly to its `devel` branch, no pull
|
||||
request, same author and no AI attribution. What it does NOT bring along is WeKan's
|
||||
house style — TSC keeps its own **GNU ChangeLog** `CHANGELOG` and its own release
|
||||
process, because a project is read on its own terms (see the CHANGELOG section below).
|
||||
The one repository under `.tools/` that is somebody else's is `sandstorm-io/sandstorm`,
|
||||
cloned for reference only.
|
||||
|
||||
Everything below marked as maintainer-specific (committing directly, the exact commit
|
||||
author, and the entire "Making a release" / publishing flow) applies only in maintainer
|
||||
@@ -121,26 +158,75 @@ pushed to Transifex as if it were human.
|
||||
"Co-Authored-By" or any other AI trailer, directly to the `main` branch of WeKan and
|
||||
the `main-v1` branch of the FerretDB fork. **Do not make pull requests.** (Contributors
|
||||
do the opposite: work on a branch and open a pull request — see the top section.)
|
||||
- Lauri Ojansivu (xet7) maintains WeKan (https://wekan.fi) and the FerretDB v1 fork.
|
||||
This is the same rule as the top section, restated where the release work is: one
|
||||
author, `Lauri Ojansivu <x@xet7.org>`, and no AI attribution anywhere.
|
||||
- Lauri Ojansivu (xet7) maintains WeKan (https://wekan.fi), the FerretDB v1 fork, and
|
||||
the two patch repositories under `.tools/` — node-patches and mongo-tools-patches.
|
||||
- Directory structure:
|
||||
- `wekan` — this repo (https://github.com/wekan/wekan); see
|
||||
`docs/DeveloperDocs/Directory-Structure.md`; `CHANGELOG.md` at root.
|
||||
- `../w/wekan.fi` — the WeKan website.
|
||||
- `.tools/` — companion repos cloned INSIDE this checkout, in one directory
|
||||
that `.gitignore` and `.meteorignore` already exclude (they used to be one
|
||||
ignored subdirectory each at the repo root). `build.sh`'s `ensure_tool_repo`
|
||||
clones one on demand, so a fresh checkout needs no manual setup:
|
||||
`.tools/FerretDB`, `.tools/node-patches`, `.tools/mongo-tools-patches`.
|
||||
- `.tools/FerretDB` (cloned on demand) — https://github.com/wekan/FerretDB, its own
|
||||
`CHANGELOG.md`. FerretDB `.go` files must contain **no** application-specific names
|
||||
(say "the client" / "a Meteor 3 driver" / a bare `#NNNN`); its `CHANGELOG.md` may
|
||||
use `wekan/wekan#NNNN`.
|
||||
- `.tools/sandstorm` (when present) — https://github.com/sandstorm-io/sandstorm.
|
||||
- `.tools/` — everything that is NOT part of this repository but is needed to
|
||||
build, test and release it, in ONE directory that `.gitignore` and
|
||||
`.meteorignore` already exclude (each used to need its own ignore entry at
|
||||
the repo root), so nothing in it can reach a commit or a Meteor rebuild. Two
|
||||
different kinds of thing live there, and the difference matters:
|
||||
|
||||
**Companion git repositories.** Separate repositories with their own history,
|
||||
branches, changelog and release flow — a commit here is never a commit there.
|
||||
`build.sh`'s `ensure_tool_repo` clones one on demand (SSH first, HTTPS
|
||||
second), so a fresh checkout needs no manual setup:
|
||||
|
||||
| Path | Repository | Branch | What it is |
|
||||
| --- | --- | --- | --- |
|
||||
| `.tools/FerretDB` | wekan/FerretDB | `main-v1` | the FerretDB v1 fork WeKan ships as its default database |
|
||||
| `.tools/node-patches` | wekan/node-patches | `main` | patches to upstream Node.js; builds the `node-<platform>` binaries the bundles, the Docker image and the snap embed |
|
||||
| `.tools/mongo-tools-patches` | wekan/mongo-tools-patches | `main` | patches to the MongoDB Database Tools; builds `<tool>-<arch>` |
|
||||
| `.tools/TSC` | Secretchronicles/TSC | `devel` | the game xet7 also maintains — same author and maintainer mode, its own GNU ChangeLog and release process |
|
||||
| `.tools/sandstorm` | sandstorm-io/sandstorm | — | upstream Sandstorm, when present — somebody else's project, cloned for reference |
|
||||
|
||||
**Unpacked toolchains and caches.** Downloads, not repositories — put there by
|
||||
the sandbox instructions in `docs/Security/Sandboxes/vscode/README.md`, deleted
|
||||
and re-fetched freely, never committed anywhere:
|
||||
`node-v<version>-linux-<arch>/` (the Node.js the test suites are run with),
|
||||
`go/` with `gopath/`, `gomodcache/` and `gocache/` (FerretDB's Go builds),
|
||||
`.meteor/` when `HOME` is pointed at `.tools`, and the `TSC*` AppImage.
|
||||
- **Do NOT add a `CLAUDE.md` or an `AGENTS.md` to any repository under
|
||||
`.tools/`.** node-patches and mongo-tools-patches each had a pair and they were
|
||||
REMOVED on purpose: the rules are the same for every one of these repositories,
|
||||
and a second copy of a rule drifts from the first. THIS file, and its `AGENTS.md`
|
||||
twin beside it, are where they live for all of them. Something true of only one
|
||||
of those repositories goes in that repository's own `README.md` or `docs/`,
|
||||
never in a new instruction file — and if you find one there, remove it rather
|
||||
than updating it.
|
||||
- `.tools/FerretDB` specifics — FerretDB `.go` files must contain **no**
|
||||
application-specific names (say "the client" / "a Meteor 3 driver" / a bare
|
||||
`#NNNN`); its `CHANGELOG.md` may use `wekan/wekan#NNNN`.
|
||||
|
||||
### CHANGELOG
|
||||
|
||||
- **Every repository writes its changelog in the format that repository's own file
|
||||
already uses.** Open its changelog, read the entries above the place you are
|
||||
adding one, and match them — never import another project's shape into it. The
|
||||
five that come up here:
|
||||
|
||||
| Repository | File | Format |
|
||||
| --- | --- | --- |
|
||||
| `wekan/wekan` | `CHANGELOG.md` | the WeKan format this section describes: `# Platforms`, `# TODO Later`, then `# v<MAJOR>.<MINOR> YYYY-MM-DD WeKan ® release` sections of `<details>` entries whose `<summary>` links the commit |
|
||||
| `wekan/node-patches` | `CHANGELOG.md` | the same WeKan format, with `# Upcoming node-patches release` |
|
||||
| `wekan/mongo-tools-patches` | `CHANGELOG.md` | the same WeKan format, with `# Upcoming mongo-tools-patches release` |
|
||||
| `wekan/FerretDB` | `CHANGELOG.md` | **upstream FerretDB's** format, not WeKan's: `## [v1.48.0](tag URL) (YYYY-MM-DD)` and `### New Features 🎉` / `### Fixed 🐛` / `### Other Changes 🤖` bullets ending `by @xet7. Thanks to xet7.` |
|
||||
| `Secretchronicles/TSC` | `CHANGELOG` (no extension) | **GNU ChangeLog** format: a `YYYY-MM-DD Name <email>` header line, then TAB-indented `* Version …` / `* Fix: …` / `* Misc: …` entries, wrapped and continued with further tabs, each ending `(by Name)` |
|
||||
|
||||
The reason is the reader, not consistency for its own sake: a FerretDB release is
|
||||
read beside upstream FerretDB's releases, and a TSC entry beside a decade of GNU
|
||||
ChangeLog entries. A WeKan-shaped `<details>` block in either would be the odd one
|
||||
out and would break the tooling that parses them. When this file and the file being
|
||||
edited disagree, **the file being edited wins** — and everything below in this
|
||||
section is about the WeKan format specifically.
|
||||
- During development, add entries under a new `# Upcoming WeKan ® release` section above
|
||||
the newest release (FerretDB uses `## Upcoming FerretDB release`). Do **not** hand-edit
|
||||
the newest release (FerretDB uses `## Upcoming FerretDB release`; the patch repos use
|
||||
`# Upcoming <repo> release`). Do **not** hand-edit
|
||||
`package.json` or any other version reference — the release workflow bumps those.
|
||||
- **The file's shape, top to bottom** — keep it exactly as it is now:
|
||||
1. `# Platforms` — the line `Newest WeKan at these platforms:` and the Install /
|
||||
|
||||
+25
-2
@@ -3,6 +3,14 @@
|
||||
# arch this image targets - amd64, arm64, 386, arm/v7, ppc64le, riscv64, s390x -
|
||||
# so ONE base covers them all, and it is the same base WeKan's per-arch .zip
|
||||
# bundles are already built in (releases/... build-extra-arches).
|
||||
#
|
||||
# The ONE it does not ship is arm/v6: debian:trixie's manifest list has arm/v5
|
||||
# and arm/v7 and nothing between them. That matters because containerd treats a
|
||||
# LOWER ARM variant as compatible, so a linux/arm/v6 request does not fail - it
|
||||
# quietly resolves to the arm/v5 (armel, SOFT-float) image, whose loader and
|
||||
# glibc cannot run the hard-float node-armv6 in the armv6 bundle. The docker job
|
||||
# therefore asks this base what it publishes and drops a platform it lacks; see
|
||||
# docs/Platforms/FOSS/Container/Docker/CPU-platforms.md.
|
||||
FROM debian:trixie
|
||||
LABEL maintainer="wekan"
|
||||
LABEL org.opencontainers.image.ref.name="debian"
|
||||
@@ -12,7 +20,7 @@ LABEL org.opencontainers.image.source="https://github.com/wekan/wekan"
|
||||
# TARGETARCH and TARGETVARIANT are automatically provided by Docker Buildx
|
||||
ARG TARGETARCH
|
||||
ARG TARGETVARIANT
|
||||
ARG VERSION=10.78
|
||||
ARG VERSION=10.85
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
ENV BUILD_DEPS="apt-utils gnupg wget bzip2 g++ curl libarchive-tools build-essential git ca-certificates python3 unzip"
|
||||
@@ -210,7 +218,22 @@ case "${TARGETARCH}" in
|
||||
"s390x") WEKAN_ARCH="s390x" ;;
|
||||
"riscv64") WEKAN_ARCH="riscv64" ;;
|
||||
"386") WEKAN_ARCH="i386" ;;
|
||||
"arm") WEKAN_ARCH="armhf" ;;
|
||||
# BOTH linux/arm/v6 and linux/arm/v7 arrive here as TARGETARCH=arm - the CPU
|
||||
# generation is in TARGETVARIANT, not in TARGETARCH - so this branch MUST read
|
||||
# the variant. Mapping "arm" straight to armhf, as it did, would hand an ARMv6
|
||||
# board (Raspberry Pi 1, Zero) the armhf bundle, which is built to Debian's
|
||||
# ARMv7-A baseline and whose instructions that board cannot execute.
|
||||
"arm")
|
||||
case "${TARGETVARIANT}" in
|
||||
"v6") WEKAN_ARCH="armv6" ;;
|
||||
# v7, and an unset variant, are Debian's armhf port: ARMv7-A,
|
||||
# VFPv3-D16 hard-float. That is what linux/arm/v7 runs.
|
||||
"v7"|"") WEKAN_ARCH="armhf" ;;
|
||||
# v5 is armel: FerretDB and the MongoDB tools publish it (they are Go),
|
||||
# but Node.js does not exist for ARMv5 at all, so there is no bundle to
|
||||
# put in an image and refusing is the only honest answer.
|
||||
*) echo "Unsupported 32-bit ARM variant: ${TARGETVARIANT} (only v6 and v7 have a WeKan bundle)"; exit 1 ;;
|
||||
esac ;;
|
||||
*) echo "Unsupported architecture: ${TARGETARCH}${TARGETVARIANT:+/${TARGETVARIANT}}"; exit 1 ;;
|
||||
esac
|
||||
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
appId: wekan-public/apps/77b94f60-dec9-0136-304e-16ff53095928
|
||||
appVersion: "v10.78.0"
|
||||
appVersion: "v10.85.0"
|
||||
files:
|
||||
userUploads:
|
||||
- README.md
|
||||
|
||||
@@ -253,6 +253,8 @@ echo 19^) Delete a git tag, locally and on the remote
|
||||
echo 20^) Move the 'stable' tag to HEAD
|
||||
echo 21^) Release the wekan-ondra / wekan-gantt-gpl variants, part 1
|
||||
echo 22^) Release the wekan-ondra / wekan-gantt-gpl variants, part 2
|
||||
echo 23^) Report ^(or repair^) the Helm chart index for past releases
|
||||
echo 24^) Rebuild the Helm index.yaml from the chart packages
|
||||
set "choice="
|
||||
set /p "choice=Choose: "
|
||||
if "%choice%"=="1" call :rel_run "releases/release-all.sh" ""
|
||||
@@ -277,6 +279,8 @@ if "%choice%"=="19" call :rel_run "releases/delete-tag.sh" "Version tag, e.g. v1
|
||||
if "%choice%"=="20" call :rel_cmd "git tag --force stable HEAD && git push --tags --force && git push --follow-tags" ""
|
||||
if "%choice%"=="21" call :rel_run "releases/release-ondra-1.sh" ""
|
||||
if "%choice%"=="22" call :rel_run "releases/release-ondra-2.sh" ""
|
||||
if "%choice%"=="23" call :rel_run "releases/backfill-charts.sh" ""
|
||||
if "%choice%"=="24" call :rel_run "releases/reindex-charts.py" ""
|
||||
if "%choice%"=="0" goto menu_releases
|
||||
goto rel_release
|
||||
|
||||
@@ -628,6 +632,8 @@ if /I "%K%"=="release-ln" (set "CMD=bash releases/release-ln.sh" ^& goto cli_go)
|
||||
if /I "%K%"=="release-x2" (set "CMD=bash releases/release-x2.sh" ^& goto cli_go)
|
||||
if /I "%K%"=="release-cleanup" (set "CMD=bash releases/release-cleanup.sh" ^& goto cli_go)
|
||||
if /I "%K%"=="release-charts" (set "CMD=bash releases/release-charts.sh" ^& goto cli_go)
|
||||
if /I "%K%"=="backfill-charts" (set "CMD=bash releases/backfill-charts.sh" ^& goto cli_go)
|
||||
if /I "%K%"=="reindex-charts" (set "CMD=python3 releases/reindex-charts.py" ^& goto cli_go)
|
||||
if /I "%K%"=="release-website" (set "CMD=bash releases/release-website.sh" ^& goto cli_go)
|
||||
if /I "%K%"=="npm-publish" (set "CMD=bash releases/npm-publish.sh" ^& goto cli_go)
|
||||
if /I "%K%"=="test-download-urls" (set "CMD=bash releases/test-download-urls.sh" ^& goto cli_go)
|
||||
|
||||
@@ -1867,6 +1867,8 @@ RELEASE_SCRIPTS=( "Release|Release ALL platforms: push CHANGELOG, trigger releas
|
||||
"Release|Move the 'stable' tag to HEAD|!git tag --force stable HEAD && git push --tags --force && git push --follow-tags|||stable-tag"
|
||||
"Release|Release the wekan-ondra / wekan-gantt-gpl variants, part 1|releases/release-ondra-1.sh|||"
|
||||
"Release|Release the wekan-ondra / wekan-gantt-gpl variants, part 2|releases/release-ondra-2.sh|||"
|
||||
"Release|Report (or repair) the Helm chart index for past releases|releases/backfill-charts.sh|||"
|
||||
"Release|Rebuild the Helm index.yaml from the chart packages|releases/reindex-charts.py|||"
|
||||
"Snap|Build the snap from snapcraft.yaml|releases/snap-build.sh|||"
|
||||
"Snap|Install the locally built .snap|releases/snap-install.sh|||"
|
||||
"Snap|Push one .snap to the Snap Store|releases/snap-push-to-store.sh|Path to the .snap file||"
|
||||
|
||||
@@ -1457,6 +1457,312 @@ THEME - Corteza
|
||||
|
||||
/* === END Corteza THEME === */
|
||||
|
||||
/* ===============
|
||||
THEME - Apple Glass Pastel
|
||||
=================*/
|
||||
|
||||
.board-color-appleglasspastel {
|
||||
background:
|
||||
radial-gradient(60% 50% at 85% 5%, rgba(255, 200, 220, 0.55), transparent 60%),
|
||||
radial-gradient(55% 50% at 5% 25%, rgba(180, 215, 255, 0.55), transparent 65%),
|
||||
radial-gradient(55% 50% at 95% 95%, rgba(200, 230, 255, 0.5), transparent 60%),
|
||||
radial-gradient(70% 60% at 0% 100%, rgba(230, 215, 255, 0.5), transparent 65%),
|
||||
linear-gradient(180deg, #f6f7fb 0%, #eef0f7 100%);
|
||||
color: #111827;
|
||||
}
|
||||
|
||||
.board-color-appleglasspastel#header,
|
||||
.board-color-appleglasspastel#header-quick-access,
|
||||
.board-color-appleglasspastel.sk-spinner div,
|
||||
.board-color-appleglasspastel .setting-content .content-body .side-menu ul li.active,
|
||||
.board-color-appleglasspastel .setting-content .content-body .side-menu ul li.active:hover {
|
||||
background: #2563eb;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.board-backgrounds-list .board-color-appleglasspastel.background-box,
|
||||
.public-board-row.board-color-appleglasspastel,
|
||||
.board-list .board-color-appleglasspastel a {
|
||||
background:
|
||||
radial-gradient(80% 70% at 80% 0%, rgba(255, 200, 220, 0.7), transparent 62%),
|
||||
radial-gradient(70% 80% at 0% 15%, rgba(180, 215, 255, 0.75), transparent 66%),
|
||||
radial-gradient(75% 70% at 100% 100%, rgba(230, 215, 255, 0.7), transparent 62%),
|
||||
linear-gradient(180deg, #f6f7fb 0%, #eef0f7 100%);
|
||||
color: #111827 !important;
|
||||
}
|
||||
|
||||
.board-color-appleglasspastel#header-quick-access {
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.55);
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
|
||||
.board-color-appleglasspastel#header #header-main-bar,
|
||||
.board-color-appleglasspastel#header-quick-access,
|
||||
.board-color-appleglasspastel .boards-left-menu .menu-item.active a,
|
||||
.board-color-appleglasspastel .boards-left-menu .menu-item.active a:hover {
|
||||
background: #2563eb;
|
||||
}
|
||||
|
||||
.board-color-appleglasspastel#header ul li.current,
|
||||
.board-color-appleglasspastel#header-quick-access ul li.current {
|
||||
border-bottom: 4px solid #dbeafe;
|
||||
}
|
||||
|
||||
.board-color-appleglasspastel#header-quick-access #header-new-board-icon,
|
||||
.board-color-appleglasspastel#header-quick-access #header-user-bar,
|
||||
.board-color-appleglasspastel#header-quick-access ul li,
|
||||
.board-color-appleglasspastel#header-quick-access a,
|
||||
.board-color-appleglasspastel#header .board-header-btn,
|
||||
.board-color-appleglasspastel#header .board-header-btn i {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.board-color-appleglasspastel#header ul li:hover,
|
||||
.board-color-appleglasspastel#header-quick-access ul li:hover,
|
||||
.board-color-appleglasspastel .board-header-btn:hover {
|
||||
background: rgba(255, 255, 255, 0.16);
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.board-color-appleglasspastel#header #header-main-bar .board-header-btn.emphasis {
|
||||
background: #1e3a8a;
|
||||
box-shadow: 0 4px 16px rgba(37, 99, 235, 0.12), 0 1px 2px rgba(0,0,0,0.04);
|
||||
}
|
||||
|
||||
.board-color-appleglasspastel#header #header-main-bar .board-header-btn.emphasis:hover,
|
||||
.board-color-appleglasspastel#header #header-main-bar .board-header-btn.emphasis .board-header-btn-close {
|
||||
background: #1d4ed8;
|
||||
}
|
||||
|
||||
.board-color-appleglasspastel#header #header-main-bar .board-header-btn.emphasis:hover .board-header-btn-close {
|
||||
background: #1e3a8a;
|
||||
}
|
||||
|
||||
.board-color-appleglasspastel.board-wrapper {
|
||||
background:
|
||||
radial-gradient(60% 50% at 85% 5%, rgba(255, 200, 220, 0.55), transparent 60%),
|
||||
radial-gradient(55% 50% at 5% 25%, rgba(180, 215, 255, 0.55), transparent 65%),
|
||||
radial-gradient(55% 50% at 95% 95%, rgba(200, 230, 255, 0.5), transparent 60%),
|
||||
radial-gradient(70% 60% at 0% 100%, rgba(230, 215, 255, 0.5), transparent 65%),
|
||||
linear-gradient(180deg, #f6f7fb 0%, #eef0f7 100%);
|
||||
}
|
||||
|
||||
.board-color-appleglasspastel .board-canvas {
|
||||
scrollbar-color: rgba(37, 99, 235, 0.35) rgba(255, 255, 255, 0);
|
||||
scrollbar-width: thin;
|
||||
}
|
||||
|
||||
.board-color-appleglasspastel .swimlane {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.board-color-appleglasspastel .swimlane .swimlane-header-wrap {
|
||||
background: rgba(255, 255, 255, 0.45);
|
||||
backdrop-filter: blur(24px) saturate(180%);
|
||||
-webkit-backdrop-filter: blur(24px) saturate(180%);
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.55);
|
||||
}
|
||||
|
||||
.board-color-appleglasspastel .swimlane-header {
|
||||
color: #0f172a;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.board-color-appleglasspastel .list {
|
||||
background: rgba(255, 255, 255, 0.65);
|
||||
backdrop-filter: blur(24px) saturate(180%);
|
||||
-webkit-backdrop-filter: blur(24px) saturate(180%);
|
||||
border: 1px solid rgba(255, 255, 255, 0.55);
|
||||
border-inline-start: none;
|
||||
border-radius: 18px;
|
||||
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.06);
|
||||
color: #111827;
|
||||
margin: 10px 0;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
.board-color-appleglasspastel .list-header {
|
||||
background: rgba(255, 255, 255, 0.45);
|
||||
border-bottom: 1px solid rgba(229, 231, 235, 0.75);
|
||||
border-radius: 18px 18px 0 0;
|
||||
}
|
||||
|
||||
.board-color-appleglasspastel .list-header .list-header-name,
|
||||
.board-color-appleglasspastel .list-header .viewer,
|
||||
.board-color-appleglasspastel .minicard-title {
|
||||
color: #0f172a;
|
||||
}
|
||||
|
||||
.board-color-appleglasspastel .list-body {
|
||||
margin-top: 8px;
|
||||
padding: 11px;
|
||||
scrollbar-color: rgba(37, 99, 235, 0.35) rgba(255, 255, 255, 0);
|
||||
scrollbar-width: thin;
|
||||
}
|
||||
|
||||
.board-color-appleglasspastel .minicard,
|
||||
.board-color-appleglasspastel .card-details,
|
||||
.board-color-appleglasspastel.pop-over,
|
||||
.board-color-appleglasspastel .sidebar {
|
||||
background: rgba(255, 255, 255, 0.72);
|
||||
backdrop-filter: blur(24px) saturate(180%);
|
||||
-webkit-backdrop-filter: blur(24px) saturate(180%);
|
||||
border: 1px solid rgba(255, 255, 255, 0.55);
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
|
||||
color: #111827;
|
||||
}
|
||||
|
||||
.board-color-appleglasspastel .minicard {
|
||||
border-radius: 12px;
|
||||
padding: 10px 10px 4px 10px;
|
||||
}
|
||||
|
||||
.board-color-appleglasspastel .minicard:hover:not(.minicard-composer),
|
||||
.board-color-appleglasspastel .is-selected .minicard,
|
||||
.board-color-appleglasspastel .draggable-hover-card .minicard {
|
||||
background: rgba(239, 246, 255, 0.88);
|
||||
}
|
||||
|
||||
.board-color-appleglasspastel .is-selected .minicard {
|
||||
border-inline-start: 3px solid #2563eb;
|
||||
}
|
||||
|
||||
.board-color-appleglasspastel .card-details {
|
||||
border-radius: 18px;
|
||||
}
|
||||
|
||||
.board-color-appleglasspastel .card-details-header {
|
||||
background: rgba(239, 246, 255, 0.78);
|
||||
border-bottom: 1px solid rgba(229, 231, 235, 0.75);
|
||||
color: #0f172a;
|
||||
}
|
||||
|
||||
.board-color-appleglasspastel .card-details-item-title,
|
||||
.board-color-appleglasspastel .card-details-left .viewer p,
|
||||
.board-color-appleglasspastel .activity-desc .activity-member {
|
||||
color: #111827;
|
||||
}
|
||||
|
||||
.board-color-appleglasspastel .quiet,
|
||||
.board-color-appleglasspastel .quiet a,
|
||||
.board-color-appleglasspastel .activity-desc,
|
||||
.board-color-appleglasspastel .sidebar-list-item-description {
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
.board-color-appleglasspastel .list.list-composer,
|
||||
.board-color-appleglasspastel .list-body .open-minicard-composer,
|
||||
.board-color-appleglasspastel .list.list-composer .open-list-composer {
|
||||
background: rgba(255, 255, 255, 0.45);
|
||||
border-radius: 12px;
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
.board-color-appleglasspastel .list-body .open-minicard-composer:hover,
|
||||
.board-color-appleglasspastel .list.list-composer .open-list-composer:hover,
|
||||
.board-color-appleglasspastel.pop-over .pop-over-list li a:not(.disabled):hover,
|
||||
.board-color-appleglasspastel .sidebar .sidebar-content .sidebar-btn:hover,
|
||||
.board-color-appleglasspastel .sidebar-list li a:hover {
|
||||
background: rgba(219, 234, 254, 0.78);
|
||||
color: #1e3a8a;
|
||||
}
|
||||
|
||||
.board-color-appleglasspastel button[type=submit].primary,
|
||||
.board-color-appleglasspastel input[type=submit].primary,
|
||||
.board-color-appleglasspastel button.primary,
|
||||
.board-color-appleglasspastel input.primary,
|
||||
.board-color-appleglasspastel .sidebar .sidebar-content .sidebar-btn {
|
||||
background: #2563eb;
|
||||
border: 0;
|
||||
border-radius: 999px;
|
||||
box-shadow: 0 4px 16px rgba(37, 99, 235, 0.12), 0 1px 2px rgba(0,0,0,0.04);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.board-color-appleglasspastel button[type="submit"].primary:hover,
|
||||
.board-color-appleglasspastel input[type="submit"].primary:hover,
|
||||
.board-color-appleglasspastel button.primary:hover,
|
||||
.board-color-appleglasspastel input.primary:hover {
|
||||
background: #1d4ed8;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.board-color-appleglasspastel input[type="email"],
|
||||
.board-color-appleglasspastel input[type="password"],
|
||||
.board-color-appleglasspastel input[type="text"],
|
||||
.board-color-appleglasspastel textarea,
|
||||
.board-color-appleglasspastel select {
|
||||
background: rgba(255, 255, 255, 0.72);
|
||||
border: 1px solid rgba(229, 231, 235, 0.9);
|
||||
border-radius: 12px;
|
||||
color: #111827;
|
||||
}
|
||||
|
||||
.board-color-appleglasspastel input:focus,
|
||||
.board-color-appleglasspastel textarea:focus,
|
||||
.board-color-appleglasspastel select:focus {
|
||||
border-color: #2563eb;
|
||||
box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.12);
|
||||
}
|
||||
|
||||
.board-color-appleglasspastel .materialCheckBox.is-checked {
|
||||
border-bottom: 2px solid #2563eb;
|
||||
border-inline-end: 2px solid #2563eb;
|
||||
}
|
||||
|
||||
.board-color-appleglasspastel .checklist-progress-bar {
|
||||
background-color: #dbeafe !important;
|
||||
}
|
||||
|
||||
.board-color-appleglasspastel .checklist-progress-bar .checklist-progress {
|
||||
background-color: #2563eb !important;
|
||||
}
|
||||
|
||||
.board-color-appleglasspastel .is-multiselection-active .multi-selection-checkbox.is-checked + .minicard {
|
||||
background: #eff6ff;
|
||||
}
|
||||
|
||||
.board-color-appleglasspastel .is-multiselection-active .multi-selection-checkbox:not(.is-checked) + .minicard:hover:not(.minicard-composer) {
|
||||
background: rgba(255, 255, 255, 0.88);
|
||||
}
|
||||
|
||||
.board-color-appleglasspastel .toggle-label:after {
|
||||
background-color: #2563eb;
|
||||
}
|
||||
|
||||
.board-color-appleglasspastel .toggle-switch:checked ~ .toggle-label {
|
||||
background-color: #93c5fd;
|
||||
}
|
||||
|
||||
.board-color-appleglasspastel .toggle-switch:checked ~ .toggle-label:after {
|
||||
background-color: #2563eb;
|
||||
}
|
||||
|
||||
.board-color-appleglasspastel .card-date.current,
|
||||
.board-color-appleglasspastel .minicard .current {
|
||||
background: #1f7d38;
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
.board-color-appleglasspastel .card-date.due,
|
||||
.board-color-appleglasspastel .minicard .due {
|
||||
background: #dc3545;
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
.board-color-appleglasspastel .sidebar .sidebar-content {
|
||||
scrollbar-color: rgba(37, 99, 235, 0.35) rgba(255, 255, 255, 0);
|
||||
}
|
||||
|
||||
@media screen and (max-width: 800px) {
|
||||
.board-color-appleglasspastel.pop-over .header {
|
||||
background: #2563eb;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
/* === END Apple Glass Pastel THEME === */
|
||||
|
||||
/* ===============
|
||||
THEME - Clear Blue
|
||||
=================*/
|
||||
|
||||
@@ -1193,7 +1193,8 @@
|
||||
(e.g. a laptop in mobile mode) gets more columns instead of two stretched ones. */
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(min(46%, 200px), 1fr));
|
||||
gap: 8px;
|
||||
/* The same single spacing value as the phone grid above, in both directions. */
|
||||
gap: 10px;
|
||||
/* #6488: sized by the column it lives in (the flex chain in the phone block
|
||||
below), not by the viewport minus a guess at the bars above it. */
|
||||
flex: 1 1 auto;
|
||||
@@ -1210,7 +1211,8 @@
|
||||
width: auto; /* the grid controls the column width */
|
||||
float: none;
|
||||
display: block;
|
||||
margin-bottom: 0.5rem;
|
||||
/* The grid gap is the spacing; this added a second one, downwards only. */
|
||||
margin-bottom: 0;
|
||||
/* NO handle reserve here. The drag handle is positioned INSIDE the tile, and
|
||||
the tile already keeps its text clear of it - so 32px here was a second,
|
||||
invisible reserve on top of that one. On a phone the tile is only ~97px
|
||||
@@ -1340,18 +1342,42 @@
|
||||
.board-list {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 8px;
|
||||
/* ONE spacing value, in both directions. It used to be an 8px gap PLUS a
|
||||
`margin-bottom: 0.5rem` on each li, so the tiles were 16px apart vertically
|
||||
and 8px apart horizontally - which reads as "the icons are too close
|
||||
together" side to side even though there is space between the rows. The
|
||||
margin is gone (below) and the gap is the whole answer. */
|
||||
gap: 10px;
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
padding: 0 0.25rem;
|
||||
margin: 0;
|
||||
/* #6488. Without these a grid's rows default to `align-content: stretch` and
|
||||
its items to `align-items: stretch`, so when the list is SHORTER than the
|
||||
column it is given - one or two rows of boards - the leftover height is
|
||||
divided among the rows and each tile is grown to fill it. A board tile
|
||||
paints its board colour over the whole cell, so a single row of boards
|
||||
became one band several times the height of a normal icon: "some board
|
||||
icons are 4x normal height or more".
|
||||
This was fixed once, but only on `.board-list.mobile-view` - the class the
|
||||
template sets from Utils.isMiniScreen(). A narrow WINDOW that is not a mini
|
||||
screen (a desktop browser resized under 800px, a tablet in desktop mode)
|
||||
matches this media query, becomes a grid here, and never got the fix. It
|
||||
belongs on the rule that creates the grid. */
|
||||
align-content: start;
|
||||
align-items: start;
|
||||
}
|
||||
.board-list li {
|
||||
width: auto; /* the grid controls the column width */
|
||||
float: none;
|
||||
display: block;
|
||||
margin-bottom: 0.5rem;
|
||||
/* The grid gap spaces the tiles; a margin here spaced them a second time,
|
||||
and only downwards. */
|
||||
margin-bottom: 0;
|
||||
/* ...and the tile is its own height, not the height of a stretched cell. */
|
||||
align-self: start;
|
||||
height: auto;
|
||||
/* Same as `.board-list.mobile-view li` above: the tile keeps its own text
|
||||
clear of the handle, so reserving the width a second time out here only
|
||||
narrowed the title. */
|
||||
@@ -1661,6 +1687,35 @@
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
/* ...and so does the pane's heading. Without this it is a flex item with the
|
||||
default `flex-shrink: 1`, so in a column too short for its contents the
|
||||
TITLE is what gets squeezed instead of the scroller below it growing a
|
||||
scrollbar. */
|
||||
.boards-right-grid > .admin-pane-title {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
/* #6488. The right column has TWO branches, not one: the board icons, and -
|
||||
when the view is Table - `+tablePage`, which is a `.table-page` (see
|
||||
boardsList.jade). Only the icons were ever given a scroller, so in Table view
|
||||
the table simply grew past the bottom of the column, and `#content .wrapper`
|
||||
is `overflow: hidden`, so the rows past the fold were clipped with no way to
|
||||
reach them. Every section of All Boards can be shown as a table - Starred,
|
||||
Templates, Remaining, Workspaces, Archive - so that was the whole page in
|
||||
one of its two views.
|
||||
The same shape as the board list: take what the column has left, be allowed
|
||||
to be shorter than the content, and scroll inside. The table is also WIDER
|
||||
than a phone, so this one scrolls in both directions. */
|
||||
.boards-right-grid > .table-page {
|
||||
flex: 1 1 auto;
|
||||
min-height: 0;
|
||||
overflow-y: auto;
|
||||
overflow-x: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
overscroll-behavior: contain;
|
||||
touch-action: pan-x pan-y;
|
||||
}
|
||||
|
||||
/* The left menu (Starred / Templates / Remaining / Workspaces / Add board) is its
|
||||
own vertical scroll area, so when it is taller than the screen you can drag-scroll
|
||||
down to its lower items — the board icons already scroll in their own column on the
|
||||
|
||||
@@ -1146,3 +1146,33 @@ body.mobile-mode .card-details .card-details-header .close-card-details-mobile-w
|
||||
user-select: none;
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
/* #1591: foldable feature groups on the opened card.
|
||||
The title is the handle. Everything after it inside the section is what folds
|
||||
away - a sibling rule rather than "hide .card-details-item-content", because
|
||||
the sections are not uniform inside: all sixteen start with an
|
||||
h3.card-details-item-title, but only three wrap what follows in a content
|
||||
element. Hiding the siblings works whatever a section puts there. */
|
||||
.card-details-item > .card-details-item-title {
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
/* The caret, drawn on the title rather than added to sixteen templates. It
|
||||
points down when open and right when folded, like the checklist one. */
|
||||
.card-details-item > .card-details-item-title::after {
|
||||
content: "\f0d7"; /* fa-caret-down */
|
||||
font-family: FontAwesome;
|
||||
font-size: 12px;
|
||||
color: #808080;
|
||||
margin-inline-start: 6px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.card-details-item.is-collapsed > .card-details-item-title::after {
|
||||
content: "\f0da"; /* fa-caret-right */
|
||||
}
|
||||
|
||||
.card-details-item.is-collapsed > *:not(.card-details-item-title) {
|
||||
display: none;
|
||||
}
|
||||
@@ -513,6 +513,31 @@ Template.cardDetails.onRendered(function () {
|
||||
// below throws "Can't select in removed DomRange", so bail out early.
|
||||
if (this.view && this.view.isDestroyed) return;
|
||||
|
||||
// #1591: re-apply the sections this user folded. The click handler toggles the
|
||||
// class as well as storing it, but on a fresh render - reopening the card, a
|
||||
// reload - only the stored state exists, and the title is plain markup that
|
||||
// nothing re-renders from the profile.
|
||||
this.autorun(() => {
|
||||
const user = ReactiveCache.getCurrentUser();
|
||||
const card = Template.currentData();
|
||||
if (!user || !card || !card._id) return;
|
||||
// Read inside the autorun so a fold made in another tab arrives here too.
|
||||
const stored = (user.profile && user.profile.collapsedCardSections) || {};
|
||||
const forCard = stored[card._id] || {};
|
||||
Meteor.defer(() => {
|
||||
if (this.view && this.view.isDestroyed) return;
|
||||
this.$('.card-details-item').each((index, item) => {
|
||||
const named = Array.from(item.classList).find(
|
||||
c => c.startsWith('card-details-item-') &&
|
||||
c !== 'card-details-item-title' &&
|
||||
c !== 'card-details-item-content');
|
||||
if (!named) return;
|
||||
const key = named.replace('card-details-item-', '');
|
||||
item.classList.toggle('is-collapsed', forCard[key] === true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// #6465: place the window beside its minicard (X only) once it has been laid
|
||||
// out, so the width measured here is the one the stylesheet gave it.
|
||||
const $cardDetails = this.$('.card-details').first();
|
||||
@@ -828,7 +853,44 @@ Template.cardDetails.helpers({
|
||||
},
|
||||
});
|
||||
|
||||
// #1591: fold any feature group on the opened card - Labels, Members, Dates,
|
||||
// Custom Fields, and the rest.
|
||||
//
|
||||
// Done here, once, rather than by editing sixteen sections in cardDetails.jade,
|
||||
// because the sections are NOT uniform inside: they all begin with an
|
||||
// `h3.card-details-item-title`, but only three of them wrap what follows in a
|
||||
// `.card-details-item-content`. So the title is the handle, and "collapsed"
|
||||
// hides every sibling after it (the CSS rule) - which works whatever the section
|
||||
// puts there.
|
||||
//
|
||||
// The state is the same per-user map the checklists use
|
||||
// (profile.collapsedCardSections), keyed by the section's own name, so it
|
||||
// survives a reload and belongs to the reader rather than to the card.
|
||||
function cardSectionKeyOf(element) {
|
||||
const item = element.closest('.card-details-item');
|
||||
if (!item) return null;
|
||||
// 'card-details-item-labels' -> 'labels'. The class that is not the generic
|
||||
// one IS the section's name; there is no separate id to invent.
|
||||
const named = Array.from(item.classList).find(
|
||||
c => c.startsWith('card-details-item-') &&
|
||||
c !== 'card-details-item-title' &&
|
||||
c !== 'card-details-item-content');
|
||||
return named ? named.replace('card-details-item-', '') : null;
|
||||
}
|
||||
|
||||
Template.cardDetails.events({
|
||||
'click .card-details-item > .card-details-item-title'(event) {
|
||||
const key = cardSectionKeyOf(event.currentTarget);
|
||||
const user = ReactiveCache.getCurrentUser();
|
||||
const card = Template.currentData();
|
||||
if (!key || !user || !card || !card._id) return;
|
||||
const collapsed = user.getCollapsedCardSection(card._id, key) === true;
|
||||
user.setCollapsedCardSection(card._id, key, !collapsed);
|
||||
// Applied straight away as well as stored: the title is plain markup, so
|
||||
// nothing re-renders on its own when the profile changes.
|
||||
event.currentTarget.closest('.card-details-item')
|
||||
.classList.toggle('is-collapsed', !collapsed);
|
||||
},
|
||||
[`${CSSEvents.transitionend} .js-card-details`](event, tpl) {
|
||||
tpl.isLoaded.set(true);
|
||||
},
|
||||
|
||||
@@ -191,3 +191,26 @@ textarea.js-edit-checklist-item {
|
||||
.edit-controls label.toggle-label {
|
||||
margin-inline-start: 2px;
|
||||
}
|
||||
|
||||
/* #1591: the fold caret on a checklist title. Sized and coloured like the
|
||||
actions menu beside it so the two read as one row of controls, and given a
|
||||
real hit area - it is a single glyph, and a caret you have to aim at is worse
|
||||
than no caret. */
|
||||
.checklist-title .checklist-collapse {
|
||||
/* Logical, so the caret sits on the reading-start side under dir=rtl too
|
||||
(tests/rtl.test.js enforces this across component CSS). */
|
||||
float: inline-start;
|
||||
margin-block-start: 2px;
|
||||
margin-inline-end: 4px;
|
||||
padding: 2px 4px;
|
||||
color: #808080;
|
||||
font-size: 14px;
|
||||
line-height: 14px;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.checklist-title .checklist-collapse:hover,
|
||||
.checklist-title .checklist-collapse:focus-visible {
|
||||
color: #2980b9;
|
||||
}
|
||||
@@ -38,6 +38,15 @@ template(name="checklistDetail")
|
||||
else
|
||||
.checklist-title
|
||||
span
|
||||
//- #1591: fold a long checklist out of the way. A caret rather than
|
||||
another entry in the actions menu, because the whole point is to do it
|
||||
at a glance while reading the card - and it is a view preference of
|
||||
this user, so it does not touch the card.
|
||||
a.fa.checklist-collapse.js-collapse-checklist(
|
||||
class="{{#if checklistCollapsed}}fa-caret-right{{else}}fa-caret-down{{/if}}"
|
||||
title="{{#if checklistCollapsed}}{{_ 'expand-checklist'}}{{else}}{{_ 'collapse-checklist'}}{{/if}}"
|
||||
role="button" tabindex="0"
|
||||
aria-expanded="{{#if checklistCollapsed}}false{{else}}true{{/if}}")
|
||||
if canModifyCard
|
||||
a.fa.fa-navicon.checklist-details-menu.js-open-checklist-details-menu(title="{{_ 'checklistActionsPopup-title'}}")
|
||||
|
||||
@@ -52,12 +61,15 @@ template(name="checklistDetail")
|
||||
+viewer
|
||||
= checklist.title
|
||||
|
||||
//- The progress bar stays visible when folded: it is the summary of what was
|
||||
folded away, so hiding it too would leave a title that says nothing.
|
||||
if $gt finishedPercent 0
|
||||
.checklist-progress-bar-container
|
||||
.checklist-progress-text {{finishedPercent}}%
|
||||
.checklist-progress-bar
|
||||
.checklist-progress(style="width:{{finishedPercent}}%")
|
||||
+checklistItems(checklist = checklist card = card)
|
||||
unless checklistCollapsed
|
||||
+checklistItems(checklist = checklist card = card)
|
||||
|
||||
template(name="checklistDeletePopup")
|
||||
p {{_ 'confirm-checklist-delete-popup'}}
|
||||
|
||||
@@ -82,6 +82,47 @@ Template.checklistDetail.helpers({
|
||||
const ret = this.checklist.finishedPercent();
|
||||
return ret;
|
||||
},
|
||||
/** #1591: is this checklist folded for THIS user?
|
||||
*
|
||||
* Per-user, keyed by card and checklist, exactly like collapsed lists and
|
||||
* swimlanes - not the checklist's own hideAllChecklistItems, which is a field
|
||||
* on the checklist and so changes what everyone on the board sees. `null` from
|
||||
* the getter means "never set", which is what makes the default (expanded)
|
||||
* distinguishable from somebody having deliberately expanded it. */
|
||||
checklistCollapsed() {
|
||||
const checklist = this.checklist;
|
||||
if (!checklist || !checklist._id) return false;
|
||||
const user = ReactiveCache.getCurrentUser();
|
||||
if (!user) return false;
|
||||
const cardId = (this.card && this.card._id) || checklist.cardId;
|
||||
const stored = user.getCollapsedCardSection(
|
||||
cardId, user.checklistSectionKey(checklist._id));
|
||||
return stored === true;
|
||||
},
|
||||
});
|
||||
|
||||
Template.checklistDetail.events({
|
||||
'click .js-collapse-checklist'(event) {
|
||||
// The caret sits inside the title, which opens the inline rename form when
|
||||
// clicked - so this must not reach it.
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
const checklist = this.checklist;
|
||||
const user = ReactiveCache.getCurrentUser();
|
||||
if (!checklist || !checklist._id || !user) return;
|
||||
const cardId = (this.card && this.card._id) || checklist.cardId;
|
||||
const key = user.checklistSectionKey(checklist._id);
|
||||
const collapsed = user.getCollapsedCardSection(cardId, key) === true;
|
||||
user.setCollapsedCardSection(cardId, key, !collapsed);
|
||||
},
|
||||
'keydown .js-collapse-checklist'(event) {
|
||||
// It is a link acting as a button, so it has to answer the keys a button
|
||||
// answers or it is unreachable without a mouse.
|
||||
if (event.key !== 'Enter' && event.key !== ' ') return;
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
$(event.currentTarget).trigger('click');
|
||||
},
|
||||
});
|
||||
|
||||
Template.checklists.helpers({
|
||||
|
||||
@@ -265,6 +265,13 @@ template(name="editCardSortOrderPopup")
|
||||
template(name="minicardChecklist")
|
||||
.minicard-checklist
|
||||
.checklist-header
|
||||
//- #1591: the same caret as on the opened card, and the same stored key,
|
||||
so folding a checklist folds it in both places.
|
||||
a.fa.checklist-collapse.js-collapse-checklist(
|
||||
class="{{#if checklistCollapsed}}fa-caret-right{{else}}fa-caret-down{{/if}}"
|
||||
title="{{#if checklistCollapsed}}{{_ 'expand-checklist'}}{{else}}{{_ 'collapse-checklist'}}{{/if}}"
|
||||
role="button" tabindex="0"
|
||||
aria-expanded="{{#if checklistCollapsed}}false{{else}}true{{/if}}")
|
||||
if canModifyCard
|
||||
+inlinedForm(classNames="js-edit-checklist-title" checklist=checklist)
|
||||
+editChecklistForm(checklist=checklist)
|
||||
@@ -275,16 +282,17 @@ template(name="minicardChecklist")
|
||||
if canModifyCard
|
||||
a.checklist-menu.js-open-checklist-menu(title="{{_ 'checklistActionsPopup-title'}}")
|
||||
i.fa.fa-bars
|
||||
.checklist-items.js-checklist-items
|
||||
each visibleItems
|
||||
+inlinedForm(classNames="js-edit-checklist-item" item=. checklist=checklist)
|
||||
+editChecklistItemForm(type='item' item=. checklist=checklist)
|
||||
unless checklistCollapsed
|
||||
.checklist-items.js-checklist-items
|
||||
each visibleItems
|
||||
+inlinedForm(classNames="js-edit-checklist-item" item=. checklist=checklist)
|
||||
+editChecklistItemForm(type='item' item=. checklist=checklist)
|
||||
else
|
||||
+checklistItemDetail(item=. checklist=checklist card=card)
|
||||
if canModifyCard
|
||||
+inlinedForm(autoclose=false classNames="js-add-checklist-item" checklist=checklist)
|
||||
+addChecklistItemForm(checklist=checklist showNewlineBecomesNewChecklistItem=false)
|
||||
else
|
||||
+checklistItemDetail(item=. checklist=checklist card=card)
|
||||
if canModifyCard
|
||||
+inlinedForm(autoclose=false classNames="js-add-checklist-item" checklist=checklist)
|
||||
+addChecklistItemForm(checklist=checklist showNewlineBecomesNewChecklistItem=false)
|
||||
else
|
||||
a.add-checklist-item.js-open-inlined-form(title="{{_ 'add-checklist-item'}}")
|
||||
i.fa.fa-plus
|
||||
a.add-checklist-item.js-open-inlined-form(title="{{_ 'add-checklist-item'}}")
|
||||
i.fa.fa-plus
|
||||
|
||||
@@ -375,6 +375,18 @@ Template.minicard.events({
|
||||
});
|
||||
|
||||
Template.minicardChecklist.helpers({
|
||||
/** #1591: folded for THIS user, under the same key the opened card uses, so
|
||||
* the two agree. `this.checklist || this` because this template is called both
|
||||
* with an explicit checklist and with one as the data context. */
|
||||
checklistCollapsed() {
|
||||
const checklist = this.checklist || this;
|
||||
if (!checklist || !checklist._id) return false;
|
||||
const user = ReactiveCache.getCurrentUser();
|
||||
if (!user) return false;
|
||||
const cardId = (this.card && this.card._id) || checklist.cardId;
|
||||
return user.getCollapsedCardSection(
|
||||
cardId, user.checklistSectionKey(checklist._id)) === true;
|
||||
},
|
||||
visibleItems() {
|
||||
const checklist = this.checklist || this;
|
||||
const items = checklist.items();
|
||||
@@ -416,6 +428,26 @@ function addMinicardChecklistItems(textarea, checklist) {
|
||||
}
|
||||
|
||||
Template.minicardChecklist.events({
|
||||
'click .js-collapse-checklist'(event) {
|
||||
// A minicard is a link to the card, and the title opens the rename form -
|
||||
// neither must happen because somebody folded a checklist.
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
const data = Template.currentData();
|
||||
const checklist = (data && data.checklist) || data || this;
|
||||
const user = ReactiveCache.getCurrentUser();
|
||||
if (!checklist || !checklist._id || !user) return;
|
||||
const cardId = (data && data.card && data.card._id) || checklist.cardId;
|
||||
const key = user.checklistSectionKey(checklist._id);
|
||||
const collapsed = user.getCollapsedCardSection(cardId, key) === true;
|
||||
user.setCollapsedCardSection(cardId, key, !collapsed);
|
||||
},
|
||||
'keydown .js-collapse-checklist'(event) {
|
||||
if (event.key !== 'Enter' && event.key !== ' ') return;
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
$(event.currentTarget).trigger('click');
|
||||
},
|
||||
'click .js-convert-checklist-item-to-card'(event) {
|
||||
event.stopPropagation();
|
||||
const formData = Blaze.getData(event.currentTarget);
|
||||
|
||||
@@ -423,8 +423,46 @@ Template.list.onRendered(function () {
|
||||
scrolled = true;
|
||||
}
|
||||
}
|
||||
// vertical auto-scroll stays on the board canvas
|
||||
const canvas = document.querySelector('.board-canvas');
|
||||
// #6584: VERTICALLY, the thing to scroll is the LIST the pointer is over,
|
||||
// not the board canvas. `.list-body` is `overflow-y: scroll` (list.css) and
|
||||
// is what holds the cards; `.board-canvas` is `overflow-y: auto` and holds
|
||||
// the swimlanes. Scrolling the canvas moves the whole board, which is what
|
||||
// the report describes: "The whole Page/Site scrolls down and not the Line".
|
||||
//
|
||||
// It only showed up DOWNWARDS, and the asymmetry is the tell. Dragging up,
|
||||
// the canvas is usually already at scrollTop 0, so computeEdgeScroll
|
||||
// returned null, nothing here fired, and jQuery UI's own `scroll` option -
|
||||
// which acts on the placeholder's scrollParent, i.e. the list body - scrolled
|
||||
// the list, exactly as expected. Dragging down, the canvas nearly always HAS
|
||||
// room, so this fired first and scrolled the board instead of the list.
|
||||
//
|
||||
// The canvas is still scrolled, but only once the list under the pointer
|
||||
// cannot go further that way - so a drag down a long list scrolls the list,
|
||||
// and a drag past the end of it moves on to the board. Same shape as the
|
||||
// horizontal case above, which already picks the lane under the pointer.
|
||||
let scrolledList = false;
|
||||
const listBodies = document.querySelectorAll('.list-body');
|
||||
const listRects = Array.prototype.map.call(listBodies, el =>
|
||||
el.getBoundingClientRect());
|
||||
// findLaneUnderPointer is a plain rectangle hit-test; the name is about
|
||||
// where it was first used, not what it can be given.
|
||||
const listIndex = findLaneUnderPointer(listRects, event.clientX, event.clientY);
|
||||
if (listIndex !== -1) {
|
||||
const nextListTop = computeEdgeScroll({
|
||||
pointer: event.clientY,
|
||||
lowEdge: listRects[listIndex].top,
|
||||
highEdge: listRects[listIndex].bottom,
|
||||
scrollPos: listBodies[listIndex].scrollTop,
|
||||
scrollSize: listBodies[listIndex].scrollHeight,
|
||||
clientSize: listBodies[listIndex].clientHeight,
|
||||
});
|
||||
if (nextListTop !== null) {
|
||||
listBodies[listIndex].scrollTop = nextListTop;
|
||||
scrolled = true;
|
||||
scrolledList = true;
|
||||
}
|
||||
}
|
||||
const canvas = scrolledList ? null : document.querySelector('.board-canvas');
|
||||
if (canvas) {
|
||||
const crect = canvas.getBoundingClientRect();
|
||||
const nextTop = computeEdgeScroll({
|
||||
|
||||
@@ -256,6 +256,16 @@ Template.listBody.onCreated(function () {
|
||||
if (clickedTitle && !clickedLinkedReference) {
|
||||
evt.stopImmediatePropagation();
|
||||
evt.preventDefault();
|
||||
// #6465: clicking the OPEN card again closes it. The toggle below has
|
||||
// always been here, but this branch returned before ever reaching it - and
|
||||
// the title covers most of the minicard, so in practice the second click
|
||||
// almost always lands here and just re-opened the card that was already
|
||||
// open. That is why it read as a missing feature rather than a dead
|
||||
// branch. Same call as below, so both click targets behave alike.
|
||||
if (Session.equals('currentCard', card._id)) {
|
||||
Utils.goBoardId(Session.get('currentBoard'));
|
||||
return;
|
||||
}
|
||||
Session.delete('popupCardId');
|
||||
Session.delete('popupCardBoardId');
|
||||
Session.set('currentCard', card._id);
|
||||
@@ -265,6 +275,12 @@ Template.listBody.onCreated(function () {
|
||||
|
||||
if (Utils.isMiniScreen()) {
|
||||
evt.preventDefault();
|
||||
// ...and on a phone, where the card is a popup rather than a pane, the
|
||||
// second click closes that popup for the same reason.
|
||||
if (Session.equals('popupCardId', card._id) && Popup.isOpen()) {
|
||||
Popup.back();
|
||||
return;
|
||||
}
|
||||
Session.set('popupCardId', card._id);
|
||||
this.cardDetailsPopup(evt);
|
||||
} else if (Session.equals('currentCard', card._id)) {
|
||||
|
||||
@@ -243,8 +243,30 @@ body.mobile-mode #content {
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
height: calc(100vh - 48px);
|
||||
height: calc(100dvh - 48px);
|
||||
/* #6488, and the reason that issue kept coming back after being closed three
|
||||
times: THE LAST PIECE OF VIEWPORT ARITHMETIC. This said
|
||||
`height: calc(100dvh - 48px)`, and 48px is a guess at how tall the header is.
|
||||
The header is not 48px and is not any one number - Utils publishes
|
||||
--wekan-header-height from a ResizeObserver for exactly this reason, because
|
||||
the quick-access bar WRAPS to a second and third row depending on the
|
||||
language and the window width, and its own comment says "every fixed number
|
||||
for it has been wrong for some of those".
|
||||
On a phone, where the bar does wrap, #content was therefore taller than the
|
||||
room under the header by however much the header exceeded 48px, so its
|
||||
bottom sat BELOW the bottom of the screen. body.mobile-mode is
|
||||
`position: fixed` and the phone rules make it `overflow: hidden`, so that
|
||||
strip is unreachable: everything below it inherits the error through the
|
||||
`height: 100%` chain (boardsList.css), and the last rows of the board list
|
||||
end up where no gesture can reach them. That is "in mobile board menu you
|
||||
cant scroll boards" - the list scrolls, it just ends off screen.
|
||||
Nothing has to be computed here. body is a flex COLUMN of exactly one
|
||||
viewport and this is its `flex: 1` item (below), so the space left under the
|
||||
header - whatever the header turns out to be this paint - IS this box. The
|
||||
arithmetic was overriding a correct answer with a wrong one.
|
||||
`min-height: 0` so it can be SHORTER than its content: a flex item will not
|
||||
shrink below its content otherwise, and an inner scroller whose ancestor
|
||||
refuses to shrink never scrolls. */
|
||||
min-height: 0;
|
||||
overscroll-behavior: contain;
|
||||
}
|
||||
#content {
|
||||
|
||||
@@ -893,14 +893,29 @@ body.mobile-mode .pop-over {
|
||||
inset-inline-end: 0 !important;
|
||||
bottom: 0 !important;
|
||||
width: 100vw !important;
|
||||
height: 100vh !important;
|
||||
max-width: 100vw !important;
|
||||
/* #6488. `100vh` is the viewport with the browser's toolbars HIDDEN, so a
|
||||
`position: fixed` box sized that way reaches under them: on a phone the
|
||||
bottom of this popup is off screen, and being fixed there is no gesture that
|
||||
brings it back. `100dvh` is the viewport as it is right now. The `vh` pair
|
||||
stays first as the fallback where `dvh` is unknown - the same fix
|
||||
body.mobile-mode already carries in layouts.css. */
|
||||
height: 100vh !important;
|
||||
max-height: 100vh !important;
|
||||
height: 100dvh !important;
|
||||
max-height: 100dvh !important;
|
||||
}
|
||||
body.mobile-mode .pop-over .content-wrapper {
|
||||
width: 100% !important;
|
||||
height: calc(100vh - 48px) !important;
|
||||
max-height: calc(100vh - 48px) !important;
|
||||
/* #6488. This was `calc(100vh - 48px)`, which is two guesses at once: the
|
||||
viewport measured with the toolbars hidden, minus a fixed 48px for the
|
||||
popup's own title bar. When the title wraps - a long board name, a
|
||||
translated label - the bar is taller than 48px and the list inside this
|
||||
wrapper ends below the screen, so its last rows cannot be scrolled to.
|
||||
Nothing needs measuring: `.pop-over` above is a flex column of exactly one
|
||||
viewport, `.pop-over .header` is `flex-shrink: 0`, and this wrapper is
|
||||
already `flex: 1 1 auto; min-height: 0` - so it is whatever the title bar
|
||||
leaves, at whatever height the title bar really is. */
|
||||
overflow-y: auto !important;
|
||||
overflow-x: hidden !important;
|
||||
}
|
||||
|
||||
@@ -365,6 +365,13 @@ Template.adminReports.helpers({
|
||||
showDatabase() {
|
||||
return Template.instance().showDatabase;
|
||||
},
|
||||
// Filesystem integrity. Without this helper the pane rendered NOTHING: the
|
||||
// menu entry set tmpl.showIntegrity, the template asked for `showIntegrity.get`,
|
||||
// and an undefined helper is simply falsy - so the branch never ran, the page
|
||||
// was blank, and Summary went on counting the problems it could not show.
|
||||
showIntegrity() {
|
||||
return Template.instance().showIntegrity;
|
||||
},
|
||||
showCpu() {
|
||||
return Template.instance().showCpu;
|
||||
},
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/* ── Admin Panel / Settings / Version ────────────────────────────────────────
|
||||
ONE table, in five categories - Platform, OS, Meteor, Database, Node - where
|
||||
each category is a row of its own that spans both columns.
|
||||
|
||||
WHY ONE TABLE. It was five, one per category, and five tables size their
|
||||
columns independently: "WeKan ® Version" made the first one's label column
|
||||
wide and "OS Type" made the next one's narrow, so the values started at a
|
||||
different x in every group and the pane read as five unrelated things. One
|
||||
table puts every label and every value in the same place. */
|
||||
|
||||
/* Two EQUAL columns, and they stay equal whatever the longest label happens to
|
||||
be. `table-layout: fixed` makes the browser take the widths from the colgroup
|
||||
instead of measuring the content, and the two `col` rules below are that
|
||||
colgroup - written here rather than as inline width attributes so a theme can
|
||||
override them in one place.
|
||||
|
||||
The `max-width: none` undoes settingBody.css's 240px cap on admin table
|
||||
headers, which exists to stop a long label blowing a column up; here the
|
||||
column width is stated outright, so the cap has nothing to protect and would
|
||||
only fight the 50%. Both rules are scoped through .info-table, so no other
|
||||
admin table is touched. */
|
||||
.setting-content .content-body .main-body table.info-table {
|
||||
table-layout: fixed;
|
||||
}
|
||||
|
||||
.setting-content .content-body .main-body table.info-table > colgroup > col {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.setting-content .content-body .main-body table.info-table th,
|
||||
.setting-content .content-body .main-body table.info-table td {
|
||||
max-width: none;
|
||||
}
|
||||
|
||||
/* The category row. It spans both columns, so it is not a label with a value
|
||||
beside it - it is a line that says what the rows under it are about.
|
||||
|
||||
BOLD and start-aligned, at the table's own font size: it names a group of rows
|
||||
inside the pane, and the pane title above it (`.admin-pane-title`, 1.25rem)
|
||||
names the pane. Growing these to that size would read as five pane titles and
|
||||
"Version" would be lost among them. `color: inherit` for the same reason it is
|
||||
on the pane title: the panel is themeable and a fixed colour goes unreadable
|
||||
on a dark one. */
|
||||
.setting-content .content-body .main-body table.info-table tr.info-category > th {
|
||||
/* start, not left: a th centres by default, and this must sit over the label
|
||||
column - which is the RIGHT edge in Arabic and Hebrew (tests/rtl.test.js). */
|
||||
text-align: start;
|
||||
font-weight: 700;
|
||||
color: inherit;
|
||||
/* Space above the group, none below it: the separation belongs BETWEEN
|
||||
groups, and a gap under the title would push it away from the rows it
|
||||
introduces. */
|
||||
padding-top: 18px;
|
||||
}
|
||||
|
||||
/* ...except the first one, which sits directly under the pane title and needs no
|
||||
second gap on top of the 12px that title already brings. */
|
||||
.setting-content .content-body .main-body table.info-table tr.info-category:first-child > th {
|
||||
padding-top: 0;
|
||||
}
|
||||
@@ -5,49 +5,45 @@
|
||||
//- templates are global) inside the Settings page, which brings the left menu, the
|
||||
//- pane title and the admin check with it. The /information URL redirects to
|
||||
//- Settings, the same way the old /translation URL does.
|
||||
//-
|
||||
//- ONE table, in FIVE categories. This was a single flat list of 40 rows in which
|
||||
//- the WeKan version, the OS load average, the DDP transport and a V8 heap counter
|
||||
//- were the same kind of thing, read top to bottom, with no way to jump to the part
|
||||
//- you came for. It is grouped now - what this IS (version and packaging), what it
|
||||
//- runs ON, how Meteor is talking to the client, what the database is, and finally
|
||||
//- Node's own memory - and each group is introduced by a row of its own that SPANS
|
||||
//- BOTH COLUMNS, in bold.
|
||||
//-
|
||||
//- One table rather than five, because five tables size their columns
|
||||
//- independently: "WeKan ® Version" made the first one's label column wide and
|
||||
//- "OS Type" made the next one's narrow, so the values started at a different x
|
||||
//- in every group and the pane read as five unrelated things. One table with a
|
||||
//- colgroup of two 50% columns puts every label and every value in the same place
|
||||
//- (.info-table in informationBody.css).
|
||||
template(name='statistics')
|
||||
table
|
||||
table.info-table
|
||||
//- Two equal columns, stated once here rather than left to the widest cell:
|
||||
with table-layout fixed these are what the browser uses, so the labels and
|
||||
the values line up down the whole pane no matter which group is longest.
|
||||
colgroup
|
||||
col
|
||||
col
|
||||
tbody
|
||||
tr.info-category
|
||||
th(colspan="2") {{_ 'Platform'}}
|
||||
tr
|
||||
th WeKan ® {{_ 'info'}}
|
||||
td {{statistics.version}}
|
||||
//- The LABEL is translated; the VALUE never is. bundle.zip, Snap, Docker
|
||||
and Sandstorm are the names of the things themselves - a package
|
||||
format, a store, a product - not words describing them, and a reader
|
||||
reporting an issue, searching the docs or grepping a log needs the same
|
||||
four strings in every language. See models/lib/platformPackaging.js.
|
||||
tr
|
||||
th {{_ 'Meteor_version'}}
|
||||
td {{statistics.meteor.meteorVersion}}
|
||||
tr
|
||||
th {{_ 'Node_version'}}
|
||||
td {{statistics.process.nodeVersion}}
|
||||
tr
|
||||
th {{_ 'Database_type'}}
|
||||
td {{statistics.mongo.databaseType}}
|
||||
tr
|
||||
th {{_ 'MongoDB_version'}}
|
||||
td {{statistics.mongo.mongoVersion}}
|
||||
tr
|
||||
th {{_ 'Database_commit'}}
|
||||
td {{statistics.mongo.databaseCommit}}
|
||||
if statistics.mongo.ferretdbVersion
|
||||
tr
|
||||
th {{_ 'FerretDB_version'}}
|
||||
td {{statistics.mongo.ferretdbVersion}}
|
||||
tr
|
||||
th {{_ 'FerretDB_commit'}}
|
||||
td {{statistics.mongo.ferretdbCommit}}
|
||||
tr
|
||||
th {{_ 'MongoDB_storage_engine'}}
|
||||
td {{statistics.mongo.mongoStorageEngine}}
|
||||
tr
|
||||
th {{_ 'MongoDB_Oplog_enabled'}}
|
||||
td {{formatBoolean statistics.mongo.mongoOplogEnabled}}
|
||||
tr
|
||||
th {{_ 'Reactivity_mode'}}
|
||||
td {{statistics.mongo.reactivity}}
|
||||
tr
|
||||
th {{_ 'Reactivity_order'}}
|
||||
td {{statistics.mongo.reactivityOrder}}
|
||||
tr
|
||||
th {{_ 'DDP_transport'}}
|
||||
td {{statistics.mongo.ddpTransport}}
|
||||
th {{_ 'package'}}
|
||||
td {{statistics.platform.packaging}}
|
||||
tr.info-category
|
||||
th(colspan="2") {{_ 'OS'}}
|
||||
tr
|
||||
th {{_ 'OS_Type'}}
|
||||
td {{statistics.os.type}}
|
||||
@@ -75,6 +71,62 @@ template(name='statistics')
|
||||
tr
|
||||
th {{_ 'OS_Cpus'}}
|
||||
td {{statistics.os.cpus.length}}
|
||||
tr.info-category
|
||||
th(colspan="2") {{_ 'Meteor'}}
|
||||
tr
|
||||
th {{_ 'Meteor_version'}}
|
||||
td {{statistics.meteor.meteorVersion}}
|
||||
//- Reactivity and DDP are Meteor's, not the database's: what is LIVE
|
||||
(reactivity), what was ASKED for (reactivity order), and how the client
|
||||
is connected (DDP transport). Whether an OpLog exists to tail is a
|
||||
property of the database and stays in that table.
|
||||
tr
|
||||
th {{_ 'Reactivity_mode'}}
|
||||
td {{statistics.mongo.reactivity}}
|
||||
tr
|
||||
th {{_ 'Reactivity_order'}}
|
||||
td {{statistics.mongo.reactivityOrder}}
|
||||
tr
|
||||
th {{_ 'DDP_transport'}}
|
||||
td {{statistics.mongo.ddpTransport}}
|
||||
tr.info-category
|
||||
th(colspan="2") {{_ 'Database'}}
|
||||
tr
|
||||
th {{_ 'Database_type'}}
|
||||
td {{statistics.mongo.databaseType}}
|
||||
tr
|
||||
th {{_ 'MongoDB_version'}}
|
||||
td {{statistics.mongo.mongoVersion}}
|
||||
tr
|
||||
th {{_ 'Database_commit'}}
|
||||
td {{statistics.mongo.databaseCommit}}
|
||||
//- Only when FerretDB is what answered: on MongoDB these two rows have
|
||||
nothing to say, and an empty row reads as a missing value.
|
||||
if statistics.mongo.ferretdbVersion
|
||||
tr
|
||||
th {{_ 'FerretDB_version'}}
|
||||
td {{statistics.mongo.ferretdbVersion}}
|
||||
tr
|
||||
th {{_ 'FerretDB_commit'}}
|
||||
td {{statistics.mongo.ferretdbCommit}}
|
||||
tr
|
||||
th {{_ 'MongoDB_storage_engine'}}
|
||||
td {{statistics.mongo.mongoStorageEngine}}
|
||||
tr
|
||||
th {{_ 'MongoDB_Oplog_enabled'}}
|
||||
td {{formatBoolean statistics.mongo.mongoOplogEnabled}}
|
||||
unless isSandstorm
|
||||
tr
|
||||
th {{_ 'Mongo_sessions_count'}}
|
||||
td {{statistics.session.sessionsCount}}
|
||||
tr.info-category
|
||||
th(colspan="2") {{_ 'Node'}}
|
||||
tr
|
||||
th {{_ 'Node_version'}}
|
||||
td {{statistics.process.nodeVersion}}
|
||||
//- A Sandstorm grain has no V8 heap figures collected for it (see
|
||||
server/statistics.js), so the version above is all this table can say
|
||||
there.
|
||||
unless isSandstorm
|
||||
tr
|
||||
th {{_ 'Node_heap_total_heap_size'}}
|
||||
@@ -121,6 +173,3 @@ template(name='statistics')
|
||||
tr
|
||||
th {{_ 'Node_memory_usage_external'}}
|
||||
td {{fileSize statistics.nodeMemoryUsage.external}}
|
||||
tr
|
||||
th {{_ 'Mongo_sessions_count'}}
|
||||
td {{statistics.session.sessionsCount}}
|
||||
@@ -456,6 +456,34 @@ body.left-menu-resizing-active {
|
||||
|
||||
/* …and exactly .materialCheckBox.is-checked: the square becomes the tick, which is
|
||||
what the transition above animates. */
|
||||
/* #6465: THE FOCUS RING MUST NOT BE DRAWN ON THE ROTATED BOX.
|
||||
The checked state below turns the square into a tick by making two borders
|
||||
transparent and rotating the element 40deg. A browser draws its focus ring
|
||||
around the element as it is - rotated - so a checkbox that is both checked and
|
||||
focused (which is exactly what a checkbox you just clicked is) comes out as a
|
||||
blue DIAMOND sitting where the tick should be. That is the glitch reported on
|
||||
the Problems page.
|
||||
|
||||
The ring is not simply removed: keyboard users need to see where they are. It
|
||||
moves to the row that CONTAINS the checkbox, which is not rotated - every one
|
||||
of these lives inside a label (problemsSummary.jade: `label.admin-problem-item
|
||||
> input.js-problem-check`) - so the indicator is a normal rectangle around the
|
||||
whole row, which is easier to see than a 13px box anyway.
|
||||
|
||||
`:focus-visible` rather than `:focus`, so clicking with a mouse does not leave
|
||||
a ring behind; `:focus-within` is the fallback where :has() is not supported,
|
||||
and lands on the same element. */
|
||||
.setting-content input[type="checkbox"]:focus,
|
||||
.setting-content input[type="checkbox"]:focus-visible {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.setting-content label:has(> input[type="checkbox"]:focus-visible) {
|
||||
outline: 2px solid #2980b9;
|
||||
outline-offset: 2px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.setting-content input[type="checkbox"]:checked {
|
||||
top: -4px;
|
||||
inset-inline-start: -3px;
|
||||
|
||||
@@ -40,6 +40,7 @@ import '/client/components/settings/translationBody.js';
|
||||
// forms.css and rendered with a black/grey background instead of the theme.
|
||||
import '/client/components/settings/adminReports.css';
|
||||
import '/client/components/settings/attachments.css';
|
||||
import '/client/components/settings/informationBody.css';
|
||||
import '/client/components/settings/lockedUsersBody.css';
|
||||
import '/client/components/settings/migrationProgress.css';
|
||||
import '/client/components/settings/peopleBody.css';
|
||||
|
||||
@@ -3,6 +3,13 @@ import { ReactiveVar } from 'meteor/reactive-var';
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { getCurrentCardFromContext } from '/client/lib/currentCard';
|
||||
import { normalizeDigits } from '/imports/lib/dateUtils';
|
||||
|
||||
// The window a typed year has to fall in. Wide on purpose: WeKan holds real
|
||||
// historical received dates and long-dated deadlines, so this is only meant to
|
||||
// catch a year that cannot have been intended - the two-digit one a browser
|
||||
// reports verbatim (0026), and the five-digit slip in the other direction.
|
||||
const MIN_PLAUSIBLE_YEAR = 1000;
|
||||
const MAX_PLAUSIBLE_YEAR = 9999;
|
||||
import {
|
||||
isValidDate,
|
||||
formatTime,
|
||||
@@ -165,6 +172,26 @@ export function datePickerEvents({ storeDate, deleteDate }) {
|
||||
return;
|
||||
}
|
||||
|
||||
// A TWO-DIGIT YEAR is a real date that is not the one anybody meant.
|
||||
// `<input type="date">` reports YYYY-MM-DD, but the browser lets the year
|
||||
// sub-field be typed as two digits and reports that literally: typing
|
||||
// 31-12-26 gives "0026-12-31", the year 26 AD. Nothing above rejects it -
|
||||
// it is a perfectly valid Date - so the card got a due date two thousand
|
||||
// years in the past, which is why the reporter saw a date they had TYPED
|
||||
// come out red (overdue) while the same date picked from the calendar,
|
||||
// which always fills four digits, came out yellow (due soon). The colour
|
||||
// was right; the year was wrong.
|
||||
//
|
||||
// Refused rather than corrected: 0026 could be meant as 2026, but guessing
|
||||
// silently rewrites what somebody typed, and this is a date other people's
|
||||
// reminders hang off. The error names the year so the fix is obvious.
|
||||
const year = newCompleteDate.getFullYear();
|
||||
if (year < MIN_PLAUSIBLE_YEAR || year > MAX_PLAUSIBLE_YEAR) {
|
||||
tpl.datePicker.error.set('invalid-year');
|
||||
evt.target.date.focus();
|
||||
return;
|
||||
}
|
||||
|
||||
storeDate.call(tpl, newCompleteDate);
|
||||
Popup.back();
|
||||
},
|
||||
|
||||
@@ -11,6 +11,7 @@ export const ALLOWED_BOARD_COLORS = [
|
||||
'dark',
|
||||
'relax',
|
||||
'corteza',
|
||||
'appleglasspastel',
|
||||
'clearblue',
|
||||
'cleargreen',
|
||||
'clearorange',
|
||||
|
||||
@@ -218,8 +218,18 @@ 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://ferretdb:27017/wekan
|
||||
# directConnection=true is REQUIRED (wekan/wekan#6582). The ferretdb service
|
||||
# above runs with --repl-set-name=rs0, so its handshake advertises a replica
|
||||
# set whose only member is its own LISTEN address, 0.0.0.0:27017. Without
|
||||
# directConnection the MongoDB driver does replica-set discovery: it drops the
|
||||
# host written here and dials the advertised 0.0.0.0:27017 instead, which
|
||||
# inside the wekan container is the wekan container itself — that is the
|
||||
# "MongoServerSelectionError: connect ECONNREFUSED 0.0.0.0:27017" a fresh
|
||||
# `docker compose up` died with. directConnection=true keeps the driver on
|
||||
# exactly this host. OpLog tailing is unaffected: Meteor only needs setName in
|
||||
# the handshake, which is still there.
|
||||
#- MONGO_URL=mongodb://wekan-ferretdb:27017/wekan?directConnection=true
|
||||
- MONGO_URL=mongodb://ferretdb:27017/wekan?directConnection=true
|
||||
#- MONGO_PASSWORD_FILE=/run/secrets/mongo_password
|
||||
#---------------------------------------------------------------
|
||||
# ==== ROOT_URL SETTING ====
|
||||
@@ -274,7 +284,8 @@ services:
|
||||
# MONGO_OPLOG_URL makes Meteor start an OpLog tail regardless of the
|
||||
# reactivity order (#6498), so it is commented out. To try OpLog tailing,
|
||||
# uncomment the next line AND set METEOR_REACTIVITY_ORDER=oplog,polling above.
|
||||
#- MONGO_OPLOG_URL=mongodb://ferretdb:27017/local?replicaSet=rs0
|
||||
# directConnection=true for the same reason as MONGO_URL above (#6582).
|
||||
#- MONGO_OPLOG_URL=mongodb://ferretdb:27017/local?replicaSet=rs0&directConnection=true
|
||||
#---------------------------------------------------------------
|
||||
# ==== OPTIONAL: KADIRA PERFORMANCE MONITORING FOR METEOR ====
|
||||
# https://github.com/edemaine/kadira-compose
|
||||
|
||||
@@ -220,8 +220,18 @@ 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://ferretdb:27017/wekan
|
||||
# directConnection=true is REQUIRED (wekan/wekan#6582). The ferretdb service
|
||||
# above runs with --repl-set-name=rs0, so its handshake advertises a replica
|
||||
# set whose only member is its own LISTEN address, 0.0.0.0:27017. Without
|
||||
# directConnection the MongoDB driver does replica-set discovery: it drops the
|
||||
# host written here and dials the advertised 0.0.0.0:27017 instead, which
|
||||
# inside the wekan container is the wekan container itself — that is the
|
||||
# "MongoServerSelectionError: connect ECONNREFUSED 0.0.0.0:27017" a fresh
|
||||
# `docker compose up` died with. directConnection=true keeps the driver on
|
||||
# exactly this host. OpLog tailing is unaffected: Meteor only needs setName in
|
||||
# the handshake, which is still there.
|
||||
#- MONGO_URL=mongodb://wekan-ferretdb:27017/wekan?directConnection=true
|
||||
- MONGO_URL=mongodb://ferretdb:27017/wekan?directConnection=true
|
||||
#- MONGO_PASSWORD_FILE=/run/secrets/mongo_password
|
||||
#---------------------------------------------------------------
|
||||
# ==== ROOT_URL SETTING ====
|
||||
@@ -276,7 +286,8 @@ services:
|
||||
# MONGO_OPLOG_URL makes Meteor start an OpLog tail regardless of the
|
||||
# reactivity order (#6498), so it is commented out. To try OpLog tailing,
|
||||
# uncomment the next line AND set METEOR_REACTIVITY_ORDER=oplog,polling above.
|
||||
#- MONGO_OPLOG_URL=mongodb://ferretdb:27017/local?replicaSet=rs0
|
||||
# directConnection=true for the same reason as MONGO_URL above (#6582).
|
||||
#- MONGO_OPLOG_URL=mongodb://ferretdb:27017/local?replicaSet=rs0&directConnection=true
|
||||
#---------------------------------------------------------------
|
||||
# ==== OPTIONAL: KADIRA PERFORMANCE MONITORING FOR METEOR ====
|
||||
# https://github.com/edemaine/kadira-compose
|
||||
|
||||
@@ -207,8 +207,18 @@ 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://ferretdb:27017/wekan
|
||||
# directConnection=true is REQUIRED (wekan/wekan#6582). The ferretdb service
|
||||
# above runs with --repl-set-name=rs0, so its handshake advertises a replica
|
||||
# set whose only member is its own LISTEN address, 0.0.0.0:27017. Without
|
||||
# directConnection the MongoDB driver does replica-set discovery: it drops the
|
||||
# host written here and dials the advertised 0.0.0.0:27017 instead, which
|
||||
# inside the wekan container is the wekan container itself — that is the
|
||||
# "MongoServerSelectionError: connect ECONNREFUSED 0.0.0.0:27017" a fresh
|
||||
# `docker compose up` died with. directConnection=true keeps the driver on
|
||||
# exactly this host. OpLog tailing is unaffected: Meteor only needs setName in
|
||||
# the handshake, which is still there.
|
||||
#- MONGO_URL=mongodb://wekan-ferretdb:27017/wekan?directConnection=true
|
||||
- MONGO_URL=mongodb://ferretdb:27017/wekan?directConnection=true
|
||||
#- MONGO_PASSWORD_FILE=/run/secrets/mongo_password
|
||||
#---------------------------------------------------------------
|
||||
# ==== ROOT_URL SETTING ====
|
||||
@@ -263,7 +273,8 @@ services:
|
||||
# MONGO_OPLOG_URL makes Meteor start an OpLog tail regardless of the
|
||||
# reactivity order (#6498), so it is commented out. To try OpLog tailing,
|
||||
# uncomment the next line AND set METEOR_REACTIVITY_ORDER=oplog,polling above.
|
||||
#- MONGO_OPLOG_URL=mongodb://ferretdb:27017/local?replicaSet=rs0
|
||||
# directConnection=true for the same reason as MONGO_URL above (#6582).
|
||||
#- MONGO_OPLOG_URL=mongodb://ferretdb:27017/local?replicaSet=rs0&directConnection=true
|
||||
#---------------------------------------------------------------
|
||||
# ==== OPTIONAL: KADIRA PERFORMANCE MONITORING FOR METEOR ====
|
||||
# https://github.com/edemaine/kadira-compose
|
||||
|
||||
@@ -224,8 +224,18 @@ 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://ferretdb:27017/wekan
|
||||
# directConnection=true is REQUIRED (wekan/wekan#6582). The ferretdb service
|
||||
# above runs with --repl-set-name=rs0, so its handshake advertises a replica
|
||||
# set whose only member is its own LISTEN address, 0.0.0.0:27017. Without
|
||||
# directConnection the MongoDB driver does replica-set discovery: it drops the
|
||||
# host written here and dials the advertised 0.0.0.0:27017 instead, which
|
||||
# inside the wekan container is the wekan container itself — that is the
|
||||
# "MongoServerSelectionError: connect ECONNREFUSED 0.0.0.0:27017" a fresh
|
||||
# `docker compose up` died with. directConnection=true keeps the driver on
|
||||
# exactly this host. OpLog tailing is unaffected: Meteor only needs setName in
|
||||
# the handshake, which is still there.
|
||||
#- MONGO_URL=mongodb://wekan-ferretdb:27017/wekan?directConnection=true
|
||||
- MONGO_URL=mongodb://ferretdb:27017/wekan?directConnection=true
|
||||
#- MONGO_PASSWORD_FILE=/run/secrets/mongo_password
|
||||
#---------------------------------------------------------------
|
||||
# ==== ROOT_URL SETTING ====
|
||||
@@ -280,7 +290,8 @@ services:
|
||||
# MONGO_OPLOG_URL makes Meteor start an OpLog tail regardless of the
|
||||
# reactivity order (#6498), so it is commented out. To try OpLog tailing,
|
||||
# uncomment the next line AND set METEOR_REACTIVITY_ORDER=oplog,polling above.
|
||||
#- MONGO_OPLOG_URL=mongodb://ferretdb:27017/local?replicaSet=rs0
|
||||
# directConnection=true for the same reason as MONGO_URL above (#6582).
|
||||
#- MONGO_OPLOG_URL=mongodb://ferretdb:27017/local?replicaSet=rs0&directConnection=true
|
||||
#---------------------------------------------------------------
|
||||
# ==== OPTIONAL: KADIRA PERFORMANCE MONITORING FOR METEOR ====
|
||||
# https://github.com/edemaine/kadira-compose
|
||||
|
||||
+14
-3
@@ -178,8 +178,18 @@ 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://ferretdb:27017/wekan
|
||||
# directConnection=true is REQUIRED (wekan/wekan#6582). The ferretdb service
|
||||
# above runs with --repl-set-name=rs0, so its handshake advertises a replica
|
||||
# set whose only member is its own LISTEN address, 0.0.0.0:27017. Without
|
||||
# directConnection the MongoDB driver does replica-set discovery: it drops the
|
||||
# host written here and dials the advertised 0.0.0.0:27017 instead, which
|
||||
# inside the wekan container is the wekan container itself — that is the
|
||||
# "MongoServerSelectionError: connect ECONNREFUSED 0.0.0.0:27017" a fresh
|
||||
# `docker compose up` died with. directConnection=true keeps the driver on
|
||||
# exactly this host. OpLog tailing is unaffected: Meteor only needs setName in
|
||||
# the handshake, which is still there.
|
||||
#- MONGO_URL=mongodb://wekan-ferretdb:27017/wekan?directConnection=true
|
||||
- MONGO_URL=mongodb://ferretdb:27017/wekan?directConnection=true
|
||||
#- MONGO_PASSWORD_FILE=/run/secrets/mongo_password
|
||||
#---------------------------------------------------------------
|
||||
# ==== ROOT_URL SETTING ====
|
||||
@@ -234,7 +244,8 @@ services:
|
||||
# MONGO_OPLOG_URL makes Meteor start an OpLog tail regardless of the
|
||||
# reactivity order (#6498), so it is commented out. To try OpLog tailing,
|
||||
# uncomment the next line AND set METEOR_REACTIVITY_ORDER=oplog,polling above.
|
||||
#- MONGO_OPLOG_URL=mongodb://ferretdb:27017/local?replicaSet=rs0
|
||||
# directConnection=true for the same reason as MONGO_URL above (#6582).
|
||||
#- MONGO_OPLOG_URL=mongodb://ferretdb:27017/local?replicaSet=rs0&directConnection=true
|
||||
#---------------------------------------------------------------
|
||||
# ==== OPTIONAL: KADIRA PERFORMANCE MONITORING FOR METEOR ====
|
||||
# https://github.com/edemaine/kadira-compose
|
||||
|
||||
@@ -7,8 +7,10 @@ the **default database of WeKan**: `docker-compose.yml` runs FerretDB v1 on its
|
||||
embedded SQLite, so there is no separate database server to install at all.
|
||||
|
||||
Whichever backend is used, WeKan talks only to FerretDB
|
||||
(`MONGO_URL=mongodb://ferretdb:27017/wekan`) — nothing in WeKan knows what is
|
||||
behind it.
|
||||
(`MONGO_URL=mongodb://ferretdb:27017/wekan?directConnection=true`) — nothing in
|
||||
WeKan knows what is behind it. See
|
||||
[directConnection](#why-the-url-says-directconnectiontrue) for why that parameter
|
||||
is not optional.
|
||||
|
||||
## Which one to use
|
||||
|
||||
@@ -55,8 +57,24 @@ The compose files do not use a FerretDB image: a small Debian container download
|
||||
the `ferretdb-<arch>` binary for its own architecture from the newest
|
||||
[wekan/FerretDB release](https://github.com/wekan/FerretDB/releases), caches it on
|
||||
the volume and runs it. Pin a version with `FERRETDB_RELEASE=download/v1.24.2`.
|
||||
The same per-arch binaries are embedded in the WeKan bundles for the platforms
|
||||
MongoDB has no server build for — ppc64le, s390x, riscv64.
|
||||
|
||||
**Seventeen of those binaries are built**, all cross-compiled from one checkout
|
||||
with CGO disabled: ten Linux (`amd64`, `arm64`, `armhf`, `armv6`, `armel`,
|
||||
`i386`, `ppc64le`, `s390x`, `riscv64`, `loong64`), three Windows (`win64`,
|
||||
`win-arm64`, `win32`), two macOS (`mac-amd64`, `mac-arm64`) and two FreeBSD
|
||||
(`freebsd-amd64`, `freebsd-arm64`). The 32-bit ARM ones are three different
|
||||
builds, not three names for one: `armhf` is `GOARM=7`, `armv6` is `GOARM=6` for
|
||||
the Raspberry Pi 1 and Zero, and `armel` is `GOARM=5` software floating point for
|
||||
genuine ARMv5.
|
||||
|
||||
A `ferretdb-<arch>` binary is embedded in **every** WeKan bundle, and it is the
|
||||
default database on the platforms MongoDB publishes no server for — ppc64le,
|
||||
s390x, riscv64, i386, armv6 and armhf — where nothing else can be. There is also
|
||||
a multi-arch image (`wekanteam/ferretdb`, `quay.io/wekan/ferretdb`,
|
||||
`ghcr.io/wekan/ferretdb`) built `FROM scratch` around these same binaries, which
|
||||
is why it covers every Linux one of them, including `linux/arm/v6` and
|
||||
`linux/loong64` that the WeKan image cannot reach — see
|
||||
[Docker CPU platforms](../../../Platforms/FOSS/Container/Docker/CPU-platforms.md).
|
||||
|
||||
The `hana` handler is behind the `ferretdb_hana` build tag; the released binaries
|
||||
are built with it, so `--handler=hana` exists. A FerretDB built elsewhere without
|
||||
@@ -75,6 +93,53 @@ merely setting `MONGO_OPLOG_URL` starts a tail regardless of the reactivity orde
|
||||
|
||||
FerretDB has no MongoDB change streams at all, in either version.
|
||||
|
||||
## Why the URL says `directConnection=true`
|
||||
|
||||
Every FerretDB v1 compose file connects with
|
||||
`mongodb://ferretdb:27017/wekan?directConnection=true`, and dropping that
|
||||
parameter breaks the stack on the first start
|
||||
([#6582](https://github.com/wekan/wekan/issues/6582)):
|
||||
|
||||
```
|
||||
MongoServerSelectionError: connect ECONNREFUSED 0.0.0.0:27017
|
||||
reason: TopologyDescription {
|
||||
type: 'ReplicaSetNoPrimary',
|
||||
servers: Map(1) { '0.0.0.0:27017' => [ServerDescription] },
|
||||
setName: 'rs0', ... }
|
||||
```
|
||||
|
||||
`0.0.0.0` appears in no compose file. It is FerretDB's own **listen** address,
|
||||
and the driver was handed it by the server.
|
||||
|
||||
Because the `ferretdb` service runs with `--repl-set-name=rs0` (see
|
||||
[The OpLog](#the-oplog) above), FerretDB answers the `hello` handshake as a
|
||||
one-member replica set, and fills the `hosts`, `me` and `primary` fields with its
|
||||
`--listen-addr` — the wildcard `0.0.0.0:27017`. A MongoDB driver that is not in
|
||||
direct-connection mode treats such a reply as an invitation to do replica-set
|
||||
**discovery**: it adopts the member list the server advertised, and drops the
|
||||
seed it was given, because the server reports a name other than the one that was
|
||||
dialled. So `mongodb://ferretdb:27017` turns into `0.0.0.0:27017`, which inside
|
||||
the `wekan-app` container means that container itself — where nothing is
|
||||
listening. Hence `ECONNREFUSED`, on a compose file that was never edited.
|
||||
|
||||
`directConnection=true` tells the driver to stay on exactly the host it was
|
||||
given and skip discovery entirely. Measured against FerretDB v1.49.0 with the
|
||||
driver the bundle ships:
|
||||
|
||||
| MONGO\_URL | Topology the driver ends up with |
|
||||
| --- | --- |
|
||||
| `mongodb://localhost:27017/wekan` | `ReplicaSetWithPrimary`, servers: `0.0.0.0:27017` — the seed was discarded |
|
||||
| `mongodb://localhost:27017/wekan?directConnection=true` | `Single`, servers: `localhost:27017` |
|
||||
|
||||
It costs nothing else. The handshake still reports `setName: 'rs0'`, and that is
|
||||
the only thing Meteor checks before it will tail an OpLog, so
|
||||
`MONGO_OPLOG_URL=...?replicaSet=rs0&directConnection=true` keeps working exactly
|
||||
as [#6480/#6481](https://github.com/wekan/wekan/issues/6480) left it.
|
||||
|
||||
This applies only to FerretDB. The MongoDB compose files talk to a real replica
|
||||
set whose members are configured with names that do resolve, so they keep plain
|
||||
`replicaSet=rs0` and must **not** gain `directConnection`.
|
||||
|
||||
## Do they all answer the same?
|
||||
|
||||
[Conformance.md](Conformance.md) — `./build.sh` → Tests → **All databases
|
||||
|
||||
@@ -2,7 +2,12 @@
|
||||
|
||||
FerretDB speaks the MongoDB wire protocol and stores the data in something else,
|
||||
so WeKan runs unchanged on top of it — WeKan only ever connects to
|
||||
`mongodb://ferretdb:27017/wekan` and knows nothing about what is behind it.
|
||||
`mongodb://ferretdb:27017/wekan?directConnection=true` and knows nothing about
|
||||
what is behind it. The `directConnection=true` is required, not decoration:
|
||||
without it the driver follows FerretDB's replica-set handshake to the wildcard
|
||||
address FerretDB listens on and the stack cannot start
|
||||
([#6582](https://github.com/wekan/wekan/issues/6582), explained in
|
||||
[1/README.md](1/README.md#why-the-url-says-directconnectiontrue)).
|
||||
|
||||
There are two versions, and they are different products:
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ Files in this directory are served by meteor as-is to the client. It hosts some
|
||||
* **[popup.tpl.jade](../../client/components/main/popup.tpl.jade)**: tpl files only define a single template so there's no need to wrap content in a template tag; the name of the template is the base name of the file (`popup` in this case);
|
||||
* **[spinner.tpl.jade](https://github.com/wekan/wekan/tree/main/client/components/main/spinner.tpl.jade)**: is the template for a "waiting" dialog;
|
||||
* **[settings](../../client/components/settings)**:
|
||||
* **[informationBody.jade](../../client/components/settings/informationBody.jade)**: `information`, `statistics` templates;
|
||||
* **[informationBody.jade](../../client/components/settings/informationBody.jade)**: the `statistics` template — the Version pane of Admin Panel / Settings, five tables (Platform, OS, Meteor, Database, Node). There is no `information` template any more: it is a pane rendered by `settingBody.jade`, not a page;
|
||||
* **[invitationCode.jade](../../client/components/settings/invitationCode.jade)**: `invitationCode` template;
|
||||
* **[peopleBody.jade](../../client/components/settings/peopleBody.jade)**: `people`, `peopleGeneral`, `peopleRow`, `editUserPopup`;
|
||||
* **[settingBody.jade](../../client/components/settings/settingBody.jade)**: `setting`, `general`, `email`, `accountSettings`, `announcementSettings`
|
||||
|
||||
@@ -0,0 +1,210 @@
|
||||
# WeKan Docker image — CPU platforms
|
||||
|
||||
This page documents, **for the WeKan Docker image**, which CPU platforms the
|
||||
multi-arch manifest carries, how that set is decided on every release, which
|
||||
database each platform starts by default, and which bundle platforms are
|
||||
deliberately not images.
|
||||
|
||||
The snap has the same page of its own:
|
||||
[Snap CPU platforms](../Snap/CPU-platforms.md).
|
||||
|
||||
## Summary
|
||||
|
||||
- **The image is assembled from the release bundles, not compiled per platform.**
|
||||
`Dockerfile` downloads `wekan-<version>-<arch>.zip` from the GitHub Release for
|
||||
the platform it is building, installs a Node.js resolved by
|
||||
[`releases/resolve-node-source.sh`](../../../../../releases/resolve-node-source.sh)
|
||||
— the same script the bundles and the snap use, so one architecture's image and
|
||||
bundle always carry the same Node.js from the same source — and runs the
|
||||
bundle. There is no per-platform compile in the image at all.
|
||||
- **At most eight Linux platforms.** `linux/amd64` and `linux/arm64` are
|
||||
**required**; `linux/ppc64le`, `linux/s390x`, `linux/riscv64`, `linux/386`,
|
||||
`linux/arm/v6` and `linux/arm/v7` are **optional** and included only when their
|
||||
bundle landed on the release **and** the base image publishes the platform.
|
||||
- **A missing optional bundle drops only itself.** One failed extra-arch build
|
||||
removes that platform from the manifest with a warning; it does not fail or
|
||||
skip the Docker job, and the platform comes back on the next release that
|
||||
builds it.
|
||||
- **`linux/arm/v6` is a candidate that drops itself today**, because
|
||||
`debian:trixie` publishes `arm/v5` and `arm/v7` and nothing between them. See
|
||||
[armv6](#armv6-wired-end-to-end-waiting-on-a-base-image) — this is the one
|
||||
platform whose absence is not about WeKan at all.
|
||||
- **Three registries, two tags each**: `wekanteam/wekan`, `quay.io/wekan/wekan`
|
||||
and `ghcr.io/wekan/wekan`, at `:v<version>` and `:latest`, built with
|
||||
`--provenance=mode=max` and verified after the push by asking each registry
|
||||
what it actually has.
|
||||
- **Not image platforms:** loong64 (no base image exists), armv6, armv7, and
|
||||
every Windows and macOS bundle. Each has a reason below, and none of them is an
|
||||
oversight.
|
||||
|
||||
## Per-platform matrix
|
||||
|
||||
| Docker platform | `TARGETARCH` | `TARGETVARIANT` | Bundle | Required | Database when nothing is set |
|
||||
|-----------------|--------------|-----------------|--------|:--------:|------------------------------|
|
||||
| `linux/amd64` | `amd64` | — | `amd64` | ✅ | external MongoDB (`MONGO_URL`) |
|
||||
| `linux/arm64` | `arm64` | (`v8`, implied) | `arm64` | ✅ | external MongoDB (`MONGO_URL`) |
|
||||
| `linux/ppc64le` | `ppc64le` | — | `ppc64le` | ❌ | bundled FerretDB v1 (SQLite) |
|
||||
| `linux/s390x` | `s390x` | — | `s390x` | ❌ | bundled FerretDB v1 (SQLite) |
|
||||
| `linux/riscv64` | `riscv64` | — | `riscv64` | ❌ | bundled FerretDB v1 (SQLite) |
|
||||
| `linux/386` | `386` | — | `i386` | ❌ | bundled FerretDB v1 (SQLite) |
|
||||
| `linux/arm/v6` | `arm` | `v6` | `armv6` | ❌ | bundled FerretDB v1 (SQLite) |
|
||||
| `linux/arm/v7` | `arm` | `v7` or unset | `armhf` | ❌ | bundled FerretDB v1 (SQLite) |
|
||||
|
||||
**`TARGETARCH` alone does not identify a platform.** ARMv6 and ARMv7 both arrive
|
||||
as `arm`; only `TARGETVARIANT` tells them apart, which is why the `Dockerfile`'s
|
||||
architecture `case` branches on the pair. Mapping `arm` straight to `armhf`, as
|
||||
it did before, would hand a Raspberry Pi 1 the ARMv7-A bundle. `v5` (armel) is
|
||||
refused outright rather than falling through: Go builds ARMv5, Node.js does not
|
||||
exist for it, so there is no bundle to put in an image.
|
||||
|
||||
**Required** means the Docker job fails if that bundle is not on the release:
|
||||
without amd64 and arm64 there is no image worth pushing, and a release that got
|
||||
that far would already have failed.
|
||||
|
||||
**The database column is a default, not a limit.** Every bundle carries a
|
||||
`ferretdb` binary, so FerretDB v1 runs on every platform; the default is decided
|
||||
by [`releases/ferretdb/wekan-entrypoint.sh`](../../../../../releases/ferretdb/wekan-entrypoint.sh)
|
||||
from a `/build/.ferretdb-default` marker that every extra-architecture bundle
|
||||
carries and the amd64/arm64 bundles have removed. `WEKAN_DB=ferretdb` or
|
||||
`WEKAN_DB=mongodb` overrides it on any platform, and setting `MONGO_URL` on a
|
||||
FerretDB-default platform points WeKan at that database instead.
|
||||
|
||||
## How the platform set is decided, on every release
|
||||
|
||||
The `docker` job in
|
||||
[`.github/workflows/release-all.yml`](../../../../../.github/workflows/release-all.yml)
|
||||
does this before it builds anything:
|
||||
|
||||
1. It holds two lists — `req="linux/amd64:amd64 linux/arm64:arm64"` and
|
||||
`opt="linux/ppc64le:ppc64le linux/s390x:s390x linux/riscv64:riscv64
|
||||
linux/386:i386 linux/arm/v6:armv6 linux/arm/v7:armhf"` — where each entry is
|
||||
*docker platform : the bundle arch the Dockerfile downloads for it*.
|
||||
2. It asks the **base image** which platforms it publishes
|
||||
(`docker buildx imagetools inspect`, with the base name read out of the
|
||||
`Dockerfile` so there is no second copy of it), and drops any candidate the
|
||||
base lacks.
|
||||
3. It asks the **release**, with an HTTP `HEAD`, whether
|
||||
`wekan-<version>-<arch>.zip` is there.
|
||||
|
||||
A missing **required** base platform or bundle is an error; a missing
|
||||
**optional** one is a warning and that platform is dropped. The chosen set then
|
||||
drives all three of the buildx `--platform` list, the wait-for-the-assets loop,
|
||||
and the post-push verification — so the three can never disagree about what the
|
||||
image was supposed to contain.
|
||||
|
||||
**Why the base is asked at all**, when a missing base would surely just fail the
|
||||
build: for 32-bit ARM it does not fail. containerd treats a **lower** ARM variant
|
||||
as compatible, so a `linux/arm/v6` request against a base that has `arm/v5` and
|
||||
`arm/v7` resolves to `arm/v5` — Debian **armel**, soft-float — and an image built
|
||||
on that would carry a hard-float `node-armv6` its own loader cannot start. A
|
||||
silent downgrade is worse than a dropped platform, so it is dropped, loudly,
|
||||
with the reason in the warning.
|
||||
|
||||
`tests/releaseDockerPlatforms.test.cjs` pins that shape: which platforms are
|
||||
required, which are optional, that `linux/loong64` is never among them, that
|
||||
every platform resolves to the bundle the Decide step paired it with, that the
|
||||
`arm` branch reads `TARGETVARIANT` and refuses `v5`, and that both loops check
|
||||
the base.
|
||||
|
||||
## The names, and the ones that do not match
|
||||
|
||||
An architecture is spelled one way by Docker, another by Debian, and a third by
|
||||
the WeKan bundles. Three of them differ here:
|
||||
|
||||
| Docker | `TARGETARCH` | WeKan bundle | Note |
|
||||
|--------|--------------|--------------|------|
|
||||
| `linux/386` | `386` | `i386` | everyone but Docker and Node.js says i386 |
|
||||
| `linux/arm/v7` | `arm` | `armhf` | Debian's 32-bit ARM port: ARMv7-A, VFPv3-D16 |
|
||||
| `linux/arm64` | `arm64` | `arm64` | buildx reports it as `linux/arm64/v8`; the verify step strips the implied `/v8` |
|
||||
|
||||
The `Dockerfile` maps `TARGETARCH` to the bundle name in one `case` and **exits
|
||||
on anything it does not know**, rather than guessing — an unrecognised platform
|
||||
would otherwise download another CPU's `.zip` and produce an image that starts
|
||||
and then dies.
|
||||
|
||||
## What is not an image platform, and why
|
||||
|
||||
### loong64 — there is no base image to build on
|
||||
|
||||
`node-loong64` and `ferretdb-loong64` both exist and the bundle is built, but no
|
||||
Docker base image publishes loong64 at any tag — not debian, not ubuntu — so
|
||||
there is no loong64 userland to install into, and the registries do not agree on
|
||||
what the platform is even called. `tests/releaseDockerPlatforms.test.cjs`
|
||||
asserts `linux/loong64` is not in the platform list, so this stays a decision
|
||||
rather than something that quietly reappears.
|
||||
|
||||
### armv6 — wired end to end, waiting on a base image
|
||||
|
||||
ARMv6 (Raspberry Pi 1 and Zero) is a **candidate platform**: `linux/arm/v6` is in
|
||||
the optional list, the `Dockerfile` resolves it to the `armv6` bundle through
|
||||
`TARGETVARIANT`, and the guard test pins both. Everything the image needs exists —
|
||||
`node-armv6` from [wekan/node-patches](https://github.com/wekan/node-patches)
|
||||
(nobody else publishes an ARMv6 Node.js) and `GOARM=6` binaries from
|
||||
[wekan/FerretDB](https://github.com/wekan/FerretDB) and
|
||||
[wekan/mongo-tools-patches](https://github.com/wekan/mongo-tools-patches).
|
||||
|
||||
**What is missing is a base image.** `debian:trixie`'s manifest list is `386`,
|
||||
`amd64`, `arm64/v8`, `arm/v5`, `arm/v7`, `ppc64le`, `riscv64`, `s390x` — there is
|
||||
no `arm/v6`. Debian has no ARMv6 port: its 32-bit ARM ports are armel (ARMv5,
|
||||
soft-float) and armhf (ARMv7-A). ARMv6 hard-float is Raspberry Pi OS territory,
|
||||
not Debian's. So the release drops the platform with a warning and the image
|
||||
ships without it, while the **armv6 bundle zip is unaffected** — that is how an
|
||||
ARMv6 board runs WeKan today.
|
||||
|
||||
The day the base publishes `arm/v6`, or the base for that one platform becomes an
|
||||
ARMv6 userland, the platform is included automatically: nothing else has to
|
||||
change. Until then, do **not** "fix" this by removing the base check — that is
|
||||
what makes the drop a warning instead of an image whose Node.js cannot start.
|
||||
|
||||
`models/lib/snapArchitectures.js` describes armv6 as shipping "a bundle zip and a
|
||||
`linux/arm/v6` Docker image"; the bundle is real today, the image is prepared and
|
||||
gated.
|
||||
|
||||
### armv7 — one 32-bit ARM slot, and it carries the baseline
|
||||
|
||||
There is one `linux/arm/v7` platform, and it must run on any ARMv7-A board, so it
|
||||
carries the **armhf** bundle: the `armv7` bundle assumes NEON, which is an
|
||||
illegal instruction on an ARMv7-A board without it. This is the same reasoning
|
||||
that gives armv7 no snap — see
|
||||
[the snap page](../Snap/CPU-platforms.md#armhf-and-armv7-are-the-same-cpu-family-built-to-different-baselines).
|
||||
|
||||
### win64, win32, win-arm64, mac-x64, mac-arm64
|
||||
|
||||
Bundle platforms that are not Linux. They are not container images and are not
|
||||
expected to be.
|
||||
|
||||
## Variant images
|
||||
|
||||
[`docker-variant.yml`](../../../../../.github/workflows/docker-variant.yml)
|
||||
publishes the variant repositories, **manually and never as part of a release**.
|
||||
It rebuilds nothing: `docker buildx imagetools create` copies the *manifest*, so
|
||||
a variant tag points at the very digests the release built and verified, and can
|
||||
never drift from `wekanteam/wekan`. Before and after the retag it checks that
|
||||
`linux/amd64`, `linux/arm64`, `linux/ppc64le`, `linux/s390x` and `linux/riscv64`
|
||||
are all present, so a variant cannot silently cover fewer architectures than
|
||||
`wekan` does. `releases/docker-publish-variant.sh` is the same thing locally.
|
||||
|
||||
## The FerretDB image covers more platforms than the WeKan image
|
||||
|
||||
[wekan/FerretDB](https://github.com/wekan/FerretDB)'s own `docker.yml` builds
|
||||
`FROM scratch` around the **prebuilt** per-architecture Go binaries, with no
|
||||
QEMU and no base image, so a platform costs it nothing but a binary. Its manifest
|
||||
is computed from whichever `ferretdb-<arch>` assets downloaded, mapping
|
||||
`amd64`→`linux/amd64`, `arm64`→`linux/arm64`, `armhf`→`linux/arm/v7`,
|
||||
`armv6`→`linux/arm/v6`, `armel`→`linux/arm/v5`, `i386`→`linux/386`,
|
||||
`ppc64le`→`linux/ppc64le`, `s390x`→`linux/s390x`, `riscv64`→`linux/riscv64` and
|
||||
`loong64`→`linux/loong64`. It is published as `wekanteam/ferretdb`,
|
||||
`quay.io/wekan/ferretdb` and `ghcr.io/wekan/ferretdb`.
|
||||
|
||||
That is why the two lists differ: the WeKan image needs a Debian userland and a
|
||||
Node.js for a platform, and the FerretDB image needs only one static binary.
|
||||
|
||||
## Related
|
||||
|
||||
- [Snap CPU platforms](../Snap/CPU-platforms.md) — the same page for the snap
|
||||
- [Which compose file, which database](README.md)
|
||||
- [FerretDB v1 and its backends](../../../../Databases/FerretDB/1/)
|
||||
- The platform list in code: the `docker` job of
|
||||
[`release-all.yml`](../../../../../.github/workflows/release-all.yml), guarded by
|
||||
`tests/releaseDockerPlatforms.test.cjs`
|
||||
- Node.js per platform: [wekan/node-patches](https://github.com/wekan/node-patches)
|
||||
@@ -1,3 +1,6 @@
|
||||
Which CPU platforms the image is published for, and why some bundle platforms are
|
||||
not images: [CPU-platforms.md](CPU-platforms.md).
|
||||
|
||||
## WeKan Docker compose files (which database?)
|
||||
|
||||
Since the default database changed, the compose files in https://github.com/wekan/wekan are:
|
||||
|
||||
@@ -10,8 +10,8 @@ and how the one-time MongoDB 3 → FerretDB v1 migration works.
|
||||
FerretDB v1 is the wekan/FerretDB fork with an embedded pure-Go SQLite backend
|
||||
that speaks the MongoDB wire protocol, so WeKan talks to it exactly like MongoDB.
|
||||
- **Six architectures are built as snaps**: amd64, arm64, armhf, ppc64el, riscv64
|
||||
and s390x — exactly `snapcraft.yaml`'s `build-for:` list. i386 and armv7 are
|
||||
release bundles but **not** snaps, for reasons that are not oversights; see
|
||||
and s390x — exactly `snapcraft.yaml`'s `build-for:` list. i386, armv6 and armv7
|
||||
are release bundles but **not** snaps, for reasons that are not oversights; see
|
||||
[CPU architecture names](#cpu-architecture-names-and-what-they-mean).
|
||||
- **MongoDB 7 *server* binaries (mongod) are included for amd64 and arm64 only.**
|
||||
The other architectures (armhf, ppc64el, riscv64, s390x) have no MongoDB server
|
||||
@@ -91,6 +91,32 @@ the `armhf` bundle, and **`armv7` has no snap** — it ships as a bundle only. A
|
||||
separate snap name or track would be the only way to offer the NEON build, which
|
||||
is not worth a second listing for one board family.
|
||||
|
||||
### armv6 has no snap, because the store has no such architecture
|
||||
|
||||
ARMv6 is the Raspberry Pi 1 and the Pi Zero: 32-bit ARM with **VFPv2** hardware
|
||||
floating point and **no NEON**. The Snap Store's only 32-bit ARM architecture is
|
||||
`armhf`, which is the **ARMv7-A** hard-float baseline — an ARMv6 board cannot run
|
||||
an armhf snap, and there is no armv6 architecture to publish one as. So there is
|
||||
nothing to fix here and nothing to add: **armv6 ships as a release bundle zip**,
|
||||
and nothing else in the Snap Store. (It is a candidate platform of the Docker
|
||||
image too, gated on a base image that publishes `linux/arm/v6` — see
|
||||
[Docker CPU platforms](../Docker/CPU-platforms.md#armv6-wired-end-to-end-waiting-on-a-base-image).)
|
||||
|
||||
It is a separate build from armhf all the way down, not a re-tag of it:
|
||||
[wekan/node-patches](https://github.com/wekan/node-patches) builds `node-armv6`
|
||||
(`--with-arm-fpu=vfp`, `-march=armv6+fp`) because nobody publishes an ARMv6
|
||||
Node.js any more — nodejs.org dropped it after Node 11 —
|
||||
and [wekan/FerretDB](https://github.com/wekan/FerretDB) and
|
||||
[wekan/mongo-tools-patches](https://github.com/wekan/mongo-tools-patches) build
|
||||
`GOARM=6` binaries beside their armhf ones. Their `armel` (`GOARM=5`) would run
|
||||
on an ARMv6 board, which is what makes it look like a substitute: it does
|
||||
floating point in **software**, so it is not one.
|
||||
|
||||
`models/lib/snapArchitectures.js` records this reason in
|
||||
`NOT_SNAP_ARCHITECTURES`, beside i386's and armv7's, and
|
||||
`tests/releaseSnapArches.test.cjs` asserts armv6 is neither a snap platform nor a
|
||||
Launchpad build.
|
||||
|
||||
### i386 has no snap, and cannot have a new one
|
||||
|
||||
core24 is Ubuntu 24.04, which has **no i386 port**, so there is no i386 core24
|
||||
@@ -107,11 +133,24 @@ version `0.X-ci`) because the store keeps whatever was ever uploaded. It is year
|
||||
stale, nothing new can be built for it, and re-releasing it would only re-publish
|
||||
`0.X-ci`. **i386 users are served by the .deb and the AppImage.**
|
||||
|
||||
### loong64, win64, win32, mac-x64, mac-arm64
|
||||
### loong64, win64, win32, win-arm64, mac-x64, mac-arm64
|
||||
|
||||
Bundle platforms with no Snap Store architecture at all. They are not snaps and
|
||||
are not expected to be.
|
||||
|
||||
### The whole bundle list, and which of it is a snap
|
||||
|
||||
The release builds fifteen bundles; six of them become snaps. The rest are
|
||||
bundles (and, for some, Docker images) only:
|
||||
|
||||
| Bundle | Snap? | Why not |
|
||||
|--------|-------|---------|
|
||||
| `amd64`, `arm64`, `armhf`, `ppc64le` (→ `ppc64el`), `riscv64`, `s390x` | ✅ | — |
|
||||
| `armv6` | ❌ | the store has no armv6 architecture |
|
||||
| `armv7` | ❌ | the store's one 32-bit ARM slot must carry the armhf baseline |
|
||||
| `i386` | ❌ | core24 has no i386 port |
|
||||
| `loong64`, `win64`, `win32`, `win-arm64`, `mac-x64`, `mac-arm64` | ❌ | no Snap Store architecture at all |
|
||||
|
||||
## New installs
|
||||
|
||||
On a fresh install, every architecture starts on **FerretDB v1 (SQLite)** with
|
||||
@@ -183,6 +222,73 @@ After a successful migration the snap switches to `database=ferretdb`.
|
||||
Architectures other than amd64 ship no MongoDB server and no MongoDB 3 client, so
|
||||
there is nothing to migrate from — they are FerretDB v1 from the first boot.
|
||||
|
||||
### Which MongoDB databases the snap can migrate from
|
||||
|
||||
**Three readers, on amd64 and arm64.** A MongoDB server only starts on data whose
|
||||
`featureCompatibilityVersion` is at most one major behind it, so which versions
|
||||
can be read is a property of which servers the snap carries:
|
||||
|
||||
| Reader | Opens data from | Used for |
|
||||
|--------|-----------------|----------|
|
||||
| mongod 7 (the server it runs) | MongoDB 6.0, 7.0 | the running database, and reading a 6/7 one to migrate |
|
||||
| **mongod 4.2** (migration only) | MongoDB 4.0, 4.2 | reading a 4.x database to migrate |
|
||||
| the MongoDB 3.2 tools (`migratemongo`) | MongoDB 3.2 | reading a 6.09-era database to migrate |
|
||||
|
||||
mongod 4.2 is bundled for **amd64 and arm64 only** — MongoDB publishes no 4.2 for
|
||||
the others, and they have been FerretDB from their first boot, so there is nothing
|
||||
there to migrate from. It carries its own OpenSSL 1.1, because core24 ships
|
||||
OpenSSL 3 and the 4.2 build will not load without 1.1. It is used **only to read**
|
||||
during a migration; the running database is never mongod 4.2.
|
||||
|
||||
What is still unreadable, therefore: **3.4, 3.6, 4.4 and 5.0**. A database from
|
||||
one of those gets the page below rather than a migration.
|
||||
|
||||
### A database from a MongoDB none of the three can read
|
||||
|
||||
A database left by a **MongoDB 4.4 or 5.0** snap (or a 3.4/3.6 one) opens in none
|
||||
of them — mongod 7 refuses it with
|
||||
|
||||
```
|
||||
This version of MongoDB is too recent to start up on the existing data files.
|
||||
Try MongoDB 4.2 or earlier.
|
||||
```
|
||||
|
||||
and neither mongod 4.2 nor the 3.2 tools can open them either. Reading those
|
||||
files needs a server the snap does not carry, so **no retry can succeed**, and
|
||||
there is nothing the snap can migrate from.
|
||||
|
||||
What it does instead of trying: it **stops**, writes
|
||||
`$SNAP_COMMON/.mongodb-data-too-old` with the version mongod itself named as
|
||||
still able to read the data, and serves an explanatory page on the web port
|
||||
instead of 502. MongoDB is not started (a start that cannot work would be
|
||||
restarted by snapd forever, and used to bounce between mongod and the migration
|
||||
three times before giving up), auto-migration is paused, and **nothing is
|
||||
changed**: the database files, the attachments and the avatars are exactly as
|
||||
they were.
|
||||
|
||||
Two ways forward, both keeping the data:
|
||||
|
||||
1. **Go back to the revision that worked** and stay there for now:
|
||||
|
||||
```
|
||||
sudo snap revert wekan
|
||||
sudo snap refresh --hold=forever wekan
|
||||
```
|
||||
|
||||
2. **Move the data across** with a MongoDB that can read it (the version the page
|
||||
names): start that MongoDB on the data directory, `mongodump` from it, restore
|
||||
the dump into this version, and let the MongoDB → FerretDB migration above run.
|
||||
|
||||
Attachments and avatars are **files on disk**, not database rows, so they are
|
||||
unaffected either way — see `$SNAP_COMMON/files`.
|
||||
|
||||
To let the snap try again — after moving the data, say — remove the marker:
|
||||
|
||||
```
|
||||
sudo rm /var/snap/wekan/common/.mongodb-data-too-old
|
||||
sudo snap restart wekan
|
||||
```
|
||||
|
||||
## Where the FerretDB v1 binary comes from
|
||||
|
||||
FerretDB v1 is built and released separately in
|
||||
@@ -263,22 +369,35 @@ publishes edge builds to stable users. Pass the version, or `--dry-run` first.
|
||||
|
||||
### What each snap currently has, and what is still to add
|
||||
|
||||
As of WeKan 10.76 the store holds:
|
||||
As of WeKan **10.78** the store holds:
|
||||
|
||||
| Snap | amd64 | arm64 | armhf | ppc64el | riscv64 | s390x |
|
||||
|------|:-----:|:-----:|:-----:|:-------:|:-------:|:-----:|
|
||||
| `wekan` | ✅ | ✅ | — | ✅ | — | ✅ |
|
||||
| `wekan-ondra` | ✅ | ✅ | ⚠️ | — | — | — |
|
||||
| `wekan-gantt-gpl` | ✅ | ✅ | — | — | — | — |
|
||||
| `wekan` | ✅ 10.78 | ✅ 10.78 | ❌ | ✅ 10.78 | ✅ 10.78 | ✅ 10.78 |
|
||||
| `wekan-ondra` | ✅ 10.78 | ✅ 10.78 | ⚠️ 0.22 | 🚫 | 🚫 | 🚫 |
|
||||
| `wekan-gantt-gpl` | ✅ 10.78 | ✅ 10.78 | 🚫 | 🚫 | 🚫 | 🚫 |
|
||||
|
||||
- **—** the architecture is built by `snapcraft.yaml` but that snap has no
|
||||
revision for it yet. Uploading one is all that is needed; the release script
|
||||
then puts it on all four channels.
|
||||
- **⚠️** `wekan-ondra`'s armhf is stuck at version **0.22**, and its i386 column at
|
||||
**0.X-ci**, on all four channels — fossils the store kept from years ago.
|
||||
Promoting channels cannot fix these: there is no newer revision to promote.
|
||||
armhf needs a build uploaded for that snap; i386 cannot be built at all (see
|
||||
[i386](#i386-has-no-snap-and-cannot-have-a-new-one)).
|
||||
`wekan-ondra` also shows an **i386** column at `0.X-ci`; nothing builds it and
|
||||
nothing can (see [i386](#i386-has-no-snap-and-cannot-have-a-new-one)).
|
||||
|
||||
The three marks mean three different things, and the difference is the whole
|
||||
point of the table:
|
||||
|
||||
- **❌ built by the release, not in the store.** `wekan`'s armhf is the only one:
|
||||
`snapcraft.yaml` declares it, the `snap-launchpad` job builds it, and it has
|
||||
been failing — most recently on Caddy, which publishes no `linux_armhf` archive
|
||||
because its asset names are Go's. That is fixed for the next release. Nothing
|
||||
to do here but release.
|
||||
- **🚫 the release does not build it for that snap at all.** The `snap-variants`
|
||||
job that publishes `wekan-ondra` and `wekan-gantt-gpl` has FOUR matrix entries —
|
||||
each variant on amd64 and on arm64, on GitHub runners. The exotic architectures
|
||||
come from `snap-launchpad`, which builds only the `wekan` name. So no upload is
|
||||
pending for these squares: they need the variant job extended to Launchpad
|
||||
remote builds under the variant snap names first.
|
||||
- **⚠️ a fossil.** `wekan-ondra`'s armhf is stuck at version **0.22** on all four
|
||||
channels — a revision the store kept from years ago. Promoting channels cannot
|
||||
fix it: there is no newer revision to promote, and per the row above nothing
|
||||
currently builds one.
|
||||
|
||||
Publishing the **stable** channel is safe for these because the snap performs its
|
||||
**automatic migrations** on start — the schema upgrades and the one-time
|
||||
@@ -288,6 +407,8 @@ manual step.
|
||||
|
||||
## Related
|
||||
|
||||
- [Docker CPU platforms](../Docker/CPU-platforms.md) — the same page for the
|
||||
Docker image, which has a different platform list and different reasons
|
||||
- FerretDB v1 fork: https://github.com/wekan/FerretDB
|
||||
- Snap install: [Install.md](Install.md)
|
||||
- Snap settings keys: [Supported-settings-keys.md](Supported-settings-keys.md)
|
||||
|
||||
@@ -10,7 +10,7 @@ This is without container (without Docker or Snap).
|
||||
|
||||
Right click and download files 1-4:
|
||||
|
||||
1. [wekan-10.78-win64.zip](https://github.com/wekan/wekan/releases/download/v10.78/wekan-10.78-win64.zip) or newest available at https://github.com/wekan/wekan/releases/
|
||||
1. [wekan-10.85-win64.zip](https://github.com/wekan/wekan/releases/download/v10.85/wekan-10.85-win64.zip) or newest available at https://github.com/wekan/wekan/releases/
|
||||
|
||||
2. [node.exe](https://nodejs.org/dist/latest-v24.x/win-x64/node.exe)
|
||||
|
||||
@@ -22,7 +22,7 @@ Right click and download files 1-4:
|
||||
|
||||
6. Double click `mongodb-windows-x86_64-7.0.34-signed.msi` . In installer, uncheck downloading MongoDB compass.
|
||||
|
||||
7. Unzip `wekan-10.78-win64.zip` , inside it is directory `bundle`, to it copy other files:
|
||||
7. Unzip `wekan-10.85-win64.zip` , inside it is directory `bundle`, to it copy other files:
|
||||
|
||||
```
|
||||
bundle (directory)
|
||||
|
||||
+7
-7
@@ -4,11 +4,11 @@ Status: **Core implemented · picker UI design** · Owner: xet7 · Related: #577
|
||||
per-user theme), Board Settings / Change Color, Member Settings / Change Color, #5514
|
||||
(the native color-wheel `<input type="color">` already used for list colors).
|
||||
|
||||
WeKan ships ~19 board theme colors. Many are near-duplicates that differ only by **one or
|
||||
two accent colors**; a few (`clearblue`) are **two-color "color slides"** (gradients). This
|
||||
document defines how the **Select Color** picker — used in **both** Board Settings and
|
||||
Member Settings (the global override) — is reorganized into **categories** with **two-level
|
||||
dropdowns** and **custom colors** where it makes sense.
|
||||
WeKan ships named board theme colors. Many are near-duplicates that differ only by **one
|
||||
or two accent colors**; the `clear*` themes are **two-color "color slides"** (gradients).
|
||||
This document defines how the **Select Color** picker — used in **both** Board Settings
|
||||
and Member Settings (the global override) — is reorganized into **categories** with
|
||||
**two-level dropdowns** and **custom colors** where it makes sense.
|
||||
|
||||
## 1. Categories
|
||||
|
||||
@@ -19,9 +19,9 @@ The colors partition into four categories (single source of truth:
|
||||
| Category | Colors | Custom colors |
|
||||
|----------|--------|---------------|
|
||||
| **flat** | belize, nephritis, pomegranate, pumpkin, wisteria, moderatepink, strongcyan, limegreen, natural | **1** (single accent) |
|
||||
| **clear** | clearblue | **2** (color slide / gradient) |
|
||||
| **clear** | clearblue, cleargreen, clearorange, clearpink, clearpurple, clearred | **2** (color slide / gradient) |
|
||||
| **dark** | midnight, dark, moderndark, exodark, cleandark | **none** (fixed) |
|
||||
| **special** | relax, corteza, modern, cleanlight | **none** (fixed) |
|
||||
| **special** | relax, corteza, appleglasspastel, modern, cleanlight | **none** (fixed) |
|
||||
|
||||
Rationale: **flat** designs are one accent color over a flat surface, so a single custom color
|
||||
fully re-skins them. **clear** designs are a two-color gradient ("slide"), so they take two
|
||||
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Inisial",
|
||||
"invalid-date": "Tanggal tidak sah",
|
||||
"invalid-time": "Masa tidak sah",
|
||||
"invalid-year": "Thon hana sah. Neutuléh mandum peuet angka, contoh jih 2026.",
|
||||
"invalid-user": "Pengguna tidak sa",
|
||||
"joined": "bergabung",
|
||||
"just-invited": "Anda baru diundang di panel ini",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Cangkuk Web Global",
|
||||
"new-outgoing-webhook": "Cangkuk Web Keluar Baru",
|
||||
"no-name": "(Tidak Diketahui)",
|
||||
"Platform": "Platform",
|
||||
"package": "Package",
|
||||
"OS": "OS",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "Pangkalan data",
|
||||
"Node": "Node",
|
||||
"Node_version": "Versi Node",
|
||||
"Meteor_version": "Versi Meteor",
|
||||
"Database_type": "Tipe database",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Mengubah ke markdown",
|
||||
"import-board-zip": "Tamah file .zip nyang na file JSON papan, dan subdirektori nan papan ngon lampiran",
|
||||
"collapse": "Ciutkan",
|
||||
"collapse-checklist": "Ciutkan dapeuta peumeriksa",
|
||||
"expand-checklist": "Peubuka dapeuta peumeriksa",
|
||||
"uncollapse": "Peubuka",
|
||||
"hideCheckedChecklistItems": "Sok item checklist nyang ka geucek",
|
||||
"hideAllChecklistItems": "Sok mandum item checklist",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Keuparah",
|
||||
"event-action": "Tindakan",
|
||||
"event-source": "Sumber",
|
||||
"event-detail": "Rincian"
|
||||
}
|
||||
"event-detail": "Rincian",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Voorletters",
|
||||
"invalid-date": "Ongeldige datum",
|
||||
"invalid-time": "Ongeldige tyd",
|
||||
"invalid-year": "Ongeldige jaar. Tik al vier syfers in, byvoorbeeld 2026.",
|
||||
"invalid-user": "Ongeldige gebruiker",
|
||||
"joined": "aangesluit het",
|
||||
"just-invited": "Jy word net uitgenooi na hierdie bord",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Globale Webhooks",
|
||||
"new-outgoing-webhook": "Nuwe Uitgaande Webhook",
|
||||
"no-name": "(Onbekend)",
|
||||
"Platform": "Platform",
|
||||
"package": "Pakket",
|
||||
"OS": "Bedryfstelsel",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "Databasis",
|
||||
"Node": "Node",
|
||||
"Node_version": "Node weergawe",
|
||||
"Meteor_version": "Meteoor weergawe",
|
||||
"Database_type": "Databasistipe",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Skakel om na markdown",
|
||||
"import-board-zip": "Voeg .zip-lêer by wat bord-JSON-lêers het, en bordnaam-subgidse met aanhegsels",
|
||||
"collapse": "Ineenstort",
|
||||
"collapse-checklist": "Vou kontrolelys toe",
|
||||
"expand-checklist": "Ontvou kontrolelys",
|
||||
"uncollapse": "Ontvou",
|
||||
"hideCheckedChecklistItems": "Versteek gemerkte kontrolelysitems",
|
||||
"hideAllChecklistItems": "Versteek alle kontrolelys-items",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Erns",
|
||||
"event-action": "Aksie",
|
||||
"event-source": "Bron",
|
||||
"event-detail": "Besonderhede"
|
||||
}
|
||||
"event-detail": "Besonderhede",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Voorletters",
|
||||
"invalid-date": "Ongeldige datum",
|
||||
"invalid-time": "Ongeldige tyd",
|
||||
"invalid-year": "Ongeldige jaar. Tik al vier syfers in, byvoorbeeld 2026.",
|
||||
"invalid-user": "Ongeldige gebruiker",
|
||||
"joined": "aangesluit het",
|
||||
"just-invited": "Jy word net uitgenooi na hierdie bord",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Globale Webhooks",
|
||||
"new-outgoing-webhook": "Nuwe Uitgaande Webhook",
|
||||
"no-name": "(Onbekend)",
|
||||
"Platform": "Platform",
|
||||
"package": "Pakket",
|
||||
"OS": "Bedryfstelsel",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "Databasis",
|
||||
"Node": "Node",
|
||||
"Node_version": "Node weergawe",
|
||||
"Meteor_version": "Meteoor weergawe",
|
||||
"Database_type": "Databasistipe",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Skakel om na markdown",
|
||||
"import-board-zip": "Voeg .zip-lêer by wat bord-JSON-lêers het, en bordnaam-subgidse met aanhegsels",
|
||||
"collapse": "Ineenstort",
|
||||
"collapse-checklist": "Vou kontrolelys toe",
|
||||
"expand-checklist": "Ontvou kontrolelys",
|
||||
"uncollapse": "Ontvou",
|
||||
"hideCheckedChecklistItems": "Versteek gemerkte kontrolelysitems",
|
||||
"hideAllChecklistItems": "Versteek alle kontrolelys-items",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Erns",
|
||||
"event-action": "Aksie",
|
||||
"event-source": "Bron",
|
||||
"event-detail": "Besonderhede"
|
||||
}
|
||||
"event-detail": "Besonderhede",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "أولية",
|
||||
"invalid-date": "تاريخ غير صالح",
|
||||
"invalid-time": "زمان نامعتبر",
|
||||
"invalid-year": "سنة غير صالحة. اكتب الأرقام الأربعة كاملة، مثل 2026.",
|
||||
"invalid-user": "کاربر نامعتبر",
|
||||
"joined": "انضمّ",
|
||||
"just-invited": "هم اکنون، شما به این برد دعوت شدهاید.",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "وبهوکهای سراسری",
|
||||
"new-outgoing-webhook": "ويبهوك جديدة",
|
||||
"no-name": "(غير معروف)",
|
||||
"Platform": "المنصة",
|
||||
"package": "الحزمة",
|
||||
"OS": "نظام التشغيل",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "قاعدة البيانات",
|
||||
"Node": "Node",
|
||||
"Node_version": "إصدار النود",
|
||||
"Meteor_version": "نسخه متئور",
|
||||
"Database_type": "نوع قاعدة البيانات",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "تحويل إلى تخفيض السعر",
|
||||
"import-board-zip": "أضف ملف .zip الذي يحتوي على ملفات JSON الخاصة باللوحة، ودلائل فرعية لأسماء اللوحة مع المرفقات",
|
||||
"collapse": "انهيار",
|
||||
"collapse-checklist": "طي قائمة التحقق",
|
||||
"expand-checklist": "توسيع قائمة التحقق",
|
||||
"uncollapse": "إلغاء الانهيار",
|
||||
"hideCheckedChecklistItems": "إخفاء عناصر قائمة التحقق المحددة",
|
||||
"hideAllChecklistItems": "إخفاء جميع عناصر قائمة التحقق",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "الخطورة",
|
||||
"event-action": "الإجراء",
|
||||
"event-source": "المصدر",
|
||||
"event-detail": "التفاصيل"
|
||||
}
|
||||
"event-detail": "التفاصيل",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "أولية",
|
||||
"invalid-date": "تاريخ غير صالح",
|
||||
"invalid-time": "زمان نامعتبر",
|
||||
"invalid-year": "سنة غير صالحة. اكتب الأرقام الأربعة كاملة، مثل 2026.",
|
||||
"invalid-user": "کاربر نامعتبر",
|
||||
"joined": "انضمّ",
|
||||
"just-invited": "هم اکنون، شما به این برد دعوت شدهاید.",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "وبهوکهای سراسری",
|
||||
"new-outgoing-webhook": "ويبهوك جديدة",
|
||||
"no-name": "(غير معروف)",
|
||||
"Platform": "المنصة",
|
||||
"package": "الحزمة",
|
||||
"OS": "نظام التشغيل",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "قاعدة البيانات",
|
||||
"Node": "Node",
|
||||
"Node_version": "إصدار النود",
|
||||
"Meteor_version": "نسخه متئور",
|
||||
"Database_type": "نوع قاعدة البيانات",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "تحويل إلى تخفيض السعر",
|
||||
"import-board-zip": "أضف ملف .zip الذي يحتوي على ملفات JSON الخاصة باللوحة، ودلائل فرعية لأسماء اللوحة مع المرفقات",
|
||||
"collapse": "انهيار",
|
||||
"collapse-checklist": "طي قائمة التحقق",
|
||||
"expand-checklist": "توسيع قائمة التحقق",
|
||||
"uncollapse": "إلغاء الانهيار",
|
||||
"hideCheckedChecklistItems": "إخفاء عناصر قائمة التحقق المحددة",
|
||||
"hideAllChecklistItems": "إخفاء جميع عناصر قائمة التحقق",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "الخطورة",
|
||||
"event-action": "الإجراء",
|
||||
"event-source": "المصدر",
|
||||
"event-detail": "التفاصيل"
|
||||
}
|
||||
"event-detail": "التفاصيل",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "أولية",
|
||||
"invalid-date": "تاريخ غير صالح",
|
||||
"invalid-time": "زمان نامعتبر",
|
||||
"invalid-year": "سنة غير صالحة. اكتب الأرقام الأربعة كاملة، مثل 2026.",
|
||||
"invalid-user": "کاربر نامعتبر",
|
||||
"joined": "انضمّ",
|
||||
"just-invited": "هم اکنون، شما به این برد دعوت شدهاید.",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "وبهوکهای سراسری",
|
||||
"new-outgoing-webhook": "ويبهوك جديدة",
|
||||
"no-name": "(غير معروف)",
|
||||
"Platform": "المنصة",
|
||||
"package": "الحزمة",
|
||||
"OS": "نظام التشغيل",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "قاعدة البيانات",
|
||||
"Node": "Node",
|
||||
"Node_version": "إصدار النود",
|
||||
"Meteor_version": "نسخه متئور",
|
||||
"Database_type": "نوع قاعدة البيانات",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "تحويل إلى تخفيض السعر",
|
||||
"import-board-zip": "أضف ملف .zip الذي يحتوي على ملفات JSON الخاصة باللوحة، ودلائل فرعية لأسماء اللوحة مع المرفقات",
|
||||
"collapse": "انهيار",
|
||||
"collapse-checklist": "طي قائمة التحقق",
|
||||
"expand-checklist": "توسيع قائمة التحقق",
|
||||
"uncollapse": "إلغاء الانهيار",
|
||||
"hideCheckedChecklistItems": "إخفاء عناصر قائمة التحقق المحددة",
|
||||
"hideAllChecklistItems": "إخفاء جميع عناصر قائمة التحقق",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "الخطورة",
|
||||
"event-action": "الإجراء",
|
||||
"event-source": "المصدر",
|
||||
"event-detail": "التفاصيل"
|
||||
}
|
||||
"event-detail": "التفاصيل",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "أولية",
|
||||
"invalid-date": "تاريخ غير صالح",
|
||||
"invalid-time": "زمان نامعتبر",
|
||||
"invalid-year": "سنة ماشي صالحة. كتب الأرقام الأربعة كاملين، بحال 2026.",
|
||||
"invalid-user": "کاربر نامعتبر",
|
||||
"joined": "انضمّ",
|
||||
"just-invited": "هم اکنون، شما به این برد دعوت شدهاید.",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "وبهوکهای سراسری",
|
||||
"new-outgoing-webhook": "ويبهوك جديدة",
|
||||
"no-name": "(غير معروف)",
|
||||
"Platform": "Platform",
|
||||
"package": "Package",
|
||||
"OS": "OS",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "قاعدة البيانات",
|
||||
"Node": "Node",
|
||||
"Node_version": "إصدار النود",
|
||||
"Meteor_version": "نسخه متئور",
|
||||
"Database_type": "نوع قاعدة البيانات",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "تحويل إلى تخفيض السعر",
|
||||
"import-board-zip": "أضف ملف .zip الذي يحتوي على ملفات JSON الخاصة باللوحة، ودلائل فرعية لأسماء اللوحة مع المرفقات",
|
||||
"collapse": "انهيار",
|
||||
"collapse-checklist": "طي قائمة التحقق",
|
||||
"expand-checklist": "توسيع قائمة التحقق",
|
||||
"uncollapse": "إلغاء الانهيار",
|
||||
"hideCheckedChecklistItems": "إخفاء عناصر قائمة التحقق المحددة",
|
||||
"hideAllChecklistItems": "إخفاء جميع عناصر قائمة التحقق",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "الخطورة",
|
||||
"event-action": "الإجراء",
|
||||
"event-source": "المصدر",
|
||||
"event-detail": "التفاصيل"
|
||||
}
|
||||
"event-detail": "التفاصيل",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Iniciales",
|
||||
"invalid-date": "Fecha no válida",
|
||||
"invalid-time": "Tiempo no válido",
|
||||
"invalid-year": "Añu inválidu. Escribi les cuatro cifres, por exemplu 2026.",
|
||||
"invalid-user": "Usuario no válido",
|
||||
"joined": "se ha unido",
|
||||
"just-invited": "Has sido invitado a este tablero",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Webhooks globales",
|
||||
"new-outgoing-webhook": "Nuevo webhook saliente",
|
||||
"no-name": "(Desconocido)",
|
||||
"Platform": "Plataforma",
|
||||
"package": "Paquete",
|
||||
"OS": "Sistema operativu",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "Base de datos",
|
||||
"Node": "Node",
|
||||
"Node_version": "Versión de Node",
|
||||
"Meteor_version": "Versión de Meteor",
|
||||
"Database_type": "Triba de base de datos",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Convertir en Markdown",
|
||||
"import-board-zip": "Añadir archivo .zip que contenga los archivos JSON del tablero y los nombres de las subcarpetas con adjuntos del tablero",
|
||||
"collapse": "Contraer",
|
||||
"collapse-checklist": "Contraer la llista de comprobación",
|
||||
"expand-checklist": "Espandir la llista de comprobación",
|
||||
"uncollapse": "Expandir",
|
||||
"hideCheckedChecklistItems": "Ocultar elementos marcados de la lista de verificación",
|
||||
"hideAllChecklistItems": "Ocultar todos los elementos de la lista de verificación",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Gravedá",
|
||||
"event-action": "Aición",
|
||||
"event-source": "Fonte",
|
||||
"event-detail": "Detalle"
|
||||
}
|
||||
"event-detail": "Detalle",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Baş hərflər",
|
||||
"invalid-date": "Yanlış tarix",
|
||||
"invalid-time": "Yanlış vaxt",
|
||||
"invalid-year": "Yanlış il. Dörd rəqəmin hamısını yazın, məsələn 2026.",
|
||||
"invalid-user": "Yanlış istifadəçi",
|
||||
"joined": "qoşuldu",
|
||||
"just-invited": "Siz sadəcə bu şuraya dəvətlisiniz",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Qlobal Webhooks",
|
||||
"new-outgoing-webhook": "Yeni Gedən Webhook",
|
||||
"no-name": "(Naməlum)",
|
||||
"Platform": "Platforma",
|
||||
"package": "Paket",
|
||||
"OS": "Əməliyyat sistemi",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "Verilənlər bazası",
|
||||
"Node": "Node",
|
||||
"Node_version": "Node versiyası",
|
||||
"Meteor_version": "Meteor versiyası",
|
||||
"Database_type": "Verilənlər bazası növü",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Markdown-a çevirin",
|
||||
"import-board-zip": "Lövhə JSON faylları olan .zip faylı və əlavələri olan board adı alt kataloqları əlavə edin",
|
||||
"collapse": "Yıxılma",
|
||||
"collapse-checklist": "Yoxlama siyahısını yığ",
|
||||
"expand-checklist": "Yoxlama siyahısını aç",
|
||||
"uncollapse": "Açmaq",
|
||||
"hideCheckedChecklistItems": "Yoxlanmış yoxlama siyahısı elementlərini gizlədin",
|
||||
"hideAllChecklistItems": "Bütün yoxlama siyahısı elementlərini gizlədin",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Ciddilik",
|
||||
"event-action": "Əməliyyat",
|
||||
"event-source": "Mənbə",
|
||||
"event-detail": "Təfərrüat"
|
||||
}
|
||||
"event-detail": "Təfərrüat",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Baş hərflər",
|
||||
"invalid-date": "Yanlış tarix",
|
||||
"invalid-time": "Yanlış vaxt",
|
||||
"invalid-year": "Yanlış il. Dörd rəqəmin hamısını yazın, məsələn 2026.",
|
||||
"invalid-user": "Yanlış istifadəçi",
|
||||
"joined": "qoşuldu",
|
||||
"just-invited": "Siz sadəcə bu şuraya dəvətlisiniz",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Qlobal Webhooks",
|
||||
"new-outgoing-webhook": "Yeni Gedən Webhook",
|
||||
"no-name": "(Naməlum)",
|
||||
"Platform": "Platforma",
|
||||
"package": "Paket",
|
||||
"OS": "Əməliyyat sistemi",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "Verilənlər bazası",
|
||||
"Node": "Node",
|
||||
"Node_version": "Node versiyası",
|
||||
"Meteor_version": "Meteor versiyası",
|
||||
"Database_type": "Verilənlər bazası növü",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Markdown-a çevirin",
|
||||
"import-board-zip": "Lövhə JSON faylları olan .zip faylı və əlavələri olan board adı alt kataloqları əlavə edin",
|
||||
"collapse": "Yıxılma",
|
||||
"collapse-checklist": "Yoxlama siyahısını yığ",
|
||||
"expand-checklist": "Yoxlama siyahısını aç",
|
||||
"uncollapse": "Açmaq",
|
||||
"hideCheckedChecklistItems": "Yoxlanmış yoxlama siyahısı elementlərini gizlədin",
|
||||
"hideAllChecklistItems": "Bütün yoxlama siyahısı elementlərini gizlədin",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Ciddilik",
|
||||
"event-action": "Əməliyyat",
|
||||
"event-source": "Mənbə",
|
||||
"event-detail": "Təfərrüat"
|
||||
}
|
||||
"event-detail": "Təfərrüat",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Baş hərflər",
|
||||
"invalid-date": "Yanlış tarix",
|
||||
"invalid-time": "Yanlış vaxt",
|
||||
"invalid-year": "Yanlış il. Dörd rəqəmin hamısını yazın, məsələn 2026.",
|
||||
"invalid-user": "Yanlış istifadəçi",
|
||||
"joined": "qoşuldu",
|
||||
"just-invited": "Siz sadəcə bu şuraya dəvətlisiniz",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Qlobal Webhooks",
|
||||
"new-outgoing-webhook": "Yeni Gedən Webhook",
|
||||
"no-name": "(Naməlum)",
|
||||
"Platform": "Platforma",
|
||||
"package": "Paket",
|
||||
"OS": "Əməliyyat sistemi",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "Verilənlər bazası",
|
||||
"Node": "Node",
|
||||
"Node_version": "Node versiyası",
|
||||
"Meteor_version": "Meteor versiyası",
|
||||
"Database_type": "Verilənlər bazası növü",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Markdown-a çevirin",
|
||||
"import-board-zip": "Lövhə JSON faylları olan .zip faylı və əlavələri olan board adı alt kataloqları əlavə edin",
|
||||
"collapse": "Yıxılma",
|
||||
"collapse-checklist": "Yoxlama siyahısını yığ",
|
||||
"expand-checklist": "Yoxlama siyahısını aç",
|
||||
"uncollapse": "Açmaq",
|
||||
"hideCheckedChecklistItems": "Yoxlanmış yoxlama siyahısı elementlərini gizlədin",
|
||||
"hideAllChecklistItems": "Bütün yoxlama siyahısı elementlərini gizlədin",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Ciddilik",
|
||||
"event-action": "Əməliyyat",
|
||||
"event-source": "Mənbə",
|
||||
"event-detail": "Təfərrüat"
|
||||
}
|
||||
"event-detail": "Təfərrüat",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Ініцыялы",
|
||||
"invalid-date": "Няправільная дата",
|
||||
"invalid-time": "Няправільны час",
|
||||
"invalid-year": "Няправільны год. Увядзіце ўсе чатыры лічбы, напрыклад 2026.",
|
||||
"invalid-user": "Няправільны карыстальнік",
|
||||
"joined": "далучыўся",
|
||||
"just-invited": "Вас толькі што запрасілі на гэтую дошку",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Глабальныя вэб-хукі",
|
||||
"new-outgoing-webhook": "Новы выходны вэб-хук",
|
||||
"no-name": "(Невядома)",
|
||||
"Platform": "Платформа",
|
||||
"package": "Пакет",
|
||||
"OS": "АС",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "База даных",
|
||||
"Node": "Node",
|
||||
"Node_version": "Версія Node",
|
||||
"Meteor_version": "Версія Meteor",
|
||||
"Database_type": "Тып базы дадзеных",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Пераўтварыць у markdown",
|
||||
"import-board-zip": "Дадайце файл .zip, які мае файлы JSON дошкі і падкаталогі з назвамі дошак з укладаннямі",
|
||||
"collapse": "Згарнуць",
|
||||
"collapse-checklist": "Згарнуць кантрольны спіс",
|
||||
"expand-checklist": "Разгарнуць кантрольны спіс",
|
||||
"uncollapse": "Разгарнуць",
|
||||
"hideCheckedChecklistItems": "Схаваць адзначаныя пункты кантрольнага спіса",
|
||||
"hideAllChecklistItems": "Схаваць усе пункты кантрольнага спіса",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Сур'ёзнасць",
|
||||
"event-action": "Дзеянне",
|
||||
"event-source": "Крыніца",
|
||||
"event-detail": "Дэталі"
|
||||
}
|
||||
"event-detail": "Дэталі",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Инициали",
|
||||
"invalid-date": "Невалидна дата",
|
||||
"invalid-time": "Невалиден час",
|
||||
"invalid-year": "Невалидна година. Въведете и четирите цифри, например 2026.",
|
||||
"invalid-user": "Невалиден потребител",
|
||||
"joined": "присъедини",
|
||||
"just-invited": "Бяхте поканени в това табло",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Глобални Webhooks",
|
||||
"new-outgoing-webhook": "Нов Изходящ Webhook",
|
||||
"no-name": "(Непознат)",
|
||||
"Platform": "Платформа",
|
||||
"package": "Пакет",
|
||||
"OS": "ОС",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "База данни",
|
||||
"Node": "Node",
|
||||
"Node_version": "Версия на Node",
|
||||
"Meteor_version": "Версия на Meteor",
|
||||
"Database_type": "Тип на базата данни",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Претвори у структуирани текст",
|
||||
"import-board-zip": "Додај .zip архиву која има списе у json облику и фасцикле по имену списа где је предметна грађа",
|
||||
"collapse": "Събери",
|
||||
"collapse-checklist": "Свиване на чеклиста",
|
||||
"expand-checklist": "Разгъване на чеклиста",
|
||||
"uncollapse": "Рашири",
|
||||
"hideCheckedChecklistItems": "Сакриј све обављене помоћне предметне радње",
|
||||
"hideAllChecklistItems": "Сакриј све помоћне предметне радње",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Сериозност",
|
||||
"event-action": "Действие",
|
||||
"event-source": "Източник",
|
||||
"event-detail": "Детайл"
|
||||
}
|
||||
"event-detail": "Детайл",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Initiales",
|
||||
"invalid-date": "Date invalide",
|
||||
"invalid-time": "Heure invalide",
|
||||
"invalid-year": "Bloavezh direizh. Skrivit ar pevar sifr, da skouer 2026.",
|
||||
"invalid-user": "Utilisateur invalide",
|
||||
"joined": "a rejoint",
|
||||
"just-invited": "Vous venez d'être invité à ce tableau",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Webhooks globaux",
|
||||
"new-outgoing-webhook": "Nouveau webhook sortant",
|
||||
"no-name": "(Inconnu)",
|
||||
"Platform": "Platform",
|
||||
"package": "Package",
|
||||
"OS": "OS",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "Diaz roadennoù",
|
||||
"Node": "Node",
|
||||
"Node_version": "Version de Node",
|
||||
"Meteor_version": "Version de Meteor",
|
||||
"Database_type": "Rizh ar bank-roadennoù",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Convertir en markdown",
|
||||
"import-board-zip": "Ajouter un fichier .zip qui contient les fichiers JSON du tableau et les noms de sous-répertoires avec les pièces jointes",
|
||||
"collapse": "Réduire",
|
||||
"collapse-checklist": "Pleg ar roll gwiriañ",
|
||||
"expand-checklist": "Astenn ar roll gwiriañ",
|
||||
"uncollapse": "Développer",
|
||||
"hideCheckedChecklistItems": "Cacher les éléments cochés de la check-list",
|
||||
"hideAllChecklistItems": "Cacher tous les éléments de la check-list",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Garvder",
|
||||
"event-action": "Ober",
|
||||
"event-source": "Mammenn",
|
||||
"event-detail": "Munud"
|
||||
}
|
||||
"event-detail": "Munud",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Inicials",
|
||||
"invalid-date": "Dades invàlides",
|
||||
"invalid-time": "Temps Invàlid",
|
||||
"invalid-year": "Any no vàlid. Escriviu les quatre xifres, per exemple 2026.",
|
||||
"invalid-user": "Usuari invàlid",
|
||||
"joined": "s'ha unitat",
|
||||
"just-invited": "Has estat convidat a aquest tauler",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Webhooks globals",
|
||||
"new-outgoing-webhook": "Nou Webbook sortt",
|
||||
"no-name": "Importa tauler des de Wekan",
|
||||
"Platform": "Plataforma",
|
||||
"package": "Paquet",
|
||||
"OS": "Sistema operatiu",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "Base de dades",
|
||||
"Node": "Node",
|
||||
"Node_version": "Versió Node",
|
||||
"Meteor_version": "Versió Meteor",
|
||||
"Database_type": "Tipus de base de dades",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Converteix a markdown",
|
||||
"import-board-zip": "Afegeix un fitxer .zip que tingui els fitxers JSON del tauler, i subdirectoris amb el nom del tauler amb els adjunts",
|
||||
"collapse": "Contraure",
|
||||
"collapse-checklist": "Contreu la llista de verificació",
|
||||
"expand-checklist": "Desplegueu la llista de verificació",
|
||||
"uncollapse": "Desplega",
|
||||
"hideCheckedChecklistItems": "Amaga els elements marcats de la checklist",
|
||||
"hideAllChecklistItems": "Amaga tots els elements de la checklist",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Gravetat",
|
||||
"event-action": "Acció",
|
||||
"event-source": "Origen",
|
||||
"event-detail": "Detall"
|
||||
}
|
||||
"event-detail": "Detall",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Inicials",
|
||||
"invalid-date": "Dades invàlides",
|
||||
"invalid-time": "Temps Invàlid",
|
||||
"invalid-year": "Any no vàlid. Escriviu les quatre xifres, per exemple 2026.",
|
||||
"invalid-user": "Usuari invàlid",
|
||||
"joined": "s'ha unitat",
|
||||
"just-invited": "Has estat convidat a aquest tauler",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Webhooks globals",
|
||||
"new-outgoing-webhook": "Nou Webbook sortt",
|
||||
"no-name": "Importa tauler des de Wekan",
|
||||
"Platform": "Plataforma",
|
||||
"package": "Paquet",
|
||||
"OS": "Sistema operatiu",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "Base de dades",
|
||||
"Node": "Node",
|
||||
"Node_version": "Versió Node",
|
||||
"Meteor_version": "Versió Meteor",
|
||||
"Database_type": "Tipus de base de dades",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Convertir en Markdown",
|
||||
"import-board-zip": "Añadir archivo .zip que contenga los archivos JSON del tablero y los nombres de las subcarpetas con adjuntos del tablero",
|
||||
"collapse": "Contraure",
|
||||
"collapse-checklist": "Contraure la llista de verificació",
|
||||
"expand-checklist": "Expandir la llista de verificació",
|
||||
"uncollapse": "Expandir",
|
||||
"hideCheckedChecklistItems": "Ocultar elementos marcados de la lista de verificación",
|
||||
"hideAllChecklistItems": "Ocultar todos los elementos de la lista de verificación",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Gravetat",
|
||||
"event-action": "Acció",
|
||||
"event-source": "Origen",
|
||||
"event-detail": "Detall"
|
||||
}
|
||||
"event-detail": "Detall",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Inicials",
|
||||
"invalid-date": "Dades invàlides",
|
||||
"invalid-time": "Temps Invàlid",
|
||||
"invalid-year": "Any no vàlid. Escriviu les quatre xifres, per exemple 2026.",
|
||||
"invalid-user": "Usuari invàlid",
|
||||
"joined": "s'ha unitat",
|
||||
"just-invited": "Has estat convidat a aquest tauler",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Webhooks globals",
|
||||
"new-outgoing-webhook": "Nou Webbook sortt",
|
||||
"no-name": "Importa tauler des de Wekan",
|
||||
"Platform": "Plataforma",
|
||||
"package": "Paquet",
|
||||
"OS": "Sistema operatiu",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "Base de dades",
|
||||
"Node": "Node",
|
||||
"Node_version": "Versió Node",
|
||||
"Meteor_version": "Versió Meteor",
|
||||
"Database_type": "Tipus de base de dades",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Converteix a markdown",
|
||||
"import-board-zip": "Afegeix un fitxer .zip que tingui els fitxers JSON del tauler, i subdirectoris amb el nom del tauler amb els adjunts",
|
||||
"collapse": "Contraure",
|
||||
"collapse-checklist": "Contreu la llista de verificació",
|
||||
"expand-checklist": "Desplegueu la llista de verificació",
|
||||
"uncollapse": "Desplega",
|
||||
"hideCheckedChecklistItems": "Amaga els elements marcats de la checklist",
|
||||
"hideAllChecklistItems": "Amaga tots els elements de la checklist",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Gravetat",
|
||||
"event-action": "Acció",
|
||||
"event-source": "Origen",
|
||||
"event-detail": "Detall"
|
||||
}
|
||||
"event-detail": "Detall",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "缩写",
|
||||
"invalid-date": "无效日期",
|
||||
"invalid-time": "无效时间",
|
||||
"invalid-year": "年份无效。请输入完整的四位数字,例如 2026。",
|
||||
"invalid-user": "无效用户",
|
||||
"joined": "加入",
|
||||
"just-invited": "您刚刚被邀请加入此论坛",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "全局 Webhooks",
|
||||
"new-outgoing-webhook": "新的传出 Webhook",
|
||||
"no-name": "(未知)",
|
||||
"Platform": "平台",
|
||||
"package": "软件包",
|
||||
"OS": "操作系统",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "数据库",
|
||||
"Node": "Node",
|
||||
"Node_version": "节点版本",
|
||||
"Meteor_version": "流星版",
|
||||
"Database_type": "数据库类型",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "转换为降价",
|
||||
"import-board-zip": "添加包含板 JSON 文件和带有附件的板名称子目录的 .zip 文件",
|
||||
"collapse": "坍塌",
|
||||
"collapse-checklist": "折叠清单",
|
||||
"expand-checklist": "展开清单",
|
||||
"uncollapse": "展开",
|
||||
"hideCheckedChecklistItems": "隐藏选中的清单项目",
|
||||
"hideAllChecklistItems": "隐藏所有清单项目",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "严重程度",
|
||||
"event-action": "操作",
|
||||
"event-source": "来源",
|
||||
"event-detail": "详情"
|
||||
}
|
||||
"event-detail": "详情",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Iniciály",
|
||||
"invalid-date": "Neplatné datum",
|
||||
"invalid-time": "Neplatný čas",
|
||||
"invalid-year": "Neplatný rok. Zadejte všechny čtyři číslice, například 2026.",
|
||||
"invalid-user": "Neplatný uživatel",
|
||||
"joined": "spojeno",
|
||||
"just-invited": "Právě jsi byl pozván(a) do tohoto tabla",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Globální webhooks",
|
||||
"new-outgoing-webhook": "Nové odchozí Webhooky",
|
||||
"no-name": "(Neznámé)",
|
||||
"Platform": "Platforma",
|
||||
"package": "Balíček",
|
||||
"OS": "OS",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "Databáze",
|
||||
"Node": "Node",
|
||||
"Node_version": "Node verze",
|
||||
"Meteor_version": "Verze Meteor",
|
||||
"Database_type": "Typ databáze",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Převést na markdown",
|
||||
"import-board-zip": "Přidejte soubor .zip, který obsahuje soubory JSON tabla a podadresáře s názvem tabla obsahující přílohy",
|
||||
"collapse": "Sbalit",
|
||||
"collapse-checklist": "Sbalit kontrolní seznam",
|
||||
"expand-checklist": "Rozbalit kontrolní seznam",
|
||||
"uncollapse": "Rozbalit",
|
||||
"hideCheckedChecklistItems": "Skrýt zaškrtnuté položky checklistu",
|
||||
"hideAllChecklistItems": "Skrýt všechny položky checklistu",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Závažnost",
|
||||
"event-action": "Akce",
|
||||
"event-source": "Zdroj",
|
||||
"event-detail": "Detail"
|
||||
}
|
||||
"event-detail": "Detail",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Iniciály",
|
||||
"invalid-date": "Neplatné datum",
|
||||
"invalid-time": "Neplatný čas",
|
||||
"invalid-year": "Neplatný rok. Zadejte všechny čtyři číslice, například 2026.",
|
||||
"invalid-user": "Neplatný uživatel",
|
||||
"joined": "spojeno",
|
||||
"just-invited": "Právě jsi byl pozván(a) do tohoto tabla",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Globální webhooks",
|
||||
"new-outgoing-webhook": "Nové odchozí Webhooky",
|
||||
"no-name": "(Neznámé)",
|
||||
"Platform": "Platforma",
|
||||
"package": "Balíček",
|
||||
"OS": "OS",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "Databáze",
|
||||
"Node": "Node",
|
||||
"Node_version": "Node verze",
|
||||
"Meteor_version": "Verze Meteor",
|
||||
"Database_type": "Typ databáze",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Převést na markdown",
|
||||
"import-board-zip": "Přidejte soubor .zip, který obsahuje soubory JSON tabla a podadresáře s názvem tabla obsahující přílohy",
|
||||
"collapse": "Sbalit",
|
||||
"collapse-checklist": "Sbalit kontrolní seznam",
|
||||
"expand-checklist": "Rozbalit kontrolní seznam",
|
||||
"uncollapse": "Rozbalit",
|
||||
"hideCheckedChecklistItems": "Skrýt zaškrtnuté položky checklistu",
|
||||
"hideAllChecklistItems": "Skrýt všechny položky checklistu",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Závažnost",
|
||||
"event-action": "Akce",
|
||||
"event-source": "Zdroj",
|
||||
"event-detail": "Detail"
|
||||
}
|
||||
"event-detail": "Detail",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Llythrennau blaen",
|
||||
"invalid-date": "Dyddiad annilys",
|
||||
"invalid-time": "Amser annilys",
|
||||
"invalid-year": "Blwyddyn annilys. Teipiwch y pedwar digid, er enghraifft 2026.",
|
||||
"invalid-user": "Defnyddiwr annilys",
|
||||
"joined": "ymunodd",
|
||||
"just-invited": "Fe'ch gwahoddir i'r bwrdd hwn",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Bachau Gwe Byd-eang",
|
||||
"new-outgoing-webhook": "Llyfr Gwe Allan Newydd",
|
||||
"no-name": "(Anhysbys)",
|
||||
"Platform": "Platfform",
|
||||
"package": "Pecyn",
|
||||
"OS": "System gweithredu",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "Cronfa ddata",
|
||||
"Node": "Node",
|
||||
"Node_version": "Fersiwn nod",
|
||||
"Meteor_version": "Fersiwn Meteor",
|
||||
"Database_type": "Math o gronfa ddata",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Trosi i markdown",
|
||||
"import-board-zip": "Ychwanegu ffeil .zip sydd â ffeiliau bwrdd JSON, ac is-gyfeiriaduron enw bwrdd gydag atodiadau",
|
||||
"collapse": "Cwymp",
|
||||
"collapse-checklist": "Crebachu'r rhestr wirio",
|
||||
"expand-checklist": "Ehangu'r rhestr wirio",
|
||||
"uncollapse": "Dad-gwymp",
|
||||
"hideCheckedChecklistItems": "Cuddio eitemau rhestr wirio wedi'u gwirio",
|
||||
"hideAllChecklistItems": "Cuddio holl eitemau'r rhestr wirio",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Difrifoldeb",
|
||||
"event-action": "Gweithred",
|
||||
"event-source": "Ffynhonnell",
|
||||
"event-detail": "Manylion"
|
||||
}
|
||||
"event-detail": "Manylion",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Llythrennau blaen",
|
||||
"invalid-date": "Dyddiad annilys",
|
||||
"invalid-time": "Amser annilys",
|
||||
"invalid-year": "Blwyddyn annilys. Teipiwch y pedwar digid, er enghraifft 2026.",
|
||||
"invalid-user": "Defnyddiwr annilys",
|
||||
"joined": "ymunodd",
|
||||
"just-invited": "Fe'ch gwahoddir i'r bwrdd hwn",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Bachau Gwe Byd-eang",
|
||||
"new-outgoing-webhook": "Llyfr Gwe Allan Newydd",
|
||||
"no-name": "(Anhysbys)",
|
||||
"Platform": "Platfform",
|
||||
"package": "Pecyn",
|
||||
"OS": "System gweithredu",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "Cronfa ddata",
|
||||
"Node": "Node",
|
||||
"Node_version": "Fersiwn nod",
|
||||
"Meteor_version": "Fersiwn Meteor",
|
||||
"Database_type": "Math o gronfa ddata",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Trosi i markdown",
|
||||
"import-board-zip": "Ychwanegu ffeil .zip sydd â ffeiliau bwrdd JSON, ac is-gyfeiriaduron enw bwrdd gydag atodiadau",
|
||||
"collapse": "Cwymp",
|
||||
"collapse-checklist": "Crebachu'r rhestr wirio",
|
||||
"expand-checklist": "Ehangu'r rhestr wirio",
|
||||
"uncollapse": "Dad-gwymp",
|
||||
"hideCheckedChecklistItems": "Cuddio eitemau rhestr wirio wedi'u gwirio",
|
||||
"hideAllChecklistItems": "Cuddio holl eitemau'r rhestr wirio",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Difrifoldeb",
|
||||
"event-action": "Gweithred",
|
||||
"event-source": "Ffynhonnell",
|
||||
"event-detail": "Manylion"
|
||||
}
|
||||
"event-detail": "Manylion",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Initialer",
|
||||
"invalid-date": "Ugyldig dato",
|
||||
"invalid-time": "Ugyldig tidsangivelse",
|
||||
"invalid-year": "Ugyldigt år. Skriv alle fire cifre, for eksempel 2026.",
|
||||
"invalid-user": "Ugyldig bruger",
|
||||
"joined": "sammenlagt",
|
||||
"just-invited": "Du er netop blevet inviteret til denne tavle",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Globale webhooks",
|
||||
"new-outgoing-webhook": "Ny udgående webhook",
|
||||
"no-name": "(Ukendt)",
|
||||
"Platform": "Platform",
|
||||
"package": "Pakke",
|
||||
"OS": "OS",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "Database",
|
||||
"Node": "Node",
|
||||
"Node_version": "Node-version",
|
||||
"Meteor_version": "Meteor-version",
|
||||
"Database_type": "Databasetype",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Konvertér til markdown",
|
||||
"import-board-zip": "Lägga till .zip-filen till tavlans JSON filer, och tavla",
|
||||
"collapse": "Sammenfold",
|
||||
"collapse-checklist": "Sammenfold tjekliste",
|
||||
"expand-checklist": "Udvid tjekliste",
|
||||
"uncollapse": "Expandera",
|
||||
"hideCheckedChecklistItems": "Dölj markerade objekt i checklistan",
|
||||
"hideAllChecklistItems": "Dölj alla objekt i checklistan",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Alvorsgrad",
|
||||
"event-action": "Handling",
|
||||
"event-source": "Kilde",
|
||||
"event-detail": "Detalje"
|
||||
}
|
||||
"event-detail": "Detalje",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Initialen",
|
||||
"invalid-date": "Ungültiges Datum",
|
||||
"invalid-time": "Ungültige Zeitangabe",
|
||||
"invalid-year": "Ungültiges Jahr. Bitte alle vier Ziffern eingeben, zum Beispiel 2026.",
|
||||
"invalid-user": "Ungültiger Benutzer",
|
||||
"joined": "beigetreten",
|
||||
"just-invited": "Sie wurden soeben zu diesem Board eingeladen",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Globale Webhooks",
|
||||
"new-outgoing-webhook": "Neuer ausgehender Webhook",
|
||||
"no-name": "(Unbekannt)",
|
||||
"Platform": "Plattform",
|
||||
"package": "Paket",
|
||||
"OS": "Betriebssystem",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "Datenbank",
|
||||
"Node": "Node",
|
||||
"Node_version": "Node-Version",
|
||||
"Meteor_version": "Meteor-Version",
|
||||
"Database_type": "Datenbanktyp",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Als Markdown konvertieren",
|
||||
"import-board-zip": "Erstelle .zip Datei, die Board JSON Dateien und Board Unterverzeichnisse mit Boardname inklusive Anhängen enthält",
|
||||
"collapse": "Einklappen",
|
||||
"collapse-checklist": "Checkliste einklappen",
|
||||
"expand-checklist": "Checkliste aufklappen",
|
||||
"uncollapse": "Aufklappen",
|
||||
"hideCheckedChecklistItems": "Erledigte Checklisteneinträge ausblenden",
|
||||
"hideAllChecklistItems": "Verberge alle Checklisteneinträge",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Schweregrad",
|
||||
"event-action": "Aktion",
|
||||
"event-source": "Quelle",
|
||||
"event-detail": "Detail"
|
||||
}
|
||||
"event-detail": "Detail",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Initialen",
|
||||
"invalid-date": "Ungültiges Datum",
|
||||
"invalid-time": "Ungültige Zeitangabe",
|
||||
"invalid-year": "Ungültiges Jahr. Bitte alle vier Ziffern eingeben, zum Beispiel 2026.",
|
||||
"invalid-user": "Ungültiger Benutzer",
|
||||
"joined": "beigetreten",
|
||||
"just-invited": "Sie wurden soeben zu diesem Board eingeladen",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Globale Webhooks",
|
||||
"new-outgoing-webhook": "Neuer ausgehender Webhook",
|
||||
"no-name": "(Unbekannt)",
|
||||
"Platform": "Plattform",
|
||||
"package": "Paket",
|
||||
"OS": "Betriebssystem",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "Datenbank",
|
||||
"Node": "Node",
|
||||
"Node_version": "Node-Version",
|
||||
"Meteor_version": "Meteor-Version",
|
||||
"Database_type": "Datenbanktyp",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Als Markdown konvertieren",
|
||||
"import-board-zip": "Erstelle .zip Datei, die Board JSON Dateien und Board Unterverzeichnisse mit Boardname inklusive Anhängen enthält",
|
||||
"collapse": "Einklappen",
|
||||
"collapse-checklist": "Checkliste einklappen",
|
||||
"expand-checklist": "Checkliste aufklappen",
|
||||
"uncollapse": "Aufklappen",
|
||||
"hideCheckedChecklistItems": "Erledigte Checklisteneinträge ausblenden",
|
||||
"hideAllChecklistItems": "Verberge alle Checklisteneinträge",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Schweregrad",
|
||||
"event-action": "Aktion",
|
||||
"event-source": "Quelle",
|
||||
"event-detail": "Detail"
|
||||
}
|
||||
"event-detail": "Detail",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Initialen",
|
||||
"invalid-date": "Ungültiges Datum",
|
||||
"invalid-time": "Ungültige Zeitangabe",
|
||||
"invalid-year": "Ungültiges Jahr. Bitte alle vier Ziffern eingeben, zum Beispiel 2026.",
|
||||
"invalid-user": "Ungültiger Benutzer",
|
||||
"joined": "beigetreten",
|
||||
"just-invited": "Sie wurden soeben zu diesem Board eingeladen",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Globale Webhooks",
|
||||
"new-outgoing-webhook": "Neuer ausgehender Webhook",
|
||||
"no-name": "(Unbekannt)",
|
||||
"Platform": "Plattform",
|
||||
"package": "Paket",
|
||||
"OS": "Betriebssystem",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "Datenbank",
|
||||
"Node": "Node",
|
||||
"Node_version": "Node-Version",
|
||||
"Meteor_version": "Meteor-Version",
|
||||
"Database_type": "Datenbanktyp",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Als Markdown konvertieren",
|
||||
"import-board-zip": "Erstelle .zip Datei, die Board JSON Dateien und Board Unterverzeichnisse mit Boardname inklusive Anhängen enthält",
|
||||
"collapse": "Einklappen",
|
||||
"collapse-checklist": "Checkliste einklappen",
|
||||
"expand-checklist": "Checkliste aufklappen",
|
||||
"uncollapse": "Aufklappen",
|
||||
"hideCheckedChecklistItems": "Erledigte Checklisteneinträge ausblenden",
|
||||
"hideAllChecklistItems": "Verberge alle Checklisteneinträge",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Schweregrad",
|
||||
"event-action": "Aktion",
|
||||
"event-source": "Quelle",
|
||||
"event-detail": "Detail"
|
||||
}
|
||||
"event-detail": "Detail",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Initialen",
|
||||
"invalid-date": "Ungültiges Datum",
|
||||
"invalid-time": "Ungültige Zeitangabe",
|
||||
"invalid-year": "Ungültiges Jahr. Bitte alle vier Ziffern eingeben, zum Beispiel 2026.",
|
||||
"invalid-user": "Ungültiger Benutzer",
|
||||
"joined": "beigetreten",
|
||||
"just-invited": "Sie wurden soeben zu diesem Board eingeladen",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Globale Webhooks",
|
||||
"new-outgoing-webhook": "Neuer ausgehender Webhook",
|
||||
"no-name": "(Unbekannt)",
|
||||
"Platform": "Plattform",
|
||||
"package": "Paket",
|
||||
"OS": "Betriebssystem",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "Datenbank",
|
||||
"Node": "Node",
|
||||
"Node_version": "Node-Version",
|
||||
"Meteor_version": "Meteor-Version",
|
||||
"Database_type": "Datenbanktyp",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Als Markdown konvertieren",
|
||||
"import-board-zip": "Erstelle .zip Datei mit JSON Board Dateien und die Unterverzeichnisse des Boardnamen mit Anhängen",
|
||||
"collapse": "Einklappen",
|
||||
"collapse-checklist": "Checkliste einklappen",
|
||||
"expand-checklist": "Checkliste aufklappen",
|
||||
"uncollapse": "Aufklappen",
|
||||
"hideCheckedChecklistItems": "Verberge erledigte Checklisteneinträge",
|
||||
"hideAllChecklistItems": "Verberge alle Checklisteneinträge",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Schweregrad",
|
||||
"event-action": "Aktion",
|
||||
"event-source": "Quelle",
|
||||
"event-detail": "Detail"
|
||||
}
|
||||
"event-detail": "Detail",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Αρχικά",
|
||||
"invalid-date": "Λανθασμένη ημερομηνία",
|
||||
"invalid-time": "Λανθασμένη ώρα",
|
||||
"invalid-year": "Μη έγκυρο έτος. Πληκτρολογήστε και τα τέσσερα ψηφία, για παράδειγμα 2026.",
|
||||
"invalid-user": "Λανθασμένος χρήστης",
|
||||
"joined": "si è unito a",
|
||||
"just-invited": "Μόλις προσκληθήκατε σε αυτόν τον πίνακα",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Webhook globali",
|
||||
"new-outgoing-webhook": "Νέο Εξερχόμενο Webhook",
|
||||
"no-name": "(Άγνωστο)",
|
||||
"Platform": "Πλατφόρμα",
|
||||
"package": "Πακέτο",
|
||||
"OS": "Λειτουργικό σύστημα",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "Βάση δεδομένων",
|
||||
"Node": "Node",
|
||||
"Node_version": "Έκδοση Node",
|
||||
"Meteor_version": "Έκδοση Meteor",
|
||||
"Database_type": "Τύπος βάσης δεδομένων",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Converti in markdown",
|
||||
"import-board-zip": "Aggiungi il file .zip contenente i file JSON della bacheca, i nomi bacheca delle sottodirectory con gli allegati",
|
||||
"collapse": "Σύμπτυξη",
|
||||
"collapse-checklist": "Σύμπτυξη λίστας ελέγχου",
|
||||
"expand-checklist": "Ανάπτυξη λίστας ελέγχου",
|
||||
"uncollapse": "Non collassare",
|
||||
"hideCheckedChecklistItems": "Nascondi gli elementi della lista di controllo selezionati",
|
||||
"hideAllChecklistItems": "Nascondi gli elementi della lista di controllo",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Σοβαρότητα",
|
||||
"event-action": "Ενέργεια",
|
||||
"event-source": "Πηγή",
|
||||
"event-detail": "Λεπτομέρεια"
|
||||
}
|
||||
"event-detail": "Λεπτομέρεια",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Αρχικά",
|
||||
"invalid-date": "Λανθασμένη ημερομηνία",
|
||||
"invalid-time": "Λανθασμένη ώρα",
|
||||
"invalid-year": "Μη έγκυρο έτος. Πληκτρολογήστε και τα τέσσερα ψηφία, για παράδειγμα 2026.",
|
||||
"invalid-user": "Λανθασμένος χρήστης",
|
||||
"joined": "si è unito a",
|
||||
"just-invited": "Μόλις προσκληθήκατε σε αυτόν τον πίνακα",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Webhook globali",
|
||||
"new-outgoing-webhook": "Νέο Εξερχόμενο Webhook",
|
||||
"no-name": "(Άγνωστο)",
|
||||
"Platform": "Πλατφόρμα",
|
||||
"package": "Πακέτο",
|
||||
"OS": "Λειτουργικό σύστημα",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "Βάση δεδομένων",
|
||||
"Node": "Node",
|
||||
"Node_version": "Έκδοση Node",
|
||||
"Meteor_version": "Έκδοση Meteor",
|
||||
"Database_type": "Τύπος βάσης δεδομένων",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Converti in markdown",
|
||||
"import-board-zip": "Aggiungi il file .zip contenente i file JSON della bacheca, i nomi bacheca delle sottodirectory con gli allegati",
|
||||
"collapse": "Σύμπτυξη",
|
||||
"collapse-checklist": "Σύμπτυξη λίστας ελέγχου",
|
||||
"expand-checklist": "Ανάπτυξη λίστας ελέγχου",
|
||||
"uncollapse": "Non collassare",
|
||||
"hideCheckedChecklistItems": "Nascondi gli elementi della lista di controllo selezionati",
|
||||
"hideAllChecklistItems": "Nascondi gli elementi della lista di controllo",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Σοβαρότητα",
|
||||
"event-action": "Ενέργεια",
|
||||
"event-source": "Πηγή",
|
||||
"event-detail": "Λεπτομέρεια"
|
||||
}
|
||||
"event-detail": "Λεπτομέρεια",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Initials",
|
||||
"invalid-date": "Invalid date",
|
||||
"invalid-time": "Invalid time",
|
||||
"invalid-year": "Invalid year. Please type all four digits, for example 2026.",
|
||||
"invalid-user": "Invalid user",
|
||||
"joined": "joined",
|
||||
"just-invited": "You are just invited to this board",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Global Webhooks",
|
||||
"new-outgoing-webhook": "New Outgoing Webhook",
|
||||
"no-name": "(Unknown)",
|
||||
"Platform": "Platform",
|
||||
"package": "Package",
|
||||
"OS": "OS",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "Database",
|
||||
"Node": "Node",
|
||||
"Node_version": "Node version",
|
||||
"Meteor_version": "Meteor version",
|
||||
"Database_type": "Database type",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Convert to markdown",
|
||||
"import-board-zip": "Add .zip file that has board JSON files, and board name subdirectories with attachments",
|
||||
"collapse": "Collapse",
|
||||
"collapse-checklist": "Collapse checklist",
|
||||
"expand-checklist": "Expand checklist",
|
||||
"uncollapse": "Uncollapse",
|
||||
"hideCheckedChecklistItems": "Hide checked checklist items",
|
||||
"hideAllChecklistItems": "Hide all checklist items",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Severity",
|
||||
"event-action": "Action",
|
||||
"event-source": "Source",
|
||||
"event-detail": "Detail"
|
||||
}
|
||||
"event-detail": "Detail",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Initials",
|
||||
"invalid-date": "Invalid date",
|
||||
"invalid-time": "Invalid time",
|
||||
"invalid-year": "Invalid year. Please type all four digits, for example 2026.",
|
||||
"invalid-user": "Invalid user",
|
||||
"joined": "joined",
|
||||
"just-invited": "You are just invited to this board",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Global Webhooks",
|
||||
"new-outgoing-webhook": "New Outgoing Webhook",
|
||||
"no-name": "(Unknown)",
|
||||
"Platform": "Platform",
|
||||
"package": "Package",
|
||||
"OS": "OS",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "Database",
|
||||
"Node": "Node",
|
||||
"Node_version": "Node version",
|
||||
"Meteor_version": "Meteor version",
|
||||
"Database_type": "Database type",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Convert to markdown",
|
||||
"import-board-zip": "Add .zip file that has board JSON files, and board name subdirectories with attachments",
|
||||
"collapse": "Collapse",
|
||||
"collapse-checklist": "Collapse checklist",
|
||||
"expand-checklist": "Expand checklist",
|
||||
"uncollapse": "Uncollapse",
|
||||
"hideCheckedChecklistItems": "Hide checked checklist items",
|
||||
"hideAllChecklistItems": "Hide all checklist items",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Severity",
|
||||
"event-action": "Action",
|
||||
"event-source": "Source",
|
||||
"event-detail": "Detail"
|
||||
}
|
||||
"event-detail": "Detail",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Initials",
|
||||
"invalid-date": "Invalid date",
|
||||
"invalid-time": "Invalid time",
|
||||
"invalid-year": "Invalid year. Please type all four digits, for example 2026.",
|
||||
"invalid-user": "Invalid user",
|
||||
"joined": "joined",
|
||||
"just-invited": "You are just invited to this board",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Global Webhooks",
|
||||
"new-outgoing-webhook": "New Outgoing Webhook",
|
||||
"no-name": "(Unknown)",
|
||||
"Platform": "Platform",
|
||||
"package": "Package",
|
||||
"OS": "OS",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "Database",
|
||||
"Node": "Node",
|
||||
"Node_version": "Node version",
|
||||
"Meteor_version": "Meteor version",
|
||||
"Database_type": "Database type",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Convert to markdown",
|
||||
"import-board-zip": "Add .zip file that has board JSON files, and board name subdirectories with attachments",
|
||||
"collapse": "Collapse",
|
||||
"collapse-checklist": "Collapse checklist",
|
||||
"expand-checklist": "Expand checklist",
|
||||
"uncollapse": "Uncollapse",
|
||||
"hideCheckedChecklistItems": "Hide checked checklist items",
|
||||
"hideAllChecklistItems": "Hide all checklist items",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Severity",
|
||||
"event-action": "Action",
|
||||
"event-source": "Source",
|
||||
"event-detail": "Detail"
|
||||
}
|
||||
"event-detail": "Detail",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Initials",
|
||||
"invalid-date": "Invalid date",
|
||||
"invalid-time": "Invalid time",
|
||||
"invalid-year": "Invalid year. Please type all four digits, for example 2026.",
|
||||
"invalid-user": "Invalid user",
|
||||
"joined": "joined",
|
||||
"just-invited": "You are just invited to this board",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Global Webhooks",
|
||||
"new-outgoing-webhook": "New Outgoing Webhook",
|
||||
"no-name": "(Unknown)",
|
||||
"Platform": "Platform",
|
||||
"package": "Package",
|
||||
"OS": "OS",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "Database",
|
||||
"Node": "Node",
|
||||
"Node_version": "Node version",
|
||||
"Meteor_version": "Meteor version",
|
||||
"Database_type": "Database type",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Convert to markdown",
|
||||
"import-board-zip": "Add .zip file that has board JSON files, and board name subdirectories with attachments",
|
||||
"collapse": "Collapse",
|
||||
"collapse-checklist": "Collapse checklist",
|
||||
"expand-checklist": "Expand checklist",
|
||||
"uncollapse": "Uncollapse",
|
||||
"hideCheckedChecklistItems": "Hide checked checklist items",
|
||||
"hideAllChecklistItems": "Hide all checklist items",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Severity",
|
||||
"event-action": "Action",
|
||||
"event-source": "Source",
|
||||
"event-detail": "Detail"
|
||||
}
|
||||
"event-detail": "Detail",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Initials",
|
||||
"invalid-date": "Invalid date",
|
||||
"invalid-time": "Invalid time",
|
||||
"invalid-year": "Invalid year. Please type all four digits, for example 2026.",
|
||||
"invalid-user": "Invalid user",
|
||||
"joined": "joined",
|
||||
"just-invited": "You are just invited to this board",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Global Webhooks",
|
||||
"new-outgoing-webhook": "New Outgoing Webhook",
|
||||
"no-name": "(Unknown)",
|
||||
"Platform": "Platform",
|
||||
"package": "Package",
|
||||
"OS": "OS",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "Database",
|
||||
"Node": "Node",
|
||||
"Node_version": "Node version",
|
||||
"Meteor_version": "Meteor version",
|
||||
"Database_type": "Database type",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Convert to markdown",
|
||||
"import-board-zip": "Add .zip file that has board JSON files, and board name subdirectories with attachments",
|
||||
"collapse": "Collapse",
|
||||
"collapse-checklist": "Collapse checklist",
|
||||
"expand-checklist": "Expand checklist",
|
||||
"uncollapse": "Uncollapse",
|
||||
"hideCheckedChecklistItems": "Hide checked checklist items",
|
||||
"hideAllChecklistItems": "Hide all checklist items",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Severity",
|
||||
"event-action": "Action",
|
||||
"event-source": "Source",
|
||||
"event-detail": "Detail"
|
||||
}
|
||||
"event-detail": "Detail",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Initials",
|
||||
"invalid-date": "Invalid date",
|
||||
"invalid-time": "Invalid time",
|
||||
"invalid-year": "Invalid year. Please type all four digits, for example 2026.",
|
||||
"invalid-user": "Invalid user",
|
||||
"joined": "joined",
|
||||
"just-invited": "You are just invited to this board",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Global Webhooks",
|
||||
"new-outgoing-webhook": "New Outgoing Webhook",
|
||||
"no-name": "(Unknown)",
|
||||
"Platform": "Platform",
|
||||
"package": "Package",
|
||||
"OS": "OS",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "Database",
|
||||
"Node": "Node",
|
||||
"Node_version": "Node version",
|
||||
"Meteor_version": "Meteor version",
|
||||
"Database_type": "Database type",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Convert to markdown",
|
||||
"import-board-zip": "Add .zip file that has board JSON files, and board name subdirectories with attachments",
|
||||
"collapse": "Collapse",
|
||||
"collapse-checklist": "Collapse checklist",
|
||||
"expand-checklist": "Expand checklist",
|
||||
"uncollapse": "Uncollapse",
|
||||
"hideCheckedChecklistItems": "Hide checked checklist items",
|
||||
"hideAllChecklistItems": "Hide all checklist items",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Severity",
|
||||
"event-action": "Action",
|
||||
"event-source": "Source",
|
||||
"event-detail": "Detail"
|
||||
}
|
||||
"event-detail": "Detail",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Initials",
|
||||
"invalid-date": "Invalid date",
|
||||
"invalid-time": "Invalid time",
|
||||
"invalid-year": "Invalid year. Please type all four digits, for example 2026.",
|
||||
"invalid-user": "Invalid user",
|
||||
"joined": "joined",
|
||||
"just-invited": "You are just invited to this board",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Global Webhooks",
|
||||
"new-outgoing-webhook": "New Outgoing Webhook",
|
||||
"no-name": "(Unknown)",
|
||||
"Platform": "Platform",
|
||||
"package": "Package",
|
||||
"OS": "OS",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "Database",
|
||||
"Node": "Node",
|
||||
"Node_version": "Node version",
|
||||
"Meteor_version": "Meteor version",
|
||||
"Database_type": "Database type",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Convert to markdown",
|
||||
"import-board-zip": "Add .zip file that has board JSON files, and board name subdirectories with attachments",
|
||||
"collapse": "Collapse",
|
||||
"collapse-checklist": "Collapse checklist",
|
||||
"expand-checklist": "Expand checklist",
|
||||
"uncollapse": "Uncollapse",
|
||||
"hideCheckedChecklistItems": "Hide checked checklist items",
|
||||
"hideAllChecklistItems": "Hide all checklist items",
|
||||
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Initials",
|
||||
"invalid-date": "Invalid date",
|
||||
"invalid-time": "Invalid time",
|
||||
"invalid-year": "Invalid year. Please type all four digits, for example 2026.",
|
||||
"invalid-user": "Invalid user",
|
||||
"joined": "joined",
|
||||
"just-invited": "You are just invited to this board",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Global Webhooks",
|
||||
"new-outgoing-webhook": "New Outgoing Webhook",
|
||||
"no-name": "(Unknown)",
|
||||
"Platform": "Platform",
|
||||
"package": "Package",
|
||||
"OS": "OS",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "Database",
|
||||
"Node": "Node",
|
||||
"Node_version": "Node version",
|
||||
"Meteor_version": "Meteor version",
|
||||
"Database_type": "Database type",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Convert to markdown",
|
||||
"import-board-zip": "Add .zip file that has board JSON files, and board name subdirectories with attachments",
|
||||
"collapse": "Collapse",
|
||||
"collapse-checklist": "Collapse checklist",
|
||||
"expand-checklist": "Expand checklist",
|
||||
"uncollapse": "Uncollapse",
|
||||
"hideCheckedChecklistItems": "Hide checked checklist items",
|
||||
"hideAllChecklistItems": "Hide all checklist items",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Severity",
|
||||
"event-action": "Action",
|
||||
"event-source": "Source",
|
||||
"event-detail": "Detail"
|
||||
}
|
||||
"event-detail": "Detail",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Initials",
|
||||
"invalid-date": "Invalid date",
|
||||
"invalid-time": "Invalid time",
|
||||
"invalid-year": "Invalid year. Please type all four digits, for example 2026.",
|
||||
"invalid-user": "Invalid user",
|
||||
"joined": "joined",
|
||||
"just-invited": "You are just invited to this board",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Global Webhooks",
|
||||
"new-outgoing-webhook": "New Outgoing Webhook",
|
||||
"no-name": "(Unknown)",
|
||||
"Platform": "Platform",
|
||||
"package": "Package",
|
||||
"OS": "OS",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "Database",
|
||||
"Node": "Node",
|
||||
"Node_version": "Node version",
|
||||
"Meteor_version": "Meteor version",
|
||||
"Database_type": "Database type",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Convert to markdown",
|
||||
"import-board-zip": "Add .zip file that has board JSON files, and board name subdirectories with attachments",
|
||||
"collapse": "Collapse",
|
||||
"collapse-checklist": "Collapse checklist",
|
||||
"expand-checklist": "Expand checklist",
|
||||
"uncollapse": "Uncollapse",
|
||||
"hideCheckedChecklistItems": "Hide checked checklist items",
|
||||
"hideAllChecklistItems": "Hide all checklist items",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Severity",
|
||||
"event-action": "Action",
|
||||
"event-source": "Source",
|
||||
"event-detail": "Detail"
|
||||
}
|
||||
"event-detail": "Detail",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Initials",
|
||||
"invalid-date": "Invalid date",
|
||||
"invalid-time": "Invalid time",
|
||||
"invalid-year": "Invalid year. Please type all four digits, for example 2026.",
|
||||
"invalid-user": "Invalid user",
|
||||
"joined": "joined",
|
||||
"just-invited": "You are just invited to this board",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Global Webhooks",
|
||||
"new-outgoing-webhook": "New Outgoing Webhook",
|
||||
"no-name": "(Unknown)",
|
||||
"Platform": "Platform",
|
||||
"package": "Package",
|
||||
"OS": "OS",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "Database",
|
||||
"Node": "Node",
|
||||
"Node_version": "Node version",
|
||||
"Meteor_version": "Meteor version",
|
||||
"Database_type": "Database type",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Convert to markdown",
|
||||
"import-board-zip": "Add .zip file that has board JSON files, and board name subdirectories with attachments",
|
||||
"collapse": "Collapse",
|
||||
"collapse-checklist": "Collapse checklist",
|
||||
"expand-checklist": "Expand checklist",
|
||||
"uncollapse": "Uncollapse",
|
||||
"hideCheckedChecklistItems": "Hide checked checklist items",
|
||||
"hideAllChecklistItems": "Hide all checklist items",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Severity",
|
||||
"event-action": "Action",
|
||||
"event-source": "Source",
|
||||
"event-detail": "Detail"
|
||||
}
|
||||
"event-detail": "Detail",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Initials",
|
||||
"invalid-date": "Invalid date",
|
||||
"invalid-time": "Invalid time",
|
||||
"invalid-year": "Invalid year. Please type all four digits, for example 2026.",
|
||||
"invalid-user": "Invalid user",
|
||||
"joined": "joined",
|
||||
"just-invited": "You are just invited to this board",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Global Webhooks",
|
||||
"new-outgoing-webhook": "New Outgoing Webhook",
|
||||
"no-name": "(Unknown)",
|
||||
"Platform": "Platform",
|
||||
"package": "Package",
|
||||
"OS": "OS",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "Database",
|
||||
"Node": "Node",
|
||||
"Node_version": "Node version",
|
||||
"Meteor_version": "Meteor version",
|
||||
"Database_type": "Database type",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Convert to markdown",
|
||||
"import-board-zip": "Add .zip file that has board JSON files, and board name subdirectories with attachments",
|
||||
"collapse": "Collapse",
|
||||
"collapse-checklist": "Collapse checklist",
|
||||
"expand-checklist": "Expand checklist",
|
||||
"uncollapse": "Uncollapse",
|
||||
"hideCheckedChecklistItems": "Hide checked checklist items",
|
||||
"hideAllChecklistItems": "Hide all checklist items",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Severity",
|
||||
"event-action": "Action",
|
||||
"event-source": "Source",
|
||||
"event-detail": "Detail"
|
||||
}
|
||||
"event-detail": "Detail",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Initials",
|
||||
"invalid-date": "Invalid date",
|
||||
"invalid-time": "Invalid time",
|
||||
"invalid-year": "Invalid year. Please type all four digits, for example 2026.",
|
||||
"invalid-user": "Invalid user",
|
||||
"joined": "joined",
|
||||
"just-invited": "You are just invited to this board",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Global Webhooks",
|
||||
"new-outgoing-webhook": "New Outgoing Webhook",
|
||||
"no-name": "(Unknown)",
|
||||
"Platform": "Platform",
|
||||
"package": "Package",
|
||||
"OS": "OS",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "Database",
|
||||
"Node": "Node",
|
||||
"Node_version": "Node version",
|
||||
"Meteor_version": "Meteor version",
|
||||
"Database_type": "Database type",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Convert to markdown",
|
||||
"import-board-zip": "Add .zip file that has board JSON files, and board name subdirectories with attachments",
|
||||
"collapse": "Collapse",
|
||||
"collapse-checklist": "Collapse checklist",
|
||||
"expand-checklist": "Expand checklist",
|
||||
"uncollapse": "Uncollapse",
|
||||
"hideCheckedChecklistItems": "Hide checked checklist items",
|
||||
"hideAllChecklistItems": "Hide all checklist items",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Severity",
|
||||
"event-action": "Action",
|
||||
"event-source": "Source",
|
||||
"event-detail": "Detail"
|
||||
}
|
||||
"event-detail": "Detail",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Iniciales",
|
||||
"invalid-date": "Fecha no válida",
|
||||
"invalid-time": "Tiempo no válido",
|
||||
"invalid-year": "Nevalida jaro. Tajpu ĉiujn kvar ciferojn, ekzemple 2026.",
|
||||
"invalid-user": "Usuario no válido",
|
||||
"joined": "se ha unido",
|
||||
"just-invited": "Has sido invitado a este tablero",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Webhooks globales",
|
||||
"new-outgoing-webhook": "Nuevo webhook saliente",
|
||||
"no-name": "(Desconocido)",
|
||||
"Platform": "Platformo",
|
||||
"package": "Pakaĵo",
|
||||
"OS": "Mastruma sistemo",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "Datumbazo",
|
||||
"Node": "Node",
|
||||
"Node_version": "Versión de Node",
|
||||
"Meteor_version": "Versión de Meteor",
|
||||
"Database_type": "Datumbaza tipo",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Convertir en Markdown",
|
||||
"import-board-zip": "Añadir archivo .zip que contenga los archivos JSON del tablero y los nombres de las subcarpetas con adjuntos del tablero",
|
||||
"collapse": "Contraer",
|
||||
"collapse-checklist": "Faldi kontrolliston",
|
||||
"expand-checklist": "Malfaldi kontrolliston",
|
||||
"uncollapse": "Expandir",
|
||||
"hideCheckedChecklistItems": "Ocultar elementos marcados de la lista de verificación",
|
||||
"hideAllChecklistItems": "Ocultar todos los elementos de la lista de verificación",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Graveco",
|
||||
"event-action": "Ago",
|
||||
"event-source": "Fonto",
|
||||
"event-detail": "Detalo"
|
||||
}
|
||||
"event-detail": "Detalo",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Iniciales",
|
||||
"invalid-date": "Fecha inválida",
|
||||
"invalid-time": "Tiempo inválido",
|
||||
"invalid-year": "Año no válido. Escribe los cuatro dígitos, por ejemplo 2026.",
|
||||
"invalid-user": "Usuario inválido",
|
||||
"joined": "unido",
|
||||
"just-invited": "Fuiste invitado a este tablero",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Webhooks globales",
|
||||
"new-outgoing-webhook": "Nuevo Gancho Web",
|
||||
"no-name": "(desconocido)",
|
||||
"Platform": "Plataforma",
|
||||
"package": "Paquete",
|
||||
"OS": "Sistema operativo",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "Base de datos",
|
||||
"Node": "Node",
|
||||
"Node_version": "Versión de Node",
|
||||
"Meteor_version": "Versión de Meteor",
|
||||
"Database_type": "Tipo de base de datos",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Convertir en Markdown",
|
||||
"import-board-zip": "Añadir archivo .zip que contenga los archivos JSON del tablero y los nombres de las subcarpetas con adjuntos del tablero",
|
||||
"collapse": "Contraer",
|
||||
"collapse-checklist": "Contraer la lista de tareas",
|
||||
"expand-checklist": "Expandir la lista de tareas",
|
||||
"uncollapse": "Expandir",
|
||||
"hideCheckedChecklistItems": "Ocultar elementos marcados de la lista de verificación",
|
||||
"hideAllChecklistItems": "Ocultar todos los elementos de la lista de verificación",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Gravedad",
|
||||
"event-action": "Acción",
|
||||
"event-source": "Origen",
|
||||
"event-detail": "Detalle"
|
||||
}
|
||||
"event-detail": "Detalle",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Iniciales",
|
||||
"invalid-date": "Fecha no válida",
|
||||
"invalid-time": "Tiempo no válido",
|
||||
"invalid-year": "Año no válido. Escribe los cuatro dígitos, por ejemplo 2026.",
|
||||
"invalid-user": "Usuario no válido",
|
||||
"joined": "se ha unido",
|
||||
"just-invited": "Has sido invitado a este tablero",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Webhooks globales",
|
||||
"new-outgoing-webhook": "Nuevo webhook saliente",
|
||||
"no-name": "(Desconocido)",
|
||||
"Platform": "Plataforma",
|
||||
"package": "Paquete",
|
||||
"OS": "Sistema operativo",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "Base de datos",
|
||||
"Node": "Node",
|
||||
"Node_version": "Versión de Node",
|
||||
"Meteor_version": "Versión de Meteor",
|
||||
"Database_type": "Tipo de base de datos",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Convertir en Markdown",
|
||||
"import-board-zip": "Añadir archivo .zip que contenga los archivos JSON del tablero y los nombres de las subcarpetas con adjuntos del tablero",
|
||||
"collapse": "Contraer",
|
||||
"collapse-checklist": "Contraer la lista de tareas",
|
||||
"expand-checklist": "Expandir la lista de tareas",
|
||||
"uncollapse": "Expandir",
|
||||
"hideCheckedChecklistItems": "Ocultar elementos marcados de la lista de verificación",
|
||||
"hideAllChecklistItems": "Ocultar todos los elementos de la lista de verificación",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Gravedad",
|
||||
"event-action": "Acción",
|
||||
"event-source": "Origen",
|
||||
"event-detail": "Detalle"
|
||||
}
|
||||
"event-detail": "Detalle",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Iniciales",
|
||||
"invalid-date": "Fecha no válida",
|
||||
"invalid-time": "Tiempo no válido",
|
||||
"invalid-year": "Año no válido. Escribe los cuatro dígitos, por ejemplo 2026.",
|
||||
"invalid-user": "Usuario no válido",
|
||||
"joined": "se ha unido",
|
||||
"just-invited": "Has sido invitado a este tablero",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Webhooks globales",
|
||||
"new-outgoing-webhook": "Nuevo webhook saliente",
|
||||
"no-name": "(Desconocido)",
|
||||
"Platform": "Plataforma",
|
||||
"package": "Paquete",
|
||||
"OS": "Sistema operativo",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "Base de datos",
|
||||
"Node": "Node",
|
||||
"Node_version": "Versión de Node",
|
||||
"Meteor_version": "Versión de Meteor",
|
||||
"Database_type": "Tipo de base de datos",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Convertir en Markdown",
|
||||
"import-board-zip": "Añadir archivo .zip que contenga los archivos JSON del tablero y los nombres de las subcarpetas con adjuntos del tablero",
|
||||
"collapse": "Contraer",
|
||||
"collapse-checklist": "Contraer la lista de tareas",
|
||||
"expand-checklist": "Expandir la lista de tareas",
|
||||
"uncollapse": "Expandir",
|
||||
"hideCheckedChecklistItems": "Ocultar elementos marcados de la lista de verificación",
|
||||
"hideAllChecklistItems": "Ocultar todos los elementos de la lista de verificación",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Gravedad",
|
||||
"event-action": "Acción",
|
||||
"event-source": "Origen",
|
||||
"event-detail": "Detalle"
|
||||
}
|
||||
"event-detail": "Detalle",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Iniciales",
|
||||
"invalid-date": "Fecha no válida",
|
||||
"invalid-time": "Tiempo no válido",
|
||||
"invalid-year": "Año no válido. Escribe los cuatro dígitos, por ejemplo 2026.",
|
||||
"invalid-user": "Usuario no válido",
|
||||
"joined": "se ha unido",
|
||||
"just-invited": "Has sido invitado a este tablero",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Webhooks globales",
|
||||
"new-outgoing-webhook": "Nuevo webhook saliente",
|
||||
"no-name": "(Desconocido)",
|
||||
"Platform": "Plataforma",
|
||||
"package": "Paquete",
|
||||
"OS": "Sistema operativo",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "Base de datos",
|
||||
"Node": "Node",
|
||||
"Node_version": "Versión de Node",
|
||||
"Meteor_version": "Versión de Meteor",
|
||||
"Database_type": "Tipo de base de datos",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Convertir en Markdown",
|
||||
"import-board-zip": "Añadir archivo .zip que contenga los archivos JSON del tablero y los nombres de las subcarpetas con adjuntos del tablero",
|
||||
"collapse": "Contraer",
|
||||
"collapse-checklist": "Contraer la lista de tareas",
|
||||
"expand-checklist": "Expandir la lista de tareas",
|
||||
"uncollapse": "Expandir",
|
||||
"hideCheckedChecklistItems": "Ocultar elementos marcados de la lista de verificación",
|
||||
"hideAllChecklistItems": "Ocultar todos los elementos de la lista de verificación",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Gravedad",
|
||||
"event-action": "Acción",
|
||||
"event-source": "Origen",
|
||||
"event-detail": "Detalle"
|
||||
}
|
||||
"event-detail": "Detalle",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Iniciales",
|
||||
"invalid-date": "Fecha no válida",
|
||||
"invalid-time": "Tiempo no válido",
|
||||
"invalid-year": "Año no válido. Escribe los cuatro dígitos, por ejemplo 2026.",
|
||||
"invalid-user": "Usuario no válido",
|
||||
"joined": "se ha unido",
|
||||
"just-invited": "Ha sido invitado a este tablero",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Webhooks globales",
|
||||
"new-outgoing-webhook": "Nuevo webhook saliente",
|
||||
"no-name": "(Desconocido)",
|
||||
"Platform": "Plataforma",
|
||||
"package": "Paquete",
|
||||
"OS": "Sistema operativo",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "Base de datos",
|
||||
"Node": "Node",
|
||||
"Node_version": "Versión de Node",
|
||||
"Meteor_version": "Versión de Meteor",
|
||||
"Database_type": "Tipo de base de datos",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Convertir en Markdown",
|
||||
"import-board-zip": "Añadir archivo .zip que contenga los archivos JSON del tablero y los nombres de las subcarpetas con adjuntos del tablero",
|
||||
"collapse": "Contraer",
|
||||
"collapse-checklist": "Contraer la lista de tareas",
|
||||
"expand-checklist": "Expandir la lista de tareas",
|
||||
"uncollapse": "Expandir",
|
||||
"hideCheckedChecklistItems": "Ocultar elementos marcados de la lista de verificación",
|
||||
"hideAllChecklistItems": "Ocultar todos los elementos de la lista de verificación",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Gravedad",
|
||||
"event-action": "Acción",
|
||||
"event-source": "Origen",
|
||||
"event-detail": "Detalle"
|
||||
}
|
||||
"event-detail": "Detalle",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Iniciales",
|
||||
"invalid-date": "Fecha no válida",
|
||||
"invalid-time": "Tiempo no válido",
|
||||
"invalid-year": "Año no válido. Escribe los cuatro dígitos, por ejemplo 2026.",
|
||||
"invalid-user": "Usuario no válido",
|
||||
"joined": "se ha unido",
|
||||
"just-invited": "Has sido invitado a este tablero",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Webhooks globales",
|
||||
"new-outgoing-webhook": "Nuevo webhook saliente",
|
||||
"no-name": "(Desconocido)",
|
||||
"Platform": "Plataforma",
|
||||
"package": "Paquete",
|
||||
"OS": "Sistema operativo",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "Base de datos",
|
||||
"Node": "Node",
|
||||
"Node_version": "Versión de Node",
|
||||
"Meteor_version": "Versión de Meteor",
|
||||
"Database_type": "Tipo de base de datos",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Convertir en Markdown",
|
||||
"import-board-zip": "Añadir archivo .zip que contenga los archivos JSON del tablero y los nombres de las subcarpetas con adjuntos del tablero",
|
||||
"collapse": "Contraer",
|
||||
"collapse-checklist": "Contraer la lista de tareas",
|
||||
"expand-checklist": "Expandir la lista de tareas",
|
||||
"uncollapse": "Expandir",
|
||||
"hideCheckedChecklistItems": "Ocultar elementos marcados de la lista de verificación",
|
||||
"hideAllChecklistItems": "Ocultar todos los elementos de la lista de verificación",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Gravedad",
|
||||
"event-action": "Acción",
|
||||
"event-source": "Origen",
|
||||
"event-detail": "Detalle"
|
||||
}
|
||||
"event-detail": "Detalle",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Iniciales",
|
||||
"invalid-date": "Fecha no válida",
|
||||
"invalid-time": "Tiempo no válido",
|
||||
"invalid-year": "Año no válido. Escribe los cuatro dígitos, por ejemplo 2026.",
|
||||
"invalid-user": "Usuario no válido",
|
||||
"joined": "se ha unido",
|
||||
"just-invited": "Has sido invitado a este tablero",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Webhooks globales",
|
||||
"new-outgoing-webhook": "Nuevo webhook saliente",
|
||||
"no-name": "(Desconocido)",
|
||||
"Platform": "Plataforma",
|
||||
"package": "Paquete",
|
||||
"OS": "Sistema operativo",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "Base de datos",
|
||||
"Node": "Node",
|
||||
"Node_version": "Versión de Node",
|
||||
"Meteor_version": "Versión de Meteor",
|
||||
"Database_type": "Tipo de base de datos",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Convertir en Markdown",
|
||||
"import-board-zip": "Añadir archivo .zip que contenga los archivos JSON del tablero y los nombres de las subcarpetas con adjuntos del tablero",
|
||||
"collapse": "Contraer",
|
||||
"collapse-checklist": "Contraer la lista de tareas",
|
||||
"expand-checklist": "Expandir la lista de tareas",
|
||||
"uncollapse": "Expandir",
|
||||
"hideCheckedChecklistItems": "Ocultar elementos marcados de la lista de verificación",
|
||||
"hideAllChecklistItems": "Ocultar todos los elementos de la lista de verificación",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Gravedad",
|
||||
"event-action": "Acción",
|
||||
"event-source": "Origen",
|
||||
"event-detail": "Detalle"
|
||||
}
|
||||
"event-detail": "Detalle",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Iniciales",
|
||||
"invalid-date": "Fecha no válida",
|
||||
"invalid-time": "Tiempo no válido",
|
||||
"invalid-year": "Año no válido. Escribe los cuatro dígitos, por ejemplo 2026.",
|
||||
"invalid-user": "Usuario no válido",
|
||||
"joined": "se ha unido",
|
||||
"just-invited": "Has sido invitado a este tablero",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Webhooks globales",
|
||||
"new-outgoing-webhook": "Nuevo webhook saliente",
|
||||
"no-name": "(Desconocido)",
|
||||
"Platform": "Plataforma",
|
||||
"package": "Paquete",
|
||||
"OS": "Sistema operativo",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "Base de datos",
|
||||
"Node": "Node",
|
||||
"Node_version": "Versión de Node",
|
||||
"Meteor_version": "Versión de Meteor",
|
||||
"Database_type": "Tipo de base de datos",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Convertir en Markdown",
|
||||
"import-board-zip": "Añadir archivo .zip que contenga los archivos JSON del tablero y los nombres de las subcarpetas con adjuntos del tablero",
|
||||
"collapse": "Contraer",
|
||||
"collapse-checklist": "Contraer la lista de tareas",
|
||||
"expand-checklist": "Expandir la lista de tareas",
|
||||
"uncollapse": "Expandir",
|
||||
"hideCheckedChecklistItems": "Ocultar elementos marcados de la lista de verificación",
|
||||
"hideAllChecklistItems": "Ocultar todos los elementos de la lista de verificación",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Gravedad",
|
||||
"event-action": "Acción",
|
||||
"event-source": "Origen",
|
||||
"event-detail": "Detalle"
|
||||
}
|
||||
"event-detail": "Detalle",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Initsiaalid",
|
||||
"invalid-date": "Vale kuupäev",
|
||||
"invalid-time": "Vale aeg",
|
||||
"invalid-year": "Vigane aasta. Sisesta kõik neli numbrit, näiteks 2026.",
|
||||
"invalid-user": "Invaliidne kasutaja",
|
||||
"joined": "liitunud",
|
||||
"just-invited": "Teid lihtsalt kutsutakse siia foorumisse",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Globaalsed veebikonksud",
|
||||
"new-outgoing-webhook": "Uus väljaminev veebikonks",
|
||||
"no-name": "(Tundmatu)",
|
||||
"Platform": "Platvorm",
|
||||
"package": "Pakett",
|
||||
"OS": "Operatsioonisüsteem",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "Andmebaas",
|
||||
"Node": "Node",
|
||||
"Node_version": "Sõlme versioon",
|
||||
"Meteor_version": "Meteori versioon",
|
||||
"Database_type": "Andmebaasi tüüp",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Teisenda markdowniks",
|
||||
"import-board-zip": "Lisa .zip fail, milles on tahvli JSON-failid ja tahvli nimega alamkataloogid manustega",
|
||||
"collapse": "Kokkupõrge",
|
||||
"collapse-checklist": "Ahenda kontrollnimekiri",
|
||||
"expand-checklist": "Laienda kontrollnimekiri",
|
||||
"uncollapse": "Laienda",
|
||||
"hideCheckedChecklistItems": "Peida märgitud kontrollnimekirja objektid",
|
||||
"hideAllChecklistItems": "Peida kõik kontrollnimekirja objektid",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Raskusaste",
|
||||
"event-action": "Toiming",
|
||||
"event-source": "Allikas",
|
||||
"event-detail": "Üksikasjad"
|
||||
}
|
||||
"event-detail": "Üksikasjad",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Inizialak",
|
||||
"invalid-date": "Baliogabeko data",
|
||||
"invalid-time": "Baliogabeko denbora",
|
||||
"invalid-year": "Urte baliogabea. Idatzi lau zifrak, adibidez 2026.",
|
||||
"invalid-user": "Baliogabeko erabiltzailea",
|
||||
"joined": "elkartu da",
|
||||
"just-invited": "Arbel honetara gonbidatu berri zaituzte",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Webhooks globales",
|
||||
"new-outgoing-webhook": "Irteera-webhook berria",
|
||||
"no-name": "(Ezezaguna)",
|
||||
"Platform": "Plataforma",
|
||||
"package": "Paketea",
|
||||
"OS": "Sistema eragilea",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "Datu-basea",
|
||||
"Node": "Node",
|
||||
"Node_version": "Nodo bertsioa",
|
||||
"Meteor_version": "Meteor bertsioa",
|
||||
"Database_type": "Datu-base mota",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Bihurtu markdown-era",
|
||||
"import-board-zip": "Gehitu arbeleko JSON fitxategiak dituen .zip fitxategia eta eranskinak dituzten arbelen izenen azpidirektorioak",
|
||||
"collapse": "Tolestu",
|
||||
"collapse-checklist": "Tolestu kontrol-zerrenda",
|
||||
"expand-checklist": "Zabaldu kontrol-zerrenda",
|
||||
"uncollapse": "Zabaldu",
|
||||
"hideCheckedChecklistItems": "Ezkutatu egiaztatutako zerrendako elementuak",
|
||||
"hideAllChecklistItems": "Ezkutatu kontrol-zerrendako elementu guztiak",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Larritasuna",
|
||||
"event-action": "Ekintza",
|
||||
"event-source": "Iturria",
|
||||
"event-detail": "Xehetasuna"
|
||||
}
|
||||
"event-detail": "Xehetasuna",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "تخصیصات اولیه",
|
||||
"invalid-date": "تاریخ نامعتبر",
|
||||
"invalid-time": "زمان نامعتبر",
|
||||
"invalid-year": "سال نامعتبر است. هر چهار رقم را وارد کنید، برای مثال 2026.",
|
||||
"invalid-user": "کاربر نامعتبر",
|
||||
"joined": "متصل",
|
||||
"just-invited": "هم اکنون، شما به این برد دعوت شدهاید.",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "وبهوکهای سراسری",
|
||||
"new-outgoing-webhook": "ويبهوك جديدة",
|
||||
"no-name": "(ناشناخته)",
|
||||
"Platform": "سکو",
|
||||
"package": "بسته",
|
||||
"OS": "سیستمعامل",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "پایگاه داده",
|
||||
"Node": "Node",
|
||||
"Node_version": "نسخه Node",
|
||||
"Meteor_version": "نسخه متئور",
|
||||
"Database_type": "نوع پایگاه داده",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "تحويل إلى تخفيض السعر",
|
||||
"import-board-zip": "أضف ملف .zip الذي يحتوي على ملفات JSON الخاصة باللوحة، ودلائل فرعية لأسماء اللوحة مع المرفقات",
|
||||
"collapse": "جمع کردن",
|
||||
"collapse-checklist": "جمع کردن چکلیست",
|
||||
"expand-checklist": "باز کردن چکلیست",
|
||||
"uncollapse": "إلغاء الانهيار",
|
||||
"hideCheckedChecklistItems": "پنهان کردن موارد انجام شده چک لیست",
|
||||
"hideAllChecklistItems": "پنهان کردن همه موارد چک لیست",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "شدت",
|
||||
"event-action": "اقدام",
|
||||
"event-source": "منبع",
|
||||
"event-detail": "جزئیات"
|
||||
}
|
||||
"event-detail": "جزئیات",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "تخصیصات اولیه",
|
||||
"invalid-date": "تاریخ نامعتبر",
|
||||
"invalid-time": "زمان نامعتبر",
|
||||
"invalid-year": "سال نامعتبر است. هر چهار رقم را وارد کنید، برای مثال 2026.",
|
||||
"invalid-user": "کاربر نامعتبر",
|
||||
"joined": "متصل",
|
||||
"just-invited": "هم اکنون، شما به این برد دعوت شدهاید.",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "وبهوکهای سراسری",
|
||||
"new-outgoing-webhook": "ويبهوك جديدة",
|
||||
"no-name": "(ناشناخته)",
|
||||
"Platform": "سکو",
|
||||
"package": "بسته",
|
||||
"OS": "سیستمعامل",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "پایگاه داده",
|
||||
"Node": "Node",
|
||||
"Node_version": "نسخه Node",
|
||||
"Meteor_version": "نسخه متئور",
|
||||
"Database_type": "نوع پایگاه داده",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "تحويل إلى تخفيض السعر",
|
||||
"import-board-zip": "أضف ملف .zip الذي يحتوي على ملفات JSON الخاصة باللوحة، ودلائل فرعية لأسماء اللوحة مع المرفقات",
|
||||
"collapse": "جمع کردن",
|
||||
"collapse-checklist": "جمع کردن چکلیست",
|
||||
"expand-checklist": "باز کردن چکلیست",
|
||||
"uncollapse": "إلغاء الانهيار",
|
||||
"hideCheckedChecklistItems": "پنهان کردن موارد انجام شده چک لیست",
|
||||
"hideAllChecklistItems": "پنهان کردن همه موارد چک لیست",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "شدت",
|
||||
"event-action": "اقدام",
|
||||
"event-source": "منبع",
|
||||
"event-detail": "جزئیات"
|
||||
}
|
||||
"event-detail": "جزئیات",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Nimikirjaimet",
|
||||
"invalid-date": "Virheellinen päivämäärä",
|
||||
"invalid-time": "Virheellinen aika",
|
||||
"invalid-year": "Virheellinen vuosi. Kirjoita kaikki neljä numeroa, esimerkiksi 2026.",
|
||||
"invalid-user": "Virheellinen käyttäjä",
|
||||
"joined": "liittyi",
|
||||
"just-invited": "Sinut on juuri kutsuttu tälle taululle",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Kaikenkattavat Webkoukut",
|
||||
"new-outgoing-webhook": "Uusi lähtevä Webkoukku",
|
||||
"no-name": "(Tuntematon)",
|
||||
"Platform": "Alusta",
|
||||
"package": "Paketti",
|
||||
"OS": "Käyttöjärjestelmä",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "Tietokanta",
|
||||
"Node": "Node",
|
||||
"Node_version": "Node-versio",
|
||||
"Meteor_version": "Meteor-versio",
|
||||
"Database_type": "Tietokannan tyyppi",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Muuta markdowniksi",
|
||||
"import-board-zip": "Lisää .zip tiedosto jossa on taulu JSON tiedostot, ja taulu nimi alihakemistot liitteineen",
|
||||
"collapse": "Pienennä",
|
||||
"collapse-checklist": "Pienennä tarkistuslista",
|
||||
"expand-checklist": "Suurenna tarkistuslista",
|
||||
"uncollapse": "Suurenna",
|
||||
"hideCheckedChecklistItems": "Piilota ruksatut tarkistuslistan kohdat",
|
||||
"hideAllChecklistItems": "Piilota kaikki tarkistuslistan kohdat",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Vakavuus",
|
||||
"event-action": "Toiminto",
|
||||
"event-source": "Lähde",
|
||||
"event-detail": "Tiedot"
|
||||
}
|
||||
"event-detail": "Tiedot",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Initiales",
|
||||
"invalid-date": "Date invalide",
|
||||
"invalid-time": "Heure invalide",
|
||||
"invalid-year": "Année invalide. Saisissez les quatre chiffres, par exemple 2026.",
|
||||
"invalid-user": "Utilisateur invalide",
|
||||
"joined": "a rejoint",
|
||||
"just-invited": "Vous venez d'être invité à ce tableau",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Webhooks globaux",
|
||||
"new-outgoing-webhook": "Nouveau webhook sortant",
|
||||
"no-name": "(Inconnu)",
|
||||
"Platform": "Plate-forme",
|
||||
"package": "Paquet",
|
||||
"OS": "OS",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "Base de données",
|
||||
"Node": "Node",
|
||||
"Node_version": "Version de Node",
|
||||
"Meteor_version": "Version de Meteor",
|
||||
"Database_type": "Type de base de données",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Convertir en markdown",
|
||||
"import-board-zip": "Ajouter un fichier .zip qui contient les fichiers JSON du tableau et les noms de sous-répertoires avec les pièces jointes",
|
||||
"collapse": "Réduire",
|
||||
"collapse-checklist": "Réduire la check-list",
|
||||
"expand-checklist": "Développer la check-list",
|
||||
"uncollapse": "Développer",
|
||||
"hideCheckedChecklistItems": "Cacher les éléments cochés de la check-list",
|
||||
"hideAllChecklistItems": "Cacher tous les éléments de la check-list",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Gravité",
|
||||
"event-action": "Action",
|
||||
"event-source": "Source",
|
||||
"event-detail": "Détail"
|
||||
}
|
||||
"event-detail": "Détail",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Initiales",
|
||||
"invalid-date": "Date invalide",
|
||||
"invalid-time": "Heure invalide",
|
||||
"invalid-year": "Année invalide. Saisissez les quatre chiffres, par exemple 2026.",
|
||||
"invalid-user": "Utilisateur invalide",
|
||||
"joined": "a rejoint",
|
||||
"just-invited": "Vous venez d'être invité à ce tableau",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Webhooks globaux",
|
||||
"new-outgoing-webhook": "Nouveau webhook sortant",
|
||||
"no-name": "(Inconnu)",
|
||||
"Platform": "Plate-forme",
|
||||
"package": "Paquet",
|
||||
"OS": "OS",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "Base de données",
|
||||
"Node": "Node",
|
||||
"Node_version": "Version de Node",
|
||||
"Meteor_version": "Version de Meteor",
|
||||
"Database_type": "Type de base de données",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Convertir en markdown",
|
||||
"import-board-zip": "Ajouter un fichier .zip qui contient les fichiers JSON du tableau et les noms de sous-répertoires avec les pièces jointes",
|
||||
"collapse": "Réduire",
|
||||
"collapse-checklist": "Réduire la check-list",
|
||||
"expand-checklist": "Développer la check-list",
|
||||
"uncollapse": "Développer",
|
||||
"hideCheckedChecklistItems": "Cacher les éléments cochés de la check-list",
|
||||
"hideAllChecklistItems": "Cacher tous les éléments de la check-list",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Gravité",
|
||||
"event-action": "Action",
|
||||
"event-source": "Source",
|
||||
"event-detail": "Détail"
|
||||
}
|
||||
"event-detail": "Détail",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
@@ -710,6 +710,7 @@
|
||||
"initials": "Initiales",
|
||||
"invalid-date": "Date invalide",
|
||||
"invalid-time": "Heure invalide",
|
||||
"invalid-year": "Année invalide. Saisissez les quatre chiffres, par exemple 2026.",
|
||||
"invalid-user": "Utilisateur invalide",
|
||||
"joined": "a rejoint",
|
||||
"just-invited": "Vous venez d'être invité à ce tableau",
|
||||
@@ -949,6 +950,12 @@
|
||||
"global-webhook": "Webhooks globaux",
|
||||
"new-outgoing-webhook": "Nouveau webhook sortant",
|
||||
"no-name": "(Inconnu)",
|
||||
"Platform": "Plate-forme",
|
||||
"package": "Paquet",
|
||||
"OS": "OS",
|
||||
"Meteor": "Meteor",
|
||||
"Database": "Base de données",
|
||||
"Node": "Node",
|
||||
"Node_version": "Version de Node",
|
||||
"Meteor_version": "Version de Meteor",
|
||||
"Database_type": "Type de base de données",
|
||||
@@ -1840,6 +1847,8 @@
|
||||
"convert-to-markdown": "Convertir en markdown",
|
||||
"import-board-zip": "Ajouter un fichier .zip qui contient les fichiers JSON du tableau et les noms de sous-répertoires avec les pièces jointes",
|
||||
"collapse": "Réduire",
|
||||
"collapse-checklist": "Réduire la check-list",
|
||||
"expand-checklist": "Développer la check-list",
|
||||
"uncollapse": "Développer",
|
||||
"hideCheckedChecklistItems": "Cacher les éléments cochés de la check-list",
|
||||
"hideAllChecklistItems": "Cacher tous les éléments de la check-list",
|
||||
@@ -2339,5 +2348,8 @@
|
||||
"event-severity": "Gravité",
|
||||
"event-action": "Action",
|
||||
"event-source": "Source",
|
||||
"event-detail": "Détail"
|
||||
}
|
||||
"event-detail": "Détail",
|
||||
"event-ip": "IP address",
|
||||
"event-attempts": "Attempts",
|
||||
"integrityReportTitle": "Filesystem integrity"
|
||||
}
|
||||
Loaded 100 of 286 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user