Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5d18f98b44 | ||
|
|
e738177e08 | ||
|
|
bb201935b9 | ||
|
|
bcfe6bd616 | ||
|
|
9c6352a7bc | ||
|
|
9110e41f20 | ||
|
|
7ae871d3a6 | ||
|
|
0ddf027d43 | ||
|
|
45124a39f3 | ||
|
|
4940af0573 | ||
|
|
924b5d1733 | ||
|
|
2119a3a51e | ||
|
|
dcda99ddf3 | ||
|
|
0e35dcd5ad | ||
|
|
991d42ca0b | ||
|
|
ac242c96b7 | ||
|
|
79d45c8e33 | ||
|
|
8e9f7102f9 | ||
|
|
1952dc309b | ||
|
|
5e7767247f | ||
|
|
676bf686c7 | ||
|
|
5cd6985368 | ||
|
|
807e72dcce | ||
|
|
71702b5821 | ||
|
|
40c56248f1 | ||
|
|
74ac7d8d3f | ||
|
|
e7186b47b0 | ||
|
|
12aa7ea2cb | ||
|
|
ef584e2826 | ||
|
|
f902be10b6 | ||
|
|
29b835de59 | ||
|
|
6ff9c5b58d | ||
|
|
1b86aeb4f5 | ||
|
|
dce99c00be | ||
|
|
e47c700c36 | ||
|
|
09506c78f3 | ||
|
|
9ec1fc0902 | ||
|
|
0b3ec2c19e | ||
|
|
a94bec921c | ||
|
|
3884da3c06 | ||
|
|
d3fa177c7f | ||
|
|
d2176e2c08 | ||
|
|
8d9c59486d | ||
|
|
0e7c2b4b94 | ||
|
|
5c9bc1c745 | ||
|
|
5e7efa0098 | ||
|
|
424862e313 | ||
|
|
9b80ad5a3c | ||
|
|
96c6fa0276 | ||
|
|
69305e1833 | ||
|
|
8aa74ab65e | ||
|
|
aee12c2494 | ||
|
|
83976b3229 | ||
|
|
39f8a138d7 | ||
|
|
120e4af7b2 | ||
|
|
15bddbc86a | ||
|
|
4e8b193801 | ||
|
|
37b65996a0 | ||
|
|
9cd0d3488f | ||
|
|
eaf07cef07 | ||
|
|
02a8775537 | ||
|
|
f2d5698acb | ||
|
|
b0c0e456af | ||
|
|
0857a2ea91 | ||
|
|
1f2e6d33ce | ||
|
|
250e0690d1 | ||
|
|
e709094533 | ||
|
|
4a5b16ee2e | ||
|
|
378d64f99a | ||
|
|
4395760a40 | ||
|
|
8417fae89c | ||
|
|
6c8fae944c | ||
|
|
decab9256b | ||
|
|
183ed35ce8 | ||
|
|
2fcf85fd61 | ||
|
|
3613c1c75e | ||
|
|
e7813046f6 | ||
|
|
9871bf1963 | ||
|
|
b32e7b659b | ||
|
|
2201372744 | ||
|
|
7431a082e2 | ||
|
|
6fe3edebb1 | ||
|
|
4b6406c264 | ||
|
|
86f6bdf9af | ||
|
|
1eeed6645d | ||
|
|
bb8c4325c6 | ||
|
|
07a3301414 | ||
|
|
1590701fc9 | ||
|
|
1d4a65d0b4 | ||
|
|
c845d25ae5 | ||
|
|
ceec27bf90 | ||
|
|
4b90424773 | ||
|
|
31eb9b26b4 | ||
|
|
a8a3c9ad19 | ||
|
|
5cfa03ec07 | ||
|
|
17ab5978ad | ||
|
|
d4c69c3932 | ||
|
|
3778a9ebcf | ||
|
|
880d94e220 | ||
|
|
37607f72b2 | ||
|
|
b1c26e6f64 | ||
|
|
8164af281d | ||
|
|
af676c8f26 | ||
|
|
b8dc7ff18e | ||
|
|
4aee129cdc | ||
|
|
03d29dd674 | ||
|
|
5a6f84ce34 | ||
|
|
0e593c7d81 | ||
|
|
4de830d663 | ||
|
|
769bb7a55d | ||
|
|
ed6c6e5a25 | ||
|
|
302ba75729 | ||
|
|
69dc8f304c | ||
|
|
e43002d5ad | ||
|
|
edd07befe2 | ||
|
|
5cc6a2f7d0 | ||
|
|
926f39c96b | ||
|
|
abd38082de | ||
|
|
5ca90f4d22 | ||
|
|
c9586e579a |
No files matched your search
@@ -10,7 +10,7 @@ ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
ENV \
|
||||
DEBUG=false \
|
||||
NODE_VERSION=v12.22.0 \
|
||||
NODE_VERSION=v12.22.1 \
|
||||
METEOR_RELEASE=1.10.2 \
|
||||
USE_EDGE=false \
|
||||
METEOR_EDGE=1.5-beta.17 \
|
||||
|
||||
@@ -81,7 +81,7 @@ parts:
|
||||
wekan:
|
||||
source: .
|
||||
plugin: nodejs
|
||||
node-engine: 12.22.0
|
||||
node-engine: 12.22.1
|
||||
node-packages:
|
||||
- node-gyp
|
||||
- node-pre-gyp
|
||||
|
||||
@@ -83,7 +83,7 @@ parts:
|
||||
wekan:
|
||||
source: .
|
||||
plugin: nodejs
|
||||
node-engine: 12.22.0
|
||||
node-engine: 12.22.1
|
||||
node-packages:
|
||||
- node-gyp
|
||||
- node-pre-gyp
|
||||
|
||||
+2
-2
@@ -6,7 +6,7 @@
|
||||
meteor-base@1.4.0
|
||||
|
||||
# Build system
|
||||
ecmascript@0.15.0
|
||||
ecmascript@0.15.1
|
||||
standard-minifier-css@1.7.2
|
||||
standard-minifier-js@2.6.0
|
||||
mquandalle:jade
|
||||
@@ -23,7 +23,7 @@ dburles:collection-helpers
|
||||
idmontie:migrations
|
||||
matb33:collection-hooks
|
||||
matteodem:easy-search
|
||||
mongo@1.10.1
|
||||
mongo@1.11.0
|
||||
mquandalle:collection-mutations
|
||||
|
||||
# Account system
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
METEOR@2.1
|
||||
METEOR@2.2
|
||||
+22
-22
@@ -1,5 +1,5 @@
|
||||
3stack:presence@1.1.2
|
||||
accounts-base@1.8.0
|
||||
accounts-base@1.9.0
|
||||
accounts-oauth@1.2.0
|
||||
accounts-password@1.7.0
|
||||
aldeed:collection2@2.10.0
|
||||
@@ -11,17 +11,17 @@ allow-deny@1.1.0
|
||||
arillo:flow-router-helpers@0.5.2
|
||||
audit-argument-checks@1.0.7
|
||||
autoupdate@1.7.0
|
||||
babel-compiler@7.6.0
|
||||
babel-compiler@7.6.1
|
||||
babel-runtime@1.5.0
|
||||
base64@1.0.12
|
||||
binary-heap@1.0.11
|
||||
blaze@2.3.4
|
||||
blaze-tools@1.0.10
|
||||
blaze@2.4.0
|
||||
blaze-tools@1.1.1
|
||||
boilerplate-generator@1.7.1
|
||||
browser-policy-common@1.0.11
|
||||
browser-policy-framing@1.1.0
|
||||
caching-compiler@1.2.2
|
||||
caching-html-compiler@1.1.3
|
||||
caching-html-compiler@1.2.0
|
||||
callback-hook@1.3.0
|
||||
cfs:access-point@0.1.49
|
||||
cfs:base-package@0.0.30
|
||||
@@ -52,12 +52,12 @@ ddp@1.4.0
|
||||
ddp-client@2.4.0
|
||||
ddp-common@1.4.0
|
||||
ddp-rate-limiter@1.0.9
|
||||
ddp-server@2.3.2
|
||||
ddp-server@2.3.3
|
||||
deps@1.0.12
|
||||
diff-sequence@1.1.1
|
||||
dynamic-import@0.6.0
|
||||
easylogic:summernote@0.8.8
|
||||
ecmascript@0.15.0
|
||||
ecmascript@0.15.1
|
||||
ecmascript-runtime@0.7.0
|
||||
ecmascript-runtime-client@0.11.0
|
||||
ecmascript-runtime-server@0.10.0
|
||||
@@ -70,8 +70,8 @@ fortawesome:fontawesome@4.7.0
|
||||
geojson-utils@1.0.10
|
||||
horka:swipebox@1.0.2
|
||||
hot-code-push@1.0.4
|
||||
html-tools@1.0.11
|
||||
htmljs@1.0.11
|
||||
html-tools@1.1.1
|
||||
htmljs@1.1.0
|
||||
http@1.4.3
|
||||
id-map@1.1.0
|
||||
idmontie:migrations@1.0.3
|
||||
@@ -84,7 +84,7 @@ kenton:accounts-sandstorm@0.7.0
|
||||
konecty:mongo-counter@0.0.5_3
|
||||
lamhieu:meteorx@2.1.1
|
||||
lamhieu:unblock@1.0.0
|
||||
launch-screen@1.2.0
|
||||
launch-screen@1.2.1
|
||||
livedata@1.0.18
|
||||
localstorage@1.2.0
|
||||
logging@1.2.0
|
||||
@@ -100,16 +100,16 @@ meteorhacks:collection-utils@1.2.0
|
||||
meteorhacks:picker@1.0.3
|
||||
meteorhacks:subs-manager@1.6.4
|
||||
meteorspark:util@0.2.0
|
||||
minifier-css@1.5.3
|
||||
minifier-css@1.5.4
|
||||
minifier-js@2.6.0
|
||||
minifiers@1.1.8-faster-rebuild.0
|
||||
minimongo@1.6.1
|
||||
minimongo@1.6.2
|
||||
mobile-status-bar@1.1.0
|
||||
modern-browsers@0.1.5
|
||||
modules@0.16.0
|
||||
modules-runtime@0.12.0
|
||||
momentjs:moment@2.29.1
|
||||
mongo@1.10.1
|
||||
mongo@1.11.0
|
||||
mongo-decimal@0.1.2
|
||||
mongo-dev-server@1.1.0
|
||||
mongo-id@1.0.7
|
||||
@@ -125,7 +125,7 @@ mquandalle:moment@1.0.1
|
||||
mquandalle:mousetrap-bindglobal@0.0.1
|
||||
msavin:usercache@1.8.0
|
||||
npm-bcrypt@0.9.3
|
||||
npm-mongo@3.8.1
|
||||
npm-mongo@3.9.0
|
||||
oauth@1.3.2
|
||||
oauth2@1.3.0
|
||||
observe-sequence@1.0.16
|
||||
@@ -208,10 +208,10 @@ simple:json-routes@2.1.0
|
||||
simple:rest-accounts-password@1.1.2
|
||||
simple:rest-bearer-token-parser@1.0.1
|
||||
simple:rest-json-error-handler@1.0.1
|
||||
socket-stream-client@0.3.1
|
||||
socket-stream-client@0.3.2
|
||||
softwarerero:accounts-t9n@1.3.11
|
||||
spacebars@1.0.15
|
||||
spacebars-compiler@1.1.3
|
||||
spacebars@1.1.0
|
||||
spacebars-compiler@1.2.1
|
||||
srp@1.1.0
|
||||
standard-minifier-css@1.7.2
|
||||
standard-minifier-js@2.6.0
|
||||
@@ -220,10 +220,10 @@ staringatlights:inject-data@2.3.0
|
||||
steffo:meteor-accounts-saml@0.0.18
|
||||
tap:i18n@1.8.2
|
||||
templates:tabs@2.3.0
|
||||
templating@1.3.2
|
||||
templating-compiler@1.3.3
|
||||
templating-runtime@1.3.2
|
||||
templating-tools@1.1.2
|
||||
templating@1.4.0
|
||||
templating-compiler@1.4.0
|
||||
templating-runtime@1.4.0
|
||||
templating-tools@1.2.0
|
||||
tmeasday:check-npm-versions@0.3.2
|
||||
tracker@1.2.0
|
||||
twbs:bootstrap@3.3.6
|
||||
@@ -234,7 +234,7 @@ useraccounts:core@1.14.2
|
||||
useraccounts:flow-routing@1.14.2
|
||||
useraccounts:unstyled@1.14.2
|
||||
verron:autosize@3.0.8
|
||||
webapp@1.10.0
|
||||
webapp@1.10.1
|
||||
webapp-hashing@1.1.0
|
||||
wekan-accounts-cas@0.1.0
|
||||
wekan-accounts-oidc@1.0.10
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ sudo: required
|
||||
|
||||
env:
|
||||
TRAVIS_DOCKER_COMPOSE_VERSION: 1.24.0
|
||||
TRAVIS_NODE_VERSION: 12.22.0
|
||||
TRAVIS_NODE_VERSION: 12.22.1
|
||||
TRAVIS_NPM_VERSION: latest
|
||||
|
||||
before_install:
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ host = https://www.transifex.com
|
||||
# tap:i18n requires us to use `-` separator in the language identifiers whereas
|
||||
# Transifex uses a `_` separator, without an option to customize it on one side
|
||||
# or the other, so we need to do a Manual mapping.
|
||||
lang_map = ar_EG:ar-EG, bg_BG:bg, en_GB:en-GB, es_AR:es-AR, es_CL:es-CL, es_419:es-LA, es_PE:es-PE, es_MX:es-MX, es_TX:es-TX, es_PY:es-PY, el_GR:el, fa_IR:fa-IR, fi_FI:fi, hu_HU:hu, id_ID:id, mn_MN:mn, no:nb, lv_LV:lv, pt_BR:pt-BR, ro_RO:ro, sl_SI:sl, zh_CN:zh-CN, zh_TW:zh-TW, zh_HK:zh-HK
|
||||
lang_map = ar_EG:ar-EG, bg_BG:bg, de_CH:de-CH, en_GB:en-GB, es_AR:es-AR, es_CL:es-CL, es_419:es-LA, es_PE:es-PE, es_MX:es-MX, es_TX:es-TX, es_PY:es-PY, el_GR:el, fa_IR:fa-IR, fi_FI:fi, hu_HU:hu, id_ID:id, mn_MN:mn, lv_LV:lv, pt_BR:pt-BR, ro_RO:ro, sl_SI:sl, zh_CN:zh-CN, zh_TW:zh-TW, zh_HK:zh-HK
|
||||
|
||||
[wekan.application]
|
||||
file_filter = i18n/<lang>.i18n.json
|
||||
|
||||
+141
@@ -1,3 +1,144 @@
|
||||
# v5.24 2021-04-24 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Copy Swimlane](https://github.com/wekan/wekan/pull/3753).
|
||||
Thanks to jrsupplee.
|
||||
|
||||
and adds the following updates:
|
||||
|
||||
- [Updated dependencies](https://github.com/wekan/wekan/commit/e738177e081e4a7e83fed3389f47847403551fc2).
|
||||
Thanks to developers of dependencies.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Fix Snap: Delete extra symlink that prevented building Snap](https://github.com/wekan/wekan/commit/45124a39f34a918b251a4a36fb016639b558f119).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v5.23 2021-04-22 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Filtering by due date](https://github.com/wekan/wekan/pull/3731).
|
||||
Thanks to mcrute.
|
||||
|
||||
and adds the following updates:
|
||||
|
||||
- [Updated dependencies](https://github.com/wekan/wekan/commit/676bf686c7a121b0da744afce5911807a6be48fe).
|
||||
Thanks to developers of dependencies.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Fix: Trello data without labels definition](https://github.com/wekan/wekan/pull/3733).
|
||||
Thanks to jrsupplee.
|
||||
- [Bug fix for Due Cards](https://github.com/wekan/wekan/pull/3741).
|
||||
Thanks to jrsupplee.
|
||||
- [Fix: The bg color of start at button is almost-due](https://github.com/wekan/wekan/pull/3749).
|
||||
Thanks to listenerri.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v5.22 2021-04-16 Wekan release
|
||||
|
||||
This release adds the following new translations:
|
||||
|
||||
- Added German (Switzerland) (de_CH) (Schwiizerdütsch). Updated translations.
|
||||
[Part 1](https://github.com/wekan/wekan/commit/09506c78f3c3439db622574eb851fa0c20d3a066),
|
||||
[Part 2](https://github.com/wekan/wekan/commit/dce99c00be80cceba686fd73b4b78b6c778d78a6),
|
||||
[Part 3](https://github.com/wekan/wekan/commit/6ff9c5b58d25ba52b11e5429c9cfe6ed6a97000e).
|
||||
Thanks to translators.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Remove allowedValues from Cards.type schema](https://github.com/wekan/wekan/pull/3724).
|
||||
Thanks to jrsupplee.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v5.21 2021-04-16 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Summernote Rich Text Editor](https://github.com/wekan/wekan/pull/3720):
|
||||
1) Add new button to insert a URL link.
|
||||
2) Add new popover allowing you to edit existing URL links.
|
||||
3) Enable spell check.
|
||||
4) Allow client side grammerly extension.
|
||||
Thanks to ryanMushy.
|
||||
|
||||
and adds the following updates:
|
||||
|
||||
- [Upgraded to Meteor 2.2](https://github.com/wekan/wekan/commit/0e7c2b4b94b1c48e8839cfba635b53cdc1a797b1).
|
||||
Thanks to Meteor developers.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Bugfix, date format not changed to local format](https://github.com/wekan/wekan/pull/3723).
|
||||
Thanks to mfilser.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v5.20 2021-04-14 Wekan release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [OpenAPI: rework the allowedValues to allow for imported variables](https://github.com/wekan/wekan/pull/3715).
|
||||
Thanks to bentiss.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v5.19 2021-04-14 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Custom Field "String Template"](https://github.com/wekan/wekan/pull/3701).
|
||||
Thanks to tod31.
|
||||
- [1) Admin reports. An option added to the admin panel that has reports an admin can run.
|
||||
Right now it has two reports for attachments and broken cards.
|
||||
2) Add the creator avatar to `cardDetails` and `minicard`. Avatar is only shown if it is selected in card settings.
|
||||
3) Added a new search operator `creator`.
|
||||
4) Bug fix for multiple label predicates](https://github.com/wekan/wekan/pull/3705).
|
||||
Thanks to jrsupplee.
|
||||
- [Update Admin Panel Rules report icon and add missing translations](https://github.com/wekan/wekan/commit/8417fae89cc89adb4559874050ff7c56cc08eb00).
|
||||
Thanks to xet7.
|
||||
|
||||
and adds the following updates:
|
||||
|
||||
- [Upgraded to Meteor 2.1.1 an updated dependencies](https://github.com/wekan/wekan/commit/bb8c4325c60582cdcda5d406071586f18681e737).
|
||||
Thanks to developers of dependencies.
|
||||
- [Updated to Node.js v12.22.1](https://github.com/wekan/wekan/commit/2201372744639ade3ba74b6ff9115988f011b9ac).
|
||||
Thanks to Node.js developers.
|
||||
- [Updated release scripts](https://github.com/wekan/wekan/commit/9871bf196352edcb5475e1b0ee4983e8f312e449).
|
||||
Thanks to xet7.
|
||||
- [Updated caniuse-lite etc dependencies](https://github.com/wekan/wekan/commit/0857a2ea91f672201ba96f2ba635165784b30fd8).
|
||||
Thanks to developers of dependencies.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Revert stable tag, because it did break Wekan version numbers](https://github.com/wekan/wekan/commit/5ca90f4d2245910580cb0af885fac17dcec44ef0).
|
||||
Thanks to xet7.
|
||||
- [Updating ARM Dockerfile](https://github.com/wekan/wekan/pull/3692).
|
||||
Thanks to loganballard.
|
||||
- [Added latest arm64 bundle symlink](https://github.com/wekan/wekan/commit/6fe3edebb18414ebe7e69b2de3269438662b6163).
|
||||
Thanks to xet7.
|
||||
- [Bug fix: Rules for moving from list/swimlane](https://github.com/wekan/wekan/pull/3706).
|
||||
Thanks to jrsupplee.
|
||||
- [Fixed Elements are duplicated on the view "My cards".
|
||||
Rewrite routine for building the My Cards hierarchical list.
|
||||
Use a separate publication for retrieving My Cards.
|
||||
Fixed bug with limit and skip projection](https://github.com/wekan/wekan/pull/3708).
|
||||
Thanks to jrsupplee.
|
||||
- [Popover needs to be destroyed anytime the details panel is closed](https://github.com/wekan/wekan/pull/3712).
|
||||
Thanks to ryanMushy.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v5.18 2021-04-14 Wekan release
|
||||
|
||||
Not released version, because some version numbers not changed in all release files.
|
||||
|
||||
# v5.17 2021-04-01 Wekan release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ ARG DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
ENV BUILD_DEPS="apt-utils libarchive-tools gnupg gosu wget curl bzip2 g++ build-essential git ca-certificates python3" \
|
||||
DEBUG=false \
|
||||
NODE_VERSION=v12.22.0 \
|
||||
NODE_VERSION=v12.22.1 \
|
||||
METEOR_RELEASE=1.10.2 \
|
||||
USE_EDGE=false \
|
||||
METEOR_EDGE=1.5-beta.17 \
|
||||
|
||||
+9
-9
@@ -4,16 +4,16 @@ FROM amd64/alpine:3.7 AS builder
|
||||
ENV QEMU_VERSION=v4.2.0-6 \
|
||||
QEMU_ARCHITECTURE=aarch64 \
|
||||
NODE_ARCHITECTURE=linux-arm64 \
|
||||
NODE_VERSION=v12.22.0 \
|
||||
WEKAN_VERSION=3.96 \
|
||||
NODE_VERSION=v12.22.1 \
|
||||
WEKAN_VERSION=latest \
|
||||
WEKAN_ARCHITECTURE=arm64
|
||||
|
||||
# Install dependencies
|
||||
RUN apk update && apk add ca-certificates outils-sha1 && \
|
||||
\
|
||||
# Download qemu static for our architecture
|
||||
wget https://github.com/multiarch/qemu-user-static/releases/download/${QEMU_VERSION}/qemu-${QEMU_ARCHITECTURE}-static.tar.gz -O - | tar -xz && \
|
||||
\
|
||||
# Install dependencies
|
||||
RUN apk update && apk add ca-certificates outils-sha1 && \
|
||||
\
|
||||
# Download qemu static for our architecture
|
||||
wget https://github.com/multiarch/qemu-user-static/releases/download/${QEMU_VERSION}/qemu-${QEMU_ARCHITECTURE}-static.tar.gz -O - | tar -xz && \
|
||||
\
|
||||
# Download wekan and shasum
|
||||
wget https://releases.wekan.team/raspi3/wekan-${WEKAN_VERSION}-${WEKAN_ARCHITECTURE}.zip && \
|
||||
wget https://releases.wekan.team/raspi3/SHA256SUMS.txt && \
|
||||
@@ -40,7 +40,7 @@ LABEL maintainer="wekan"
|
||||
# Set the environment variables (defaults where required)
|
||||
ENV QEMU_ARCHITECTURE=aarch64 \
|
||||
NODE_ARCHITECTURE=linux-arm64 \
|
||||
NODE_VERSION=v12.22.0 \
|
||||
NODE_VERSION=v12.22.1 \
|
||||
NODE_ENV=production \
|
||||
NPM_VERSION=latest \
|
||||
WITH_API=true \
|
||||
|
||||
@@ -52,7 +52,7 @@ that by providing one-click installation on various platforms.
|
||||
|
||||
- Wekan is used in [most countries of the world](https://snapcraft.io/wekan).
|
||||
- Wekan largest user has 13k users using Wekan in their company.
|
||||
- Wekan has been [translated](https://transifex.com/wekan/wekan) to about 62 languages.
|
||||
- Wekan has been [translated](https://transifex.com/wekan/wekan) to about 63 languages.
|
||||
- [Features][features]: Wekan has real-time user interface.
|
||||
- [Platforms][platforms]: Wekan supports many platforms.
|
||||
Wekan is critical part of new platforms Wekan is currently being integrated to.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
appId: wekan-public/apps/77b94f60-dec9-0136-304e-16ff53095928
|
||||
appVersion: "v5.17.0"
|
||||
appVersion: "v5.24.0"
|
||||
files:
|
||||
userUploads:
|
||||
- README.md
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
template(name="commentForm")
|
||||
.new-comment.js-new-comment(
|
||||
class="{{#if commentFormIsOpen}}is-open{{/if}}")
|
||||
+userAvatar(userId=currentUser._id)
|
||||
+userAvatar(userId=currentUser._id noRemove=true)
|
||||
form.js-new-comment-form
|
||||
+editor(class="js-new-comment-input")
|
||||
| {{getUnsavedValue 'cardComment' currentCard._id}}
|
||||
|
||||
@@ -3,6 +3,7 @@ const commentFormIsOpen = new ReactiveVar(false);
|
||||
BlazeComponent.extendComponent({
|
||||
onDestroyed() {
|
||||
commentFormIsOpen.set(false);
|
||||
$('.note-popover').hide();
|
||||
},
|
||||
|
||||
commentFormIsOpen() {
|
||||
|
||||
@@ -119,3 +119,24 @@ template(name="cardCustomField-dropdown")
|
||||
if value
|
||||
+viewer
|
||||
= selectedItem
|
||||
|
||||
template(name="cardCustomField-stringtemplate")
|
||||
if canModifyCard
|
||||
+inlinedForm(classNames="js-card-customfield-stringtemplate")
|
||||
each item in stringtemplateItems.get
|
||||
input.js-card-customfield-stringtemplate-item(type="text" value=item placeholder="")
|
||||
input.js-card-customfield-stringtemplate-item.last(type="text" value="" placeholder="{{_ 'custom-field-stringtemplate-item-placeholder'}}")
|
||||
.edit-controls.clearfix
|
||||
button.primary(type="submit") {{_ 'save'}}
|
||||
a.fa.fa-times-thin.js-close-inlined-form
|
||||
else
|
||||
a.js-open-inlined-form
|
||||
if value
|
||||
+viewer
|
||||
= formattedValue
|
||||
else
|
||||
| {{_ 'edit'}}
|
||||
else
|
||||
if value
|
||||
+viewer
|
||||
= formattedValue
|
||||
@@ -1,3 +1,6 @@
|
||||
import { DatePicker } from '/client/lib/datepicker';
|
||||
import Cards from '/models/cards';
|
||||
|
||||
Template.cardCustomFieldsPopup.helpers({
|
||||
hasCustomField() {
|
||||
const card = Cards.findOne(Session.get('currentCard'));
|
||||
@@ -234,3 +237,90 @@ CardCustomField.register('cardCustomField');
|
||||
];
|
||||
}
|
||||
}.register('cardCustomField-dropdown'));
|
||||
|
||||
// cardCustomField-stringtemplate
|
||||
(class extends CardCustomField {
|
||||
onCreated() {
|
||||
super.onCreated();
|
||||
|
||||
this.stringtemplateFormat = this.data().definition.settings.stringtemplateFormat;
|
||||
this.stringtemplateSeparator = this.data().definition.settings.stringtemplateSeparator;
|
||||
|
||||
this.stringtemplateItems = new ReactiveVar(this.data().value ?? []);
|
||||
}
|
||||
|
||||
formattedValue() {
|
||||
return (this.data().value ?? [])
|
||||
.filter(value => !!value.trim())
|
||||
.map(value => this.stringtemplateFormat.replace(/%\{value\}/gi, value))
|
||||
.join(this.stringtemplateSeparator ?? '');
|
||||
}
|
||||
|
||||
getItems() {
|
||||
return Array.from(this.findAll('input'))
|
||||
.map(input => input.value)
|
||||
.filter(value => !!value.trim());
|
||||
}
|
||||
|
||||
events() {
|
||||
return [
|
||||
{
|
||||
'submit .js-card-customfield-stringtemplate'(event) {
|
||||
event.preventDefault();
|
||||
const items = this.getItems();
|
||||
this.card.setCustomField(this.customFieldId, items);
|
||||
},
|
||||
|
||||
'keydown .js-card-customfield-stringtemplate-item'(event) {
|
||||
if (event.keyCode === 13) {
|
||||
event.preventDefault();
|
||||
|
||||
if (event.metaKey || event.ctrlKey) {
|
||||
this.find('button[type=submit]').click();
|
||||
} else if (event.target.value.trim()) {
|
||||
const inputLast = this.find('input.last');
|
||||
|
||||
let items = this.getItems();
|
||||
|
||||
if (event.target === inputLast) {
|
||||
inputLast.value = '';
|
||||
} else if (event.target.nextSibling === inputLast) {
|
||||
inputLast.focus();
|
||||
} else {
|
||||
event.target.blur();
|
||||
|
||||
const idx = Array.from(this.findAll('input')).indexOf(
|
||||
event.target,
|
||||
);
|
||||
items.splice(idx + 1, 0, '');
|
||||
|
||||
Tracker.afterFlush(() => {
|
||||
const element = this.findAll('input')[idx + 1];
|
||||
element.focus();
|
||||
element.value = '';
|
||||
});
|
||||
}
|
||||
|
||||
this.stringtemplateItems.set(items);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
'blur .js-card-customfield-stringtemplate-item'(event) {
|
||||
if (
|
||||
!event.target.value.trim() ||
|
||||
event.target === this.find('input.last')
|
||||
) {
|
||||
const items = this.getItems();
|
||||
this.stringtemplateItems.set(items);
|
||||
this.find('input.last').value = '';
|
||||
}
|
||||
},
|
||||
|
||||
'click .js-close-inlined-form'(event) {
|
||||
this.stringtemplateItems.set(this.data().value ?? []);
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
}.register('cardCustomField-stringtemplate'));
|
||||
@@ -1,122 +1,4 @@
|
||||
// Helper function to replace HH with H for 24 hours format, because H allows also single-digit hours
|
||||
function adjustedTimeFormat() {
|
||||
return moment
|
||||
.localeData()
|
||||
.longDateFormat('LT')
|
||||
.replace(/HH/i, 'H');
|
||||
}
|
||||
|
||||
// Edit received, start, due & end dates
|
||||
BlazeComponent.extendComponent({
|
||||
template() {
|
||||
return 'editCardDate';
|
||||
},
|
||||
|
||||
onCreated() {
|
||||
this.error = new ReactiveVar('');
|
||||
this.card = this.data();
|
||||
this.date = new ReactiveVar(moment.invalid());
|
||||
},
|
||||
|
||||
onRendered() {
|
||||
const $picker = this.$('.js-datepicker')
|
||||
.datepicker({
|
||||
todayHighlight: true,
|
||||
todayBtn: 'linked',
|
||||
language: TAPi18n.getLanguage(),
|
||||
})
|
||||
.on(
|
||||
'changeDate',
|
||||
function(evt) {
|
||||
this.find('#date').value = moment(evt.date).format('L');
|
||||
this.error.set('');
|
||||
this.find('#time').focus();
|
||||
}.bind(this),
|
||||
);
|
||||
|
||||
if (this.date.get().isValid()) {
|
||||
$picker.datepicker('update', this.date.get().toDate());
|
||||
}
|
||||
},
|
||||
|
||||
showDate() {
|
||||
if (this.date.get().isValid()) return this.date.get().format('L');
|
||||
return '';
|
||||
},
|
||||
showTime() {
|
||||
if (this.date.get().isValid()) return this.date.get().format('LT');
|
||||
return '';
|
||||
},
|
||||
dateFormat() {
|
||||
return moment.localeData().longDateFormat('L');
|
||||
},
|
||||
timeFormat() {
|
||||
return moment.localeData().longDateFormat('LT');
|
||||
},
|
||||
|
||||
events() {
|
||||
return [
|
||||
{
|
||||
'keyup .js-date-field'() {
|
||||
// parse for localized date format in strict mode
|
||||
const dateMoment = moment(this.find('#date').value, 'L', true);
|
||||
if (dateMoment.isValid()) {
|
||||
this.error.set('');
|
||||
this.$('.js-datepicker').datepicker('update', dateMoment.toDate());
|
||||
}
|
||||
},
|
||||
'keyup .js-time-field'() {
|
||||
// parse for localized time format in strict mode
|
||||
const dateMoment = moment(
|
||||
this.find('#time').value,
|
||||
adjustedTimeFormat(),
|
||||
true,
|
||||
);
|
||||
if (dateMoment.isValid()) {
|
||||
this.error.set('');
|
||||
}
|
||||
},
|
||||
'submit .edit-date'(evt) {
|
||||
evt.preventDefault();
|
||||
|
||||
// if no time was given, init with 12:00
|
||||
const time =
|
||||
evt.target.time.value ||
|
||||
moment(new Date().setHours(12, 0, 0)).format('LT');
|
||||
const newTime = moment(time, adjustedTimeFormat(), true);
|
||||
const newDate = moment(evt.target.date.value, 'L', true);
|
||||
const dateString = `${evt.target.date.value} ${time}`;
|
||||
const newCompleteDate = moment(
|
||||
dateString,
|
||||
'L ' + adjustedTimeFormat(),
|
||||
true,
|
||||
);
|
||||
if (!newTime.isValid()) {
|
||||
this.error.set('invalid-time');
|
||||
evt.target.time.focus();
|
||||
}
|
||||
if (!newDate.isValid()) {
|
||||
this.error.set('invalid-date');
|
||||
evt.target.date.focus();
|
||||
}
|
||||
if (newCompleteDate.isValid()) {
|
||||
this._storeDate(newCompleteDate.toDate());
|
||||
Popup.close();
|
||||
} else {
|
||||
if (!this.error) {
|
||||
this.error.set('invalid');
|
||||
}
|
||||
}
|
||||
},
|
||||
'click .js-delete-date'(evt) {
|
||||
evt.preventDefault();
|
||||
this._deleteDate();
|
||||
Popup.close();
|
||||
},
|
||||
},
|
||||
];
|
||||
},
|
||||
});
|
||||
import { DatePicker } from '/client/lib/datepicker';
|
||||
|
||||
Template.dateBadge.helpers({
|
||||
canModifyCard() {
|
||||
@@ -305,7 +187,6 @@ class CardStartDate extends CardDate {
|
||||
// if dueAt or endAt exist & are > startAt, startAt doesn't need to be flagged
|
||||
if ((endAt && theDate.isAfter(endAt)) || (dueAt && theDate.isAfter(dueAt)))
|
||||
classes += 'long-overdue';
|
||||
else if (theDate.isBefore(now, 'minute')) classes += 'almost-due';
|
||||
else classes += 'current';
|
||||
return classes;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ const descriptionFormIsOpen = new ReactiveVar(false);
|
||||
BlazeComponent.extendComponent({
|
||||
onDestroyed() {
|
||||
descriptionFormIsOpen.set(false);
|
||||
$('.note-popover').hide();
|
||||
},
|
||||
|
||||
descriptionFormIsOpen() {
|
||||
|
||||
@@ -110,15 +110,24 @@ template(name="cardDetails")
|
||||
a.card-label.add-label.js-end-date
|
||||
i.fa.fa-plus
|
||||
|
||||
hr
|
||||
if currentBoard.allowsCreator
|
||||
.card-details-item.card-details-item-creator
|
||||
h3.card-details-item-title
|
||||
i.fa.fa-user
|
||||
| {{_ 'creator'}}
|
||||
|
||||
+userAvatar(userId=userId noRemove=true)
|
||||
| {{! XXX Hack to hide syntaxic coloration /// }}
|
||||
|
||||
//.card-details-items
|
||||
if currentBoard.allowsMembers
|
||||
hr
|
||||
.card-details-item.card-details-item-members
|
||||
h3.card-details-item-title
|
||||
i.fa.fa-users
|
||||
| {{_ 'members'}}
|
||||
each getMembers
|
||||
+userAvatar(userId=this cardId=../_id)
|
||||
each userId in getMembers
|
||||
+userAvatar(userId=userId cardId=_id)
|
||||
| {{! XXX Hack to hide syntaxic coloration /// }}
|
||||
if canModifyCard
|
||||
unless currentUser.isWorker
|
||||
@@ -131,8 +140,8 @@ template(name="cardDetails")
|
||||
h3.card-details-item-title
|
||||
i.fa.fa-user
|
||||
| {{_ 'assignee'}}
|
||||
each getAssignees
|
||||
+userAvatarAssignee(userId=this cardId=../_id)
|
||||
each userId in getAssignees
|
||||
+userAvatar(userId=userId cardId=_id assignee=true)
|
||||
| {{! XXX Hack to hide syntaxic coloration /// }}
|
||||
if canModifyCard
|
||||
a.assignee.add-assignee.card-details-item-add-button.js-add-assignees(title="{{_ 'assignee'}}")
|
||||
@@ -488,23 +497,6 @@ template(name="cardAssigneesPopup")
|
||||
if currentUser.isCardAssignee
|
||||
i.fa.fa-check
|
||||
|
||||
template(name="userAvatarAssignee")
|
||||
a.assignee.js-assignee(title="{{userData.profile.fullname}} ({{userData.username}})")
|
||||
if userData.profile.avatarUrl
|
||||
img.avatar.avatar-image(src="{{userData.profile.avatarUrl}}")
|
||||
else
|
||||
+userAvatarAssigneeInitials(userId=userData._id)
|
||||
|
||||
if showStatus
|
||||
span.assignee-presence-status(class=presenceStatusClassName)
|
||||
span.member-type(class=memberType)
|
||||
|
||||
unless isSandstorm
|
||||
if showEdit
|
||||
if $eq currentUser._id userData._id
|
||||
a.edit-avatar.js-change-avatar
|
||||
i.fa.fa-pencil
|
||||
|
||||
template(name="cardAssigneePopup")
|
||||
.board-assignee-menu
|
||||
.mini-profile-info
|
||||
@@ -522,10 +514,6 @@ template(name="cardAssigneePopup")
|
||||
with currentUser
|
||||
li: a.js-edit-profile {{_ 'edit-profile'}}
|
||||
|
||||
template(name="userAvatarAssigneeInitials")
|
||||
svg.avatar.avatar-assignee-initials(viewBox="0 0 {{viewPortWidth}} 15")
|
||||
text(x="50%" y="13" text-anchor="middle")= initials
|
||||
|
||||
template(name="cardMorePopup")
|
||||
p.quiet
|
||||
span.clearfix
|
||||
|
||||
@@ -1,11 +1,18 @@
|
||||
import { DatePicker } from '/client/lib/datepicker';
|
||||
import Cards from '/models/cards';
|
||||
import Boards from '/models/boards';
|
||||
import Checklists from '/models/checklists';
|
||||
import Integrations from '/models/integrations';
|
||||
import Users from '/models/users';
|
||||
import Lists from '/models/lists';
|
||||
import CardComments from '/models/cardComments';
|
||||
import { ALLOWED_COLORS } from '/config/const';
|
||||
import moment from 'moment';
|
||||
import { UserAvatar } from '../users/userAvatar';
|
||||
|
||||
const subManager = new SubsManager();
|
||||
const { calculateIndexData } = Utils;
|
||||
|
||||
let cardColors;
|
||||
Meteor.startup(() => {
|
||||
cardColors = Cards.simpleSchema()._schema.color.allowedValues;
|
||||
});
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
mixins() {
|
||||
return [Mixins.InfiniteScrolling];
|
||||
@@ -160,9 +167,7 @@ BlazeComponent.extendComponent({
|
||||
integration,
|
||||
'CardSelected',
|
||||
params,
|
||||
() => {
|
||||
return;
|
||||
},
|
||||
() => {},
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -290,7 +295,7 @@ BlazeComponent.extendComponent({
|
||||
Utils.goBoardId(this.data().boardId);
|
||||
},
|
||||
'click .js-copy-link'() {
|
||||
StringToCopyElement = document.getElementById('cardURL_copy');
|
||||
const StringToCopyElement = document.getElementById('cardURL_copy');
|
||||
StringToCopyElement.value =
|
||||
window.location.origin + window.location.pathname;
|
||||
StringToCopyElement.select();
|
||||
@@ -407,122 +412,6 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
}).register('cardDetails');
|
||||
|
||||
Template.cardDetails.helpers({
|
||||
userData() {
|
||||
// We need to handle a special case for the search results provided by the
|
||||
// `matteodem:easy-search` package. Since these results gets published in a
|
||||
// separate collection, and not in the standard Meteor.Users collection as
|
||||
// expected, we use a component parameter ("property") to distinguish the
|
||||
// two cases.
|
||||
const userCollection = this.esSearch ? ESSearchResults : Users;
|
||||
return userCollection.findOne(this.userId, {
|
||||
fields: {
|
||||
profile: 1,
|
||||
username: 1,
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
receivedSelected() {
|
||||
if (this.getReceived().length === 0) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
startSelected() {
|
||||
if (this.getStart().length === 0) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
endSelected() {
|
||||
if (this.getEnd().length === 0) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
dueSelected() {
|
||||
if (this.getDue().length === 0) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
memberSelected() {
|
||||
if (this.getMembers().length === 0) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
labelSelected() {
|
||||
if (this.getLabels().length === 0) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
assigneeSelected() {
|
||||
if (this.getAssignees().length === 0) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
requestBySelected() {
|
||||
if (this.getRequestBy().length === 0) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
assigneeBySelected() {
|
||||
if (this.getAssigneeBy().length === 0) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
memberType() {
|
||||
const user = Users.findOne(this.userId);
|
||||
return user && user.isBoardAdmin() ? 'admin' : 'normal';
|
||||
},
|
||||
|
||||
presenceStatusClassName() {
|
||||
const user = Users.findOne(this.userId);
|
||||
const userPresence = presences.findOne({ userId: this.userId });
|
||||
if (user && user.isInvitedTo(Session.get('currentBoard'))) return 'pending';
|
||||
else if (!userPresence) return 'disconnected';
|
||||
else if (Session.equals('currentBoard', userPresence.state.currentBoardId))
|
||||
return 'active';
|
||||
else return 'idle';
|
||||
},
|
||||
});
|
||||
|
||||
Template.userAvatarAssigneeInitials.helpers({
|
||||
initials() {
|
||||
const user = Users.findOne(this.userId);
|
||||
return user && user.getInitials();
|
||||
},
|
||||
|
||||
viewPortWidth() {
|
||||
const user = Users.findOne(this.userId);
|
||||
return ((user && user.getInitials().length) || 1) * 12;
|
||||
},
|
||||
});
|
||||
|
||||
// We extends the normal InlinedForm component to support UnsavedEdits draft
|
||||
// feature.
|
||||
(class extends InlinedForm {
|
||||
@@ -697,7 +586,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
boards() {
|
||||
const boards = Boards.find(
|
||||
return Boards.find(
|
||||
{
|
||||
archived: false,
|
||||
'members.userId': Meteor.userId(),
|
||||
@@ -707,7 +596,6 @@ BlazeComponent.extendComponent({
|
||||
sort: { sort: 1 /* boards default sorting */ },
|
||||
},
|
||||
);
|
||||
return boards;
|
||||
},
|
||||
|
||||
swimlanes() {
|
||||
@@ -736,7 +624,7 @@ Template.copyCardPopup.events({
|
||||
'click .js-done'() {
|
||||
const card = Cards.findOne(Session.get('currentCard'));
|
||||
const lSelect = $('.js-select-lists')[0];
|
||||
listId = lSelect.options[lSelect.selectedIndex].value;
|
||||
const listId = lSelect.options[lSelect.selectedIndex].value;
|
||||
const slSelect = $('.js-select-swimlanes')[0];
|
||||
const swimlaneId = slSelect.options[slSelect.selectedIndex].value;
|
||||
const bSelect = $('.js-select-boards')[0];
|
||||
@@ -801,7 +689,7 @@ Template.copyChecklistToManyCardsPopup.events({
|
||||
});
|
||||
|
||||
// copy subtasks
|
||||
cursor = Cards.find({ parentId: oldId });
|
||||
const cursor = Cards.find({ parentId: oldId });
|
||||
cursor.forEach(function() {
|
||||
'use strict';
|
||||
const subtask = arguments[0];
|
||||
@@ -827,7 +715,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
colors() {
|
||||
return cardColors.map(color => ({ color, name: '' }));
|
||||
return ALLOWED_COLORS.map(color => ({ color, name: '' }));
|
||||
},
|
||||
|
||||
isSelected(color) {
|
||||
@@ -871,7 +759,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
boards() {
|
||||
const boards = Boards.find(
|
||||
return Boards.find(
|
||||
{
|
||||
archived: false,
|
||||
'members.userId': Meteor.userId(),
|
||||
@@ -883,7 +771,6 @@ BlazeComponent.extendComponent({
|
||||
sort: { sort: 1 /* boards default sorting */ },
|
||||
},
|
||||
);
|
||||
return boards;
|
||||
},
|
||||
|
||||
cards() {
|
||||
|
||||
@@ -211,6 +211,7 @@ avatar-radius = 50%
|
||||
word-wrap: break-word
|
||||
max-width: 36%
|
||||
flex-grow: 1
|
||||
&.card-details-item-creator,
|
||||
&.card-details-item-received,
|
||||
&.card-details-item-start,
|
||||
&.card-details-item-due,
|
||||
|
||||
@@ -82,6 +82,9 @@ template(name="minicard")
|
||||
+minicardCustomFieldDate
|
||||
else if $eq definition.type "checkbox"
|
||||
.materialCheckBox(class="{{#if value }}is-checked{{/if}}")
|
||||
else if $eq definition.type "stringtemplate"
|
||||
+viewer
|
||||
= formattedStringtemplateCustomFieldValue(definition)
|
||||
else
|
||||
+viewer
|
||||
= trueValue
|
||||
@@ -96,6 +99,10 @@ template(name="minicard")
|
||||
each getMembers
|
||||
+userAvatar(userId=this)
|
||||
|
||||
if showCreator
|
||||
.minicard-creator
|
||||
+userAvatar(userId=this.userId noRemove=true)
|
||||
|
||||
.badges
|
||||
unless currentUser.isNoComments
|
||||
if comments.count
|
||||
|
||||
@@ -21,6 +21,34 @@ BlazeComponent.extendComponent({
|
||||
}).format(customFieldTrueValue);
|
||||
},
|
||||
|
||||
formattedStringtemplateCustomFieldValue(definition) {
|
||||
const customField = this.data()
|
||||
.customFieldsWD()
|
||||
.find(f => f._id === definition._id);
|
||||
|
||||
const customFieldTrueValue =
|
||||
customField && customField.trueValue ? customField.trueValue : [];
|
||||
|
||||
return customFieldTrueValue
|
||||
.filter(value => !!value.trim())
|
||||
.map(value =>
|
||||
definition.settings.stringtemplateFormat.replace(/%\{value\}/gi, value),
|
||||
)
|
||||
.join(definition.settings.stringtemplateSeparator ?? '');
|
||||
},
|
||||
|
||||
showCreator() {
|
||||
if (this.data().board()) {
|
||||
return (
|
||||
this.data().board.allowsCreator === null ||
|
||||
this.data().board().allowsCreator === undefined ||
|
||||
this.data().board().allowsCreator
|
||||
);
|
||||
// return this.data().board().allowsCreator;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
events() {
|
||||
return [
|
||||
{
|
||||
|
||||
@@ -89,7 +89,7 @@
|
||||
border-radius: 2px
|
||||
margin-right: 3px
|
||||
margin-bottom: 3px
|
||||
|
||||
|
||||
.minicard-custom-fields
|
||||
display:block;
|
||||
.minicard-custom-field
|
||||
@@ -163,7 +163,8 @@
|
||||
line-height: 12px
|
||||
|
||||
.minicard-members,
|
||||
.minicard-assignees
|
||||
.minicard-assignees,
|
||||
.minicard-creator
|
||||
float: right
|
||||
margin-left: 5px
|
||||
margin-bottom: 4px
|
||||
@@ -187,6 +188,9 @@
|
||||
.minicard-assignees
|
||||
border-bottom: 1px solid red
|
||||
|
||||
.minicard-creator
|
||||
border-bottom: 1px solid green
|
||||
|
||||
.minicard-members:empty,
|
||||
.minicard-assignees:empty
|
||||
display: none
|
||||
|
||||
@@ -3,7 +3,7 @@ import {
|
||||
OPERATOR_HAS,
|
||||
OPERATOR_SORT,
|
||||
OPERATOR_USER,
|
||||
ORDER_DESCENDING,
|
||||
ORDER_ASCENDING,
|
||||
PREDICATE_DUE_AT,
|
||||
} from '../../../config/search-const';
|
||||
import { QueryParams } from '../../../config/query-classes';
|
||||
@@ -62,14 +62,14 @@ class DueCardsComponent extends CardSearchPagedComponent {
|
||||
// queryParams[OPERATOR_LIMIT] = 5;
|
||||
queryParams.addPredicate(OPERATOR_SORT, {
|
||||
name: PREDICATE_DUE_AT,
|
||||
order: ORDER_DESCENDING,
|
||||
order: ORDER_ASCENDING,
|
||||
});
|
||||
|
||||
if (Utils.dueCardsView() !== 'all') {
|
||||
queryParams.addPredicate(OPERATOR_USER, Meteor.user().username);
|
||||
}
|
||||
|
||||
this.runGlobalSearch(queryParams.getQueryParams());
|
||||
this.runGlobalSearch(queryParams);
|
||||
}
|
||||
|
||||
dueCardsView() {
|
||||
|
||||
@@ -49,7 +49,7 @@ Template.editor.onRendered(() => {
|
||||
['para', ['ul', 'ol', 'paragraph']],
|
||||
['table', ['table']],
|
||||
//['insert', ['link', 'picture', 'video']], // iframe tag will be sanitized TODO if iframe[class=note-video-clip] can be added into safe list, insert video can be enabled
|
||||
//['insert', ['link', 'picture']], // modal popup has issue somehow :(
|
||||
['insert', ['link']], //, 'picture']], // modal popup has issue somehow :(
|
||||
['view', ['fullscreen', 'help']],
|
||||
];
|
||||
const cleanPastedHTML = function(input) {
|
||||
@@ -234,6 +234,8 @@ Template.editor.onRendered(() => {
|
||||
},
|
||||
},
|
||||
dialogsInBody: true,
|
||||
spellCheck: true,
|
||||
disableGrammar: false,
|
||||
disableDragAndDrop: true,
|
||||
toolbar,
|
||||
popover: {
|
||||
@@ -245,6 +247,7 @@ Template.editor.onRendered(() => {
|
||||
['float', ['floatLeft', 'floatRight', 'floatNone']],
|
||||
['remove', ['removeMedia']],
|
||||
],
|
||||
link: [['link', ['linkDialogShow', 'unlink']]],
|
||||
table: [
|
||||
['add', ['addRowDown', 'addRowUp', 'addColLeft', 'addColRight']],
|
||||
['delete', ['deleteRow', 'deleteCol', 'deleteTable']],
|
||||
|
||||
@@ -11,9 +11,10 @@ template(name="globalSearchModalTitle")
|
||||
| {{_ 'globalSearch-title'}}
|
||||
|
||||
template(name="resultsPaged")
|
||||
h1
|
||||
= resultsHeading.get
|
||||
a.fa.fa-link(title="{{_ 'link-to-search' }}" href="{{ getSearchHref }}")
|
||||
if resultsHeading.get
|
||||
h1
|
||||
= resultsHeading.get
|
||||
a.fa.fa-link(title="{{_ 'link-to-search' }}" href="{{ getSearchHref }}")
|
||||
each card in results.get
|
||||
+resultCard(card)
|
||||
table.global-search-footer
|
||||
@@ -50,8 +51,7 @@ template(name="globalSearch")
|
||||
each msg in errorMessages
|
||||
li.global-search-error-messages
|
||||
= msg
|
||||
else
|
||||
+resultsPaged(this)
|
||||
+resultsPaged(this)
|
||||
else if serverError.get
|
||||
.global-search-page
|
||||
.global-search-help
|
||||
|
||||
@@ -123,6 +123,7 @@ class GlobalSearchComponent extends CardSearchPagedComponent {
|
||||
operator_member_abbrev: TAPi18n.__('operator-member-abbrev'),
|
||||
operator_assignee: TAPi18n.__('operator-assignee'),
|
||||
operator_assignee_abbrev: TAPi18n.__('operator-assignee-abbrev'),
|
||||
operator_creator: TAPi18n.__('operator-creator'),
|
||||
operator_due: TAPi18n.__('operator-due'),
|
||||
operator_created: TAPi18n.__('operator-created'),
|
||||
operator_modified: TAPi18n.__('operator-modified'),
|
||||
@@ -167,6 +168,7 @@ class GlobalSearchComponent extends CardSearchPagedComponent {
|
||||
['\n* ', 'globalSearch-instructions-operator-at'],
|
||||
['\n* ', 'globalSearch-instructions-operator-member'],
|
||||
['\n* ', 'globalSearch-instructions-operator-assignee'],
|
||||
['\n* ', 'globalSearch-instructions-operator-creator'],
|
||||
['\n* ', 'globalSearch-instructions-operator-due'],
|
||||
['\n* ', 'globalSearch-instructions-operator-created'],
|
||||
['\n* ', 'globalSearch-instructions-operator-modified'],
|
||||
@@ -202,9 +204,8 @@ class GlobalSearchComponent extends CardSearchPagedComponent {
|
||||
}
|
||||
|
||||
events() {
|
||||
return [
|
||||
return super.events().concat([
|
||||
{
|
||||
...super.events()[0],
|
||||
'submit .js-search-query-form'(evt) {
|
||||
evt.preventDefault();
|
||||
this.searchAllBoards(evt.target.searchQuery.value);
|
||||
@@ -257,7 +258,7 @@ class GlobalSearchComponent extends CardSearchPagedComponent {
|
||||
this.hasResults.set(false);
|
||||
},
|
||||
},
|
||||
];
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -77,6 +77,8 @@ Template.userFormsLayout.helpers({
|
||||
} else if (lang.name === 'ar-EG') {
|
||||
// ar-EG = Arabic (Egypt), simply Masri (مَصرى, [ˈmɑsˤɾi], Egyptian, Masr refers to Cairo)
|
||||
name = 'مَصرى';
|
||||
} else if (lang.name === 'de-CH') {
|
||||
name = 'Schwiizerdütsch';
|
||||
} else if (lang.name === 'fa-IR') {
|
||||
// fa-IR = Persian (Iran)
|
||||
name = 'فارسی/پارسی (ایران)';
|
||||
|
||||
@@ -6,16 +6,6 @@ template(name="myCardsHeaderBar")
|
||||
i.fa.fa-list
|
||||
| {{_ 'my-cards'}}
|
||||
|
||||
.board-header-btns.left
|
||||
a.board-header-btn.js-toggle-my-cards-choose-sort(title="{{_ 'myCardsSortChange-title'}}")
|
||||
i.fa.fa-caret-down
|
||||
if $eq myCardsSort 'board'
|
||||
i.fa.fa-th-large
|
||||
| {{_ 'myCardsSortChange-choice-board'}}
|
||||
if $eq myCardsSort 'dueAt'
|
||||
i.fa.fa-calendar
|
||||
| {{_ 'myCardsSortChange-choice-dueat'}}
|
||||
|
||||
template(name="myCardsModalTitle")
|
||||
if currentUser
|
||||
h2
|
||||
@@ -28,46 +18,22 @@ template(name="myCards")
|
||||
+spinner
|
||||
else
|
||||
.wrapper
|
||||
if $eq myCardsSort 'board'
|
||||
each board in myCardsList
|
||||
.my-cards-board-wrapper
|
||||
.my-cards-board-title(class=board.colorClass, id="header")
|
||||
a(href=board.originRelativeUrl)
|
||||
+viewer
|
||||
= board.title
|
||||
each swimlane in board.mySwimlanes
|
||||
.my-cards-swimlane-title(class="{{#if swimlane.colorClass}}{{ swimlane.colorClass }}{{else}}swimlane-default-color{{/if}}")
|
||||
+viewer
|
||||
= swimlane.title
|
||||
each list in swimlane.myLists
|
||||
.my-cards-list-wrapper
|
||||
.my-cards-list-title(class=list.colorClass)
|
||||
+viewer
|
||||
= list.title
|
||||
each card in list.myCards
|
||||
.my-cards-card-wrapper
|
||||
a.minicard-wrapper(href=card.originRelativeUrl)
|
||||
+minicard(card)
|
||||
else
|
||||
.my-cards-dueat-list-wrapper
|
||||
each card in myDueCardsList
|
||||
+resultCard(card)
|
||||
|
||||
template(name="myCardsSortChangePopup")
|
||||
if currentUser
|
||||
ul.pop-over-list
|
||||
li
|
||||
with "my-cards-sort-board"
|
||||
a.js-my-cards-sort-board
|
||||
i.fa.fa-th-large.colorful
|
||||
| {{_ 'myCardsSortChange-choice-board'}}
|
||||
if $eq Utils.myCardsSort "board"
|
||||
i.fa.fa-check
|
||||
hr
|
||||
li
|
||||
with "my-cards-sort-dueat"
|
||||
a.js-my-cards-sort-dueat
|
||||
i.fa.fa-calendar.colorful
|
||||
| {{_ 'myCardsSortChange-choice-dueat'}}
|
||||
if $eq Utils.myCardsSort "dueAt"
|
||||
i.fa.fa-check
|
||||
each board in myCardsList
|
||||
.my-cards-board-wrapper
|
||||
.my-cards-board-title(class=board.colorClass, id="header")
|
||||
a(href=board.originRelativeUrl)
|
||||
+viewer
|
||||
= board.title
|
||||
each swimlane in board.mySwimlanes
|
||||
.my-cards-swimlane-title(class="{{#if swimlane.colorClass}}{{ swimlane.colorClass }}{{else}}swimlane-default-color{{/if}}")
|
||||
+viewer
|
||||
= swimlane.title
|
||||
each list in swimlane.myLists
|
||||
.my-cards-list-wrapper
|
||||
.my-cards-list-title(class=list.colorClass)
|
||||
+viewer
|
||||
= list.title
|
||||
each card in list.myCards
|
||||
.my-cards-card-wrapper
|
||||
a.minicard-wrapper(href=card.originRelativeUrl)
|
||||
+minicard(card)
|
||||
@@ -1,14 +1,4 @@
|
||||
import { CardSearchPagedComponent } from '../../lib/cardSearch';
|
||||
import { QueryParams } from '../../../config/query-classes';
|
||||
import {
|
||||
OPERATOR_LIMIT,
|
||||
OPERATOR_SORT,
|
||||
OPERATOR_USER,
|
||||
ORDER_DESCENDING,
|
||||
PREDICATE_DUE_AT,
|
||||
} from '../../../config/search-const';
|
||||
|
||||
// const subManager = new SubsManager();
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
myCardsSort() {
|
||||
@@ -34,48 +24,21 @@ Template.myCards.helpers({
|
||||
},
|
||||
});
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
events() {
|
||||
return [
|
||||
{
|
||||
'click .js-my-cards-sort-board'() {
|
||||
Utils.setMyCardsSort('board');
|
||||
Popup.close();
|
||||
},
|
||||
|
||||
'click .js-my-cards-sort-dueat'() {
|
||||
Utils.setMyCardsSort('dueAt');
|
||||
Popup.close();
|
||||
},
|
||||
},
|
||||
];
|
||||
},
|
||||
}).register('myCardsSortChangePopup');
|
||||
|
||||
class MyCardsComponent extends CardSearchPagedComponent {
|
||||
onCreated() {
|
||||
super.onCreated();
|
||||
|
||||
const queryParams = new QueryParams();
|
||||
queryParams.addPredicate(OPERATOR_USER, Meteor.user().username);
|
||||
queryParams.addPredicate(OPERATOR_SORT, {
|
||||
name: PREDICATE_DUE_AT,
|
||||
order: ORDER_DESCENDING,
|
||||
});
|
||||
queryParams.addPredicate(OPERATOR_LIMIT, 100);
|
||||
|
||||
this.runGlobalSearch(queryParams);
|
||||
this.runGlobalSearch(null);
|
||||
Meteor.subscribe('setting');
|
||||
}
|
||||
|
||||
myCardsSort() {
|
||||
// eslint-disable-next-line no-console
|
||||
//console.log('sort:', Utils.myCardsSort());
|
||||
return Utils.myCardsSort();
|
||||
}
|
||||
|
||||
sortByBoard() {
|
||||
return this.myCardsSort() === 'board';
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
getSubscription(queryParams) {
|
||||
return Meteor.subscribe(
|
||||
'myCards',
|
||||
this.sessionId,
|
||||
this.subscriptionCallbacks,
|
||||
);
|
||||
}
|
||||
|
||||
myCardsList() {
|
||||
@@ -87,35 +50,9 @@ class MyCardsComponent extends CardSearchPagedComponent {
|
||||
const cursor = this.getResults();
|
||||
|
||||
if (cursor) {
|
||||
let newBoard = false;
|
||||
let newSwimlane = false;
|
||||
let newList = false;
|
||||
|
||||
cursor.forEach(card => {
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('card:', card.title);
|
||||
if (list === null || card.listId !== list._id) {
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('new list');
|
||||
list = card.getList();
|
||||
if (list.archived) {
|
||||
list = null;
|
||||
return;
|
||||
}
|
||||
list.myCards = [card];
|
||||
newList = true;
|
||||
}
|
||||
if (swimlane === null || card.swimlaneId !== swimlane._id) {
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('new swimlane');
|
||||
swimlane = card.getSwimlane();
|
||||
if (swimlane.archived) {
|
||||
swimlane = null;
|
||||
return;
|
||||
}
|
||||
swimlane.myLists = [list];
|
||||
newSwimlane = true;
|
||||
}
|
||||
if (board === null || card.boardId !== board._id) {
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('new board');
|
||||
@@ -126,23 +63,38 @@ class MyCardsComponent extends CardSearchPagedComponent {
|
||||
}
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('board:', b, b._id, b.title);
|
||||
board.mySwimlanes = [swimlane];
|
||||
newBoard = true;
|
||||
}
|
||||
|
||||
if (newBoard) {
|
||||
boards.push(board);
|
||||
} else if (newSwimlane) {
|
||||
board.mySwimlanes.push(swimlane);
|
||||
} else if (newList) {
|
||||
swimlane.myLists.push(list);
|
||||
} else {
|
||||
list.myCards.push(card);
|
||||
board.mySwimlanes = [];
|
||||
swimlane = null;
|
||||
list = null;
|
||||
}
|
||||
|
||||
newBoard = false;
|
||||
newSwimlane = false;
|
||||
newList = false;
|
||||
if (swimlane === null || card.swimlaneId !== swimlane._id) {
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('new swimlane');
|
||||
swimlane = card.getSwimlane();
|
||||
if (swimlane.archived) {
|
||||
swimlane = null;
|
||||
return;
|
||||
}
|
||||
board.mySwimlanes.push(swimlane);
|
||||
swimlane.myLists = [];
|
||||
list = null;
|
||||
}
|
||||
|
||||
if (list === null || card.listId !== list._id) {
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('new list');
|
||||
list = card.getList();
|
||||
if (list.archived) {
|
||||
list = null;
|
||||
return;
|
||||
}
|
||||
swimlane.myLists.push(list);
|
||||
list.myCards = [];
|
||||
}
|
||||
|
||||
list.myCards.push(card);
|
||||
});
|
||||
|
||||
// sort the data structure
|
||||
@@ -182,27 +134,5 @@ class MyCardsComponent extends CardSearchPagedComponent {
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
myDueCardsList() {
|
||||
const cursor = this.getResults();
|
||||
const cards = [];
|
||||
cursor.forEach(card => {
|
||||
cards.push(card);
|
||||
});
|
||||
|
||||
cards.sort((a, b) => {
|
||||
const x = a.dueAt === null ? new Date('2100-12-31') : a.dueAt;
|
||||
const y = b.dueAt === null ? new Date('2100-12-31') : b.dueAt;
|
||||
|
||||
if (x > y) return 1;
|
||||
else if (x < y) return -1;
|
||||
|
||||
return 0;
|
||||
});
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('cursor:', cards);
|
||||
return cards;
|
||||
}
|
||||
}
|
||||
MyCardsComponent.register('myCards');
|
||||
@@ -0,0 +1,111 @@
|
||||
template(name="adminReports")
|
||||
.setting-content
|
||||
unless currentUser.isAdmin
|
||||
| {{_ 'error-notAuthorized'}}
|
||||
else
|
||||
.content-body
|
||||
.side-menu
|
||||
ul
|
||||
li
|
||||
a.js-report-broken(data-id="report-broken")
|
||||
i.fa.fa-chain-broken
|
||||
| {{_ 'broken-cards'}}
|
||||
|
||||
li
|
||||
a.js-report-files(data-id="report-orphaned-files")
|
||||
i.fa.fa-paperclip
|
||||
| {{_ 'orphanedFilesReportTitle'}}
|
||||
|
||||
li
|
||||
a.js-report-files(data-id="report-files")
|
||||
i.fa.fa-paperclip
|
||||
| {{_ 'filesReportTitle'}}
|
||||
|
||||
li
|
||||
a.js-report-rules(data-id="report-rules")
|
||||
i.fa.fa-magic
|
||||
| {{_ 'rulesReportTitle'}}
|
||||
|
||||
.main-body
|
||||
if loading.get
|
||||
+spinner
|
||||
else if showBrokenCardsReport.get
|
||||
+brokenCardsReport
|
||||
else if showFilesReport.get
|
||||
+filesReport
|
||||
else if showOrphanedFilesReport.get
|
||||
+orphanedFilesReport
|
||||
else if showRulesReport.get
|
||||
+rulesReport
|
||||
|
||||
|
||||
template(name="brokenCardsReport")
|
||||
.global-search-results-list-wrapper
|
||||
h1 {{_ 'broken-cards'}}
|
||||
if resultsCount
|
||||
+resultsPaged(this)
|
||||
else
|
||||
div {{_ 'no-results' }}
|
||||
|
||||
template(name="rulesReport")
|
||||
h1 {{_ 'rulesReportTitle'}}
|
||||
if resultsCount
|
||||
table.table
|
||||
tr
|
||||
th Rule Title
|
||||
th Board Title
|
||||
th actionType
|
||||
th activityType
|
||||
|
||||
each rule in rows
|
||||
tr
|
||||
td {{ rule.title }}
|
||||
td {{ rule.boardTitle }}
|
||||
td {{ rule.action.actionType }}
|
||||
td {{ rule.trigger.activityType }}
|
||||
else
|
||||
div {{_ 'no-results' }}
|
||||
|
||||
template(name="filesReport")
|
||||
h1 {{_ 'filesReportTitle'}}
|
||||
if resultsCount
|
||||
table.table
|
||||
tr
|
||||
th Filename
|
||||
th.right Size (kB)
|
||||
th MIME Type
|
||||
th.center Usage
|
||||
th MD5 Sum
|
||||
th ID
|
||||
|
||||
each att in attachmentFiles
|
||||
tr
|
||||
td {{ att.filename }}
|
||||
td.right {{fileSize att.length }}
|
||||
td {{ att.contentType }}
|
||||
td.center {{usageCount att._id.toHexString }}
|
||||
td {{ att.md5 }}
|
||||
td {{ att._id.toHexString }}
|
||||
else
|
||||
div {{_ 'no-results' }}
|
||||
|
||||
template(name="orphanedFilesReport")
|
||||
h1 {{_ 'orphanedFilesReportTitle'}}
|
||||
if resultsCount
|
||||
table.table
|
||||
tr
|
||||
th Filename
|
||||
th.right Size (kB)
|
||||
th MIME Type
|
||||
th MD5 Sum
|
||||
th ID
|
||||
|
||||
each att in attachmentFiles
|
||||
tr
|
||||
td {{ att.filename }}
|
||||
td.right {{fileSize att.length }}
|
||||
td {{ att.contentType }}
|
||||
td {{ att.md5 }}
|
||||
td {{ att._id.toHexString }}
|
||||
else
|
||||
div {{_ 'no-results' }}
|
||||
@@ -0,0 +1,156 @@
|
||||
import { AttachmentStorage } from '/models/attachments';
|
||||
import { CardSearchPagedComponent } from '/client/lib/cardSearch';
|
||||
import SessionData from '/models/usersessiondata';
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
subscription: null,
|
||||
showFilesReport: new ReactiveVar(false),
|
||||
showBrokenCardsReport: new ReactiveVar(false),
|
||||
showOrphanedFilesReport: new ReactiveVar(false),
|
||||
showRulesReport: new ReactiveVar(false),
|
||||
|
||||
onCreated() {
|
||||
this.error = new ReactiveVar('');
|
||||
this.loading = new ReactiveVar(false);
|
||||
},
|
||||
|
||||
events() {
|
||||
return [
|
||||
{
|
||||
'click a.js-report-broken': this.switchMenu,
|
||||
'click a.js-report-files': this.switchMenu,
|
||||
'click a.js-report-orphaned-files': this.switchMenu,
|
||||
'click a.js-report-rules': this.switchMenu,
|
||||
},
|
||||
];
|
||||
},
|
||||
|
||||
switchMenu(event) {
|
||||
const target = $(event.target);
|
||||
if (!target.hasClass('active')) {
|
||||
this.loading.set(true);
|
||||
this.showFilesReport.set(false);
|
||||
this.showBrokenCardsReport.set(false);
|
||||
this.showOrphanedFilesReport.set(false);
|
||||
if (this.subscription) {
|
||||
this.subscription.stop();
|
||||
}
|
||||
|
||||
$('.side-menu li.active').removeClass('active');
|
||||
target.parent().addClass('active');
|
||||
const targetID = target.data('id');
|
||||
|
||||
if ('report-broken' === targetID) {
|
||||
this.showBrokenCardsReport.set(true);
|
||||
this.subscription = Meteor.subscribe(
|
||||
'brokenCards',
|
||||
SessionData.getSessionId(),
|
||||
() => {
|
||||
this.loading.set(false);
|
||||
},
|
||||
);
|
||||
} else if ('report-files' === targetID) {
|
||||
this.showFilesReport.set(true);
|
||||
this.subscription = Meteor.subscribe('attachmentsList', () => {
|
||||
this.loading.set(false);
|
||||
});
|
||||
} else if ('report-orphaned-files' === targetID) {
|
||||
this.showOrphanedFilesReport.set(true);
|
||||
this.subscription = Meteor.subscribe('orphanedAttachments', () => {
|
||||
this.loading.set(false);
|
||||
});
|
||||
} else if ('report-rules' === targetID) {
|
||||
this.subscription = Meteor.subscribe('rulesReport', () => {
|
||||
this.showRulesReport.set(true);
|
||||
this.loading.set(false);
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
}).register('adminReports');
|
||||
|
||||
Template.filesReport.helpers({
|
||||
attachmentFiles() {
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('attachments:', AttachmentStorage.find());
|
||||
// console.log('attachments.count:', AttachmentStorage.find().count());
|
||||
return AttachmentStorage.find();
|
||||
},
|
||||
|
||||
rulesReport() {
|
||||
const rules = [];
|
||||
|
||||
Rules.find().forEach(rule => {
|
||||
rules.push({
|
||||
_id: rule._id,
|
||||
title: rule.title,
|
||||
boardId: rule.boardId,
|
||||
boardTitle: rule.board().title,
|
||||
action: rule.action().fetch(),
|
||||
trigger: rule.trigger().fetch(),
|
||||
});
|
||||
});
|
||||
|
||||
return rules;
|
||||
},
|
||||
|
||||
resultsCount() {
|
||||
return AttachmentStorage.find().count();
|
||||
},
|
||||
|
||||
fileSize(size) {
|
||||
return Math.round(size / 1024);
|
||||
},
|
||||
|
||||
usageCount(key) {
|
||||
return Attachments.find({ 'copies.attachments.key': key }).count();
|
||||
},
|
||||
});
|
||||
|
||||
Template.orphanedFilesReport.helpers({
|
||||
attachmentFiles() {
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('attachments:', AttachmentStorage.find());
|
||||
// console.log('attachments.count:', AttachmentStorage.find().count());
|
||||
return AttachmentStorage.find();
|
||||
},
|
||||
|
||||
resultsCount() {
|
||||
return AttachmentStorage.find().count();
|
||||
},
|
||||
|
||||
fileSize(size) {
|
||||
return Math.round(size / 1024);
|
||||
},
|
||||
});
|
||||
|
||||
Template.rulesReport.helpers({
|
||||
rows() {
|
||||
const rules = [];
|
||||
|
||||
Rules.find().forEach(rule => {
|
||||
rules.push({
|
||||
_id: rule._id,
|
||||
title: rule.title,
|
||||
boardId: rule.boardId,
|
||||
boardTitle: rule.board().title,
|
||||
action: rule.action(),
|
||||
trigger: rule.trigger(),
|
||||
});
|
||||
});
|
||||
|
||||
console.log('rows:', rules);
|
||||
return rules;
|
||||
},
|
||||
|
||||
resultsCount() {
|
||||
return Rules.find().count();
|
||||
},
|
||||
});
|
||||
|
||||
class BrokenCardsComponent extends CardSearchPagedComponent {
|
||||
onCreated() {
|
||||
super.onCreated();
|
||||
}
|
||||
}
|
||||
BrokenCardsComponent.register('brokenCardsReport');
|
||||
@@ -12,6 +12,10 @@ template(name="settingHeaderBar")
|
||||
i.fa(class="fa-users")
|
||||
span {{_ 'people'}}
|
||||
|
||||
a.setting-header-btn.informations(href="{{pathFor 'admin-reports'}}")
|
||||
i.fa(class="fa-list")
|
||||
span {{_ 'reports'}}
|
||||
|
||||
a.setting-header-btn.informations(href="{{pathFor 'information'}}")
|
||||
i.fa(class="fa-info-circle")
|
||||
span {{_ 'info'}}
|
||||
|
||||
@@ -105,6 +105,14 @@ template(name="boardCardSettingsPopup")
|
||||
span
|
||||
i.fa.fa-users
|
||||
| {{_ 'members'}}
|
||||
|
||||
div.check-div
|
||||
a.flex.js-field-has-creator(class="{{#if allowsCreator}}is-checked{{/if}}")
|
||||
.materialCheckBox(class="{{#if allowsCreator}}is-checked{{/if}}")
|
||||
span
|
||||
i.fa.fa-user
|
||||
| {{_ 'creator'}}
|
||||
|
||||
div.check-div
|
||||
a.flex.js-field-has-assignee(class="{{#if allowsAssignee}}is-checked{{/if}}")
|
||||
.materialCheckBox(class="{{#if allowsAssignee}}is-checked{{/if}}")
|
||||
|
||||
@@ -730,6 +730,14 @@ BlazeComponent.extendComponent({
|
||||
return this.currentBoard.allowsSubtasks;
|
||||
},
|
||||
|
||||
allowsCreator() {
|
||||
return (
|
||||
this.currentBoard.allowsCreator === null ||
|
||||
this.currentBoard.allowsCreator === undefined ||
|
||||
this.currentBoard.allowsCreator
|
||||
);
|
||||
},
|
||||
|
||||
allowsMembers() {
|
||||
return this.currentBoard.allowsMembers;
|
||||
},
|
||||
@@ -889,6 +897,19 @@ BlazeComponent.extendComponent({
|
||||
this.currentBoard.allowsSubtasks,
|
||||
);
|
||||
},
|
||||
'click .js-field-has-creator'(evt) {
|
||||
evt.preventDefault();
|
||||
this.currentBoard.allowsCreator = !this.currentBoard.allowsCreator;
|
||||
this.currentBoard.setAllowsCreator(this.currentBoard.allowsCreator);
|
||||
$(`.js-field-has-creator ${MCB}`).toggleClass(
|
||||
CKCLS,
|
||||
this.currentBoard.allowsCreator,
|
||||
);
|
||||
$('.js-field-has-creator').toggleClass(
|
||||
CKCLS,
|
||||
this.currentBoard.allowsCreator,
|
||||
);
|
||||
},
|
||||
'click .js-field-has-members'(evt) {
|
||||
evt.preventDefault();
|
||||
this.currentBoard.allowsMembers = !this.currentBoard.allowsMembers;
|
||||
|
||||
@@ -50,6 +50,15 @@ template(name="createCustomFieldPopup")
|
||||
each dropdownItems.get
|
||||
input.js-dropdown-item(type="text" value=name placeholder="")
|
||||
input.js-dropdown-item.last(type="text" value="" placeholder="{{_ 'custom-field-dropdown-options-placeholder'}}")
|
||||
|
||||
div.js-field-settings.js-field-settings-stringtemplate(class="{{#if isTypeNotSelected 'stringtemplate'}}hide{{/if}}")
|
||||
label
|
||||
| {{_ 'custom-field-stringtemplate-format'}}
|
||||
input.js-field-stringtemplate-format(type="text" value=getStringtemplateFormat)
|
||||
label
|
||||
| {{_ 'custom-field-stringtemplate-separator'}}
|
||||
input.js-field-stringtemplate-separator(type="text" value=getStringtemplateSeparator)
|
||||
|
||||
a.flex.js-field-show-on-card(class="{{#if showOnCard}}is-checked{{/if}}")
|
||||
.materialCheckBox(class="{{#if showOnCard}}is-checked{{/if}}")
|
||||
|
||||
|
||||
@@ -16,7 +16,15 @@ BlazeComponent.extendComponent({
|
||||
}).register('customFieldsSidebar');
|
||||
|
||||
const CreateCustomFieldPopup = BlazeComponent.extendComponent({
|
||||
_types: ['text', 'number', 'date', 'dropdown', 'currency', 'checkbox'],
|
||||
_types: [
|
||||
'text',
|
||||
'number',
|
||||
'date',
|
||||
'dropdown',
|
||||
'currency',
|
||||
'checkbox',
|
||||
'stringtemplate',
|
||||
],
|
||||
|
||||
_currencyList: [
|
||||
{
|
||||
@@ -77,6 +85,18 @@ const CreateCustomFieldPopup = BlazeComponent.extendComponent({
|
||||
? this.data().settings.dropdownItems
|
||||
: [],
|
||||
);
|
||||
|
||||
this.stringtemplateFormat = new ReactiveVar(
|
||||
this.data().settings && this.data().settings.stringtemplateFormat
|
||||
? this.data().settings.stringtemplateFormat
|
||||
: '',
|
||||
);
|
||||
|
||||
this.stringtemplateSeparator = new ReactiveVar(
|
||||
this.data().settings && this.data().settings.stringtemplateSeparator
|
||||
? this.data().settings.stringtemplateSeparator
|
||||
: '',
|
||||
);
|
||||
},
|
||||
|
||||
types() {
|
||||
@@ -121,6 +141,14 @@ const CreateCustomFieldPopup = BlazeComponent.extendComponent({
|
||||
return items;
|
||||
},
|
||||
|
||||
getStringtemplateFormat() {
|
||||
return this.stringtemplateFormat.get();
|
||||
},
|
||||
|
||||
getStringtemplateSeparator() {
|
||||
return this.stringtemplateSeparator.get();
|
||||
},
|
||||
|
||||
getSettings() {
|
||||
const settings = {};
|
||||
switch (this.type.get()) {
|
||||
@@ -136,6 +164,14 @@ const CreateCustomFieldPopup = BlazeComponent.extendComponent({
|
||||
settings.dropdownItems = dropdownItems;
|
||||
break;
|
||||
}
|
||||
case 'stringtemplate': {
|
||||
const stringtemplateFormat = this.stringtemplateFormat.get();
|
||||
settings.stringtemplateFormat = stringtemplateFormat;
|
||||
|
||||
const stringtemplateSeparator = this.stringtemplateSeparator.get();
|
||||
settings.stringtemplateSeparator = stringtemplateSeparator;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return settings;
|
||||
},
|
||||
@@ -158,6 +194,14 @@ const CreateCustomFieldPopup = BlazeComponent.extendComponent({
|
||||
evt.target.value = '';
|
||||
}
|
||||
},
|
||||
'input .js-field-stringtemplate-format'(evt) {
|
||||
const value = evt.target.value;
|
||||
this.stringtemplateFormat.set(value);
|
||||
},
|
||||
'input .js-field-stringtemplate-separator'(evt) {
|
||||
const value = evt.target.value;
|
||||
this.stringtemplateSeparator.set(value);
|
||||
},
|
||||
'click .js-field-show-on-card'(evt) {
|
||||
let $target = $(evt.target);
|
||||
if (!$target.hasClass('js-field-show-on-card')) {
|
||||
|
||||
@@ -72,6 +72,43 @@ template(name="filterSidebar")
|
||||
| (<span class="username">{{ username }}</span>)
|
||||
if Filter.assignees.isSelected _id
|
||||
i.fa.fa-check
|
||||
|
||||
hr
|
||||
h3
|
||||
i.fa.fa-list-alt
|
||||
| {{_ 'filter-dates-label' }}
|
||||
ul.sidebar-list
|
||||
li(class="{{#if Filter.dueAt.isSelected 'noDate'}}active{{/if}}")
|
||||
a.name.js-toggle-no-due-date-filter
|
||||
span.sidebar-list-item-description
|
||||
| {{_ 'filter-no-due-date' }}
|
||||
if Filter.dueAt.isSelected 'noDate'
|
||||
i.fa.fa-check
|
||||
li(class="{{#if Filter.dueAt.isSelected 'past'}}active{{/if}}")
|
||||
a.name.js-toggle-overdue-filter
|
||||
span.sidebar-list-item-description
|
||||
| {{_ 'filter-overdue' }}
|
||||
if Filter.dueAt.isSelected 'past'
|
||||
i.fa.fa-check
|
||||
li(class="{{#if Filter.dueAt.isSelected 'today'}}active{{/if}}")
|
||||
a.name.js-toggle-due-today-filter
|
||||
span.sidebar-list-item-description
|
||||
| {{_ 'filter-due-today' }}
|
||||
if Filter.dueAt.isSelected 'today'
|
||||
i.fa.fa-check
|
||||
li(class="{{#if Filter.dueAt.isSelected 'tomorrow'}}active{{/if}}")
|
||||
a.name.js-toggle-due-tomorrow-filter
|
||||
span.sidebar-list-item-description
|
||||
| {{_ 'filter-due-tomorrow' }}
|
||||
if Filter.dueAt.isSelected 'tomorrow'
|
||||
i.fa.fa-check
|
||||
li(class="{{#if Filter.dueAt.isSelected 'week'}}active{{/if}}")
|
||||
a.name.js-toggle-due-this-week-filter
|
||||
span.sidebar-list-item-description
|
||||
| {{_ 'filter-due-this-week' }}
|
||||
if Filter.dueAt.isSelected 'week'
|
||||
i.fa.fa-check
|
||||
|
||||
hr
|
||||
h3
|
||||
i.fa.fa-list-alt
|
||||
|
||||
@@ -23,6 +23,31 @@ BlazeComponent.extendComponent({
|
||||
Filter.assignees.toggle(this.currentData()._id);
|
||||
Filter.resetExceptions();
|
||||
},
|
||||
'click .js-toggle-no-due-date-filter'(evt) {
|
||||
evt.preventDefault();
|
||||
Filter.dueAt.noDate();
|
||||
Filter.resetExceptions();
|
||||
},
|
||||
'click .js-toggle-overdue-filter'(evt) {
|
||||
evt.preventDefault();
|
||||
Filter.dueAt.past();
|
||||
Filter.resetExceptions();
|
||||
},
|
||||
'click .js-toggle-due-today-filter'(evt) {
|
||||
evt.preventDefault();
|
||||
Filter.dueAt.today();
|
||||
Filter.resetExceptions();
|
||||
},
|
||||
'click .js-toggle-due-tomorrow-filter'(evt) {
|
||||
evt.preventDefault();
|
||||
Filter.dueAt.tomorrow();
|
||||
Filter.resetExceptions();
|
||||
},
|
||||
'click .js-toggle-due-this-week-filter'(evt) {
|
||||
evt.preventDefault();
|
||||
Filter.dueAt.thisWeek();
|
||||
Filter.resetExceptions();
|
||||
},
|
||||
'click .js-toggle-archive-filter'(evt) {
|
||||
evt.preventDefault();
|
||||
Filter.archive.toggle(this.currentData()._id);
|
||||
|
||||
@@ -39,6 +39,8 @@ template(name="swimlaneActionPopup")
|
||||
hr
|
||||
ul.pop-over-list
|
||||
li: a.js-close-swimlane {{_ 'archive-swimlane'}}
|
||||
ul.pop-over-list
|
||||
li: a.js-copy-swimlane {{_ 'copy-swimlane'}}
|
||||
ul.pop-over-list
|
||||
li: a.js-move-swimlane {{_ 'move-swimlane'}}
|
||||
|
||||
|
||||
@@ -55,6 +55,7 @@ Template.swimlaneActionPopup.events({
|
||||
Popup.close();
|
||||
},
|
||||
'click .js-move-swimlane': Popup.open('moveSwimlane'),
|
||||
'click .js-copy-swimlane': Popup.open('copySwimlane'),
|
||||
});
|
||||
|
||||
Template.swimlaneActionPopup.events({
|
||||
|
||||
@@ -71,3 +71,13 @@ template(name="moveSwimlanePopup")
|
||||
|
||||
.edit-controls.clearfix
|
||||
button.primary.confirm.js-done {{_ 'done'}}
|
||||
|
||||
template(name="copySwimlanePopup")
|
||||
unless currentUser.isWorker
|
||||
label {{_ 'boards'}}:
|
||||
select.js-select-boards(autofocus)
|
||||
each toBoard in toBoards
|
||||
option(value="{{toBoard._id}}" selected="{{#if $eq toBoard.title board.title}}1{{/if}}") {{toBoard.title}}
|
||||
|
||||
.edit-controls.clearfix
|
||||
button.primary.confirm.js-done {{_ 'done'}}
|
||||
@@ -324,45 +324,54 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
}).register('listsGroup');
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
class MoveSwimlaneComponent extends BlazeComponent {
|
||||
serverMethod = 'moveSwimlane';
|
||||
|
||||
onCreated() {
|
||||
this.currentSwimlane = this.currentData();
|
||||
},
|
||||
}
|
||||
|
||||
board() {
|
||||
return Boards.findOne(Session.get('currentBoard'));
|
||||
},
|
||||
}
|
||||
|
||||
toBoardsSelector() {
|
||||
return {
|
||||
archived: false,
|
||||
'members.userId': Meteor.userId(),
|
||||
type: 'board',
|
||||
_id: { $ne: this.board()._id },
|
||||
};
|
||||
}
|
||||
|
||||
toBoards() {
|
||||
const boards = Boards.find(
|
||||
{
|
||||
archived: false,
|
||||
'members.userId': Meteor.userId(),
|
||||
type: 'board',
|
||||
_id: { $ne: this.board()._id },
|
||||
},
|
||||
{
|
||||
sort: { title: 1 },
|
||||
},
|
||||
);
|
||||
|
||||
return boards;
|
||||
},
|
||||
return Boards.find(this.toBoardsSelector(), { sort: { title: 1 } });
|
||||
}
|
||||
|
||||
events() {
|
||||
return [
|
||||
{
|
||||
'click .js-done'() {
|
||||
const swimlane = Swimlanes.findOne(this.currentSwimlane._id);
|
||||
// const swimlane = Swimlanes.findOne(this.currentSwimlane._id);
|
||||
const bSelect = $('.js-select-boards')[0];
|
||||
let boardId;
|
||||
if (bSelect) {
|
||||
boardId = bSelect.options[bSelect.selectedIndex].value;
|
||||
Meteor.call('moveSwimlane', this.currentSwimlane._id, boardId);
|
||||
Meteor.call(this.serverMethod, this.currentSwimlane._id, boardId);
|
||||
}
|
||||
Popup.close();
|
||||
},
|
||||
},
|
||||
];
|
||||
},
|
||||
}).register('moveSwimlanePopup');
|
||||
}
|
||||
}
|
||||
MoveSwimlaneComponent.register('moveSwimlanePopup');
|
||||
|
||||
(class extends MoveSwimlaneComponent {
|
||||
serverMethod = 'copySwimlane';
|
||||
toBoardsSelector() {
|
||||
const selector = super.toBoardsSelector();
|
||||
delete selector._id;
|
||||
return selector;
|
||||
}
|
||||
}.register('copySwimlanePopup'));
|
||||
@@ -1,5 +1,5 @@
|
||||
template(name="userAvatar")
|
||||
a.member.js-member(title="{{userData.profile.fullname}} ({{userData.username}}) {{_ memberType}}")
|
||||
a.member(class="js-{{#if assignee}}assignee{{else}}member{{/if}}" title="{{userData.profile.fullname}} ({{userData.username}}) {{_ memberType}}")
|
||||
if userData.profile.avatarUrl
|
||||
img.avatar.avatar-image(src="{{userData.profile.avatarUrl}}")
|
||||
else
|
||||
@@ -72,9 +72,10 @@ template(name="cardMemberPopup")
|
||||
h3= user.profile.fullname
|
||||
p.quiet @{{ user.username }}
|
||||
ul.pop-over-list
|
||||
if currentUser.isNotCommentOnly
|
||||
if currentUser.isNotWorker
|
||||
li: a.js-remove-member {{_ 'remove-member-from-card'}}
|
||||
unless noRemove
|
||||
if currentUser.isNotCommentOnly
|
||||
if currentUser.isNotWorker
|
||||
li: a.js-remove-member {{_ 'remove-member-from-card'}}
|
||||
|
||||
if $eq currentUser._id user._id
|
||||
with currentUser
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
import Cards from '/models/cards';
|
||||
import Avatars from '/models/avatars';
|
||||
import Users from '/models/users';
|
||||
|
||||
Template.userAvatar.helpers({
|
||||
userData() {
|
||||
// We need to handle a special case for the search results provided by the
|
||||
@@ -30,10 +34,6 @@ Template.userAvatar.helpers({
|
||||
},
|
||||
});
|
||||
|
||||
Template.userAvatar.events({
|
||||
'click .js-change-avatar': Popup.open('changeAvatar'),
|
||||
});
|
||||
|
||||
Template.userAvatarInitials.helpers({
|
||||
initials() {
|
||||
const user = Users.findOne(this.userId);
|
||||
|
||||
@@ -25,10 +25,6 @@ template(name="memberMenuPopup")
|
||||
a.js-global-search(href="{{pathFor 'global-search'}}")
|
||||
i.fa.fa-search
|
||||
| {{_ 'globalSearch-title'}}
|
||||
li
|
||||
a.js-broken-cards(href="{{pathFor 'broken-cards'}}")
|
||||
i.fa.fa-chain-broken
|
||||
| {{_ 'broken-cards'}}
|
||||
li
|
||||
a(href="{{pathFor 'home'}}")
|
||||
span.fa.fa-home
|
||||
|
||||
@@ -174,6 +174,8 @@ Template.changeLanguagePopup.helpers({
|
||||
} else if (lang.name === 'fa-IR') {
|
||||
// fa-IR = Persian (Iran)
|
||||
name = 'فارسی/پارسی (ایران)';
|
||||
} else if (lang.name === 'de-CH') {
|
||||
name = 'Schwiizerdütsch';
|
||||
} else if (lang.name === 'fr-BE') {
|
||||
name = 'Français (Belgique)';
|
||||
} else if (lang.name === 'fr-CA') {
|
||||
|
||||
@@ -32,8 +32,11 @@ export class CardSearchPagedComponent extends BlazeComponent {
|
||||
that.searching.set(false);
|
||||
that.hasResults.set(false);
|
||||
that.serverError.set(true);
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Error.reason:', error.reason);
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Error.message:', error.message);
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Error.stack:', error.stack);
|
||||
},
|
||||
};
|
||||
@@ -62,7 +65,6 @@ export class CardSearchPagedComponent extends BlazeComponent {
|
||||
// console.log('getting results');
|
||||
const sessionData = this.getSessionData();
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('selector:', sessionData.getSelector());
|
||||
console.log('session data:', sessionData);
|
||||
const cards = [];
|
||||
sessionData.cards.forEach(cardId => {
|
||||
@@ -72,7 +74,7 @@ export class CardSearchPagedComponent extends BlazeComponent {
|
||||
if (this.queryErrors.length) {
|
||||
// console.log('queryErrors:', this.queryErrorMessages());
|
||||
this.hasQueryErrors.set(true);
|
||||
return null;
|
||||
// return null;
|
||||
}
|
||||
|
||||
if (cards) {
|
||||
@@ -99,10 +101,8 @@ export class CardSearchPagedComponent extends BlazeComponent {
|
||||
}
|
||||
}
|
||||
|
||||
runGlobalSearch(queryParams) {
|
||||
this.searching.set(true);
|
||||
this.stopSubscription();
|
||||
this.subscriptionHandle = Meteor.subscribe(
|
||||
getSubscription(queryParams) {
|
||||
return Meteor.subscribe(
|
||||
'globalSearch',
|
||||
this.sessionId,
|
||||
queryParams.params,
|
||||
@@ -111,6 +111,12 @@ export class CardSearchPagedComponent extends BlazeComponent {
|
||||
);
|
||||
}
|
||||
|
||||
runGlobalSearch(queryParams) {
|
||||
this.searching.set(true);
|
||||
this.stopSubscription();
|
||||
this.subscriptionHandle = this.getSubscription(queryParams);
|
||||
}
|
||||
|
||||
queryErrorMessages() {
|
||||
const messages = [];
|
||||
|
||||
|
||||
+15
-17
@@ -6,17 +6,17 @@ function adjustedTimeFormat() {
|
||||
.replace(/HH/i, 'H');
|
||||
}
|
||||
|
||||
DatePicker = BlazeComponent.extendComponent({
|
||||
export class DatePicker extends BlazeComponent {
|
||||
template() {
|
||||
return 'datepicker';
|
||||
},
|
||||
}
|
||||
|
||||
onCreated(defaultTime = '1970-01-01 08:00:00') {
|
||||
this.error = new ReactiveVar('');
|
||||
this.card = this.data();
|
||||
this.date = new ReactiveVar(moment.invalid());
|
||||
this.defaultTime = defaultTime;
|
||||
},
|
||||
}
|
||||
|
||||
startDayOfWeek() {
|
||||
const currentUser = Meteor.user();
|
||||
@@ -25,7 +25,7 @@ DatePicker = BlazeComponent.extendComponent({
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
onRendered() {
|
||||
const $picker = this.$('.js-datepicker')
|
||||
@@ -42,7 +42,7 @@ DatePicker = BlazeComponent.extendComponent({
|
||||
this.error.set('');
|
||||
const timeInput = this.find('#time');
|
||||
timeInput.focus();
|
||||
if (!timeInput.value) {
|
||||
if (!timeInput.value && this.defaultTime) {
|
||||
const currentHour = evt.date.getHours();
|
||||
const defaultMoment = moment(
|
||||
currentHour > 0 ? evt.date : this.defaultTime,
|
||||
@@ -55,22 +55,22 @@ DatePicker = BlazeComponent.extendComponent({
|
||||
if (this.date.get().isValid()) {
|
||||
$picker.datepicker('update', this.date.get().toDate());
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
showDate() {
|
||||
if (this.date.get().isValid()) return this.date.get().format('L');
|
||||
return '';
|
||||
},
|
||||
}
|
||||
showTime() {
|
||||
if (this.date.get().isValid()) return this.date.get().format('LT');
|
||||
return '';
|
||||
},
|
||||
}
|
||||
dateFormat() {
|
||||
return moment.localeData().longDateFormat('L');
|
||||
},
|
||||
}
|
||||
timeFormat() {
|
||||
return moment.localeData().longDateFormat('LT');
|
||||
},
|
||||
}
|
||||
|
||||
events() {
|
||||
return [
|
||||
@@ -106,7 +106,7 @@ DatePicker = BlazeComponent.extendComponent({
|
||||
const dateString = `${evt.target.date.value} ${time}`;
|
||||
const newCompleteDate = moment(
|
||||
dateString,
|
||||
'L ' + adjustedTimeFormat(),
|
||||
`L ${adjustedTimeFormat()}`,
|
||||
true,
|
||||
);
|
||||
if (!newTime.isValid()) {
|
||||
@@ -120,10 +120,8 @@ DatePicker = BlazeComponent.extendComponent({
|
||||
if (newCompleteDate.isValid()) {
|
||||
this._storeDate(newCompleteDate.toDate());
|
||||
Popup.close();
|
||||
} else {
|
||||
if (!this.error) {
|
||||
this.error.set('invalid');
|
||||
}
|
||||
} else if (!this.error) {
|
||||
this.error.set('invalid');
|
||||
}
|
||||
},
|
||||
'click .js-delete-date'(evt) {
|
||||
@@ -133,5 +131,5 @@ DatePicker = BlazeComponent.extendComponent({
|
||||
},
|
||||
},
|
||||
];
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,125 @@ function showFilterSidebar() {
|
||||
Sidebar.setView('filter');
|
||||
}
|
||||
|
||||
class DateFilter {
|
||||
constructor() {
|
||||
this._dep = new Tracker.Dependency();
|
||||
this.subField = ''; // Prevent name mangling in Filter
|
||||
this._filter = null;
|
||||
this._filterState = null;
|
||||
}
|
||||
|
||||
_updateState(state) {
|
||||
this._filterState = state;
|
||||
showFilterSidebar();
|
||||
this._dep.changed();
|
||||
}
|
||||
|
||||
// past builds a filter for all dates before now
|
||||
past() {
|
||||
if (this._filterState == 'past') { this.reset(); return; }
|
||||
this._filter = { $lte: moment().toDate() };
|
||||
this._updateState('past');
|
||||
}
|
||||
|
||||
// today is a convenience method for calling relativeDay with 0
|
||||
today() {
|
||||
if (this._filterState == 'today') { this.reset(); return; }
|
||||
this.relativeDay(0);
|
||||
this._updateState('today');
|
||||
}
|
||||
|
||||
// tomorrow is a convenience method for calling relativeDay with 1
|
||||
tomorrow() {
|
||||
if (this._filterState == 'tomorrow') { this.reset(); return; }
|
||||
this.relativeDay(1);
|
||||
this._updateState('tomorrow');
|
||||
}
|
||||
|
||||
// thisWeek is a convenience method for calling relativeWeek with 1
|
||||
thisWeek() {
|
||||
this.relativeWeek(1);
|
||||
}
|
||||
|
||||
// relativeDay builds a filter starting from now and including all
|
||||
// days up to today +/- offset.
|
||||
relativeDay(offset) {
|
||||
if (this._filterState == 'day') { this.reset(); return; }
|
||||
|
||||
var startDay = moment().startOf('day').toDate(),
|
||||
endDay = moment().endOf('day').add(offset, 'day').toDate();
|
||||
|
||||
if (offset >= 0) {
|
||||
this._filter = { $gte: startDay, $lte: endDay };
|
||||
} else {
|
||||
this._filter = { $lte: startDay, $gte: endDay };
|
||||
}
|
||||
|
||||
this._updateState('day');
|
||||
}
|
||||
|
||||
// relativeWeek builds a filter starting from today and including all
|
||||
// weeks up to today +/- offset. This considers the user's preferred
|
||||
// start of week day (as defined by Meteor).
|
||||
relativeWeek(offset) {
|
||||
if (this._filterState == 'week') { this.reset(); return; }
|
||||
|
||||
// getStartDayOfWeek returns the offset from Sunday of the user's
|
||||
// preferred starting day of the week. This date should be added
|
||||
// to the moment start of week to get the real start of week date.
|
||||
// The default is 1, meaning Monday.
|
||||
const currentUser = Meteor.user();
|
||||
const weekStartDay = currentUser ? currentUser.getStartDayOfWeek() : 1;
|
||||
|
||||
// Moments are mutable so they must be cloned before modification
|
||||
var thisWeekStart = moment().startOf('day').startOf('week').add(weekStartDay, 'days');
|
||||
var thisWeekEnd = thisWeekStart.clone().add(offset, 'week').endOf('day');
|
||||
var startDate = thisWeekStart.toDate();
|
||||
var endDate = thisWeekEnd.toDate();
|
||||
|
||||
if (offset >= 0) {
|
||||
this._filter = { $gte: startDate, $lte: endDate };
|
||||
} else {
|
||||
this._filter = { $lte: startDate, $gte: endDate };
|
||||
}
|
||||
|
||||
this._updateState('week');
|
||||
}
|
||||
|
||||
// noDate builds a filter for items where date is not set
|
||||
noDate() {
|
||||
if (this._filterState == 'noDate') { this.reset(); return; }
|
||||
this._filter = null;
|
||||
this._updateState('noDate');
|
||||
}
|
||||
|
||||
reset() {
|
||||
this._filter = null;
|
||||
this._filterState = null;
|
||||
this._dep.changed();
|
||||
}
|
||||
|
||||
isSelected(val) {
|
||||
this._dep.depend();
|
||||
return this._filterState == val;
|
||||
}
|
||||
|
||||
_isActive() {
|
||||
this._dep.depend();
|
||||
return this._filterState !== null;
|
||||
}
|
||||
|
||||
_getMongoSelector() {
|
||||
this._dep.depend();
|
||||
return this._filter;
|
||||
}
|
||||
|
||||
_getEmptySelector() {
|
||||
this._dep.depend();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Use a "set" filter for a field that is a set of documents uniquely
|
||||
// identified. For instance `{ labels: ['labelA', 'labelC', 'labelD'] }`.
|
||||
// use "subField" for searching inside object Fields.
|
||||
@@ -462,6 +581,7 @@ Filter = {
|
||||
assignees: new SetFilter(),
|
||||
archive: new SetFilter(),
|
||||
hideEmpty: new SetFilter(),
|
||||
dueAt: new DateFilter(),
|
||||
customFields: new SetFilter('_id'),
|
||||
advanced: new AdvancedFilter(),
|
||||
lists: new AdvancedFilter(), // we need the ability to filter list by name as well
|
||||
@@ -472,6 +592,7 @@ Filter = {
|
||||
'assignees',
|
||||
'archive',
|
||||
'hideEmpty',
|
||||
'dueAt',
|
||||
'customFields',
|
||||
],
|
||||
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
export const ALLOWED_BOARD_COLORS = [
|
||||
'belize',
|
||||
'nephritis',
|
||||
'pomegranate',
|
||||
'pumpkin',
|
||||
'wisteria',
|
||||
'moderatepink',
|
||||
'strongcyan',
|
||||
'limegreen',
|
||||
'midnight',
|
||||
'dark',
|
||||
'relax',
|
||||
'corteza',
|
||||
'clearblue',
|
||||
'natural',
|
||||
'modern',
|
||||
'moderndark',
|
||||
];
|
||||
export const ALLOWED_COLORS = [
|
||||
'white',
|
||||
'green',
|
||||
'yellow',
|
||||
'orange',
|
||||
'red',
|
||||
'purple',
|
||||
'blue',
|
||||
'sky',
|
||||
'lime',
|
||||
'pink',
|
||||
'black',
|
||||
'silver',
|
||||
'peachpuff',
|
||||
'crimson',
|
||||
'plum',
|
||||
'darkgreen',
|
||||
'slateblue',
|
||||
'magenta',
|
||||
'gold',
|
||||
'navy',
|
||||
'gray',
|
||||
'saddlebrown',
|
||||
'paleturquoise',
|
||||
'mistyrose',
|
||||
'indigo',
|
||||
];
|
||||
export const TYPE_BOARD = 'board';
|
||||
export const TYPE_CARD = 'cardType-card';
|
||||
export const TYPE_LINKED_BOARD = 'cardType-linkedBoard';
|
||||
export const TYPE_LINKED_CARD = 'cardType-linkedCard';
|
||||
export const TYPE_TEMPLATE_BOARD = 'template-board';
|
||||
export const TYPE_TEMPLATE_CONTAINER = 'template-container';
|
||||
+15
-2
@@ -3,6 +3,7 @@ import {
|
||||
OPERATOR_BOARD,
|
||||
OPERATOR_COMMENT,
|
||||
OPERATOR_CREATED_AT,
|
||||
OPERATOR_CREATOR,
|
||||
OPERATOR_DUE,
|
||||
OPERATOR_HAS,
|
||||
OPERATOR_LABEL,
|
||||
@@ -52,7 +53,9 @@ export class QueryParams {
|
||||
|
||||
hasOperator(operator) {
|
||||
return (
|
||||
this.params[operator] !== undefined && this.params[operator].length > 0
|
||||
this.params[operator] !== undefined &&
|
||||
(this.params[operator].length === undefined ||
|
||||
this.params[operator].length > 0)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -68,7 +71,11 @@ export class QueryParams {
|
||||
}
|
||||
|
||||
getPredicate(operator) {
|
||||
return this.params[operator][0];
|
||||
if (typeof this.params[operator] === 'object') {
|
||||
return this.params[operator][0];
|
||||
} else {
|
||||
return this.params[operator];
|
||||
}
|
||||
}
|
||||
|
||||
getPredicates(operator) {
|
||||
@@ -107,6 +114,7 @@ export class QueryErrors {
|
||||
[OPERATOR_USER, 'user-username-not-found'],
|
||||
[OPERATOR_ASSIGNEE, 'user-username-not-found'],
|
||||
[OPERATOR_MEMBER, 'user-username-not-found'],
|
||||
[OPERATOR_CREATOR, 'user-username-not-found'],
|
||||
];
|
||||
|
||||
constructor() {
|
||||
@@ -196,6 +204,10 @@ export class Query {
|
||||
return this.queryParams;
|
||||
}
|
||||
|
||||
setQueryParams(queryParams) {
|
||||
this.queryParams = queryParams;
|
||||
}
|
||||
|
||||
addPredicate(operator, predicate) {
|
||||
this.queryParams.addPredicate(operator, predicate);
|
||||
}
|
||||
@@ -238,6 +250,7 @@ export class Query {
|
||||
'operator-member': OPERATOR_MEMBER,
|
||||
'operator-member-abbrev': OPERATOR_MEMBER,
|
||||
'operator-assignee': OPERATOR_ASSIGNEE,
|
||||
'operator-creator': OPERATOR_CREATOR,
|
||||
'operator-assignee-abbrev': OPERATOR_ASSIGNEE,
|
||||
'operator-status': OPERATOR_STATUS,
|
||||
'operator-due': OPERATOR_DUE,
|
||||
|
||||
@@ -291,6 +291,28 @@ FlowRouter.route('/people', {
|
||||
},
|
||||
});
|
||||
|
||||
FlowRouter.route('/admin-reports', {
|
||||
name: 'admin-reports',
|
||||
triggersEnter: [
|
||||
AccountsTemplates.ensureSignedIn,
|
||||
() => {
|
||||
Session.set('currentBoard', null);
|
||||
Session.set('currentList', null);
|
||||
Session.set('currentCard', null);
|
||||
|
||||
Filter.reset();
|
||||
Session.set('sortBy', '');
|
||||
EscapeActions.executeAll();
|
||||
},
|
||||
],
|
||||
action() {
|
||||
BlazeLayout.render('defaultLayout', {
|
||||
headerBar: 'settingHeaderBar',
|
||||
content: 'adminReports',
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
FlowRouter.notFound = {
|
||||
action() {
|
||||
BlazeLayout.render('defaultLayout', { content: 'notFound' });
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
export const DEFAULT_LIMIT = 25;
|
||||
export const OPERATOR_ASSIGNEE = 'assignee';
|
||||
export const OPERATOR_ASSIGNEE = 'assignees';
|
||||
export const OPERATOR_COMMENT = 'comment';
|
||||
export const OPERATOR_CREATED_AT = 'createdAt';
|
||||
export const OPERATOR_CREATOR = 'userId';
|
||||
export const OPERATOR_DUE = 'dueAt';
|
||||
export const OPERATOR_BOARD = 'board';
|
||||
export const OPERATOR_HAS = 'has';
|
||||
export const OPERATOR_LABEL = 'label';
|
||||
export const OPERATOR_LIMIT = 'limit';
|
||||
export const OPERATOR_LIST = 'list';
|
||||
export const OPERATOR_MEMBER = 'member';
|
||||
export const OPERATOR_MEMBER = 'members';
|
||||
export const OPERATOR_MODIFIED_AT = 'modifiedAt';
|
||||
export const OPERATOR_SORT = 'sort';
|
||||
export const OPERATOR_STATUS = 'status';
|
||||
|
||||
+1
-1
@@ -118,7 +118,7 @@ services:
|
||||
#-------------------------------------------------------------------------------------
|
||||
# ==== MONGODB AND METEOR VERSION ====
|
||||
# a) Quay automatic builds do work work, https://quay.io/wekan/wekan
|
||||
image: quay.io/wekan/wekan:stable
|
||||
image: quay.io/wekan/wekan
|
||||
# b) Using specific version tag:
|
||||
# image: quay.io/wekan/wekan:v4.52
|
||||
# c) Docker Hub builds do work https://hub.docker.com/r/wekanteam/wekan
|
||||
|
||||
+1009
-990
File diff suppressed because it is too large.
Load diff
+1009
-990
File diff suppressed because it is too large.
Load diff
+1009
-990
File diff suppressed because it is too large.
Load diff
+1009
-990
File diff suppressed because it is too large.
Load diff
+1009
-990
File diff suppressed because it is too large.
Load diff
+1009
-990
File diff suppressed because it is too large.
Load diff
+1009
-990
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
+20
-1
@@ -344,6 +344,12 @@
|
||||
"list-label-short-sort": "(M)",
|
||||
"filter": "Filter",
|
||||
"filter-cards": "Karten oder Listen filtern",
|
||||
"filter-dates-label": "Nach Datum filtern",
|
||||
"filter-no-due-date": "Kein Fälligkeitsdatum",
|
||||
"filter-overdue": "Überfällig",
|
||||
"filter-due-today": "Heute fällig",
|
||||
"filter-due-this-week": "Diese Woche fällig",
|
||||
"filter-due-tomorrow": "Morgen fällig",
|
||||
"list-filter-label": "Liste nach Titel filtern",
|
||||
"filter-clear": "Filter entfernen",
|
||||
"filter-labels-label": "Nach Label filtern",
|
||||
@@ -900,6 +906,7 @@
|
||||
"operator-member-abbrev": "m",
|
||||
"operator-assignee": "Zugewiesener",
|
||||
"operator-assignee-abbrev": "a",
|
||||
"operator-creator": "Ersteller",
|
||||
"operator-status": "Status",
|
||||
"operator-due": "Fällig",
|
||||
"operator-created": "erstellt",
|
||||
@@ -951,6 +958,7 @@
|
||||
"globalSearch-instructions-operator-at": "`__operator_user_abbrev__username` – Kurzform für `user:<username>`",
|
||||
"globalSearch-instructions-operator-member": "`__operator_member__:<username>` – Karten, von denen *<username>* *Mitglied* ist",
|
||||
"globalSearch-instructions-operator-assignee": "`__operator_assignee__:<username>` – Karten, denen *<username>* *zugewiesen* ist",
|
||||
"globalSearch-instructions-operator-creator": "`__operator_creator__:<username>` – Karten, die von *<username>* angelegt wurden",
|
||||
"globalSearch-instructions-operator-due": "`__operator_due__:<n>` – Karten, die spätestens in *<n>* Tagen fällig sind. `__operator_due__:__predicate_overdue__` zeigt alle Karten, für die die Fälligkeit überschritten ist.",
|
||||
"globalSearch-instructions-operator-created": "`__operator_created__:<n>` – Karten, die vor maximal *<n>* Tagen angelegt wurden",
|
||||
"globalSearch-instructions-operator-modified": "`__operator_modified__:<n>` – Karten, die vor maximal *<n>* Tagen geändert wurden",
|
||||
@@ -987,5 +995,16 @@
|
||||
"hide-system-messages-of-all-users": "Alle System-Nachrichten aller Nutzer verbergen",
|
||||
"now-system-messages-of-all-users-are-hidden": "Alle System-Nachrichten aller Nutzer sind nun verborgen",
|
||||
"move-swimlane": "Swimlane verschieben",
|
||||
"moveSwimlanePopup-title": "Swimlane verschieben"
|
||||
"moveSwimlanePopup-title": "Swimlane verschieben",
|
||||
"custom-field-stringtemplate": "String-Vorlage",
|
||||
"custom-field-stringtemplate-format": "Format (verwende %{value} als Platzhalter)",
|
||||
"custom-field-stringtemplate-separator": "Trenner (verwende   oder für einen Leerschritt)",
|
||||
"custom-field-stringtemplate-item-placeholder": "Drücke die Eingabetaste, um weitere Einträge hinzuzufügen",
|
||||
"creator": "Ersteller",
|
||||
"filesReportTitle": "Dateien-Bericht",
|
||||
"orphanedFilesReportTitle": "Verwaister Datei-Bericht",
|
||||
"reports": "Berichte",
|
||||
"rulesReportTitle": "Regeln-Bericht",
|
||||
"copy-swimlane": "Kopiere Swimlane",
|
||||
"copySwimlanePopup-title": "Swimlane kopieren"
|
||||
}
|
||||
+1009
-990
File diff suppressed because it is too large.
Load diff
+1009
-990
File diff suppressed because it is too large.
Load diff
+20
-1
@@ -344,6 +344,12 @@
|
||||
"list-label-short-sort": "(M)",
|
||||
"filter": "Filter",
|
||||
"filter-cards": "Filter Cards or Lists",
|
||||
"filter-dates-label": "Filter by date",
|
||||
"filter-no-due-date": "No due date",
|
||||
"filter-overdue": "Overdue",
|
||||
"filter-due-today": "Due today",
|
||||
"filter-due-this-week": "Due this week",
|
||||
"filter-due-tomorrow": "Due tomorrow",
|
||||
"list-filter-label": "Filter List by Title",
|
||||
"filter-clear": "Clear filter",
|
||||
"filter-labels-label": "Filter by label",
|
||||
@@ -901,6 +907,7 @@
|
||||
"operator-member-abbrev": "m",
|
||||
"operator-assignee": "assignee",
|
||||
"operator-assignee-abbrev": "a",
|
||||
"operator-creator": "creator",
|
||||
"operator-status": "status",
|
||||
"operator-due": "due",
|
||||
"operator-created": "created",
|
||||
@@ -952,6 +959,7 @@
|
||||
"globalSearch-instructions-operator-at": "`__operator_user_abbrev__username` - shorthand for `user:<username>`",
|
||||
"globalSearch-instructions-operator-member": "`__operator_member__:<username>` - cards where *<username>* is a *member*",
|
||||
"globalSearch-instructions-operator-assignee": "`__operator_assignee__:<username>` - cards where *<username>* is an *assignee*",
|
||||
"globalSearch-instructions-operator-creator": "`__operator_creator__:<username>` - cards where *<username>* is the card's creator",
|
||||
"globalSearch-instructions-operator-due": "`__operator_due__:<n>` - cards which are due up to *<n>* days from now. `__operator_due__:__predicate_overdue__ lists all cards past their due date.",
|
||||
"globalSearch-instructions-operator-created": "`__operator_created__:<n>` - cards which were created *<n>* days ago or less",
|
||||
"globalSearch-instructions-operator-modified": "`__operator_modified__:<n>` - cards which were modified *<n>* days ago or less",
|
||||
@@ -988,5 +996,16 @@
|
||||
"hide-system-messages-of-all-users": "Hide system messages of all users",
|
||||
"now-system-messages-of-all-users-are-hidden": "Now system messages of all users are hidden",
|
||||
"move-swimlane": "Move Swimlane",
|
||||
"moveSwimlanePopup-title": "Move Swimlane"
|
||||
"moveSwimlanePopup-title": "Move Swimlane",
|
||||
"custom-field-stringtemplate": "String Template",
|
||||
"custom-field-stringtemplate-format": "Format (use %{value} as placeholder)",
|
||||
"custom-field-stringtemplate-separator": "Separator (use   or for a space)",
|
||||
"custom-field-stringtemplate-item-placeholder": "Press enter to add more items",
|
||||
"creator": "Creator",
|
||||
"filesReportTitle": "Files Report",
|
||||
"orphanedFilesReportTitle": "Orphaned Files Report",
|
||||
"reports": "Reports",
|
||||
"rulesReportTitle": "Rules Report",
|
||||
"copy-swimlane": "Copy Swimlane",
|
||||
"copySwimlanePopup-title": "Copy Swimlane"
|
||||
}
|
||||
+1009
-990
File diff suppressed because it is too large.
Load diff
+1009
-990
File diff suppressed because it is too large.
Load diff
+1009
-990
File diff suppressed because it is too large.
Load diff
+1009
-990
File diff suppressed because it is too large.
Load diff
+1009
-990
File diff suppressed because it is too large.
Load diff
+1009
-990
File diff suppressed because it is too large.
Load diff
+1009
-990
File diff suppressed because it is too large.
Load diff
+1009
-990
File diff suppressed because it is too large.
Load diff
+1009
-990
File diff suppressed because it is too large.
Load diff
+1009
-990
File diff suppressed because it is too large.
Load diff
+1009
-990
File diff suppressed because it is too large.
Load diff
+1009
-990
File diff suppressed because it is too large.
Load diff
+20
-1
@@ -344,6 +344,12 @@
|
||||
"list-label-short-sort": "(M)",
|
||||
"filter": "Filtrer",
|
||||
"filter-cards": "Filtrer les cartes ou listes",
|
||||
"filter-dates-label": "Filtrer par date",
|
||||
"filter-no-due-date": "Pas de date d'échéance",
|
||||
"filter-overdue": "Échue",
|
||||
"filter-due-today": "Arrive à échéance aujourd'hui",
|
||||
"filter-due-this-week": "Arrive à échéance cette semaine",
|
||||
"filter-due-tomorrow": "Arrive à échéance demain",
|
||||
"list-filter-label": "Filtrer la liste par titre",
|
||||
"filter-clear": "Supprimer les filtres",
|
||||
"filter-labels-label": "Filtrer par étiquette",
|
||||
@@ -900,6 +906,7 @@
|
||||
"operator-member-abbrev": "m",
|
||||
"operator-assignee": "personne assignée",
|
||||
"operator-assignee-abbrev": "a",
|
||||
"operator-creator": "créateur",
|
||||
"operator-status": "statut",
|
||||
"operator-due": "échéance",
|
||||
"operator-created": "créé",
|
||||
@@ -951,6 +958,7 @@
|
||||
"globalSearch-instructions-operator-at": "`__operator_user_abbrev__nom` - raccourci pour `__operator_user__:<nom>`",
|
||||
"globalSearch-instructions-operator-member": "`__operator_member__:<nom>` - cartes pour lesquelles l'utilisateur *<nom>* est *participant*",
|
||||
"globalSearch-instructions-operator-assignee": "`__operator_assignee__:<nom>` - cartes *assignées* à l'utilisateur *<nom>*",
|
||||
"globalSearch-instructions-operator-creator": "`__operator_creator__:<utilisateur>` - cartes dont le créateur est *<utilisateur>*",
|
||||
"globalSearch-instructions-operator-due": "`__operator_due__:<n>` - cartes qui arrive à échéance dans moins de *<n>* jours à partir d'aujourd'hui.\n`__operator_due__:__predicate_overdue__` liste toutes les cartes ayant passé la date d'échéance.",
|
||||
"globalSearch-instructions-operator-created": "`__operator_created__:<n>` - cartes qui ont été créées il y a *<n>* jours ou moins",
|
||||
"globalSearch-instructions-operator-modified": "`__operator_modified__:<n>` - cartes qui ont été modifiées il y a *<n>* jours ou moins",
|
||||
@@ -987,5 +995,16 @@
|
||||
"hide-system-messages-of-all-users": "Masquer les messages système de tous les utilisateurs",
|
||||
"now-system-messages-of-all-users-are-hidden": "Les messages système de tous les utilisateurs seront dorénavant masqués",
|
||||
"move-swimlane": "Déplacer le couloir",
|
||||
"moveSwimlanePopup-title": "Déplacer le Couloir"
|
||||
"moveSwimlanePopup-title": "Déplacer le Couloir",
|
||||
"custom-field-stringtemplate": "Modèle de chaîne",
|
||||
"custom-field-stringtemplate-format": "Format (utiliser %{valeur} pour marquer un emplacement)",
|
||||
"custom-field-stringtemplate-separator": "Séparateur (utiliser   ou pour un espace)",
|
||||
"custom-field-stringtemplate-item-placeholder": "Appuyez sur Entrée pour ajouter plus d'éléments",
|
||||
"creator": "Créateur",
|
||||
"filesReportTitle": "Rapports sur les fichiers",
|
||||
"orphanedFilesReportTitle": "Rapports sur les fichiers orphelins",
|
||||
"reports": "Rapports",
|
||||
"rulesReportTitle": "Rapports sur les règles",
|
||||
"copy-swimlane": "Copier le couloir",
|
||||
"copySwimlanePopup-title": "Copie de Couloir"
|
||||
}
|
||||
+1009
-990
File diff suppressed because it is too large.
Load diff
+20
-1
@@ -344,6 +344,12 @@
|
||||
"list-label-short-sort": "(י)",
|
||||
"filter": "מסנן",
|
||||
"filter-cards": "סינון כרטיסים או רשימות",
|
||||
"filter-dates-label": "סינון לפי תאריך",
|
||||
"filter-no-due-date": "אין מועד סיום",
|
||||
"filter-overdue": "מועד הסיום עבר",
|
||||
"filter-due-today": "מועד הסיום הוא היום",
|
||||
"filter-due-this-week": "מועד הסיום הוא השבוע",
|
||||
"filter-due-tomorrow": "מועד הסיום הוא מחר",
|
||||
"list-filter-label": "סינון רשימה לפי כותרת",
|
||||
"filter-clear": "ניקוי המסנן",
|
||||
"filter-labels-label": "סינון לפי תווית",
|
||||
@@ -900,6 +906,7 @@
|
||||
"operator-member-abbrev": "ח",
|
||||
"operator-assignee": "אחראי",
|
||||
"operator-assignee-abbrev": "א",
|
||||
"operator-creator": "יוצר",
|
||||
"operator-status": "מצב",
|
||||
"operator-due": "תפוגה",
|
||||
"operator-created": "נוצר",
|
||||
@@ -951,6 +958,7 @@
|
||||
"globalSearch-instructions-operator-at": "`__operator_user_abbrev__username` - קיצור של `user:<username>`",
|
||||
"globalSearch-instructions-operator-member": "`__operator_member__:<username>` - כרטיסים בהם *<username>* *חבר*",
|
||||
"globalSearch-instructions-operator-assignee": "`__operator_assignee__:<username>` - כרטיסים שהוקצו אל *<username>*",
|
||||
"globalSearch-instructions-operator-creator": "`__operator_creator__:<username>` - כרטיסים שנוצרו על ידי *<username>*",
|
||||
"globalSearch-instructions-operator-due": "`__operator_due__:<n>` - כרטיסים שהתוקף שלהם יפוג עד עוד *<n>* ימים מעכשיו. `__operator_due__:__predicate_overdue__ מציג את כל הכרטיסים שתאריך התוקף שלהם עבר.",
|
||||
"globalSearch-instructions-operator-created": "`__operator_created__:<n>` - כרטיסים שנוצרו לפני *<n>* ימים או פחות",
|
||||
"globalSearch-instructions-operator-modified": "`__operator_modified__:<n>` - כרטיסים שנערכו לפני *<n>* ימים או פחות",
|
||||
@@ -987,5 +995,16 @@
|
||||
"hide-system-messages-of-all-users": "להסתיר את הודעות המערכת של כל המשתמשים",
|
||||
"now-system-messages-of-all-users-are-hidden": "כעת הודעות המערכת של כל המשתמשים מוסתרות",
|
||||
"move-swimlane": "העברת מסלול",
|
||||
"moveSwimlanePopup-title": "העברת מסלול"
|
||||
"moveSwimlanePopup-title": "העברת מסלול",
|
||||
"custom-field-stringtemplate": "תבנית מחרוזת",
|
||||
"custom-field-stringtemplate-format": "תבנית (להשתמש ב־%{value} כממלא מקום)",
|
||||
"custom-field-stringtemplate-separator": "מפריד (להשתמש ב־  או ב־ כרווח)",
|
||||
"custom-field-stringtemplate-item-placeholder": "יש ללחוץ על enter כדי להוסיף עוד פריטים",
|
||||
"creator": "יוצר",
|
||||
"filesReportTitle": "דוח קבצים",
|
||||
"orphanedFilesReportTitle": "דוח קבצים יתומים",
|
||||
"reports": "דוחות",
|
||||
"rulesReportTitle": "דוח כללים",
|
||||
"copy-swimlane": "העתקת מסלול",
|
||||
"copySwimlanePopup-title": "העתקת מסלול"
|
||||
}
|
||||
+1009
-990
File diff suppressed because it is too large.
Load diff
+1009
-990
File diff suppressed because it is too large.
Load diff
+1009
-990
File diff suppressed because it is too large.
Load diff
+1009
-990
File diff suppressed because it is too large.
Load diff
+1009
-990
File diff suppressed because it is too large.
Load diff
+1009
-990
File diff suppressed because it is too large.
Load diff
+1009
-990
File diff suppressed because it is too large.
Load diff
+1009
-990
File diff suppressed because it is too large.
Load diff
+1009
-990
File diff suppressed because it is too large.
Load diff
+1009
-990
File diff suppressed because it is too large.
Load diff
+1009
-990
File diff suppressed because it is too large.
Load diff
+1009
-990
File diff suppressed because it is too large.
Load diff
+1009
-990
File diff suppressed because it is too large.
Load diff
+1009
-990
File diff suppressed because it is too large.
Load diff
+1009
-990
File diff suppressed because it is too large.
Load diff
+155
-11
@@ -144,7 +144,7 @@
|
||||
"board-view-collapse": "Slå sammen",
|
||||
"board-view-gantt": "Gantt",
|
||||
"board-view-lists": "Lister",
|
||||
"bucket-example": "Som \"Bucket List\" for eksempel",
|
||||
"bucket-example": "Som 'Bucket List' for eksempel",
|
||||
"cancel": "Avbryt",
|
||||
"card-archived": "Dette kortet er flyttet til Arkivet",
|
||||
"board-archived": "Denne tavlen er flyttet til Arkivet",
|
||||
@@ -207,7 +207,7 @@
|
||||
"clipboard": "Utklippstavle eller Dra og Slipp",
|
||||
"close": "Lukk",
|
||||
"close-board": "Lukk Tavle",
|
||||
"close-board-pop": "Du vil ha muligheten til å gjenopprette Tavle ved å klikke på \"Arkiv\"-knappen i hjem-menyen.",
|
||||
"close-board-pop": "Du vil ha muligheten til å gjenopprette Tavle ved å klikke på 'Arkiv'-knappen i hjem-menyen.",
|
||||
"color-black": "svart",
|
||||
"color-blue": "blå",
|
||||
"color-crimson": "høyrød",
|
||||
@@ -322,11 +322,15 @@
|
||||
"error-user-notAllowSelf": "Du kan ikke invitere deg selv",
|
||||
"error-user-notCreated": "Denne Brukeren er ikke opprettet",
|
||||
"error-username-taken": "Brukernavn allerede i bruk",
|
||||
"error-orgname-taken": "Navn på Organisasjon allerede benyttet",
|
||||
"error-teamname-taken": "Navn på Team allerede benyttet",
|
||||
"error-email-taken": "E-postadressen er allerede i bruk",
|
||||
"export-board": "Eksporter tavle",
|
||||
"export-board-json": "Eksporter tavle til JSON",
|
||||
"export-board-csv": "Eksporter tavle til CSV",
|
||||
"export-board-tsv": "Eksporter tavle til TSV",
|
||||
"export-board-excel": "Eksporter Tavle til Excel",
|
||||
"user-can-not-export-excel": "Bruker kan ikke eksportere til Excel",
|
||||
"export-board-html": "Eksporter tavle til HTML",
|
||||
"exportBoardPopup-title": "Eksporter tavle",
|
||||
"sort": "Sorter",
|
||||
@@ -340,6 +344,12 @@
|
||||
"list-label-short-sort": "(M)",
|
||||
"filter": "Filtrer",
|
||||
"filter-cards": "Filtrer Kort eller Lister",
|
||||
"filter-dates-label": "Filtrer etter dato",
|
||||
"filter-no-due-date": "Ingen forfallsdato",
|
||||
"filter-overdue": "Forfalt",
|
||||
"filter-due-today": "Forfall i dag",
|
||||
"filter-due-this-week": "Forfall denne uke",
|
||||
"filter-due-tomorrow": "Forfall i morgen",
|
||||
"list-filter-label": "Filtrer Liste etter tittel",
|
||||
"filter-clear": "Fjern filter",
|
||||
"filter-labels-label": "Filtrer etter Etikett",
|
||||
@@ -382,6 +392,7 @@
|
||||
"import-csv-placeholder": "Lim inn gyldig CSV/TSV-data her",
|
||||
"import-map-members": "Tilknytt medlemmer",
|
||||
"import-members-map": "Importert Tavle har medlemmer. Vennligst tilknytt medlemmer som skal importeres til dine Brukere.",
|
||||
"import-members-map-note": "Merk: Ikke registrerte medlemmer vil bli lagt til nåværende bruker.",
|
||||
"import-show-user-mapping": "Gjennomgang tilknytning medlemmer",
|
||||
"import-user-select": "Velg eksisterende Bruker som skal tilknyttes dette Medlemmet",
|
||||
"importMapMembersAddPopup-title": "Velg Medlem",
|
||||
@@ -527,7 +538,9 @@
|
||||
"custom-login-logo-image-url": "Tilpass URL logo-bilde innlogging",
|
||||
"custom-login-logo-link-url": "Tilpass URL logo-link innlogging",
|
||||
"text-below-custom-login-logo": "Tekst under tilpasset logo innlogging",
|
||||
"automatic-linked-url-schemes": "Egendefinerte URL-tilordninger som automatisk skal kunne klikkes på. Kun én URL-tilordning per linje",
|
||||
"username": "Brukernavn",
|
||||
"import-usernames": "Importer Brukernavn",
|
||||
"view-it": "Se det",
|
||||
"warn-list-archived": "advarsel: dette kortet er i en liste i arkivet",
|
||||
"watch": "Overvåk",
|
||||
@@ -546,7 +559,7 @@
|
||||
"wipLimitErrorPopup-dialog-pt2": "Vennligst flytt noen oppgaver ut av denne listen eller sett høyere WIP-begrensning.",
|
||||
"admin-panel": "Admin-panel",
|
||||
"settings": "Innstillinger",
|
||||
"people": "Folk",
|
||||
"people": "Medlemmer",
|
||||
"registration": "Registrering",
|
||||
"disable-self-registration": "Deaktiver selvregistrering",
|
||||
"invite": "Inviter",
|
||||
@@ -599,7 +612,8 @@
|
||||
"minutes": "minutter",
|
||||
"seconds": "sekunder",
|
||||
"show-field-on-card": "Vis dette feltet på kort",
|
||||
"automatically-field-on-card": "Automatisk oppretting av felt på alle kort",
|
||||
"automatically-field-on-card": "Legg til felt på nye kort",
|
||||
"always-field-on-card": "Legg til felt på alle kort",
|
||||
"showLabel-field-on-card": "Vis feltetikett på minikort",
|
||||
"yes": "Ja",
|
||||
"no": "Nei",
|
||||
@@ -607,6 +621,7 @@
|
||||
"accounts-allowEmailChange": "Tillat endring e-post",
|
||||
"accounts-allowUserNameChange": "Tillat endring brukernavn",
|
||||
"createdAt": "Opprettet på",
|
||||
"modifiedAt": "Endret kl. ",
|
||||
"verified": "Verifisert",
|
||||
"active": "Aktiv",
|
||||
"card-received": "Mottatt",
|
||||
@@ -669,6 +684,7 @@
|
||||
"r-removed-from": "Fjernet fra",
|
||||
"r-the-board": "tavlen",
|
||||
"r-list": "listen",
|
||||
"list": "Liste",
|
||||
"set-filter": "Sett filter",
|
||||
"r-moved-to": "Flyttet til",
|
||||
"r-moved-from": "Flyttet fra",
|
||||
@@ -851,16 +867,144 @@
|
||||
"person": "Person",
|
||||
"my-cards": "Mine Kort",
|
||||
"card": "Kort",
|
||||
"list": "Liste",
|
||||
"board": "Tavle",
|
||||
"context-separator": "/",
|
||||
"myCardsSortChange-title": "Sortering mine Kort",
|
||||
"myCardsSortChangePopup-title": "Sortering mine Kort",
|
||||
"myCardsSortChange-choice-board": "På Tavle",
|
||||
"myCardsSortChange-choice-dueat": "På dato Varighet",
|
||||
"dueCards-title": "Due Cards",
|
||||
"dueCardsViewChange-title": "Due Cards View",
|
||||
"dueCardsViewChange-choice-me": "Me",
|
||||
"dueCardsViewChange-choice-all": "All Users",
|
||||
"dueCardsViewChange-choice-all-description": "Shows all incomplete cards with a *Due* date from boards for which the user has permission.",
|
||||
"broken-cards": "Broken Cards"
|
||||
"dueCards-title": "Forfalte Kort",
|
||||
"dueCardsViewChange-title": "Oversikt Forfalte Kort",
|
||||
"dueCardsViewChangePopup-title": "Oversikt Forfalte Kort",
|
||||
"dueCardsViewChange-choice-me": "Meg",
|
||||
"dueCardsViewChange-choice-all": "Alle Brukere",
|
||||
"dueCardsViewChange-choice-all-description": "Viser alle kort som ikke er ferdigstilt, med \"Forfallsdato\" fra tavler som brukeren har rettigheter til.",
|
||||
"broken-cards": "Broken Cards",
|
||||
"board-title-not-found": "Tavle '%s' ikke funnet.",
|
||||
"swimlane-title-not-found": "Svømmebane '%s' ikke funnet.",
|
||||
"list-title-not-found": "Liste '%s' ikke funnet.",
|
||||
"label-not-found": "Merke '%s' ikke funnet.",
|
||||
"label-color-not-found": "Farge på Merke %s ikke funnet.",
|
||||
"user-username-not-found": "Brukernavn '%s' ikke funnet.",
|
||||
"comment-not-found": "Kort med kommentar som inneholder teksten '%s' ikke funnet.",
|
||||
"globalSearch-title": "Søk i alle Tavler.",
|
||||
"no-cards-found": "Ingen Kort funnet.",
|
||||
"one-card-found": "Ett Kort funnet.",
|
||||
"n-cards-found": "%s Kort funnet.",
|
||||
"n-n-of-n-cards-found": "__start__-__end__ av __total__ Kort funnet",
|
||||
"operator-board": "Tavle",
|
||||
"operator-board-abbrev": "t",
|
||||
"operator-swimlane": "svømmebane",
|
||||
"operator-swimlane-abbrev": "s",
|
||||
"operator-list": "listen",
|
||||
"operator-list-abbrev": "l",
|
||||
"operator-label": "etikett",
|
||||
"operator-label-abbrev": "#",
|
||||
"operator-user": "bruker",
|
||||
"operator-user-abbrev": "@",
|
||||
"operator-member": "Medlem",
|
||||
"operator-member-abbrev": "m",
|
||||
"operator-assignee": "Rettighetstaker",
|
||||
"operator-assignee-abbrev": "r",
|
||||
"operator-creator": "oppretter",
|
||||
"operator-status": "status",
|
||||
"operator-due": "forfall",
|
||||
"operator-created": "opprettet",
|
||||
"operator-modified": "endret",
|
||||
"operator-sort": "sorter",
|
||||
"operator-comment": "kommentar",
|
||||
"operator-has": "har",
|
||||
"operator-limit": "begens",
|
||||
"predicate-archived": "arkivert",
|
||||
"predicate-open": "åpne",
|
||||
"predicate-ended": "avsluttet",
|
||||
"predicate-all": "alle",
|
||||
"predicate-overdue": "forfalt",
|
||||
"predicate-week": "uke",
|
||||
"predicate-month": "måned",
|
||||
"predicate-quarter": "kvartal",
|
||||
"predicate-year": "år",
|
||||
"predicate-due": "forfall",
|
||||
"predicate-modified": "endret",
|
||||
"predicate-created": "opprettet",
|
||||
"predicate-attachment": "vedlegg",
|
||||
"predicate-description": "beskrivelse",
|
||||
"predicate-checklist": "sjekkliste",
|
||||
"predicate-start": "start",
|
||||
"predicate-end": "slutt",
|
||||
"predicate-assignee": "Rettighetstaker",
|
||||
"predicate-member": "Medlem",
|
||||
"predicate-public": "offentlig",
|
||||
"predicate-private": "privat",
|
||||
"operator-unknown-error": "%s er ikke en operator",
|
||||
"operator-number-expected": "operator __operator__ forventet et tall, mottok '__value__'",
|
||||
"operator-sort-invalid": "sortering av '%s' er ugyldig",
|
||||
"operator-status-invalid": "'%s' er ikke en gyldig status",
|
||||
"operator-has-invalid": "%s er ikke en gyldig kontroll av eksistens",
|
||||
"operator-limit-invalid": "%ser ikke en gyldig begrensning. Begrensning må være et positivt heltall.",
|
||||
"next-page": "Neste Side",
|
||||
"previous-page": "Forrige Side",
|
||||
"heading-notes": "Notater",
|
||||
"globalSearch-instructions-heading": "Søk etter Instruksjoner",
|
||||
"globalSearch-instructions-description": "Søk kan inkludere operatorer for å avgrense søket. Operatoren spesifiseres ved å skrive operatorens navn og verdi, atskilt med et kolon. For eksempel vil en spesifisering av operatoren `liste:Blokkert' begrense søket til Kort som er inkludert i en liste med navnet \"Blokkert\". Hvis verdien inneholder mellomrom eller spesialtegn, må den være spesifisert i anførselstegn (f.eks. `__operator_list__:\"To Review\"`).",
|
||||
"globalSearch-instructions-operators": "Tilgjengelige operatorer:",
|
||||
"globalSearch-instructions-operator-board": "`__operator_board__:<title>` - kort i tavlene samsvarer med angitt *<title>*",
|
||||
"globalSearch-instructions-operator-list": "`__operator_list__:<title>` - kort i listene stemmer med angitt *<title>*",
|
||||
"globalSearch-instructions-operator-swimlane": "`__operator_swimlane__:<title>` - kort i svømmebaner samsvarer med angitt *<title>*",
|
||||
"globalSearch-instructions-operator-comment": "`__operator_comment__:<text>` - kort med en kommetar inneholdende *<text>*.",
|
||||
"globalSearch-instructions-operator-label": "`__operator_label__:<color>` `__operator_label__:<name>` - kort med merke som samsvarer med *<color>* or *<name>",
|
||||
"globalSearch-instructions-operator-hash": "`__operator_label_abbrev__<name|color>` - forkortelse for `__operator_label__:<color>` eller `__operator_label__:<name>`",
|
||||
"globalSearch-instructions-operator-user": "`__operator_user__:<username>` - kort hvor *<username>* ier et *medlemr* or *rettighetstaker*",
|
||||
"globalSearch-instructions-operator-at": "`__operator_user_abbrev__username` - forkortelse for bruker:<username>`",
|
||||
"globalSearch-instructions-operator-member": "`__operator_member__:<username>` - kort hvor *<username>* er et *medlem*",
|
||||
"globalSearch-instructions-operator-assignee": "`__operator_assignee__:<username>` - kort hvor *<username>* er en *rettighetstaker*",
|
||||
"globalSearch-instructions-operator-creator": "`__operator_creator__:<username>` - kort hvor *<username>* er kortenes oppretter",
|
||||
"globalSearch-instructions-operator-due": "`__operator_due__:<n>` - kort som forfaller om *<n>* dager fra nå. `__operator_due__:__predicate_overdue__ lister alle kort med passert forfallsdato.",
|
||||
"globalSearch-instructions-operator-created": "`__operator_created__:<n>` - kort som er opprettet *<n>* dager siden eller mindre",
|
||||
"globalSearch-instructions-operator-modified": "`__operator_modified__:<n>` - kort som er modifisert *<n>* dager siden eller mindre",
|
||||
"globalSearch-instructions-operator-status": "`__operator_status__:<status>` - hvor *<status>* er en av de følgende:",
|
||||
"globalSearch-instructions-status-archived": "`__predicate_archived__` - arkiverte kort",
|
||||
"globalSearch-instructions-status-all": "`__predicate_all__` - alle arkiverte eller ikke arkiverte kort",
|
||||
"globalSearch-instructions-status-ended": "`__predicate_ended__` - kort med en sluttdato",
|
||||
"globalSearch-instructions-status-public": "`__predicate_public__` - kort bare i offentlige tavler",
|
||||
"globalSearch-instructions-status-private": "`__predicate_private__` - kort bare i private tavler",
|
||||
"globalSearch-instructions-operator-has": "`__operator_has__:<field>` - hvor *<field>* er en av `__predicate_attachment__`, `__predicate_checklist__`, `__predicate_description__`, `__predicate_start__`, `__predicate_due__`, `__predicate_end__`, `__predicate_assignee__` eller `__predicate_member__`. Plassering av et `-` foran *<field>* søk i mangel på en verdi i et felt (f.eks. `har:-forfall` søker etter alle kort uten en forfallsdato).",
|
||||
"globalSearch-instructions-operator-sort": "`__operator_sort__:<sort-name>` - hvor *<sort-name>* er en av `__predicate_due__`, `__predicate_created__` eller `__predicate_modified__`. For en synkende sortering, plassér en `-` foran navn på sortering.",
|
||||
"globalSearch-instructions-operator-limit": "`__operator_limit__:<n>` - hvor*<n>* er et positivt heltall som angir antall kort som skal vises på siden.",
|
||||
"globalSearch-instructions-notes-1": "Flere operatorer kan angis.",
|
||||
"globalSearch-instructions-notes-2": "Like operatorer er knyttet sammen med \"ELLER\". Kort som samsvarer med noen av de angitte kriteriene vil returneres.\n`__operator_list__:Tilgjengelig __operator_list__:Blokkert` vil returnere Kort som inneholder lister med navnet \"Blokkert\" eller \"Tilgjengelig\".",
|
||||
"globalSearch-instructions-notes-3": "Forskjellige operatorer er knyttet sammen med *OG*. Bare kort som samsvarer med alle de angitte kriteriene vil returneres. `__operator_list__:Tilgjengelig __operator_list__:rød` vil kun returnere kort i listen *Tilgjengelig* og som er markert med et *rødt* merke.",
|
||||
"globalSearch-instructions-notes-3-2": "Dager kan angis som et positivt eller negativt heltall, eller ved bruk av `__predicate_week__`, `__predicate_month__`, `__predicate_quarter__` eller `__predicate_year__` for den aktuelle perioden.",
|
||||
"globalSearch-instructions-notes-4": "Tekstsøk er ikke \"case\"-sensitive.",
|
||||
"globalSearch-instructions-notes-5": "Som standard er arkiverte kort ikke søkbare, ",
|
||||
"link-to-search": "Link til dette søket",
|
||||
"excel-font": "Arial",
|
||||
"number": "Nummer",
|
||||
"label-colors": "Farge Merke",
|
||||
"label-names": "Navn på Merke",
|
||||
"archived-at": "arkivert på",
|
||||
"sort-cards": "Sortér Kort",
|
||||
"cardsSortPopup-title": "Sortér Kort",
|
||||
"due-date": "Forfalldato",
|
||||
"server-error": "Serverfeil",
|
||||
"server-error-troubleshooting": "For hjelp til feilsøk ber vi om innsending av feilmelding generert av server.\nFor Snap-installasjon, kjør: `sudo snap logs wekan.wekan`\nFor Docker-installasjon, kjør: `sudo docker logs wekan-app`",
|
||||
"title-alphabetically": "Tittel (alfabetisk)",
|
||||
"created-at-newest-first": "Opprettet på (Nyeste Først)",
|
||||
"created-at-oldest-first": "Opprettet på (Eldste Først)",
|
||||
"links-heading": "Linker",
|
||||
"hide-system-messages-of-all-users": "Skjul systemmeldinger for alle brukere",
|
||||
"now-system-messages-of-all-users-are-hidden": "Systemmeldinger er nå skjult for alle brukere",
|
||||
"move-swimlane": "Flytt Svømmebane",
|
||||
"moveSwimlanePopup-title": "Flytt Svømmebane",
|
||||
"custom-field-stringtemplate": "Mal Tekststreng",
|
||||
"custom-field-stringtemplate-format": "Format (bruk %{value} som standardverdi)",
|
||||
"custom-field-stringtemplate-separator": "Tekstseparator (bruk   eller som separator)",
|
||||
"custom-field-stringtemplate-item-placeholder": "Trykk Enter for å legge til flere objekt",
|
||||
"creator": "Oppretter",
|
||||
"filesReportTitle": "Rapportering Filer",
|
||||
"orphanedFilesReportTitle": "Rapportering Foreldreløse Filer",
|
||||
"reports": "Rapportering",
|
||||
"rulesReportTitle": "Rapportering Regler",
|
||||
"copy-swimlane": "Kopiér Svømmebane",
|
||||
"copySwimlanePopup-title": "Kopiér Svømmebane"
|
||||
}
|
||||
Loaded 100 of 148 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user