Compare commits

...
60 Commits
Author SHA1 Message Date
Lauri Ojansivu 0765278195 v2.73 2019-05-14 16:48:18 +03:00
Lauri Ojansivu f782b9c298 Update translations (fi). 2019-05-14 16:42:05 +03:00
Lauri Ojansivu e611685e50 Fix lint errors. 2019-05-14 16:37:41 +03:00
Lauri Ojansivu 3edef95c4e - [Few fixes for Dockerfile](https://github.com/wekan/wekan/pulls/2407).
Thanks to bentiss !
2019-05-14 16:31:13 +03:00
Lauri Ojansivu 9b902e1ca0 Merge pull request #2407 from bentiss/dockerfile-fixes
Few fixes for Dockerfile
2019-05-14 16:28:51 +03:00
Lauri Ojansivu fc835815d8 - [Card count placement and export API functionality back](https://github.com/wekan/wekan/pulls/2406).
Thanks to bentiss.

Closes #2403,
closes #2328
2019-05-14 16:27:15 +03:00
Lauri Ojansivu da083c2e20 Merge pull request #2406 from bentiss/fixes
card count placement and export API functionality back
2019-05-14 16:25:05 +03:00
Lauri Ojansivu 6ee17ab080 - Fixed [#2338](https://github.com/wekan/wekan/issues/2338) -> [Slow opening of big boards with too many archived items](https://github.com/wekan/wekan/pull/2402).
If some Wekan users see errors with this, please empty your browser cache.
  Thanks to nerminator.

Closes #2338
2019-05-14 16:23:52 +03:00
Benjamin Tissoires 1e34585548 Dockerfile: no need to change the permissions once again
we carefully used gosu where needed, so there is no need to re-run a
check on the permissions.
2019-05-14 10:33:41 +02:00
Benjamin Tissoires 76cd5a2844 Dockerfile: use gosu for creating the openapi files 2019-05-14 10:33:41 +02:00
Benjamin Tissoires ffd1b93abf Dockerfile: bump api2html to version 0.3.3 2019-05-14 10:33:41 +02:00
Benjamin Tissoires 1eea102f26 openAPI: also handle export statement in the scripts
The files are actually modules, not plain scripts, and thus we are allowed
to use `export`. Without `parseModule`, the script would silently fail
when parsing `export.js` and the export function will not be present.
2019-05-14 10:10:21 +02:00
Benjamin Tissoires 94c1367684 Restore export API
Commit 477d71e0b9 was based on an older version of export.js, which
means it reverted a few changes that were made previously.

Fixes #2328
2019-05-14 09:37:56 +02:00
Benjamin Tissoires 9bf19f81a4 Fix card count position
When introducing markdown in the title (b795115042), the card
count got pushed outside of the List Header.

Add its own style (by manually merge small and quiet), and restore its
original placement.

Fixes #2403
2019-05-14 09:37:34 +02:00
Lauri Ojansivu 21de0ec396 Merge pull request #2402 from nerminator/feature/performance_archive
Fixed #2338 -> Slow opening of big boards with too many archived items
2019-05-13 12:56:12 +03:00
wekan ab4fec0f3c Fixed #2338 -> Slow opening of big boards with too many archived items 2019-05-13 11:01:50 +02:00
Lauri Ojansivu b983479476 v2.72 2019-05-13 10:49:41 +03:00
Lauri Ojansivu f6e5e514ef Merge pull request #2401 from guyzyl/devel
Added BIDI support to "Add Card" #884
2019-05-13 10:42:42 +03:00
Guy Zylberberg ddd828083e Added BIDI support to "Add Card" #884 2019-05-13 00:37:40 +03:00
Lauri Ojansivu e079b4df17 v2.71 2019-05-12 20:49:27 +03:00
Lauri Ojansivu 4e5ff17e18 Update translations. 2019-05-12 20:43:23 +03:00
Lauri Ojansivu 86e1a9cd5d Update changelog. 2019-05-12 20:40:32 +03:00
Lauri Ojansivu 8a0efffdf8 Merge pull request #2400 from atilaromero/devel
Add partentId support on card web API
2019-05-12 20:27:50 +03:00
Lauri Ojansivu c21f710a70 Fix typo. 2019-05-12 19:15:49 +03:00
Atila Romero f3382abe3b Add partentId support on card web API 2019-05-12 10:26:08 -03:00
Lauri Ojansivu d6c86f3cba v2.70 2019-05-11 23:50:47 +03:00
Lauri Ojansivu 3a6516f0cb Update changelog. 2019-05-11 23:47:11 +03:00
Lauri Ojansivu b795115042 - [View markdown on List names, Custom Fields (Text and Dropdown), Label names,
All Boards view Board names and Board descriptions](https://github.com/wekan/wekan/issues/2334).

Thanks to shaygover and xet7 !

Related #2334
2019-05-11 23:40:18 +03:00
Lauri Ojansivu 52fe845d24 v2.69 2019-05-11 00:07:37 +03:00
Lauri Ojansivu b2b6bb2d39 Update changelog. 2019-05-11 00:05:34 +03:00
Lauri Ojansivu db40ca25ac - Fix translation name in Wekan menu: oc to Occitan.
Thanks to xet7 !
2019-05-11 00:02:40 +03:00
Lauri Ojansivu 3eef42eee0 v2.68 2019-05-10 23:18:12 +03:00
Lauri Ojansivu 38d0ad74a9 Update changelog. 2019-05-10 23:13:20 +03:00
Lauri Ojansivu 3bbc805ee4 Option to login to the LDAP server with the user's own username and password, instead of an administrator key. Default: false (use administrator key).
With new setting: LDAP_USER_AUTHENTICATION=true
Added to Snap, Docker and Source.

Thanks to xet7 !

Related https://github.com/wekan/wekan/pull/2399
2019-05-10 23:04:51 +03:00
Lauri Ojansivu c37a454bd5 Merge branch 'thiagofernando-devel' into devel 2019-05-10 22:23:15 +03:00
Lauri Ojansivu 6f98be5608 Merge branch 'devel' of https://github.com/thiagofernando/wekan into thiagofernando-devel 2019-05-10 22:21:50 +03:00
Lauri Ojansivu ab4dab2ade v2.67 2019-05-10 21:01:34 +03:00
Lauri Ojansivu 88ffddfeba Update changelog. 2019-05-10 20:58:35 +03:00
Thiago Fernando 36f148a7cb Update loginHandler.js
additional option to login in ldap server with user account
2019-05-10 14:58:19 -03:00
Thiago Fernando fd1af07e43 Update ldap.js 2019-05-10 14:56:07 -03:00
Lauri Ojansivu fca87b53f0 Update changelog. 2019-05-10 20:55:35 +03:00
Thiago Fernando ce0473480b Merge pull request #1 from wekan/devel
ldap changes
2019-05-10 14:54:25 -03:00
Lauri Ojansivu 828f6ea321 - Add Feature: Move board to Archive button at each board at All Boards page.
Thanks to xet7 !

Related #2389
2019-05-10 20:50:53 +03:00
Lauri Ojansivu 7ff4067e88 v2.66 2019-05-09 16:32:34 +03:00
Lauri Ojansivu 491d27638a Delete user feature. 2019-05-09 16:24:13 +03:00
Lauri Ojansivu e1b016cf3d Prevent data loss.
Thanks to xet7 !
2019-05-09 16:17:53 +03:00
Lauri Ojansivu c850669777 Merge pull request #2384 from Akuket/origin/edge
Delete user feature
2019-05-09 16:06:17 +03:00
Lauri Ojansivu 04c7372a4e Update changelog. 2019-05-09 16:02:54 +03:00
Lauri Ojansivu 64ee60a008 Fix missing profile checks.
Thanks to justinr1234 !
2019-05-09 14:32:38 +03:00
Lauri Ojansivu 434ed895ed Merge pull request #2395 from guyzyl/devel
Fixed RTL issue #884
2019-05-09 14:24:35 +03:00
Guy Zylberberg 1bdc1017d6 Fixed RTL issue #884 2019-05-08 21:30:38 +03:00
Lauri Ojansivu 6218d8c7ed Update translations. 2019-05-08 18:20:49 +03:00
Lauri Ojansivu c250554177 Update translations. Add Chinese (Hong Kong). 2019-05-06 20:57:01 +03:00
Lauri Ojansivu de772a8c3b Update changelog. 2019-04-29 01:18:17 +03:00
Lauri Ojansivu 23f1cf5f49 Update translations. 2019-04-29 01:17:52 +03:00
Lauri Ojansivu 723fa11a74 Merge pull request #2385 from faust64/patch-1
fix(oidc): can not log in
2019-04-26 23:08:45 +03:00
Lauri Ojansivu 94b602e167 Update translations. 2019-04-26 23:07:38 +03:00
Samuel b17359ec6f fix(oidc): can not log in
Trying to configure wekan authenticating against LemonLDAP-NG, I used to read about errors like the following:

```
XXX: getUserInfo response:  { sub: 'demoone' }
XXX: userinfo: { sub: 'demoone' }
{"line":"431","file":"oauth.js","message":"Error in OAuth Server: id is not defined","time":{"$date":1556286530412},"level":"warn"}
Exception while invoking method 'login' { stack: 'ReferenceError: id is not defined\n    at Object.handleOauthRequest (packages/wekan-oidc.js:39:68)\n    at OAuth._requestHandlers.(anonymous function) (packages/oauth2.js:27:31)\n    at middleware (packages/oauth.js:203:5)\n    at packages/oauth.js:176:5',
source: 'method' }
```

Looking at the sources, that error message seems to be right: we have several references to `id`, `uid`, `displayName` or `email`, which are not defined. Probably a typo, assuming we meant these to be strings.

Applying that patch, I confirm I can finally log in:

```
XXX: getUserInfo response:  { sub: 'demoone' }
XXX: userinfo: { sub: 'demoone' }
XXX: serviceData: { id: undefined,
  username: undefined,
  fullname: undefined,
  accessToken: 'e57dc4e9e81cc98c279db3ed08b1c72f',
  expiresAt: 1556298699213,
  email: undefined }
XXX: profile: { name: undefined, email: undefined }
```

All the credit goes to @pcurie .
2019-04-26 18:21:42 +02:00
guillaume cdef8a33e4 Delete user feature 2019-04-26 17:53:48 +02:00
Lauri Ojansivu 11a91bfc78 Update translations. 2019-04-24 16:12:29 +03:00
70 changed files with 1486 additions and 440 deletions

No files matched your search

+1 -1
View File
@@ -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 = bg_BG:bg, en_GB:en-GB, es_AR:es-AR, el_GR:el, fi_FI:fi, hu_HU:hu, id_ID:id, mn_MN:mn, no:nb, lv_LV:lv, pt_BR:pt-BR, ro_RO:ro, zh_CN:zh-CN, zh_TW:zh-TW
lang_map = bg_BG:bg, en_GB:en-GB, es_AR:es-AR, el_GR:el, fi_FI:fi, hu_HU:hu, id_ID:id, mn_MN:mn, no:nb, lv_LV:lv, pt_BR:pt-BR, ro_RO:ro, zh_CN:zh-CN, zh_TW:zh-TW, zh_HK:zh-HK
[wekan.application]
file_filter = i18n/<lang>.i18n.json
+107 -1
View File
@@ -1,3 +1,109 @@
# v2.73 2019-05-14 Wekan release
This release fixes the following bugs with Apache I-CLA:
- [Card count placement and export API functionality back](https://github.com/wekan/wekan/pulls/2406).
Thanks to bentiss.
- [Few fixes for Dockerfile](https://github.com/wekan/wekan/pulls/2407).
Thanks to bentiss.
and fixes the following bugs:
- Fixed [#2338](https://github.com/wekan/wekan/issues/2338) -> [Slow opening of big boards with too many archived items](https://github.com/wekan/wekan/pull/2402).
If some Wekan users see errors with this, please empty your browser cache.
Thanks to nerminator.
Thanks to above GitHub users for their contributions and translators for their translations.
# v2.72 2019-05-13 Wekan release
This release adds the following new features:
- [Added BIDI support to "Add Card"](https://github.com/wekan/wekan/pull/2401).
Related [#884](https://github.com/wekan/wekan/issues/884).
Thanks to guyzyl.
Thanks to above GitHub users for their contributions and translators for their translations.
# v2.71 2019-05-12 Wekan release
This release adds the following new features:
- [Add partentId support on card web API](https://github.com/wekan/wekan/pulls/2400).
Thanks to atilaromero.
Thanks to above GitHub users for their contributions and translators for their translations.
# v2.70 2019-05-11 Wekan release
This release adds the following new features:
- [View markdown on List names, Custom Fields (Text and Dropdown), Label names,
All Boards view Board names and Board descriptions](https://github.com/wekan/wekan/commit/b795115042c2eb6bccbf029f21d78849a44128ca).
Related [#2334](https://github.com/wekan/wekan/issues/2334).
Thanks to shaygover and xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v2.69 2019-05-11 Wekan release
This release fixes the following translation names:
- [Fix translation name in Wekan menu: oc to Occitan](https://github.com/wekan/wekan/commit/db40ca25ac5df17fcc8b7c93f12b7e2bffc349d2).
Thanks to xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v2.68 2019-05-10 Wekan release
This release adds the following new features:
- [Option to login to the LDAP server with the user's own username and password, instead of an administrator
key](https://github.com/wekan/wekan/pull/2399). Default: false (use administrator key).
With new setting: LDAP_USER_AUTHENTICATION=true.
Thanks to thiagofernando.
- [Added above new LDAP_USER_AUTHENTION=true option to Snap, Docker and Source settings](https://github.com/wekan/wekan/commit/3bbc805ee42e3c1638b50260d3fafc2b5f936923).
Thanks to xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v2.67 2019-05-10 Wekan release
This release adds the following new features:
- [Move board to Archive button at each board at All Boards page](https://github.com/wekan/wekan/commit/828f6ea321020eda77fea399df52889e2081dfac).
Thanks to xet7. Related [#2389](https://github.com/wekan/wekan/issues/2389).
- [If adding Subtasks does not work on old board, added wiki page how to make it work again](https://github.com/wekan/wekan/wiki/Subtasks).
Thanks to xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v2.66 2019-05-09 Wekan release
This release adds the following new features:
- [Delete user feature](https://github.com/wekan/wekan/pull/2384).
Thanks to Akuket.
- Change to Delete user feature: [When last board admin is removed, board is not deleted, other board users can
still use it](https://github.com/wekan/wekan/commit/e1b016cf3d4ff93e9e0fe1feb96372e3e1625233).
Thanks to xet7.
and adds the following new translations:
- Add Chinese (Hong Kong).
Thanks to translators.
and fixes the following bugs:
- [Fix OIDC login](https://github.com/wekan/wekan/pull/2385). Related [#2383](https://github.com/wekan/wekan/issues/2383).
Thanks to faust64.
- [Fix missing profile checks](https://github.com/wekan/wekan/pull/2396).
Thanks to justinr1234.
- [Fix RTL issue #884, part 1](https://github.com/wekan/wekan/pull/2395).
Thanks to guyzyl.
Thanks to above GitHub users for their contributions and translators for their translations.
# v2.65 2019-04-24 Wekan release
This release adds the following new features:
@@ -63,7 +169,7 @@ and adds the following updates:
and fixes the following bugs:
- [Fix Full width of lists and space before first list](https://github.com/wekan/wekan/pull/2343).
Thanks to hupptehcnologies.
Thanks to hupptechnologies.
- Remove [extra](https://github.com/wekan/wekan/pull/2332) [quotes](https://github.com/wekan/wekan/pull/2333) from docker-compose.yml.
Thanks to hibare.
- Fix Docker builds by moving all separately cloned wekan/packages/* repos like ldap, oidc, etc code to wekan repo code,
+6 -5
View File
@@ -61,6 +61,7 @@ ENV BUILD_DEPS="apt-utils bsdtar gnupg gosu wget curl bzip2 build-essential pyth
LDAP_ENCRYPTION=false \
LDAP_CA_CERT="" \
LDAP_REJECT_UNAUTHORIZED=false \
LDAP_USER_AUTHENTICATION=false \
LDAP_USER_SEARCH_FILTER="" \
LDAP_USER_SEARCH_SCOPE="" \
LDAP_USER_SEARCH_FIELD="" \
@@ -193,7 +194,7 @@ RUN \
\
# Get additional packages
#mkdir -p /home/wekan/app/packages && \
chown wekan:wekan --recursive /home/wekan && \
#chown wekan:wekan --recursive /home/wekan && \
# REPOS BELOW ARE INCLUDED TO WEKAN REPO
#cd /home/wekan/app/packages && \
#gosu wekan:wekan git clone --depth 1 -b master https://github.com/wekan/flow-router.git kadira-flow-router && \
@@ -211,7 +212,7 @@ RUN \
gosu wekan:wekan /home/wekan/.meteor/meteor -- help; \
\
# extract the OpenAPI specification
npm install -g api2html@0.3.0 && \
npm install -g api2html@0.3.3 && \
mkdir -p /home/wekan/python && \
chown wekan:wekan --recursive /home/wekan/python && \
cd /home/wekan/python && \
@@ -219,9 +220,9 @@ RUN \
cd /home/wekan/python/esprima-python && \
python3 setup.py install --record files.txt && \
cd /home/wekan/app &&\
mkdir -p ./public/api && \
python3 ./openapi/generate_openapi.py --release $(git describe --tags --abbrev=0) > ./public/api/wekan.yml && \
/opt/nodejs/bin/api2html -c ./public/logo-header.png -o ./public/api/wekan.html ./public/api/wekan.yml; \
gosu wekan:wekan mkdir -p ./public/api && \
gosu wekan:wekan python3 ./openapi/generate_openapi.py --release $(git describe --tags --abbrev=0) > ./public/api/wekan.yml && \
gosu wekan:wekan /opt/nodejs/bin/api2html -c ./public/logo-header.png -o ./public/api/wekan.html ./public/api/wekan.yml; \
# Build app
cd /home/wekan/app && \
gosu wekan:wekan /home/wekan/.meteor/meteor add standard-minifier-js && \
+1 -1
View File
@@ -1,5 +1,5 @@
appId: wekan-public/apps/77b94f60-dec9-0136-304e-16ff53095928
appVersion: "v2.65.0"
appVersion: "v2.73.0"
files:
userUploads:
- README.md
+2
View File
@@ -30,6 +30,8 @@ template(name="boardBody")
+listsGroup(currentBoard)
else if isViewCalendar
+calendarView
else
+listsGroup(currentBoard)
template(name="calendarView")
if isViewCalendar
+5 -5
View File
@@ -14,7 +14,7 @@ BlazeComponent.extendComponent({
const currentBoardId = Session.get('currentBoard');
if (!currentBoardId)
return;
const handle = subManager.subscribe('board', currentBoardId);
const handle = subManager.subscribe('board', currentBoardId, false);
Tracker.nonreactive(() => {
Tracker.autorun(() => {
this.isBoardReady.set(handle.ready());
@@ -191,19 +191,19 @@ BlazeComponent.extendComponent({
isViewSwimlanes() {
const currentUser = Meteor.user();
if (!currentUser) return false;
return (currentUser.profile.boardView === 'board-view-swimlanes');
return ((currentUser.profile || {}).boardView === 'board-view-swimlanes');
},
isViewLists() {
const currentUser = Meteor.user();
if (!currentUser) return true;
return (currentUser.profile.boardView === 'board-view-lists');
return ((currentUser.profile || {}).boardView === 'board-view-lists');
},
isViewCalendar() {
const currentUser = Meteor.user();
if (!currentUser) return false;
return (currentUser.profile.boardView === 'board-view-cal');
return ((currentUser.profile || {}).boardView === 'board-view-cal');
},
openNewListForm() {
@@ -335,6 +335,6 @@ BlazeComponent.extendComponent({
isViewCalendar() {
const currentUser = Meteor.user();
if (!currentUser) return false;
return (currentUser.profile.boardView === 'board-view-cal');
return ((currentUser.profile || {}).boardView === 'board-view-cal');
},
}).register('calendarView');
+3 -3
View File
@@ -98,7 +98,7 @@ template(name="boardHeaderBar")
a.board-header-btn.js-toggle-board-view(
title="{{_ 'board-view'}}")
i.fa.fa-th-large
span {{_ currentUser.profile.boardView}}
span {{#if currentUser.profile.boardView}}{{_ currentUser.profile.boardView}}{{else}}{{_ 'board-view-lists'}}{{/if}}
if canModifyBoard
a.board-header-btn.js-multiselection-activate(
@@ -193,10 +193,10 @@ template(name="boardChangeTitlePopup")
form
label
| {{_ 'title'}}
input.js-board-name(type="text" value=title autofocus)
input.js-board-name(type="text" value=title autofocus dir="auto")
label
| {{_ 'description'}}
textarea.js-board-desc= description
textarea.js-board-desc(dir="auto")= description
input.primary.wide(type="submit" value="{{_ 'rename'}}")
template(name="boardCreateRulePopup")
+5 -3
View File
@@ -89,12 +89,14 @@ BlazeComponent.extendComponent({
},
'click .js-toggle-board-view'() {
const currentUser = Meteor.user();
if (currentUser.profile.boardView === 'board-view-swimlanes') {
if ((currentUser.profile || {}).boardView === 'board-view-swimlanes') {
currentUser.setBoardView('board-view-cal');
} else if (currentUser.profile.boardView === 'board-view-lists') {
} else if ((currentUser.profile || {}).boardView === 'board-view-lists') {
currentUser.setBoardView('board-view-swimlanes');
} else if (currentUser.profile.boardView === 'board-view-cal') {
} else if ((currentUser.profile || {}).boardView === 'board-view-cal') {
currentUser.setBoardView('board-view-lists');
} else {
currentUser.setBoardView('board-view-swimlanes');
}
},
'click .js-toggle-sidebar'() {
+9 -4
View File
@@ -18,11 +18,15 @@ template(name="boardList")
else
a.js-open-board.board-list-item(href="{{pathFor 'board' id=_id slug=slug}}")
span.details
span.board-list-item-name= title
span.board-list-item-name
+viewer
= title
i.fa.js-star-board(
class="fa-star{{#if isStarred}} is-star-active{{else}}-o{{/if}}"
title="{{_ 'star-board-title'}}")
p.board-list-item-desc= description
p.board-list-item-desc
+viewer
= description
if hasSpentTimeCards
i.fa.js-has-spenttime-cards(
class="fa-circle{{#if hasOvertimeCards}} has-overtime-card-active{{else}} no-overtime-card-active{{/if}}"
@@ -30,8 +34,9 @@ template(name="boardList")
i.fa.js-clone-board(
class="fa-clone"
title="{{_ 'duplicate-board'}}")
i.fa.js-archive-board(
class="fa-archive"
title="{{_ 'archive-board'}}")
template(name="boardListHeaderBar")
h1 {{_ 'my-boards'}}
+7 -2
View File
@@ -33,12 +33,12 @@ BlazeComponent.extendComponent({
},
hasOvertimeCards() {
subManager.subscribe('board', this.currentData()._id);
subManager.subscribe('board', this.currentData()._id, false);
return this.currentData().hasOvertimeCards();
},
hasSpentTimeCards() {
subManager.subscribe('board', this.currentData()._id);
subManager.subscribe('board', this.currentData()._id, false);
return this.currentData().hasSpentTimeCards();
},
@@ -70,6 +70,11 @@ BlazeComponent.extendComponent({
);
evt.preventDefault();
},
'click .js-archive-board'(evt) {
const boardId = this.currentData()._id;
Meteor.call('archiveBoard', boardId);
evt.preventDefault();
},
'click .js-accept-invite'() {
const boardId = this.currentData()._id;
Meteor.user().removeInvite(boardId);
+14
View File
@@ -106,15 +106,29 @@ $spaceBetweenTiles = 16px
transition-duration: .15s
transition-property: color, font-size, background
.fa-archive
position: absolute;
bottom: 0
font-size: 14px
height: 18px
line-height: 18px
opacity: 0
left: 0
padding: 9px 9px
transition-duration: .15s
transition-property: color, font-size, background
li:hover a
&:hover
.fa-star,
.fa-clone,
.fa-archive,
.fa-star-o
color: white
.fa-star,
.fa-clone,
.fa-archive,
.fa-star-o
color: white
opacity: .75
@@ -4,9 +4,10 @@ template(name="cardCustomFieldsPopup")
li.item(class="")
a.name.js-select-field(href="#")
span.full-name
+viewer
= name
if hasCustomField
i.fa.fa-check
i.fa.fa-check
hr
a.quiet-button.full.js-settings
i.fa.fa-cog
@@ -61,9 +62,13 @@ template(name="cardCustomField-dropdown")
select.inline
each items
if($eq data.value this._id)
option(value=_id selected="selected") {{name}}
option(value=_id selected="selected")
+viewer
= name
else
option(value=_id) {{name}}
option(value=_id)
+viewer
= name
.edit-controls.clearfix
button.primary(type="submit") {{_ 'save'}}
a.fa.fa-times-thin.js-close-inlined-form
@@ -73,4 +78,4 @@ template(name="cardCustomField-dropdown")
+viewer
= selectedItem
else
| {{_ 'edit'}}
| {{_ 'edit'}}
+8 -5
View File
@@ -77,7 +77,9 @@ template(name="cardDetails")
h3.card-details-item-title {{_ 'labels'}}
a(class="{{#if canModifyCard}}js-add-labels{{else}}is-disabled{{/if}}" title="{{_ 'card-labels-title'}}")
each labels
span.card-label(class="card-label-{{color}}" title=name)= name
span.card-label(class="card-label-{{color}}" title=name)
+viewer
= name
if canModifyCard
a.card-label.add-label.js-add-labels(title="{{_ 'card-labels-title'}}")
i.fa.fa-plus
@@ -86,7 +88,8 @@ template(name="cardDetails")
each customFieldsWD
.card-details-item.card-details-item-customfield
h3.card-details-item-title
= definition.name
+viewer
= definition.name
+cardCustomField
.card-details-items
@@ -197,20 +200,20 @@ template(name="cardDetails")
+activities(card=this mode="card")
template(name="editCardTitleForm")
textarea.js-edit-card-title(rows='1' autofocus)
textarea.js-edit-card-title(rows='1' autofocus dir="auto")
= getTitle
.edit-controls.clearfix
button.primary.confirm.js-submit-edit-card-title-form(type="submit") {{_ 'save'}}
a.fa.fa-times-thin.js-close-inlined-form
template(name="editCardRequesterForm")
input.js-edit-card-requester(type='text' autofocus value=getRequestedBy)
input.js-edit-card-requester(type='text' autofocus value=getRequestedBy dir="auto")
.edit-controls.clearfix
button.primary.confirm.js-submit-edit-card-requester-form(type="submit") {{_ 'save'}}
a.fa.fa-times-thin.js-close-inlined-form
template(name="editCardAssignerForm")
input.js-edit-card-assigner(type='text' autofocus value=getAssignedBy)
input.js-edit-card-assigner(type='text' autofocus value=getAssignedBy dir="auto")
.edit-controls.clearfix
button.primary.confirm.js-submit-edit-card-assigner-form(type="submit") {{_ 'save'}}
a.fa.fa-times-thin.js-close-inlined-form
+3 -3
View File
@@ -424,7 +424,7 @@ Template.moveCardPopup.events({
});
BlazeComponent.extendComponent({
onCreated() {
subManager.subscribe('board', Session.get('currentBoard'));
subManager.subscribe('board', Session.get('currentBoard'), false);
this.selectedBoardId = new ReactiveVar(Session.get('currentBoard'));
},
@@ -453,7 +453,7 @@ BlazeComponent.extendComponent({
return [{
'change .js-select-boards'(evt) {
this.selectedBoardId.set($(evt.currentTarget).val());
subManager.subscribe('board', this.selectedBoardId.get());
subManager.subscribe('board', this.selectedBoardId.get(), false);
},
}];
},
@@ -676,7 +676,7 @@ BlazeComponent.extendComponent({
if (selection === 'none') {
this.parentBoard.set(null);
} else {
subManager.subscribe('board', $(evt.currentTarget).val());
subManager.subscribe('board', $(evt.currentTarget).val(), false);
this.parentBoard.set(selection);
list.prop('disabled', false);
}
+1 -1
View File
@@ -56,7 +56,7 @@ template(name="addChecklistItemForm")
a.fa.fa-times-thin.js-close-inlined-form
template(name="editChecklistItemForm")
textarea.js-edit-checklist-item(rows='1' autofocus)
textarea.js-edit-checklist-item(rows='1' autofocus dir="auto")
if $eq type 'item'
= item.title
else
+2 -1
View File
@@ -31,7 +31,8 @@ template(name="cardLabelsPopup")
a.card-label-edit-button.fa.fa-pencil.js-edit-label
span.card-label.card-label-selectable.js-select-label(class="card-label-{{color}}"
class="{{# if isLabelSelected ../_id }}active{{/if}}")
= name
+viewer
= name
if(isLabelSelected ../_id)
i.card-label-selectable-icon.fa.fa-check
if currentUser.isBoardAdmin
+2 -1
View File
@@ -58,7 +58,8 @@ template(name="minicard")
.minicard-custom-field
if definition.showLabelOnMiniCard
.minicard-custom-field-item
= definition.name
+viewer
= definition.name
.minicard-custom-field-item
+viewer
= trueValue
+3 -3
View File
@@ -50,13 +50,13 @@ template(name="subtaskDeleteDialog")
button.toggle-delete-subtask-dialog(type="button") {{_ 'cancel'}}
template(name="addSubtaskItemForm")
textarea.js-add-subtask-item(rows='1' autofocus)
textarea.js-add-subtask-item(rows='1' autofocus dir="auto")
.edit-controls.clearfix
button.primary.confirm.js-submit-add-subtask-item-form(type="submit") {{_ 'save'}}
a.fa.fa-times-thin.js-close-inlined-form
template(name="editSubtaskItemForm")
textarea.js-edit-subtask-item(rows='1' autofocus)
textarea.js-edit-subtask-item(rows='1' autofocus dir="auto")
if $eq type 'item'
= item.title
else
@@ -76,7 +76,7 @@ template(name="subtasksItems")
else
+subtaskItemDetail(item = item subtasks = subtasks)
if canModifyCard
+inlinedForm(autoclose=false classNames="js-add-subtask-item" subtasks = subtasks)
+inlinedForm(autoclose=false classNames="js-add-subtask-item" subtasks = subtasks dir="auto")
+addSubtaskItemForm
else
a.add-subtask-item.js-open-inlined-form
+2 -2
View File
@@ -69,10 +69,10 @@ BlazeComponent.extendComponent({
const listId = Blaze.getData(ui.item.parents('.list').get(0))._id;
const currentBoard = Boards.findOne(Session.get('currentBoard'));
let swimlaneId = '';
const boardView = Meteor.user().profile.boardView;
const boardView = (Meteor.user().profile || {}).boardView;
if (boardView === 'board-view-swimlanes' || currentBoard.isTemplatesBoard())
swimlaneId = Blaze.getData(ui.item.parents('.swimlane').get(0))._id;
else if ((boardView === 'board-view-lists') || (boardView === 'board-view-cal'))
else if ((boardView === 'board-view-lists') || (boardView === 'board-view-cal') || !boardView)
swimlaneId = currentBoard.getDefaultSwimline()._id;
// Normally the jquery-ui sortable library moves the dragged DOM element
+4
View File
@@ -99,6 +99,10 @@
.highlight
color: #ce1414
.cardCount
color: #8c8c8c
font-size: 0.8em
.list-body
flex: 1 1 auto
flex-direction: column
+3 -3
View File
@@ -39,7 +39,7 @@ template(name="addCardForm")
.minicard-labels
each getLabels
.minicard-label(class="card-label-{{color}}" title="{{name}}")
textarea.minicard-composer-textarea.js-card-title(autofocus)
textarea.minicard-composer-textarea.js-card-title(autofocus dir="auto")
if members.get
.minicard-members.js-minicard-composer-members
each members.get
@@ -96,7 +96,7 @@ template(name="searchElementPopup")
form
label
| {{_ 'title'}}
input.js-element-title(type="text" placeholder="{{_ 'title'}}" autofocus required)
input.js-element-title(type="text" placeholder="{{_ 'title'}}" autofocus required dir="auto")
unless isTemplateSearch
label {{_ 'boards'}}:
.link-board-wrapper
@@ -105,7 +105,7 @@ template(name="searchElementPopup")
each boards
option(value="{{_id}}") {{title}}
form.js-search-term-form
input(type="text" name="searchTerm" placeholder="{{_ 'search-example'}}" autofocus)
input(type="text" name="searchTerm" placeholder="{{_ 'search-example'}}" autofocus dir="auto")
.list-body.js-perfect-scrollbar.search-card-results
.minicards.clearfix.js-minicards
if isBoardTemplateSearch
+15 -15
View File
@@ -48,7 +48,7 @@ BlazeComponent.extendComponent({
const board = this.data().board();
let linkedId = '';
let swimlaneId = '';
const boardView = Meteor.user().profile.boardView;
const boardView = (Meteor.user().profile || {}).boardView;
let cardType = 'cardType-card';
if (title) {
if (board.isTemplatesBoard()) {
@@ -72,7 +72,7 @@ BlazeComponent.extendComponent({
}
} else if (boardView === 'board-view-swimlanes')
swimlaneId = this.parentComponent().parentComponent().data()._id;
else if ((boardView === 'board-view-lists') || (boardView === 'board-view-cal'))
else if ((boardView === 'board-view-lists') || (boardView === 'board-view-cal') || !boardView)
swimlaneId = board.getDefaultSwimline()._id;
const _id = Cards.insert({
@@ -149,7 +149,7 @@ BlazeComponent.extendComponent({
idOrNull(swimlaneId) {
const currentUser = Meteor.user();
if (currentUser.profile.boardView === 'board-view-swimlanes' ||
if ((currentUser.profile || {}).boardView === 'board-view-swimlanes' ||
this.data().board().isTemplatesBoard())
return swimlaneId;
return undefined;
@@ -348,7 +348,7 @@ BlazeComponent.extendComponent({
this.boardId = Session.get('currentBoard');
// In order to get current board info
subManager.subscribe('board', this.boardId);
subManager.subscribe('board', this.boardId, false);
this.board = Boards.findOne(this.boardId);
// List where to insert card
const list = $(Popup._getTopStack().openerElement).closest('.js-list');
@@ -356,10 +356,10 @@ BlazeComponent.extendComponent({
// Swimlane where to insert card
const swimlane = $(Popup._getTopStack().openerElement).closest('.js-swimlane');
this.swimlaneId = '';
const boardView = Meteor.user().profile.boardView;
const boardView = (Meteor.user().profile || {}).boardView;
if (boardView === 'board-view-swimlanes')
this.swimlaneId = Blaze.getData(swimlane[0])._id;
else if (boardView === 'board-view-lists')
else if (boardView === 'board-view-lists' || !boardView)
this.swimlaneId = Swimlanes.findOne({boardId: this.boardId})._id;
},
@@ -414,7 +414,7 @@ BlazeComponent.extendComponent({
events() {
return [{
'change .js-select-boards'(evt) {
subManager.subscribe('board', $(evt.currentTarget).val());
subManager.subscribe('board', $(evt.currentTarget).val(), false);
this.selectedBoardId.set($(evt.currentTarget).val());
},
'change .js-select-swimlanes'(evt) {
@@ -485,13 +485,13 @@ BlazeComponent.extendComponent({
this.isBoardTemplateSearch;
let board = {};
if (this.isTemplateSearch) {
board = Boards.findOne(Meteor.user().profile.templatesBoardId);
board = Boards.findOne((Meteor.user().profile || {}).templatesBoardId);
} else {
// Prefetch first non-current board id
board = Boards.findOne({
archived: false,
'members.userId': Meteor.userId(),
_id: {$nin: [Session.get('currentBoard'), Meteor.user().profile.templatesBoardId]},
_id: {$nin: [Session.get('currentBoard'), (Meteor.user().profile || {}).templatesBoardId]},
});
}
if (!board) {
@@ -500,17 +500,17 @@ BlazeComponent.extendComponent({
}
const boardId = board._id;
// Subscribe to this board
subManager.subscribe('board', boardId);
subManager.subscribe('board', boardId, false);
this.selectedBoardId = new ReactiveVar(boardId);
if (!this.isBoardTemplateSearch) {
this.boardId = Session.get('currentBoard');
// In order to get current board info
subManager.subscribe('board', this.boardId);
subManager.subscribe('board', this.boardId, false);
this.swimlaneId = '';
// Swimlane where to insert card
const swimlane = $(Popup._getTopStack().openerElement).parents('.js-swimlane');
if (Meteor.user().profile.boardView === 'board-view-swimlanes')
if ((Meteor.user().profile || {}).boardView === 'board-view-swimlanes')
this.swimlaneId = Blaze.getData(swimlane[0])._id;
else
this.swimlaneId = Swimlanes.findOne({boardId: this.boardId})._id;
@@ -547,7 +547,7 @@ BlazeComponent.extendComponent({
} else if (this.isBoardTemplateSearch) {
const boards = board.searchBoards(this.term.get());
boards.forEach((board) => {
subManager.subscribe('board', board.linkedId);
subManager.subscribe('board', board.linkedId, false);
});
return boards;
} else {
@@ -558,7 +558,7 @@ BlazeComponent.extendComponent({
events() {
return [{
'change .js-select-boards'(evt) {
subManager.subscribe('board', $(evt.currentTarget).val());
subManager.subscribe('board', $(evt.currentTarget).val(), false);
this.selectedBoardId.set($(evt.currentTarget).val());
},
'submit .js-search-term-form'(evt) {
@@ -620,7 +620,7 @@ BlazeComponent.extendComponent({
this.listId = this.parentComponent().data()._id;
this.swimlaneId = '';
const boardView = Meteor.user().profile.boardView;
const boardView = (Meteor.user().profile || {}).boardView;
if (boardView === 'board-view-swimlanes')
this.swimlaneId = this.parentComponent().parentComponent().parentComponent().data()._id;
},
+3 -2
View File
@@ -10,7 +10,8 @@ template(name="listHeader")
a.list-header-left-icon.fa.fa-angle-left.js-unselect-list
h2.list-header-name(
class="{{#if currentUser.isBoardMember}}js-open-inlined-form is-editable{{/if}}")
= title
+viewer
= title
if wipLimit.enabled
|&nbsp;(
span(class="{{#if reachedWipLimit}}highlight{{/if}}") {{cards.count}}
@@ -18,7 +19,7 @@ template(name="listHeader")
if showCardsCountForList cards.count
|&nbsp;
p.quiet.small {{cardsCount}} {{_ 'cards-count'}}
span(class="cardCount") {{cardsCount}} {{_ 'cards-count'}}
if isMiniScreen
if currentList
if isWatching
+1 -1
View File
@@ -30,7 +30,7 @@ BlazeComponent.extendComponent({
cardsCount() {
const list = Template.currentData();
let swimlaneId = '';
const boardView = Meteor.user().profile.boardView;
const boardView = (Meteor.user().profile || {}).boardView;
if (boardView === 'board-view-swimlanes')
swimlaneId = this.parentComponent().parentComponent().data()._id;
+2 -1
View File
@@ -1,5 +1,6 @@
template(name="editor")
textarea.editor(
dir="auto"
class="{{class}}"
id=id
autofocus=autofocus
@@ -7,7 +8,7 @@ template(name="editor")
+Template.contentBlock
template(name="viewer")
.viewer
.viewer(dir="auto")
+mentions
+markdown
{{> UI.contentBlock }}
+2
View File
@@ -68,6 +68,8 @@ Template.userFormsLayout.helpers({
name = 'Brezhoneg';
} else if (lang.name === 'ig') {
name = 'Igbo';
} else if (lang.name === 'oc') {
name = 'Occitan';
}
return { tag, name };
}).sort(function(a, b) {
+4 -1
View File
@@ -107,5 +107,8 @@ template(name="editUserPopup")
label
| {{_ 'password'}}
input.js-profile-password(type="password")
div.buttonsContainer
input.primary.wide(type="submit" value="{{_ 'save'}}")
div
input#deleteButton.primary.wide(type="button" value="{{_ 'delete'}}")
input.primary.wide(type="submit" value="{{_ 'save'}}")
+9
View File
@@ -98,6 +98,7 @@ Template.peopleRow.helpers({
Template.editUserPopup.onCreated(function() {
this.authenticationMethods = new ReactiveVar([]);
this.errorMessage = new ReactiveVar('');
Meteor.call('getAuthenticationsEnabled', (_, result) => {
if (result) {
@@ -129,6 +130,9 @@ Template.editUserPopup.helpers({
const selected = Users.findOne(userId).authenticationMethod;
return selected === 'ldap';
},
errorMessage() {
return Template.instance().errorMessage.get();
},
});
BlazeComponent.extendComponent({
@@ -220,4 +224,9 @@ Template.editUserPopup.events({
});
} else Popup.close();
},
'click #deleteButton'() {
Users.remove(this.userId);
Popup.close();
},
});
@@ -34,3 +34,15 @@ table
button
min-width: 60px;
.content-wrapper
margin-top: 10px
.buttonsContainer
display: flex
input
margin: 0
div
margin: auto
+3 -1
View File
@@ -189,7 +189,9 @@ template(name="labelsWidget")
each currentBoard.labels
a.card-label(class="card-label-{{color}}"
class="{{#if currentUser.isNotCommentOnly}}js-label{{/if}}")
span.card-label-name= name
span.card-label-name
+viewer
= name
if currentUser.isBoardAdmin
a.card-label.add-label.js-add-label
i.fa.fa-plus
+49 -47
View File
@@ -1,54 +1,56 @@
template(name="archivesSidebar")
+basicTabs(tabs=tabs)
+tabContent(slug="cards")
p.quiet
a.js-restore-all-cards {{_ 'restore-all'}}
| -
a.js-delete-all-cards {{_ 'delete-all'}}
each archivedCards
.minicard-wrapper.js-minicard
+minicard(this)
if currentUser.isBoardMember
if isArchiveReady.get
+basicTabs(tabs=tabs)
+tabContent(slug="cards")
p.quiet
a.js-restore-card {{_ 'restore'}}
a.js-restore-all-cards {{_ 'restore-all'}}
| -
a.js-delete-card {{_ 'delete'}}
if cardIsInArchivedList
p.quiet.small ({{_ 'warn-list-archived'}})
else
p.no-items-message {{_ 'no-archived-cards'}}
+tabContent(slug="lists")
p.quiet
a.js-restore-all-lists {{_ 'restore-all'}}
| -
a.js-delete-all-lists {{_ 'delete-all'}}
ul.archived-lists
each archivedLists
li.archived-lists-item
= title
a.js-delete-all-cards {{_ 'delete-all'}}
each archivedCards
.minicard-wrapper.js-minicard
+minicard(this)
if currentUser.isBoardMember
p.quiet
a.js-restore-list {{_ 'restore'}}
a.js-restore-card {{_ 'restore'}}
| -
a.js-delete-list {{_ 'delete'}}
else
li.no-items-message {{_ 'no-archived-lists'}}
a.js-delete-card {{_ 'delete'}}
if cardIsInArchivedList
p.quiet.small ({{_ 'warn-list-archived'}})
else
p.no-items-message {{_ 'no-archived-cards'}}
+tabContent(slug="swimlanes")
p.quiet
a.js-restore-all-swimlanes {{_ 'restore-all'}}
| -
a.js-delete-all-swimlanes {{_ 'delete-all'}}
ul.archived-lists
each archivedSwimlanes
li.archived-lists-item
= title
if currentUser.isBoardMember
p.quiet
a.js-restore-swimlane {{_ 'restore'}}
| -
a.js-delete-swimlane {{_ 'delete'}}
else
li.no-items-message {{_ 'no-archived-swimlanes'}}
+tabContent(slug="lists")
p.quiet
a.js-restore-all-lists {{_ 'restore-all'}}
| -
a.js-delete-all-lists {{_ 'delete-all'}}
ul.archived-lists
each archivedLists
li.archived-lists-item
= title
if currentUser.isBoardMember
p.quiet
a.js-restore-list {{_ 'restore'}}
| -
a.js-delete-list {{_ 'delete'}}
else
li.no-items-message {{_ 'no-archived-lists'}}
+tabContent(slug="swimlanes")
p.quiet
a.js-restore-all-swimlanes {{_ 'restore-all'}}
| -
a.js-delete-all-swimlanes {{_ 'delete-all'}}
ul.archived-lists
each archivedSwimlanes
li.archived-lists-item
= title
if currentUser.isBoardMember
p.quiet
a.js-restore-swimlane {{_ 'restore'}}
| -
a.js-delete-swimlane {{_ 'delete'}}
else
li.no-items-message {{_ 'no-archived-swimlanes'}}
else
+spinner
@@ -1,4 +1,26 @@
const subManager = new SubsManager();
BlazeComponent.extendComponent({
onCreated() {
this.isArchiveReady = new ReactiveVar(false);
// The pattern we use to manually handle data loading is described here:
// https://kadira.io/academy/meteor-routing-guide/content/subscriptions-and-data-management/using-subs-manager
// XXX The boardId should be readed from some sort the component "props",
// unfortunatly, Blaze doesn't have this notion.
this.autorun(() => {
const currentBoardId = Session.get('currentBoard');
if (!currentBoardId)
return;
const handle = subManager.subscribe('board', currentBoardId, true);
Tracker.nonreactive(() => {
Tracker.autorun(() => {
this.isArchiveReady.set( handle.ready() );
});
});
});
},
tabs() {
return [
{ name: TAPi18n.__('cards'), slug: 'cards' },
@@ -6,7 +6,9 @@ template(name="customFieldsSidebar")
div.minicard
a.fa.fa-pencil.js-edit-custom-field.minicard-edit-button
div.minicard-title
| {{ name }} ({{ type }})
+viewer
=name
| ({{ type }})
if currentUser.isBoardMember
hr
@@ -1,6 +1,6 @@
template(name="searchSidebar")
form.js-search-term-form
input(type="text" name="searchTerm" placeholder="{{_ 'search-example'}}" autofocus)
input(type="text" name="searchTerm" placeholder="{{_ 'search-example'}}" autofocus dir="auto")
.list-body.js-perfect-scrollbar
.minicards.clearfix.js-minicards
each (results)
+1 -1
View File
@@ -8,7 +8,7 @@ function currentListIsInThisSwimlane(swimlaneId) {
function currentCardIsInThisList(listId, swimlaneId) {
const currentCard = Cards.findOne(Session.get('currentCard'));
const currentUser = Meteor.user();
if (currentUser && currentUser.profile.boardView === 'board-view-swimlanes')
if (currentUser && currentUser.profile && currentUser.profile.boardView === 'board-view-swimlanes')
return currentCard && currentCard.listId === listId && currentCard.swimlaneId === swimlaneId;
else // Default view: board-view-lists
return currentCard && currentCard.listId === listId;
+4 -1
View File
@@ -53,7 +53,10 @@ template(name="editProfilePopup")
input.js-profile-email(type="email" value="{{emails.[0].address}}")
else
input.js-profile-email(type="email" value="{{emails.[0].address}}" readonly)
input.primary.wide(type="submit" value="{{_ 'save'}}")
div.buttonsContainer
input.primary.wide(type="submit" value="{{_ 'save'}}")
div
input#deleteButton.primary.wide(type="button" value="{{_ 'delete'}}")
template(name="changePasswordPopup")
+atForm(state='changePwd')
+7
View File
@@ -95,6 +95,11 @@ Template.editProfilePopup.events({
});
} else Popup.back();
},
'click #deleteButton'() {
Users.remove(Meteor.userId());
Popup.close();
AccountsTemplates.logout();
},
});
// XXX For some reason the useraccounts autofocus isnt working in this case.
@@ -114,6 +119,8 @@ Template.changeLanguagePopup.helpers({
name = 'Brezhoneg';
} else if (lang.name === 'ig') {
name = 'Igbo';
} else if (lang.name === 'oc') {
name = 'Occitan';
}
return { tag, name };
}).sort(function (a, b) {
+1 -1
View File
@@ -135,6 +135,6 @@ $(document).on('click', (evt) => {
}
});
$(document).on('click', 'a[href=#]', (evt) => {
$(document).on('click', 'a[href=\\#]', (evt) => {
evt.preventDefault();
});
+3
View File
@@ -400,6 +400,9 @@ services:
# Reject Unauthorized Certificate
#- LDAP_REJECT_UNAUTHORIZED=false
#
# Option to login to the LDAP server with the user's own username and password, instead of an administrator key. Default: false (use administrator key).
#- LDAP_USER_AUTHENTICATION="true"
#
# Optional extra LDAP filters. Don't forget the outmost enclosing parentheses if needed
#- LDAP_USER_SEARCH_FILTER=
#
+4 -4
View File
@@ -271,9 +271,9 @@
"email-enrollAccount-subject": "Ihr Benutzerkonto auf __siteName__ wurde erstellt",
"email-enrollAccount-text": "Hallo __user__,\n\num den Dienst nutzen zu können, klicken Sie bitte auf folgenden Link:\n\n__url__\n\nDanke.",
"email-fail": "Senden der E-Mail fehlgeschlagen",
"email-fail-text": "Fehler beim Senden des E-Mails",
"email-fail-text": "Fehler beim Senden der E-Mail",
"email-invalid": "Ungültige E-Mail-Adresse",
"email-invite": "via E-Mail einladen",
"email-invite": "per E-Mail einladen",
"email-invite-subject": "__inviter__ hat Ihnen eine Einladung geschickt",
"email-invite-text": "Hallo __user__,\n\n__inviter__ hat Sie zu dem Board \"__board__\" eingeladen.\n\nBitte klicken Sie auf folgenden Link:\n\n__url__\n\nDanke.",
"email-resetPassword-subject": "Setzten Sie ihr Passwort auf __siteName__ zurück",
@@ -686,8 +686,8 @@
"duplicate-board": "Board duplizieren",
"people-number": "Anzahl der Personen:",
"swimlaneDeletePopup-title": "Swimlane löschen?",
"swimlane-delete-pop": "Alle Aktionen werden aus dem Aktivitäts-Feed entfernt und du kannst die Swimlane auch nicht wiederherstellen: Es gibt kein Undo!",
"swimlane-delete-pop": "Alle Aktionen werden aus dem Aktivitätenfeed entfernt und die Swimlane kann nicht wiederhergestellt werden. Es gibt kein Rückgängig!",
"restore-all": "Alles wiederherstellen",
"delete-all": "Alles löschen",
"loading": "Loading, please wait."
"loading": "Laden, bitte warten."
}
+31 -31
View File
@@ -23,10 +23,10 @@
"act-createCustomField": "creó el campo personalizado __customField__ en la tarjeta __card__ de la lista __list__ del carril __swimlane__ del tablero __board__",
"act-createList": "añadida la lista __list__ al tablero __board__",
"act-addBoardMember": "añadido el mimbro __member__ al tablero __board__",
"act-archivedBoard": "El tablero __board__ se ha movido a Archivo",
"act-archivedCard": "La tarjeta __card__ de la lista __list__ del carril __swimlane__ del tablero __board__ se ha movido a Archivo",
"act-archivedList": "La lista __list__ del carril __swimlane__ del tablero __board__ se ha movido a Archivo",
"act-archivedSwimlane": "El carril __swimlane__ del tablero __board__ se ha movido a Archivo",
"act-archivedBoard": "El tablero __board__ se ha archivado",
"act-archivedCard": "La tarjeta __card__ de la lista __list__ del carril __swimlane__ del tablero __board__ se ha archivado",
"act-archivedList": "La lista __list__ del carril __swimlane__ del tablero __board__ se ha archivado",
"act-archivedSwimlane": "El carril __swimlane__ del tablero __board__ se ha archivado",
"act-importBoard": "importado el tablero __board__",
"act-importCard": "importada la tarjeta __card__ a la lista __list__ del carrril __swimlane__ del tablero __board__",
"act-importList": "importada la lista __list__ al carril __swimlane__ del tablero __board__",
@@ -42,7 +42,7 @@
"activities": "Actividades",
"activity": "Actividad",
"activity-added": "ha añadido %s a %s",
"activity-archived": "%s movido a Archivo",
"activity-archived": "%s se ha archivado",
"activity-attached": "ha adjuntado %s a %s",
"activity-created": "ha creado %s",
"activity-customfield-created": "creó el campo personalizado %s",
@@ -92,19 +92,19 @@
"and-n-other-card_plural": "y otras __count__ tarjetas",
"apply": "Aplicar",
"app-is-offline": "Cargando, espera por favor. Refrescar esta página causará pérdida de datos. Si la carga no funciona, por favor comprueba que el servidor no se ha parado.",
"archive": "Mover al Archivo",
"archive-all": "Mover todo al Archivo",
"archive-board": "Mover Tablero al Archivo",
"archive-card": "Mover tarjeta al Archivo",
"archive-list": "Mover Lista al Archivo",
"archive-swimlane": "Mover carril al Archivo",
"archive-selection": "Mover selección al Archivo",
"archiveBoardPopup-title": "¿Mover Tablero al Archivo?",
"archived-items": "Archivar",
"archive": "Archivar",
"archive-all": "Archivar todo",
"archive-board": "Archivar este tablero",
"archive-card": "Archivar esta tarjeta",
"archive-list": "Archivar esta lista",
"archive-swimlane": "Archivar este carril",
"archive-selection": "Archivar esta selección",
"archiveBoardPopup-title": "¿Archivar este tablero?",
"archived-items": "Archivo",
"archived-boards": "Tableros en Archivo",
"restore-board": "Restaurar el tablero",
"no-archived-boards": "No hay Tableros en el Archivo",
"archives": "Archivar",
"archives": "Archivo",
"template": "Plantilla",
"templates": "Plantillas",
"assign-member": "Asignar miembros",
@@ -133,8 +133,8 @@
"board-view-lists": "Listas",
"bucket-example": "Como “Cosas por hacer” por ejemplo",
"cancel": "Cancelar",
"card-archived": "Esta tarjeta se movió al Archivo",
"board-archived": "Este tablero se movió al Archivo",
"card-archived": "Se archivó esta tarjeta",
"board-archived": "Se archivó este tablero",
"card-comments-title": "Esta tarjeta tiene %s comentarios.",
"card-delete-notice": "la eliminación es permanente. Perderás todas las acciones asociadas a esta tarjeta.",
"card-delete-pop": "Se eliminarán todas las acciones del historial de actividades y no se podrá volver a abrir la tarjeta. Esta acción no puede deshacerse.",
@@ -347,7 +347,7 @@
"leave-board-pop": "¿Seguro que quieres abandonar __boardTitle__? Serás desvinculado de todas las tarjetas en este tablero.",
"leaveBoardPopup-title": "¿Abandonar el tablero?",
"link-card": "Enlazar a esta tarjeta",
"list-archive-cards": "Mover todas las tarjetas de la lista al Archivo",
"list-archive-cards": "Archivar todas las tarjetas de esta lista",
"list-archive-cards-pop": "Esto eliminará del tablero todas las tarjetas en esta lista. Para ver las tarjetas en el Archivo y recuperarlas al tablero haga click en \"Menu\" > \"Archivo\"",
"list-move-cards": "Mover todas las tarjetas de esta lista",
"list-select-cards": "Seleccionar todas las tarjetas de esta lista",
@@ -514,7 +514,7 @@
"OS_Loadavg": "Carga media del sistema",
"OS_Platform": "Plataforma del sistema",
"OS_Release": "Publicación del sistema",
"OS_Totalmem": "Memoria Total del sistema",
"OS_Totalmem": "Memoria total del sistema",
"OS_Type": "Tipo de sistema",
"OS_Uptime": "Tiempo activo del sistema",
"days": "días",
@@ -528,8 +528,8 @@
"no": "No",
"accounts": "Cuentas",
"accounts-allowEmailChange": "Permitir cambiar el correo electrónico",
"accounts-allowUserNameChange": "Permitir el cambio del nombre de usuario",
"createdAt": "Creado en",
"accounts-allowUserNameChange": "Permitir cambiar el nombre de usuario",
"createdAt": "Fecha de alta",
"verified": "Verificado",
"active": "Activo",
"card-received": "Recibido",
@@ -592,7 +592,7 @@
"set-filter": "Filtrar",
"r-moved-to": "Movido a",
"r-moved-from": "Movido desde",
"r-archived": "Movido a Archivo",
"r-archived": "Se archivó",
"r-unarchived": "Restaurado del archivo",
"r-a-card": "una tarjeta",
"r-when-a-label-is": "Cuando una etiqueta es",
@@ -610,11 +610,11 @@
"r-when-the-item": "Cuando el elemento de la lista de verificación es",
"r-checked": "Marcado",
"r-unchecked": "Desmarcado",
"r-move-card-to": "Mover tarjeta a",
"r-move-card-to": "Mover la tarjeta a",
"r-top-of": "Arriba de",
"r-bottom-of": "Abajo de",
"r-its-list": "su lista",
"r-archive": "Mover al Archivo",
"r-archive": "Archivar",
"r-unarchive": "Restaurar del Archivo",
"r-card": "tarjeta",
"r-add": "Añadir",
@@ -635,15 +635,15 @@
"r-to": "a",
"r-subject": "asunto",
"r-rule-details": "Detalle de la regla",
"r-d-move-to-top-gen": "Mover tarjeta arriba de su lista",
"r-d-move-to-top-spec": "Mover tarjeta arriba de la lista",
"r-d-move-to-bottom-gen": "Mover tarjeta abajo de su lista",
"r-d-move-to-bottom-spec": "Mover tarjeta al fondo de la lista",
"r-d-move-to-top-gen": "Mover la tarjeta al inicio de su lista",
"r-d-move-to-top-spec": "Mover la tarjeta al inicio de la lista",
"r-d-move-to-bottom-gen": "Mover la tarjeta al final de su lista",
"r-d-move-to-bottom-spec": "Mover la tarjeta al final de la lista",
"r-d-send-email": "Enviar email",
"r-d-send-email-to": "a",
"r-d-send-email-subject": "asunto",
"r-d-send-email-message": "mensaje",
"r-d-archive": "Mover tarjeta al Archivo",
"r-d-archive": "Archivar la tarjeta",
"r-d-unarchive": "Restaurar tarjeta del Archivo",
"r-d-add-label": "Añadir etiqueta",
"r-d-remove-label": "Eliminar etiqueta",
@@ -675,7 +675,7 @@
"authentication-method": "Método de autenticación",
"authentication-type": "Tipo de autenticación",
"custom-product-name": "Nombre de producto personalizado",
"layout": "Disñeo",
"layout": "Diseño",
"hide-logo": "Ocultar logo",
"add-custom-html-after-body-start": "Añade HTML personalizado después de <body> ",
"add-custom-html-before-body-end": "Añade HTML personalizado después de </body>",
@@ -689,5 +689,5 @@
"swimlane-delete-pop": "Todas las acciones serán eliminadas del historial de actividades y no se podrá recuperar el carril de flujo. Esta acción no puede deshacerse.",
"restore-all": "Restaurar todas",
"delete-all": "Borrar todas",
"loading": "Loading, please wait."
"loading": "Cargando. Por favor, espere."
}
+70 -70
View File
@@ -83,7 +83,7 @@
"added": "Lisätty",
"addMemberPopup-title": "Jäsenet",
"admin": "Ylläpitäjä",
"admin-desc": "Voi nähfä ja muokata kortteja, poistaa jäseniä, ja muuttaa taulun asetuksia.",
"admin-desc": "Voi nähdä ja muokata kortteja, poistaa jäseniä, ja muuttaa taulun asetuksia.",
"admin-announcement": "Ilmoitus",
"admin-announcement-active": "Aktiivinen järjestelmänlaajuinen ilmoitus",
"admin-announcement-title": "Ilmoitus ylläpitäjältä",
@@ -103,7 +103,7 @@
"archived-items": "Arkisto",
"archived-boards": "Taulut Arkistossa",
"restore-board": "Palauta taulu",
"no-archived-boards": "Ei tauluja Arkistossa",
"no-archived-boards": "Ei tauluja Arkistossa.",
"archives": "Arkisto",
"template": "Malli",
"templates": "Mallit",
@@ -114,7 +114,7 @@
"attachmentDeletePopup-title": "Poista liitetiedosto?",
"attachments": "Liitetiedostot",
"auto-watch": "Automaattisesti seuraa tauluja kun ne on luotu",
"avatar-too-big": "Profiilikuva on liian suuri (70KB maksimi)",
"avatar-too-big": "Profiilikuva on liian suuri (enintään 70 kt)",
"back": "Takaisin",
"board-change-color": "Muokkaa väriä",
"board-nb-stars": "%s tähteä",
@@ -125,9 +125,9 @@
"boardChangeTitlePopup-title": "Nimeä taulu uudelleen",
"boardChangeVisibilityPopup-title": "Muokkaa näkyvyyttä",
"boardChangeWatchPopup-title": "Muokkaa seuraamista",
"boardMenuPopup-title": "Taulu asetukset",
"boardMenuPopup-title": "Tauluasetukset",
"boards": "Taulut",
"board-view": "Taulu näkymä",
"board-view": "Taulunäkymä",
"board-view-cal": "Kalenteri",
"board-view-swimlanes": "Swimlanet",
"board-view-lists": "Listat",
@@ -136,8 +136,8 @@
"card-archived": "Tämä kortti on siirretty Arkistoon.",
"board-archived": "Tämä taulu on siirretty Arkistoon.",
"card-comments-title": "Tässä kortissa on %s kommenttia.",
"card-delete-notice": "Poistaminen on lopullista. Menetät kaikki toimet jotka on liitetty tähän korttiin.",
"card-delete-pop": "Kaikki toimet poistetaan toimintasyötteestä ja et tule pystymään uudelleenavaamaan korttia. Tätä ei voi peruuttaa.",
"card-delete-notice": "Poistaminen on lopullista. Menetät kaikki tähän korttiin liitetyt toimet.",
"card-delete-pop": "Kaikki toimet poistetaan toimintasyötteestä, etkä pysty avata korttia uudelleen. Tätä ei voi peruuttaa.",
"card-delete-suggest-archive": "Voit siirtää kortin Arkistoon poistaaksesi sen taululta ja säilyttääksesi toimintalokin.",
"card-due": "Erääntyy",
"card-due-on": "Erääntyy",
@@ -154,14 +154,14 @@
"cardCustomField-datePopup-title": "Muokkaa päivää",
"cardCustomFieldsPopup-title": "Muokkaa mukautettuja kenttiä",
"cardDeletePopup-title": "Poista kortti?",
"cardDetailsActionsPopup-title": "Kortti toimet",
"cardDetailsActionsPopup-title": "Korttitoimet",
"cardLabelsPopup-title": "Tunnisteet",
"cardMembersPopup-title": "Jäsenet",
"cardMorePopup-title": "Lisää",
"cardTemplatePopup-title": "Luo malli",
"cards": "Kortit",
"cards-count": "korttia",
"casSignIn": "CAS kirjautuminen",
"casSignIn": "CAS-kirjautuminen",
"cardType-card": "Kortti",
"cardType-linkedCard": "Linkitetty kortti",
"cardType-linkedBoard": "Linkitetty taulu",
@@ -182,7 +182,7 @@
"clipboard": "Leikepöytä tai raahaa ja pudota",
"close": "Sulje",
"close-board": "Sulje taulu",
"close-board-pop": "Voit palauttaa taulun klikkaamalla “Arkisto” painiketta taululistan yläpalkista.",
"close-board-pop": "Voit palauttaa taulun klikkaamalla “Arkisto”-painiketta taululistan yläpalkista.",
"color-black": "musta",
"color-blue": "sininen",
"color-crimson": "karmiininpunainen",
@@ -216,14 +216,14 @@
"no-comments": "Ei kommentteja",
"no-comments-desc": "Ei voi nähdä kommentteja ja toimintaa.",
"computer": "Tietokone",
"confirm-subtask-delete-dialog": "Oletko varma että haluat poistaa alitehtävän?",
"confirm-checklist-delete-dialog": "Oletko varma että haluat poistaa tarkistuslistan?",
"confirm-subtask-delete-dialog": "Haluatko varmasti poistaa alitehtävän?",
"confirm-checklist-delete-dialog": "Haluatko varmasti poistaa tarkistuslistan?",
"copy-card-link-to-clipboard": "Kopioi kortin linkki leikepöydälle",
"linkCardPopup-title": "Linkitä kortti",
"searchElementPopup-title": "Etsi",
"copyCardPopup-title": "Kopioi kortti",
"copyChecklistToManyCardsPopup-title": "Kopioi tarkistuslistan malli monille korteille",
"copyChecklistToManyCardsPopup-instructions": "Kohde korttien otsikot ja kuvaukset JSON muodossa",
"copyChecklistToManyCardsPopup-instructions": "Kohde korttien otsikot ja kuvaukset JSON-muodossa",
"copyChecklistToManyCardsPopup-format": "[ {\"title\": \"Ensimmäisen kortin otsikko\", \"description\":\"Ensimmäisen kortin kuvaus\"}, {\"title\":\"Toisen kortin otsikko\",\"description\":\"Toisen kortin kuvaus\"},{\"title\":\"Viimeisen kortin otsikko\",\"description\":\"Viimeisen kortin kuvaus\"} ]",
"create": "Luo",
"createBoardPopup-title": "Luo taulu",
@@ -237,7 +237,7 @@
"custom-field-date": "Päivämäärä",
"custom-field-dropdown": "Pudotusvalikko",
"custom-field-dropdown-none": "(ei mitään)",
"custom-field-dropdown-options": "Luettelon vaihtoehdot",
"custom-field-dropdown-options": "Listan vaihtoehdot",
"custom-field-dropdown-options-placeholder": "Paina Enter lisätäksesi lisää vaihtoehtoja",
"custom-field-dropdown-unknown": "(tuntematon)",
"custom-field-number": "Numero",
@@ -245,13 +245,13 @@
"custom-fields": "Mukautetut kentät",
"date": "Päivämäärä",
"decline": "Kieltäydy",
"default-avatar": "Oletus profiilikuva",
"default-avatar": "Oletusprofiilikuva",
"delete": "Poista",
"deleteCustomFieldPopup-title": "Poista mukautettu kenttä?",
"deleteLabelPopup-title": "Poista tunniste?",
"description": "Kuvaus",
"disambiguateMultiLabelPopup-title": "Yksikäsitteistä tunniste toiminta",
"disambiguateMultiMemberPopup-title": "Yksikäsitteistä jäsen toiminta",
"disambiguateMultiLabelPopup-title": "Yksikäsitteistä tunnistetoiminta",
"disambiguateMultiMemberPopup-title": "Yksikäsitteistä jäsentoiminta",
"discard": "Hylkää",
"done": "Valmis",
"download": "Lataa",
@@ -259,7 +259,7 @@
"edit-avatar": "Muokkaa profiilikuvaa",
"edit-profile": "Muokkaa profiilia",
"edit-wip-limit": "Muokkaa WIP-rajaa",
"soft-wip-limit": "Pehmeä WIP raja",
"soft-wip-limit": "Pehmeä WIP-raja",
"editCardStartDatePopup-title": "Muokkaa aloituspäivää",
"editCardDueDatePopup-title": "Muokkaa eräpäivää",
"editCustomFieldPopup-title": "Muokkaa kenttää",
@@ -268,25 +268,25 @@
"editNotificationPopup-title": "Muokkaa ilmoituksia",
"editProfilePopup-title": "Muokkaa profiilia",
"email": "Sähköposti",
"email-enrollAccount-subject": "An account created for you on __siteName__",
"email-enrollAccount-text": "Hei __user__,\n\nAlkaaksesi käyttämään palvelua, klikkaa allaolevaa linkkiä.\n\n__url__\n\nKiitos.",
"email-enrollAccount-subject": "Sinulle on luotu tili palveluun __siteName__",
"email-enrollAccount-text": "Hei __user__,\n\nKlikkaa alla olevaa linkkiä aloittaaksesi palvelun käytön.\n\n__url__\n\nKiitos.",
"email-fail": "Sähköpostin lähettäminen epäonnistui",
"email-fail-text": "Virhe yrittäessä lähettää sähköpostia",
"email-invalid": "Virheellinen sähköposti",
"email-invite": "Kutsu sähköpostilla",
"email-invite-subject": "__inviter__ lähetti sinulle kutsun",
"email-invite-text": "Hyvä __user__,\n\n__inviter__ kutsuu sinut liittymään taululle \"__board__\" yhteistyötä varten.\n\nOle hyvä ja seuraa allaolevaa linkkiä:\n\n__url__\n\nKiitos.",
"email-resetPassword-subject": "Reset your password on __siteName__",
"email-resetPassword-text": "Hei __user__,\n\nNollataksesi salasanasi, klikkaa allaolevaa linkkiä.\n\n__url__\n\nKiitos.",
"email-invite-text": "Hyvä __user__,\n\n__inviter__ kutsuu sinut liittymään taululle \"__board__\" yhteistyötä varten.\n\nOle hyvä ja seuraa alla olevaa linkkiä:\n\n__url__\n\nKiitos.",
"email-resetPassword-subject": "Nollaa salasanasi palvelussa __siteName__",
"email-resetPassword-text": "Hei __user__,\n\nNollataksesi salasanasi, klikkaa alla olevaa linkkiä.\n\n__url__\n\nKiitos.",
"email-sent": "Sähköposti lähetetty",
"email-verifyEmail-subject": "Varmista sähköpostiosoitteesi osoitteessa __url__",
"email-verifyEmail-text": "Hei __user__,\n\nvahvistaaksesi sähköpostiosoitteesi, klikkaa allaolevaa linkkiä.\n\n__url__\n\nKiitos.",
"email-verifyEmail-text": "Hei __user__,\n\nvahvistaaksesi sähköpostiosoitteesi, klikkaa alla olevaa linkkiä.\n\n__url__\n\nKiitos.",
"enable-wip-limit": "Ota käyttöön WIP-raja",
"error-board-doesNotExist": "Tämä taulu ei ole olemassa",
"error-board-doesNotExist": "Tätä taulua ei ole olemassa",
"error-board-notAdmin": "Tehdäksesi tämän sinun täytyy olla tämän taulun ylläpitäjä",
"error-board-notAMember": "Tehdäksesi tämän sinun täytyy olla tämän taulun jäsen",
"error-json-malformed": "Tekstisi ei ole kelvollisessa JSON muodossa",
"error-json-schema": "JSON tietosi ei sisällä oikeaa tietoa oikeassa muodossa",
"error-json-malformed": "Tekstisi ei ole kelvollisessa JSON-muodossa",
"error-json-schema": "JSON-tietosi ei sisällä oikeaa tietoa oikeassa muodossa",
"error-list-doesNotExist": "Tätä listaa ei ole olemassa",
"error-user-doesNotExist": "Tätä käyttäjää ei ole olemassa",
"error-user-notAllowSelf": "Et voi kutsua itseäsi",
@@ -316,14 +316,14 @@
"import-board-c": "Tuo taulu",
"import-board-title-trello": "Tuo taulu Trellosta",
"import-board-title-wekan": "Tuo taulu edellisestä viennistä",
"import-sandstorm-backup-warning": "Älä poista tietoja joita toit alkuperäisestä viennistä tai Trellosta ennenkuin tarkistat onnistuuko sulkea ja avata tämä jyvä uudelleen, vai näkyykö Board not found virhe, joka tarkoittaa tietojen häviämistä.",
"import-sandstorm-warning": "Tuotu taulu poistaa kaikki olemassaolevan taulun tiedot ja korvaa ne tuodulla taululla.",
"import-sandstorm-backup-warning": "Älä poista tietoja joita toit alkuperäisestä viennistä tai Trellosta ennen kuin tarkistat onnistuuko sulkea ja avata tämä jyvä uudelleen, vai näkyykö Board not found -virhe, joka tarkoittaa tietojen häviämistä.",
"import-sandstorm-warning": "Tuotu taulu poistaa kaikki olemassa olevan taulun tiedot ja korvaa ne tuodulla taululla.",
"from-trello": "Trellosta",
"from-wekan": "Edellisestä viennistä",
"import-board-instruction-trello": "Trello taulullasi, mene 'Menu', sitten 'More', 'Print and Export', 'Export JSON', ja kopioi tuloksena saamasi teksti",
"import-board-instruction-trello": "Mene Trello-taulullasi 'Menu', sitten 'More', 'Print and Export', 'Export JSON', ja kopioi tuloksena saamasi teksti",
"import-board-instruction-wekan": "Taulullasi, mene 'Valikko', sitten 'Vie taulu', ja kopioi teksti ladatusta tiedostosta.",
"import-board-instruction-about-errors": "Jos virheitä tulee taulua tuotaessa, joskus tuonti silti toimii, ja taulu on Kaikki taulut sivulla.",
"import-json-placeholder": "Liitä kelvollinen JSON tietosi tähän",
"import-json-placeholder": "Liitä kelvollinen JSON-tietosi tähän",
"import-map-members": "Vastaavat jäsenet",
"import-members-map": "Tuomallasi taululla on muutamia jäseniä. Ole hyvä ja valitse tuomiasi jäseniä vastaavat käyttäjäsi",
"import-show-user-mapping": "Tarkasta vastaavat jäsenet",
@@ -345,17 +345,17 @@
"last-admin-desc": "Et voi vaihtaa rooleja koska täytyy olla olemassa ainakin yksi ylläpitäjä.",
"leave-board": "Jää pois taululta",
"leave-board-pop": "Haluatko varmasti poistua taululta __boardTitle__? Sinut poistetaan kaikista tämän taulun korteista.",
"leaveBoardPopup-title": "Jää pois taululta ?",
"leaveBoardPopup-title": "Poistu taululta?",
"link-card": "Linkki tähän korttiin",
"list-archive-cards": "Siirrä kaikki tämän listan kortit Arkistoon",
"list-archive-cards-pop": "Tämä poistaa kaikki tämän listan kortit taululta. Nähdäksesi Arkistossa olevat kortit ja tuodaksesi ne takaisin taululle, klikkaa “Valikko” > “Arkisto”.",
"list-move-cards": "Siirrä kaikki kortit tässä listassa",
"list-select-cards": "Valitse kaikki kortit tässä listassa",
"set-color-list": "Aseta väri",
"listActionPopup-title": "Listaa toimet",
"swimlaneActionPopup-title": "Swimlane toimet",
"listActionPopup-title": "Listatoimet",
"swimlaneActionPopup-title": "Swimlane-toimet",
"swimlaneAddPopup-title": "Lisää Swimlane alle",
"listImportCardPopup-title": "Tuo Trello kortti",
"listImportCardPopup-title": "Tuo Trello-kortti",
"listMorePopup-title": "Lisää",
"link-list": "Linkki tähän listaan",
"list-delete-pop": "Kaikki toimet poistetaan toimintasyötteestä ja listan poistaminen on lopullista. Tätä ei pysty peruuttamaan.",
@@ -365,7 +365,7 @@
"log-out": "Kirjaudu ulos",
"log-in": "Kirjaudu sisään",
"loginPopup-title": "Kirjaudu sisään",
"memberMenuPopup-title": "Jäsen asetukset",
"memberMenuPopup-title": "Jäsenasetukset",
"members": "Jäsenet",
"menu": "Valikko",
"move-selection": "Siirrä valinta",
@@ -390,7 +390,7 @@
"notify-watch": "Vastaanota päivityksiä kaikilta tauluilta, listoilta tai korteilta joita seuraat.",
"optional": "valinnainen",
"or": "tai",
"page-maybe-private": "Tämä sivu voi olla yksityinen. Voit ehkä pystyä näkemään sen <a href='%s'>kirjautumalla sisään</a>.",
"page-maybe-private": "Tämä sivu voi olla yksityinen. Saatat nähdä sen <a href='%s'>kirjautumalla sisään</a>.",
"page-not-found": "Sivua ei löytynyt.",
"password": "Salasana",
"paste-or-dragdrop": "liittääksesi, tai vedä & pudota kuvatiedosto siihen (vain kuva)",
@@ -407,7 +407,7 @@
"remove-cover": "Poista kansi",
"remove-from-board": "Poista taululta",
"remove-label": "Poista tunniste",
"listDeletePopup-title": "Poista lista ?",
"listDeletePopup-title": "Poista lista?",
"remove-member": "Poista jäsen",
"remove-member-from-card": "Poista kortilta",
"remove-member-pop": "Poista __name__ (__username__) taululta __boardTitle__? Jäsen poistetaan kaikilta taulun korteilta. Heille lähetetään ilmoitus.",
@@ -419,7 +419,7 @@
"search": "Etsi",
"rules": "Säännöt",
"search-cards": "Etsi korttien otsikoista ja kuvauksista tällä taululla",
"search-example": "Teksti jota etsitään?",
"search-example": "Etsittävä teksti?",
"select-color": "Valitse väri",
"set-wip-limit-value": "Aseta tämän listan tehtävien enimmäismäärä",
"setWipLimitPopup-title": "Aseta WIP-raja",
@@ -429,9 +429,9 @@
"shortcut-clear-filters": "Poista kaikki suodattimet",
"shortcut-close-dialog": "Sulje valintaikkuna",
"shortcut-filter-my-cards": "Suodata korttini",
"shortcut-show-shortcuts": "Tuo esiin tämä pikavalinta lista",
"shortcut-toggle-filterbar": "Muokkaa suodatus sivupalkin näkyvyyttä",
"shortcut-toggle-sidebar": "Muokkaa taulu sivupalkin näkyvyyttä",
"shortcut-show-shortcuts": "Tuo esiin tämä pikavalintalista",
"shortcut-toggle-filterbar": "Muokkaa suodatussivupalkin näkyvyyttä",
"shortcut-toggle-sidebar": "Muokkaa taulusivupalkin näkyvyyttä",
"show-cards-minimum-count": "Näytä korttien lukumäärä jos lista sisältää enemmän kuin",
"sidebar-open": "Avaa sivupalkki",
"sidebar-close": "Sulje sivupalkki",
@@ -446,8 +446,8 @@
"spent-time-hours": "Käytetty aika (tuntia)",
"overtime-hours": "Ylityö (tuntia)",
"overtime": "Ylityö",
"has-overtime-cards": "Sisältää ylityö kortteja",
"has-spenttime-cards": "Sisältää käytetty aika kortteja",
"has-overtime-cards": "Sisältää ylityökortteja",
"has-spenttime-cards": "Sisältää käytetty aika -kortteja",
"time": "Aika",
"title": "Otsikko",
"tracking": "Ilmoitukset",
@@ -465,13 +465,13 @@
"watch": "Seuraa",
"watching": "Seurataan",
"watching-info": "Sinulle ilmoitetaan tämän taulun muutoksista",
"welcome-board": "Tervetuloa taulu",
"welcome-board": "Tervetuloa-taulu",
"welcome-swimlane": "Merkkipaalu 1",
"welcome-list1": "Perusasiat",
"welcome-list2": "Edistynyt",
"card-templates-swimlane": "Kortti mallit",
"list-templates-swimlane": "Lista mallit",
"board-templates-swimlane": "Taulu mallit",
"card-templates-swimlane": "Korttimallit",
"list-templates-swimlane": "Listamallit",
"board-templates-swimlane": "Taulumallit",
"what-to-do": "Mitä haluat tehdä?",
"wipLimitErrorPopup-title": "Virheellinen WIP-raja",
"wipLimitErrorPopup-dialog-pt1": "Tässä listassa olevien tehtävien määrä on korkeampi kuin asettamasi WIP-raja.",
@@ -480,36 +480,36 @@
"settings": "Asetukset",
"people": "Ihmiset",
"registration": "Rekisteröinti",
"disable-self-registration": "Poista käytöstä itse-rekisteröityminen",
"disable-self-registration": "Poista käytöstä itserekisteröityminen",
"invite": "Kutsu",
"invite-people": "Kutsu ihmisiä",
"to-boards": "Taulu(i)lle",
"email-addresses": "Sähköpostiosoite",
"smtp-host-description": "SMTP palvelimen osoite jolla sähköpostit lähetetään.",
"smtp-port-description": "Portti jota STMP palvelimesi käyttää lähteville sähköposteille.",
"smtp-tls-description": "Ota käyttöön TLS tuki SMTP palvelimelle",
"smtp-host": "SMTP isäntä",
"smtp-port": "SMTP portti",
"smtp-host-description": "SMTP-palvelimen osoite jolla sähköpostit lähetetään.",
"smtp-port-description": "STMP-palvelimesi käyttämä lähteville sähköposteille tarkoitettu portti.",
"smtp-tls-description": "Ota käyttöön TLS-tuki SMTP-palvelimelle",
"smtp-host": "SMTP-isäntä",
"smtp-port": "SMTP-portti",
"smtp-username": "Käyttäjätunnus",
"smtp-password": "Salasana",
"smtp-tls": "TLS tuki",
"smtp-tls": "TLS-tuki",
"send-from": "Lähettäjä",
"send-smtp-test": "Lähetä testi sähköposti itsellesi",
"send-smtp-test": "Lähetä testisähköposti itsellesi",
"invitation-code": "Kutsukoodi",
"email-invite-register-subject": "__inviter__ lähetti sinulle kutsun",
"email-invite-register-text": "Hei __user__,\n\n__inviter__ kutsuu sinut mukaan kanban taulun käyttöön.\n\nOle hyvä ja seuraa allaolevaa linkkiä:\n__url__\n\nJa kutsukoodisi on: __icode__\n\nKiitos.",
"email-smtp-test-subject": "SMTP testi sähköposti",
"email-invite-register-text": "Hei __user__,\n\n__inviter__ kutsuu sinut mukaan kanban-taulun käyttöön.\n\nOle hyvä ja seuraa alla olevaa linkkiä:\n__url__\n\nKutsukoodisi on: __icode__\n\nKiitos.",
"email-smtp-test-subject": "SMTP-testisähköposti",
"email-smtp-test-text": "Olet onnistuneesti lähettänyt sähköpostin",
"error-invitation-code-not-exist": "Kutsukoodi ei ole olemassa",
"error-invitation-code-not-exist": "Kutsukoodia ei ole olemassa",
"error-notAuthorized": "Sinulla ei ole oikeutta tarkastella tätä sivua.",
"outgoing-webhooks": "Lähtevät Webkoukut",
"outgoingWebhooksPopup-title": "Lähtevät Webkoukut",
"boardCardTitlePopup-title": "Kortin otsikko suodatin",
"boardCardTitlePopup-title": "Kortin otsikkosuodatin",
"new-outgoing-webhook": "Uusi lähtevä Webkoukku",
"no-name": "(Tuntematon)",
"Node_version": "Node versio",
"Node_version": "Node-versio",
"OS_Arch": "Käyttöjärjestelmän arkkitehtuuri",
"OS_Cpus": "Käyttöjärjestelmän CPU määrä",
"OS_Cpus": "Käyttöjärjestelmän CPU-määrä",
"OS_Freemem": "Käyttöjärjestelmän vapaa muisti",
"OS_Loadavg": "Käyttöjärjestelmän kuorman keskiarvo",
"OS_Platform": "Käyttöjärjestelmäalusta",
@@ -548,13 +548,13 @@
"delete-board-confirm-popup": "Kaikki listat, kortit, tunnisteet ja toimet poistetaan ja et pysty palauttamaan taulun sisältöä. Tätä ei voi peruuttaa.",
"boardDeletePopup-title": "Poista taulu?",
"delete-board": "Poista taulu",
"default-subtasks-board": "Alitehtävät __board__ taululle",
"default-subtasks-board": "Alitehtävät taululle __board__",
"default": "Oletus",
"queue": "Jono",
"subtask-settings": "Alitehtävä asetukset",
"boardSubtaskSettingsPopup-title": "Taulu alitehtävien asetukset",
"subtask-settings": "Alitehtävä-asetukset",
"boardSubtaskSettingsPopup-title": "Taulualitehtävien asetukset",
"show-subtasks-field": "Korteilla voi olla alitehtäviä",
"deposit-subtasks-board": "Tallenta alitehtävät tälle taululle:",
"deposit-subtasks-board": "Talleta alitehtävät tälle taululle:",
"deposit-subtasks-list": "Laskeutumislista alatehtäville tallennettu tänne:",
"show-parent-in-minicard": "Näytä ylätehtävä minikortilla:",
"prefix-with-full-path": "Etuliite koko polulla",
@@ -562,7 +562,7 @@
"subtext-with-full-path": "Aliteksti koko polulla",
"subtext-with-parent": "Aliteksti ylätehtävällä",
"change-card-parent": "Muuta kortin ylätehtävää",
"parent-card": "Ylätehtävä kortti",
"parent-card": "Ylätehtäväkortti",
"source-board": "Lähdetaulu",
"no-parent": "Älä näytä ylätehtävää",
"activity-added-label": "lisätty tunniste '%s' kohteeseen %s",
@@ -576,7 +576,7 @@
"r-rule": "Sääntö",
"r-add-trigger": "Lisää liipaisin",
"r-add-action": "Lisää toimi",
"r-board-rules": "Taulu säännöt",
"r-board-rules": "Taulusäännöt",
"r-add-rule": "Lisää sääntö",
"r-view-rule": "Näytä sääntö",
"r-delete-rule": "Poista sääntö",
@@ -682,10 +682,10 @@
"error-undefined": "Jotain meni pieleen",
"error-ldap-login": "Virhe tapahtui yrittäessä kirjautua sisään",
"display-authentication-method": "Näytä kirjautumistapa",
"default-authentication-method": "Oletus kirjautumistapa",
"default-authentication-method": "Oletuskirjautumistapa",
"duplicate-board": "Tee kaksoiskappale taulusta",
"people-number": "Ihmisten määrä on:",
"swimlaneDeletePopup-title": "Poista Swimlane ?",
"swimlaneDeletePopup-title": "Poista Swimlane?",
"swimlane-delete-pop": "Kaikki toimet poistetaan toimintasyötteestä ja swimlanen poistaminen on lopullista. Tätä ei pysty peruuttamaan.",
"restore-all": "Palauta kaikki",
"delete-all": "Poista kaikki",
+8 -8
View File
@@ -12,11 +12,11 @@
"act-addChecklistItem": "נוסף פריט סימון __checklistItem__ לרשימת המטלות __checklist__ לכרטיס __card__ ברשימה __list__ במסלול __swimlane__ בלוח __board__",
"act-removeChecklist": "הוסרה רשימת מטלות __checklist__ מהכרטיס __card__ ברשימה __list__ שבמסלול __swimlane__ בלוח __board__",
"act-removeChecklistItem": "פריט הסימון __checklistItem__ הוסר מרשימת המטלות __checkList__ בכרטיס __card__ ברשימה __list__ מהמסלול __swimlane__ בלוח __board__",
"act-checkedItem": "checked __checklistItem__ of checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-uncheckedItem": "unchecked __checklistItem__ of checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-completeChecklist": "completed checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-uncompleteChecklist": "uncompleted checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-addComment": "commented on card __card__: __comment__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-checkedItem": "הפריט __checklistItem__ ששייך לרשימת המשימות __checklist__ בכרטיס __card__ שברשימת __list__ במסלול __swimlane__ שבלוח __board__ סומן",
"act-uncheckedItem": "בוטל הסימון __checklistItem__ ברשימת המטלות __checklist__ בכרטיס __card__ ברשימה __list__ במסלול __swimlane__ בלוח __board__",
"act-completeChecklist": "רשימת המטלות __checklist__ בכרטיס __card__ שברשימה __list__ תחת המסלול __swimlane__ בלוח __board__ הושלמה",
"act-uncompleteChecklist": "ההשלמה של רשימת המטלות __checklist__ בכרטיס __card__ שברשימה __list__ תחת המסלול __swimlane__ בלוח __board__ בוטלה",
"act-addComment": "התקבלה תגובה על הכרטיס __card__:‏ __comment__ ברשימה __list__ במסלול __swimlane__ בלוח __board__",
"act-createBoard": "הלוח __board__ נוצר",
"act-createSwimlane": "נוצר מסלול __swimlane__ בלוח __board__",
"act-createCard": "הכרטיס __card__ נוצר ברשימה __list__ במסלול __swimlane__ שבלוח __board__",
@@ -60,14 +60,14 @@
"activity-unchecked-item": "בוטל הסימון של %s ברשימת המשימות %s מתוך %s",
"activity-checklist-added": "נוספה רשימת משימות אל %s",
"activity-checklist-removed": "הוסרה רשימת משימות מ־%s",
"activity-checklist-completed": "completed checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
"activity-checklist-completed": "רשימת המטלות __checklist__ בכרטיס __card__ שברשימה __list__ תחת המסלול __swimlane__ בלוח __board__ הושלמה",
"activity-checklist-uncompleted": "רשימת המשימות %s מתוך %s סומנה כבלתי מושלמת",
"activity-checklist-item-added": "נוסף פריט רשימת משימות אל ‚%s‘ תחת %s",
"activity-checklist-item-removed": "הוסר פריט מרשימת המשימות ‚%s’ תחת %s",
"add": "הוספה",
"activity-checked-item-card": "סומן %s ברשימת המשימות %s",
"activity-unchecked-item-card": "הסימון של %s בוטל ברשימת המשימות %s",
"activity-checklist-completed-card": "completed checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
"activity-checklist-completed-card": "רשימת המטלות __checklist__ בכרטיס __card__ שברשימה __list__ תחת המסלול __swimlane__ בלוח __board__ הושלמה",
"activity-checklist-uncompleted-card": "רשימת המשימות %s סומנה כבלתי מושלמת",
"add-attachment": "הוספת קובץ מצורף",
"add-board": "הוספת לוח",
@@ -689,5 +689,5 @@
"swimlane-delete-pop": "כל הפעולות יוסרו מהזנת הפעילות ולא תהיה לך אפשרות לשחזר את המסלול. אי אפשר לחזור אחורה.",
"restore-all": "לשחזר הכול",
"delete-all": "למחוק הכול",
"loading": "Loading, please wait."
"loading": "העמוד בטעינה, אנא המתינו."
}
+43 -43
View File
@@ -1,6 +1,6 @@
{
"accept": "受け入れ",
"act-activity-notify": "Activity Notification",
"act-activity-notify": "アクティビティ通知",
"act-addAttachment": "added attachment __attachment__ to card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-deleteAttachment": "deleted attachment __attachment__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-addSubtask": "added subtask __subtask__ to card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
@@ -42,7 +42,7 @@
"activities": "アクティビティ",
"activity": "アクティビティ",
"activity-added": "%s を %s に追加しました",
"activity-archived": "%s moved to Archive",
"activity-archived": "%sをアーカイブしました",
"activity-attached": "%s を %s に添付しました",
"activity-created": "%s を作成しました",
"activity-customfield-created": "%s を作成しました",
@@ -55,7 +55,7 @@
"activity-removed": "%s を %s から削除しました",
"activity-sent": "%s を %s に送りました",
"activity-unjoined": "%s への参加を止めました",
"activity-subtask-added": "added subtask to %s",
"activity-subtask-added": "%sにサブタスクを追加しました",
"activity-checked-item": "checked %s in checklist %s of %s",
"activity-unchecked-item": "unchecked %s in checklist %s of %s",
"activity-checklist-added": "%s にチェックリストを追加しました",
@@ -162,7 +162,7 @@
"cards": "カード",
"cards-count": "カード",
"casSignIn": "Sign In with CAS",
"cardType-card": "Card",
"cardType-card": "カード",
"cardType-linkedCard": "Linked Card",
"cardType-linkedBoard": "Linked Board",
"change": "変更",
@@ -175,7 +175,7 @@
"changePasswordPopup-title": "パスワードの変更",
"changePermissionsPopup-title": "パーミッションの変更",
"changeSettingsPopup-title": "設定の変更",
"subtasks": "Subtasks",
"subtasks": "サブタスク",
"checklists": "チェックリスト",
"click-to-star": "ボードにスターをつける",
"click-to-unstar": "ボードからスターを外す",
@@ -185,14 +185,14 @@
"close-board-pop": "You will be able to restore the board by clicking the “Archive” button from the home header.",
"color-black": "黒",
"color-blue": "青",
"color-crimson": "crimson",
"color-darkgreen": "darkgreen",
"color-gold": "gold",
"color-gray": "gray",
"color-crimson": "濃赤",
"color-darkgreen": "濃緑",
"color-gold": "金",
"color-gray": "灰",
"color-green": "緑",
"color-indigo": "indigo",
"color-indigo": "藍",
"color-lime": "ライム",
"color-magenta": "magenta",
"color-magenta": "マゼンタ",
"color-mistyrose": "mistyrose",
"color-navy": "navy",
"color-orange": "オレンジ",
@@ -203,12 +203,12 @@
"color-purple": "紫",
"color-red": "赤",
"color-saddlebrown": "saddlebrown",
"color-silver": "silver",
"color-silver": "銀",
"color-sky": "空",
"color-slateblue": "slateblue",
"color-white": "white",
"color-white": "白",
"color-yellow": "黄",
"unset-color": "Unset",
"unset-color": "設定しない",
"comment": "コメント",
"comment-placeholder": "コメントを書く",
"comment-only": "コメントのみ",
@@ -216,15 +216,15 @@
"no-comments": "No comments",
"no-comments-desc": "Can not see comments and activities.",
"computer": "コンピューター",
"confirm-subtask-delete-dialog": "Are you sure you want to delete subtask?",
"confirm-checklist-delete-dialog": "Are you sure you want to delete checklist?",
"confirm-subtask-delete-dialog": "本当にサブタスクを削除してもよろしいでしょうか?",
"confirm-checklist-delete-dialog": "本当にチェックリストを削除してもよろしいでしょうか?",
"copy-card-link-to-clipboard": "カードへのリンクをクリップボードにコピー",
"linkCardPopup-title": "Link Card",
"searchElementPopup-title": "検索",
"copyCardPopup-title": "カードをコピー",
"copyChecklistToManyCardsPopup-title": "Copy Checklist Template to Many Cards",
"copyChecklistToManyCardsPopup-instructions": "Destination Card Titles and Descriptions in this JSON format",
"copyChecklistToManyCardsPopup-format": "[ {\"title\": \"First card title\", \"description\":\"First card description\"}, {\"title\":\"Second card title\",\"description\":\"Second card description\"},{\"title\":\"Last card title\",\"description\":\"Last card description\"} ]",
"copyChecklistToManyCardsPopup-format": "[ {\"title\": \"1つ目のカードタイトル\", \"description\":\"1つ目のカードの説明\"}, {\"title\":\"2つ目のカードタイトル\",\"description\":\"2つ目のカードの説明\"},{\"title\":\"最後のカードタイトル\",\"description\":\"最後のカードの説明\"} ]",
"create": "作成",
"createBoardPopup-title": "ボードの作成",
"chooseBoardSourcePopup-title": "ボードをインポート",
@@ -233,15 +233,15 @@
"createCustomFieldPopup-title": "フィールドを作成",
"current": "現在",
"custom-field-delete-pop": "There is no undo. This will remove this custom field from all cards and destroy its history.",
"custom-field-checkbox": "Checkbox",
"custom-field-checkbox": "チェックボックス",
"custom-field-date": "日付",
"custom-field-dropdown": "Dropdown List",
"custom-field-dropdown": "ドロップダウンリスト",
"custom-field-dropdown-none": "(none)",
"custom-field-dropdown-options": "List Options",
"custom-field-dropdown-options-placeholder": "Press enter to add more options",
"custom-field-dropdown-unknown": "(unknown)",
"custom-field-number": "Number",
"custom-field-text": "Text",
"custom-field-text": "テキスト",
"custom-fields": "カスタムフィールド",
"date": "日付",
"decline": "拒否",
@@ -271,7 +271,7 @@
"email-enrollAccount-subject": "__siteName__であなたのアカウントが作成されました",
"email-enrollAccount-text": "こんにちは、__user__さん。\n\nサービスを開始するには、以下をクリックしてください。\n\n__url__\n\nよろしくお願いします。",
"email-fail": "メールの送信に失敗しました",
"email-fail-text": "Error trying to send email",
"email-fail-text": "メールの送信中にエラーが発生しました",
"email-invalid": "無効なメールアドレス",
"email-invite": "メールで招待",
"email-invite-subject": "__inviter__があなたを招待しています",
@@ -311,7 +311,7 @@
"headerBarCreateBoardPopup-title": "ボードの作成",
"home": "ホーム",
"import": "インポート",
"link": "Link",
"link": "リンク",
"import-board": "ボードをインポート",
"import-board-c": "ボードをインポート",
"import-board-title-trello": "Trelloからボードをインポート",
@@ -328,12 +328,12 @@
"import-members-map": "Your imported board has some members. Please map the members you want to import to your users",
"import-show-user-mapping": "メンバー紐付けの確認",
"import-user-select": "Pick your existing user you want to use as this member",
"importMapMembersAddPopup-title": "Select member",
"importMapMembersAddPopup-title": "メンバーを選択",
"info": "バージョン",
"initials": "イニシャル",
"invalid-date": "無効な日付",
"invalid-time": "Invalid time",
"invalid-user": "Invalid user",
"invalid-time": "無効な時間",
"invalid-user": "無効なユーザ",
"joined": "参加しました",
"just-invited": "このボードのメンバーに招待されています",
"keyboard-shortcuts": "キーボード・ショートカット",
@@ -347,11 +347,11 @@
"leave-board-pop": "Are you sure you want to leave __boardTitle__? You will be removed from all cards on this board.",
"leaveBoardPopup-title": "ボードから退出しますか?",
"link-card": "このカードへのリンク",
"list-archive-cards": "Move all cards in this list to Archive",
"list-archive-cards": "リスト内の全カードをアーカイブする",
"list-archive-cards-pop": "This will remove all the cards in this list from the board. To view cards in Archive and bring them back to the board, click “Menu” > “Archive”.",
"list-move-cards": "リストの全カードを移動する",
"list-select-cards": "リストの全カードを選択",
"set-color-list": "Set Color",
"set-color-list": "色を選択",
"listActionPopup-title": "操作一覧",
"swimlaneActionPopup-title": "スイムレーン操作",
"swimlaneAddPopup-title": "Add a Swimlane below",
@@ -658,36 +658,36 @@
"r-d-check-one": "Check item",
"r-d-uncheck-one": "Uncheck item",
"r-d-check-of-list": "of checklist",
"r-d-add-checklist": "Add checklist",
"r-d-remove-checklist": "Remove checklist",
"r-d-add-checklist": "チェックリストを追加",
"r-d-remove-checklist": "チェックリストを削除",
"r-by": "by",
"r-add-checklist": "Add checklist",
"r-add-checklist": "チェックリストを追加",
"r-with-items": "with items",
"r-items-list": "item1,item2,item3",
"r-add-swimlane": "Add swimlane",
"r-swimlane-name": "swimlane name",
"r-items-list": "アイテム1、アイテム2、アイテム3",
"r-add-swimlane": "スイムレーンを追加",
"r-swimlane-name": "スイムレーン名",
"r-board-note": "Note: leave a field empty to match every possible value.",
"r-checklist-note": "Note: checklist's items have to be written as comma separated values.",
"r-when-a-card-is-moved": "When a card is moved to another list",
"r-when-a-card-is-moved": "カードが別のリストに移動したとき",
"ldap": "LDAP",
"oauth2": "OAuth2",
"cas": "CAS",
"authentication-method": "Authentication method",
"authentication-type": "Authentication type",
"authentication-method": "認証方式",
"authentication-type": "認証タイプ",
"custom-product-name": "Custom Product Name",
"layout": "Layout",
"hide-logo": "Hide Logo",
"layout": "レイアウト",
"hide-logo": "ロゴを隠す",
"add-custom-html-after-body-start": "Add Custom HTML after <body> start",
"add-custom-html-before-body-end": "Add Custom HTML before </body> end",
"error-undefined": "Something went wrong",
"error-ldap-login": "An error occurred while trying to login",
"display-authentication-method": "Display Authentication Method",
"default-authentication-method": "Default Authentication Method",
"duplicate-board": "Duplicate Board",
"duplicate-board": "ボードの複製",
"people-number": "The number of people is:",
"swimlaneDeletePopup-title": "Delete Swimlane ?",
"swimlaneDeletePopup-title": "スイムレーンを削除しますか?",
"swimlane-delete-pop": "All actions will be removed from the activity feed and you won't be able to recover the swimlane. There is no undo.",
"restore-all": "Restore all",
"delete-all": "Delete all",
"loading": "Loading, please wait."
"restore-all": "全てをリストアする",
"delete-all": "全てを削除する",
"loading": "ローディング中です、しばらくお待ちください。"
}
+9 -9
View File
@@ -31,8 +31,8 @@
"act-importCard": "Zaimportowano kartę __card__ do listy __list__ na diagramie czynności __swimlane__ na tablicy __board__",
"act-importList": "Zaimportowano listę __list__ na diagram czynności __swimlane__ do tablicy __board__",
"act-joinMember": "Dodano użytkownika __member__ do karty __card__ na liście __list__ na diagramie czynności __swimlane__ na tablicy __board__",
"act-moveCard": "przeniesiono kartę __card__ na tablicy __board__ z listy __oldList__ na diagramie czynności __oldSwimlane__ na listę __list__ na diagramie czynności __swimlane__",
"act-moveCardToOtherBoard": "Przeniesiono kartę __card__ z listy __oldList__ na diagramie czynności __oldSwimlane__ na tablicy __oldBoard__ do listy __listy__ na diagramie czynności __swimlane__ na tablicy __board__",
"act-moveCard": "przeniósł/a kartę __card__ na tablicy __board__ z listy __oldList__ na diagramie czynności __oldSwimlane__ na listę __list__ na diagramie czynności __swimlane__",
"act-moveCardToOtherBoard": "przeniósł/a kartę __card__ z listy __oldList__ na diagramie czynności __oldSwimlane__ na tablicy __oldBoard__ do listy __listy__ na diagramie czynności __swimlane__ na tablicy __board__",
"act-removeBoardMember": "Usunięto użytkownika __member__ z tablicy __board__",
"act-restoredCard": "Przywrócono kartę __card__ na listę __list__ na diagram czynności__ na tablicy __board__",
"act-unjoinMember": "Usunięto użytkownika __member__ z karty __card__ na liście __list__ na diagramie czynności __swimlane__ na tablicy __board__",
@@ -683,11 +683,11 @@
"error-ldap-login": "Wystąpił błąd w trakcie logowania",
"display-authentication-method": "Wyświetl metodę logowania",
"default-authentication-method": "Domyślna metoda logowania",
"duplicate-board": "Duplicate Board",
"people-number": "The number of people is:",
"swimlaneDeletePopup-title": "Delete Swimlane ?",
"swimlane-delete-pop": "All actions will be removed from the activity feed and you won't be able to recover the swimlane. There is no undo.",
"restore-all": "Restore all",
"delete-all": "Delete all",
"loading": "Loading, please wait."
"duplicate-board": "Duplikuj tablicę",
"people-number": "Liczba użytkowników to:",
"swimlaneDeletePopup-title": "Usunąć diagram czynności?",
"swimlane-delete-pop": "Wszystkie akcje będą usunięte z widoku aktywności, nie można będzie przywrócić diagramu czynności. Usunięcie jest nieodwracalne.",
"restore-all": "Przywróć wszystkie",
"delete-all": "Usuń wszystkie",
"loading": "Ładowanie, proszę czekać."
}
+1 -1
View File
@@ -689,5 +689,5 @@
"swimlane-delete-pop": "Todas as ações serão excluídas da lista de atividades e você não poderá recuperar a raia. Não há como desfazer.",
"restore-all": "Restaurar tudo",
"delete-all": "Excluir tudo",
"loading": "Loading, please wait."
"loading": "Carregando, aguarde por favor."
}
+2 -2
View File
@@ -4,7 +4,7 @@
"act-addAttachment": "прикрепил вложение __attachment__ в карточку __card__ в списке __list__ на дорожке __swimlane__ доски __board__",
"act-deleteAttachment": "удалил вложение __attachment__ из карточки __card__ в списке __list__ на дорожке __swimlane__ доски __board__",
"act-addSubtask": "добавил подзадачу __subtask__ для карточки __card__ в списке __list__ на дорожке __swimlane__ доски __board__",
"act-addLabel": "Добавлена метка __label__ в карточку __card__ в списке __list__ на дорожке __swimlane__ доски __board__",
"act-addLabel": "добавил метку __label__ в карточку __card__ в списке __list__ на дорожке __swimlane__ доски __board__",
"act-addedLabel": "Добавлена метка __label__ в карточку __card__ в списке __list__ на дорожке __swimlane__ доски __board__",
"act-removeLabel": "Снята метка __label__ с карточки __card__ в списке __list__ на дорожке __swimlane__ доски __board__",
"act-removedLabel": "Снята метка __label__ с карточки __card__ в списке __list__ на дорожке __swimlane__ доски __board__",
@@ -689,5 +689,5 @@
"swimlane-delete-pop": "Все действия будут удалены из ленты активности участников, и вы не сможете восстановить дорожку. Данное действие необратимо.",
"restore-all": "Восстановить все",
"delete-all": "Удалить все",
"loading": "Loading, please wait."
"loading": "Идет загрузка, пожалуйста подождите"
}
+4 -4
View File
@@ -684,10 +684,10 @@
"display-authentication-method": "Visa autentiseringsmetod",
"default-authentication-method": "Standard autentiseringsmetod",
"duplicate-board": "Dubbletttavla",
"people-number": "The number of people is:",
"people-number": "Antalet personer är:",
"swimlaneDeletePopup-title": "Delete Swimlane ?",
"swimlane-delete-pop": "All actions will be removed from the activity feed and you won't be able to recover the swimlane. There is no undo.",
"restore-all": "Restore all",
"delete-all": "Delete all",
"loading": "Loading, please wait."
"restore-all": "Återställ alla",
"delete-all": "Ta bort alla",
"loading": "Läser in, var god vänta."
}
+1 -1
View File
@@ -59,7 +59,7 @@
"activity-checked-item": "checked %s in checklist %s of %s",
"activity-unchecked-item": "unchecked %s in checklist %s of %s",
"activity-checklist-added": "%s içine yapılacak listesi ekledi",
"activity-checklist-removed": "removed a checklist from %s",
"activity-checklist-removed": "%s Tarafından yapılacaklar listesi silinmiştir",
"activity-checklist-completed": "completed checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
"activity-checklist-uncompleted": "uncompleted the checklist %s of %s",
"activity-checklist-item-added": "%s içinde %s yapılacak listesine öğe ekledi",
+10 -10
View File
@@ -24,14 +24,14 @@
"act-createList": "添加列表 __list__ 至看板 __board__",
"act-addBoardMember": "添加成员 __member__ 到看板 __board__",
"act-archivedBoard": "看板 __board__ 已被移入归档",
"act-archivedCard": "Card __card__ at list __list__ at swimlane __swimlane__ at board __board__ moved to Archive",
"act-archivedCard": "将看板 __board__ 中的泳道 __swimlane__ 中的列表 __list__ 中的卡片 移动到归档中",
"act-archivedList": "看板 __board__ 中的泳道 __swimlane__ 中的列表 __list__ 已被移入归档",
"act-archivedSwimlane": "看板 __board__ 中的泳道 __swimlane__ 已被移入归档",
"act-importBoard": "导入看板 __board__",
"act-importCard": "imported card __card__ to list __list__ at swimlane __swimlane__ at board __board__",
"act-importList": "imported list __list__ to swimlane __swimlane__ at board __board__",
"act-joinMember": "added member __member__ to card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-moveCard": "moved card __card__ at board __board__ from list __oldList__ at swimlane __oldSwimlane__ to list __list__ at swimlane __swimlane__",
"act-importCard": "已将卡片 __card__ 导入到 __board__ 看板中的 __swimlane__ 泳道中的 __list__ 列表中",
"act-importList": "已将列表导入到 __board__ 看板中的 __swimlane__  泳道中的 __list__  列表中",
"act-joinMember": "已将成员 __member__  添加到 __board__ 看板中的 __swimlane__ 泳道中的 __list__  列表中的 __card__ 卡片中",
"act-moveCard": "移动卡片 __card__ 到看板 __board__ 从列表 __oldList__ 泳道 __oldSwimlane__ 至列表 __list__ 泳道 __swimlane__",
"act-moveCardToOtherBoard": "移动卡片 __card__ 从列表 __oldList__ 泳道 __oldSwimlane__ 看板 __oldBoard__ 至列表 __list__ 泳道 __swimlane__ 看板 __board__",
"act-removeBoardMember": "从看板 __board__ 移除成员 __member__ ",
"act-restoredCard": "恢复卡片 __card__ 至列表 __list__ 泳道 __swimlane__ 看板 __board__",
@@ -685,9 +685,9 @@
"default-authentication-method": "缺省认证方式",
"duplicate-board": "复制看板",
"people-number": "人数是:",
"swimlaneDeletePopup-title": "Delete Swimlane ?",
"swimlane-delete-pop": "All actions will be removed from the activity feed and you won't be able to recover the swimlane. There is no undo.",
"restore-all": "Restore all",
"delete-all": "Delete all",
"loading": "Loading, please wait."
"swimlaneDeletePopup-title": "是否删除泳道?",
"swimlane-delete-pop": "所有活动将从活动源中删除,您将无法恢复泳道。此操作无法撤销。",
"restore-all": "全部恢复",
"delete-all": "全部删除",
"loading": "加载中,请稍等。"
}
+693
View File
@@ -0,0 +1,693 @@
{
"accept": "Accept",
"act-activity-notify": "Activity Notification",
"act-addAttachment": "added attachment __attachment__ to card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-deleteAttachment": "deleted attachment __attachment__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-addSubtask": "added subtask __subtask__ to card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-addLabel": "Added label __label__ to card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-addedLabel": "Added label __label__ to card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-removeLabel": "Removed label __label__ from card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-removedLabel": "Removed label __label__ from card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-addChecklist": "added checklist __checklist__ to card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-addChecklistItem": "added checklist item __checklistItem__ to checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-removeChecklist": "removed checklist __checklist__ from card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-removeChecklistItem": "removed checklist item __checklistItem__ from checklist __checkList__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-checkedItem": "checked __checklistItem__ of checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-uncheckedItem": "unchecked __checklistItem__ of checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-completeChecklist": "completed checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-uncompleteChecklist": "uncompleted checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-addComment": "commented on card __card__: __comment__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-createBoard": "created board __board__",
"act-createSwimlane": "created swimlane __swimlane__ to board __board__",
"act-createCard": "created card __card__ to list __list__ at swimlane __swimlane__ at board __board__",
"act-createCustomField": "created custom field __customField__ to card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-createList": "added list __list__ to board __board__",
"act-addBoardMember": "added member __member__ to board __board__",
"act-archivedBoard": "Board __board__ moved to Archive",
"act-archivedCard": "Card __card__ at list __list__ at swimlane __swimlane__ at board __board__ moved to Archive",
"act-archivedList": "List __list__ at swimlane __swimlane__ at board __board__ moved to Archive",
"act-archivedSwimlane": "Swimlane __swimlane__ at board __board__ moved to Archive",
"act-importBoard": "imported board __board__",
"act-importCard": "imported card __card__ to list __list__ at swimlane __swimlane__ at board __board__",
"act-importList": "imported list __list__ to swimlane __swimlane__ at board __board__",
"act-joinMember": "added member __member__ to card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-moveCard": "moved card __card__ at board __board__ from list __oldList__ at swimlane __oldSwimlane__ to list __list__ at swimlane __swimlane__",
"act-moveCardToOtherBoard": "moved card __card__ from list __oldList__ at swimlane __oldSwimlane__ at board __oldBoard__ to list __list__ at swimlane __swimlane__ at board __board__",
"act-removeBoardMember": "removed member __member__ from board __board__",
"act-restoredCard": "restored card __card__ to list __list__ at swimlane __swimlane__ at board __board__",
"act-unjoinMember": "removed member __member__ from card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-withBoardTitle": "__board__",
"act-withCardTitle": "[__board__] __card__",
"actions": "Actions",
"activities": "Activities",
"activity": "Activity",
"activity-added": "added %s to %s",
"activity-archived": "%s moved to Archive",
"activity-attached": "attached %s to %s",
"activity-created": "created %s",
"activity-customfield-created": "created custom field %s",
"activity-excluded": "excluded %s from %s",
"activity-imported": "imported %s into %s from %s",
"activity-imported-board": "imported %s from %s",
"activity-joined": "joined %s",
"activity-moved": "moved %s from %s to %s",
"activity-on": "on %s",
"activity-removed": "removed %s from %s",
"activity-sent": "sent %s to %s",
"activity-unjoined": "unjoined %s",
"activity-subtask-added": "added subtask to %s",
"activity-checked-item": "checked %s in checklist %s of %s",
"activity-unchecked-item": "unchecked %s in checklist %s of %s",
"activity-checklist-added": "added checklist to %s",
"activity-checklist-removed": "removed a checklist from %s",
"activity-checklist-completed": "completed checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
"activity-checklist-uncompleted": "uncompleted the checklist %s of %s",
"activity-checklist-item-added": "added checklist item to '%s' in %s",
"activity-checklist-item-removed": "removed a checklist item from '%s' in %s",
"add": "Add",
"activity-checked-item-card": "checked %s in checklist %s",
"activity-unchecked-item-card": "unchecked %s in checklist %s",
"activity-checklist-completed-card": "completed checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
"activity-checklist-uncompleted-card": "uncompleted the checklist %s",
"add-attachment": "Add Attachment",
"add-board": "Add Board",
"add-card": "Add Card",
"add-swimlane": "Add Swimlane",
"add-subtask": "Add Subtask",
"add-checklist": "Add Checklist",
"add-checklist-item": "Add an item to checklist",
"add-cover": "Add Cover",
"add-label": "Add Label",
"add-list": "Add List",
"add-members": "Add Members",
"added": "Added",
"addMemberPopup-title": "Members",
"admin": "Admin",
"admin-desc": "Can view and edit cards, remove members, and change settings for the board.",
"admin-announcement": "Announcement",
"admin-announcement-active": "Active System-Wide Announcement",
"admin-announcement-title": "Announcement from Administrator",
"all-boards": "All boards",
"and-n-other-card": "And __count__ other card",
"and-n-other-card_plural": "And __count__ other cards",
"apply": "Apply",
"app-is-offline": "Loading, please wait. Refreshing the page will cause data loss. If loading does not work, please check that server has not stopped.",
"archive": "Move to Archive",
"archive-all": "Move All to Archive",
"archive-board": "Move Board to Archive",
"archive-card": "Move Card to Archive",
"archive-list": "Move List to Archive",
"archive-swimlane": "Move Swimlane to Archive",
"archive-selection": "Move selection to Archive",
"archiveBoardPopup-title": "Move Board to Archive?",
"archived-items": "Archive",
"archived-boards": "Boards in Archive",
"restore-board": "Restore Board",
"no-archived-boards": "No Boards in Archive.",
"archives": "Archive",
"template": "Template",
"templates": "Templates",
"assign-member": "Assign member",
"attached": "attached",
"attachment": "Attachment",
"attachment-delete-pop": "Deleting an attachment is permanent. There is no undo.",
"attachmentDeletePopup-title": "Delete Attachment?",
"attachments": "Attachments",
"auto-watch": "Automatically watch boards when they are created",
"avatar-too-big": "The avatar is too large (70KB max)",
"back": "Back",
"board-change-color": "Change color",
"board-nb-stars": "%s stars",
"board-not-found": "Board not found",
"board-private-info": "This board will be <strong>private</strong>.",
"board-public-info": "This board will be <strong>public</strong>.",
"boardChangeColorPopup-title": "Change Board Background",
"boardChangeTitlePopup-title": "Rename Board",
"boardChangeVisibilityPopup-title": "Change Visibility",
"boardChangeWatchPopup-title": "Change Watch",
"boardMenuPopup-title": "Board Settings",
"boards": "Boards",
"board-view": "Board View",
"board-view-cal": "Calendar",
"board-view-swimlanes": "Swimlanes",
"board-view-lists": "Lists",
"bucket-example": "Like “Bucket List” for example",
"cancel": "Cancel",
"card-archived": "This card is moved to Archive.",
"board-archived": "This board is moved to Archive.",
"card-comments-title": "This card has %s comment.",
"card-delete-notice": "Deleting is permanent. You will lose all actions associated with this card.",
"card-delete-pop": "All actions will be removed from the activity feed and you won't be able to re-open the card. There is no undo.",
"card-delete-suggest-archive": "You can move a card to Archive to remove it from the board and preserve the activity.",
"card-due": "Due",
"card-due-on": "Due on",
"card-spent": "Spent Time",
"card-edit-attachments": "Edit attachments",
"card-edit-custom-fields": "Edit custom fields",
"card-edit-labels": "Edit labels",
"card-edit-members": "Edit members",
"card-labels-title": "Change the labels for the card.",
"card-members-title": "Add or remove members of the board from the card.",
"card-start": "Start",
"card-start-on": "Starts on",
"cardAttachmentsPopup-title": "Attach From",
"cardCustomField-datePopup-title": "Change date",
"cardCustomFieldsPopup-title": "Edit custom fields",
"cardDeletePopup-title": "Delete Card?",
"cardDetailsActionsPopup-title": "Card Actions",
"cardLabelsPopup-title": "Labels",
"cardMembersPopup-title": "Members",
"cardMorePopup-title": "More",
"cardTemplatePopup-title": "Create template",
"cards": "Cards",
"cards-count": "Cards",
"casSignIn": "Sign In with CAS",
"cardType-card": "Card",
"cardType-linkedCard": "Linked Card",
"cardType-linkedBoard": "Linked Board",
"change": "Change",
"change-avatar": "Change Avatar",
"change-password": "Change Password",
"change-permissions": "Change permissions",
"change-settings": "Change Settings",
"changeAvatarPopup-title": "Change Avatar",
"changeLanguagePopup-title": "Change Language",
"changePasswordPopup-title": "Change Password",
"changePermissionsPopup-title": "Change Permissions",
"changeSettingsPopup-title": "Change Settings",
"subtasks": "Subtasks",
"checklists": "Checklists",
"click-to-star": "Click to star this board.",
"click-to-unstar": "Click to unstar this board.",
"clipboard": "Clipboard or drag & drop",
"close": "Close",
"close-board": "Close Board",
"close-board-pop": "You will be able to restore the board by clicking the “Archive” button from the home header.",
"color-black": "black",
"color-blue": "blue",
"color-crimson": "crimson",
"color-darkgreen": "darkgreen",
"color-gold": "gold",
"color-gray": "gray",
"color-green": "green",
"color-indigo": "indigo",
"color-lime": "lime",
"color-magenta": "magenta",
"color-mistyrose": "mistyrose",
"color-navy": "navy",
"color-orange": "orange",
"color-paleturquoise": "paleturquoise",
"color-peachpuff": "peachpuff",
"color-pink": "pink",
"color-plum": "plum",
"color-purple": "purple",
"color-red": "red",
"color-saddlebrown": "saddlebrown",
"color-silver": "silver",
"color-sky": "sky",
"color-slateblue": "slateblue",
"color-white": "white",
"color-yellow": "yellow",
"unset-color": "Unset",
"comment": "Comment",
"comment-placeholder": "Write Comment",
"comment-only": "Comment only",
"comment-only-desc": "Can comment on cards only.",
"no-comments": "No comments",
"no-comments-desc": "Can not see comments and activities.",
"computer": "Computer",
"confirm-subtask-delete-dialog": "Are you sure you want to delete subtask?",
"confirm-checklist-delete-dialog": "Are you sure you want to delete checklist?",
"copy-card-link-to-clipboard": "Copy card link to clipboard",
"linkCardPopup-title": "Link Card",
"searchElementPopup-title": "Search",
"copyCardPopup-title": "Copy Card",
"copyChecklistToManyCardsPopup-title": "Copy Checklist Template to Many Cards",
"copyChecklistToManyCardsPopup-instructions": "Destination Card Titles and Descriptions in this JSON format",
"copyChecklistToManyCardsPopup-format": "[ {\"title\": \"First card title\", \"description\":\"First card description\"}, {\"title\":\"Second card title\",\"description\":\"Second card description\"},{\"title\":\"Last card title\",\"description\":\"Last card description\"} ]",
"create": "Create",
"createBoardPopup-title": "Create Board",
"chooseBoardSourcePopup-title": "Import board",
"createLabelPopup-title": "Create Label",
"createCustomField": "Create Field",
"createCustomFieldPopup-title": "Create Field",
"current": "current",
"custom-field-delete-pop": "There is no undo. This will remove this custom field from all cards and destroy its history.",
"custom-field-checkbox": "Checkbox",
"custom-field-date": "Date",
"custom-field-dropdown": "Dropdown List",
"custom-field-dropdown-none": "(none)",
"custom-field-dropdown-options": "List Options",
"custom-field-dropdown-options-placeholder": "Press enter to add more options",
"custom-field-dropdown-unknown": "(unknown)",
"custom-field-number": "Number",
"custom-field-text": "Text",
"custom-fields": "Custom Fields",
"date": "Date",
"decline": "Decline",
"default-avatar": "Default avatar",
"delete": "Delete",
"deleteCustomFieldPopup-title": "Delete Custom Field?",
"deleteLabelPopup-title": "Delete Label?",
"description": "Description",
"disambiguateMultiLabelPopup-title": "Disambiguate Label Action",
"disambiguateMultiMemberPopup-title": "Disambiguate Member Action",
"discard": "Discard",
"done": "Done",
"download": "Download",
"edit": "Edit",
"edit-avatar": "Change Avatar",
"edit-profile": "Edit Profile",
"edit-wip-limit": "Edit WIP Limit",
"soft-wip-limit": "Soft WIP Limit",
"editCardStartDatePopup-title": "Change start date",
"editCardDueDatePopup-title": "Change due date",
"editCustomFieldPopup-title": "Edit Field",
"editCardSpentTimePopup-title": "Change spent time",
"editLabelPopup-title": "Change Label",
"editNotificationPopup-title": "Edit Notification",
"editProfilePopup-title": "Edit Profile",
"email": "Email",
"email-enrollAccount-subject": "An account created for you on __siteName__",
"email-enrollAccount-text": "Hello __user__,\n\nTo start using the service, simply click the link below.\n\n__url__\n\nThanks.",
"email-fail": "Sending email failed",
"email-fail-text": "Error trying to send email",
"email-invalid": "Invalid email",
"email-invite": "Invite via Email",
"email-invite-subject": "__inviter__ sent you an invitation",
"email-invite-text": "Dear __user__,\n\n__inviter__ invites you to join board \"__board__\" for collaborations.\n\nPlease follow the link below:\n\n__url__\n\nThanks.",
"email-resetPassword-subject": "Reset your password on __siteName__",
"email-resetPassword-text": "Hello __user__,\n\nTo reset your password, simply click the link below.\n\n__url__\n\nThanks.",
"email-sent": "Email sent",
"email-verifyEmail-subject": "Verify your email address on __siteName__",
"email-verifyEmail-text": "Hello __user__,\n\nTo verify your account email, simply click the link below.\n\n__url__\n\nThanks.",
"enable-wip-limit": "Enable WIP Limit",
"error-board-doesNotExist": "This board does not exist",
"error-board-notAdmin": "You need to be admin of this board to do that",
"error-board-notAMember": "You need to be a member of this board to do that",
"error-json-malformed": "Your text is not valid JSON",
"error-json-schema": "Your JSON data does not include the proper information in the correct format",
"error-list-doesNotExist": "This list does not exist",
"error-user-doesNotExist": "This user does not exist",
"error-user-notAllowSelf": "You can not invite yourself",
"error-user-notCreated": "This user is not created",
"error-username-taken": "This username is already taken",
"error-email-taken": "Email has already been taken",
"export-board": "Export board",
"filter": "Filter",
"filter-cards": "Filter Cards",
"filter-clear": "Clear filter",
"filter-no-label": "No label",
"filter-no-member": "No member",
"filter-no-custom-fields": "No Custom Fields",
"filter-on": "Filter is on",
"filter-on-desc": "You are filtering cards on this board. Click here to edit filter.",
"filter-to-selection": "Filter to selection",
"advanced-filter-label": "Advanced Filter",
"advanced-filter-description": "Advanced Filter allows to write a string containing following operators: == != <= >= && || ( ) A space is used as a separator between the Operators. You can filter for all Custom Fields by typing their names and values. For Example: Field1 == Value1. Note: If fields or values contains spaces, you need to encapsulate them into single quotes. For Example: 'Field 1' == 'Value 1'. For single control characters (' \\/) to be skipped, you can use \\. For example: Field1 == I\\'m. Also you can combine multiple conditions. For Example: F1 == V1 || F1 == V2. Normally all operators are interpreted from left to right. You can change the order by placing brackets. For Example: F1 == V1 && ( F2 == V2 || F2 == V3 ). Also you can search text fields using regex: F1 == /Tes.*/i",
"fullname": "Full Name",
"header-logo-title": "Go back to your boards page.",
"hide-system-messages": "Hide system messages",
"headerBarCreateBoardPopup-title": "Create Board",
"home": "Home",
"import": "Import",
"link": "Link",
"import-board": "import board",
"import-board-c": "Import board",
"import-board-title-trello": "Import board from Trello",
"import-board-title-wekan": "Import board from previous export",
"import-sandstorm-backup-warning": "Do not delete data you import from original exported board or Trello before checking does this grain close and open again, or do you get Board not found error, that means data loss.",
"import-sandstorm-warning": "Imported board will delete all existing data on board and replace it with imported board.",
"from-trello": "From Trello",
"from-wekan": "From previous export",
"import-board-instruction-trello": "In your Trello board, go to 'Menu', then 'More', 'Print and Export', 'Export JSON', and copy the resulting text.",
"import-board-instruction-wekan": "In your board, go to 'Menu', then 'Export board', and copy the text in the downloaded file.",
"import-board-instruction-about-errors": "If you get errors when importing board, sometimes importing still works, and board is at All Boards page.",
"import-json-placeholder": "Paste your valid JSON data here",
"import-map-members": "Map members",
"import-members-map": "Your imported board has some members. Please map the members you want to import to your users",
"import-show-user-mapping": "Review members mapping",
"import-user-select": "Pick your existing user you want to use as this member",
"importMapMembersAddPopup-title": "Select member",
"info": "Version",
"initials": "Initials",
"invalid-date": "Invalid date",
"invalid-time": "Invalid time",
"invalid-user": "Invalid user",
"joined": "joined",
"just-invited": "You are just invited to this board",
"keyboard-shortcuts": "Keyboard shortcuts",
"label-create": "Create Label",
"label-default": "%s label (default)",
"label-delete-pop": "There is no undo. This will remove this label from all cards and destroy its history.",
"labels": "Labels",
"language": "Language",
"last-admin-desc": "You can’t change roles because there must be at least one admin.",
"leave-board": "Leave Board",
"leave-board-pop": "Are you sure you want to leave __boardTitle__? You will be removed from all cards on this board.",
"leaveBoardPopup-title": "Leave Board ?",
"link-card": "Link to this card",
"list-archive-cards": "Move all cards in this list to Archive",
"list-archive-cards-pop": "This will remove all the cards in this list from the board. To view cards in Archive and bring them back to the board, click “Menu” > “Archive”.",
"list-move-cards": "Move all cards in this list",
"list-select-cards": "Select all cards in this list",
"set-color-list": "Set Color",
"listActionPopup-title": "List Actions",
"swimlaneActionPopup-title": "Swimlane Actions",
"swimlaneAddPopup-title": "Add a Swimlane below",
"listImportCardPopup-title": "Import a Trello card",
"listMorePopup-title": "More",
"link-list": "Link to this list",
"list-delete-pop": "All actions will be removed from the activity feed and you won't be able to recover the list. There is no undo.",
"list-delete-suggest-archive": "You can move a list to Archive to remove it from the board and preserve the activity.",
"lists": "Lists",
"swimlanes": "Swimlanes",
"log-out": "Log Out",
"log-in": "登入",
"loginPopup-title": "登入",
"memberMenuPopup-title": "Member Settings",
"members": "Members",
"menu": "Menu",
"move-selection": "Move selection",
"moveCardPopup-title": "Move Card",
"moveCardToBottom-title": "Move to Bottom",
"moveCardToTop-title": "Move to Top",
"moveSelectionPopup-title": "Move selection",
"multi-selection": "Multi-Selection",
"multi-selection-on": "Multi-Selection is on",
"muted": "Muted",
"muted-info": "You will never be notified of any changes in this board",
"my-boards": "My Boards",
"name": "Name",
"no-archived-cards": "No cards in Archive.",
"no-archived-lists": "No lists in Archive.",
"no-archived-swimlanes": "No swimlanes in Archive.",
"no-results": "No results",
"normal": "Normal",
"normal-desc": "Can view and edit cards. Can't change settings.",
"not-accepted-yet": "Invitation not accepted yet",
"notify-participate": "Receive updates to any cards you participate as creater or member",
"notify-watch": "Receive updates to any boards, lists, or cards you’re watching",
"optional": "optional",
"or": "or",
"page-maybe-private": "This page may be private. You may be able to view it by <a href='%s'>logging in</a>.",
"page-not-found": "Page not found.",
"password": "Password",
"paste-or-dragdrop": "to paste, or drag & drop image file to it (image only)",
"participating": "Participating",
"preview": "Preview",
"previewAttachedImagePopup-title": "Preview",
"previewClipboardImagePopup-title": "Preview",
"private": "Private",
"private-desc": "This board is private. Only people added to the board can view and edit it.",
"profile": "Profile",
"public": "Public",
"public-desc": "This board is public. It's visible to anyone with the link and will show up in search engines like Google. Only people added to the board can edit.",
"quick-access-description": "Star a board to add a shortcut in this bar.",
"remove-cover": "Remove Cover",
"remove-from-board": "Remove from Board",
"remove-label": "Remove Label",
"listDeletePopup-title": "Delete List ?",
"remove-member": "Remove Member",
"remove-member-from-card": "Remove from Card",
"remove-member-pop": "Remove __name__ (__username__) from __boardTitle__? The member will be removed from all cards on this board. They will receive a notification.",
"removeMemberPopup-title": "Remove Member?",
"rename": "Rename",
"rename-board": "Rename Board",
"restore": "Restore",
"save": "儲存",
"search": "Search",
"rules": "Rules",
"search-cards": "Search from card titles and descriptions on this board",
"search-example": "Text to search for?",
"select-color": "Select Color",
"set-wip-limit-value": "Set a limit for the maximum number of tasks in this list",
"setWipLimitPopup-title": "Set WIP Limit",
"shortcut-assign-self": "Assign yourself to current card",
"shortcut-autocomplete-emoji": "Autocomplete emoji",
"shortcut-autocomplete-members": "Autocomplete members",
"shortcut-clear-filters": "Clear all filters",
"shortcut-close-dialog": "Close Dialog",
"shortcut-filter-my-cards": "Filter my cards",
"shortcut-show-shortcuts": "Bring up this shortcuts list",
"shortcut-toggle-filterbar": "Toggle Filter Sidebar",
"shortcut-toggle-sidebar": "Toggle Board Sidebar",
"show-cards-minimum-count": "Show cards count if list contains more than",
"sidebar-open": "Open Sidebar",
"sidebar-close": "Close Sidebar",
"signupPopup-title": "Create an Account",
"star-board-title": "Click to star this board. It will show up at top of your boards list.",
"starred-boards": "Starred Boards",
"starred-boards-description": "Starred boards show up at the top of your boards list.",
"subscribe": "Subscribe",
"team": "Team",
"this-board": "this board",
"this-card": "this card",
"spent-time-hours": "Spent time (hours)",
"overtime-hours": "Overtime (hours)",
"overtime": "Overtime",
"has-overtime-cards": "Has overtime cards",
"has-spenttime-cards": "Has spent time cards",
"time": "Time",
"title": "Title",
"tracking": "Tracking",
"tracking-info": "You will be notified of any changes to those cards you are involved as creator or member.",
"type": "Type",
"unassign-member": "Unassign member",
"unsaved-description": "You have an unsaved description.",
"unwatch": "Unwatch",
"upload": "Upload",
"upload-avatar": "Upload an avatar",
"uploaded-avatar": "Uploaded an avatar",
"username": "Username",
"view-it": "View it",
"warn-list-archived": "warning: this card is in an list at Archive",
"watch": "Watch",
"watching": "Watching",
"watching-info": "You will be notified of any change in this board",
"welcome-board": "Welcome Board",
"welcome-swimlane": "Milestone 1",
"welcome-list1": "Basics",
"welcome-list2": "Advanced",
"card-templates-swimlane": "Card Templates",
"list-templates-swimlane": "List Templates",
"board-templates-swimlane": "Board Templates",
"what-to-do": "What do you want to do?",
"wipLimitErrorPopup-title": "Invalid WIP Limit",
"wipLimitErrorPopup-dialog-pt1": "The number of tasks in this list is higher than the WIP limit you've defined.",
"wipLimitErrorPopup-dialog-pt2": "Please move some tasks out of this list, or set a higher WIP limit.",
"admin-panel": "Admin Panel",
"settings": "Settings",
"people": "People",
"registration": "Registration",
"disable-self-registration": "Disable Self-Registration",
"invite": "Invite",
"invite-people": "Invite People",
"to-boards": "To board(s)",
"email-addresses": "Email Addresses",
"smtp-host-description": "The address of the SMTP server that handles your emails.",
"smtp-port-description": "The port your SMTP server uses for outgoing emails.",
"smtp-tls-description": "Enable TLS support for SMTP server",
"smtp-host": "SMTP Host",
"smtp-port": "SMTP Port",
"smtp-username": "Username",
"smtp-password": "Password",
"smtp-tls": "TLS support",
"send-from": "From",
"send-smtp-test": "Send a test email to yourself",
"invitation-code": "Invitation Code",
"email-invite-register-subject": "__inviter__ sent you an invitation",
"email-invite-register-text": "Dear __user__,\n\n__inviter__ invites you to kanban board for collaborations.\n\nPlease follow the link below:\n__url__\n\nAnd your invitation code is: __icode__\n\nThanks.",
"email-smtp-test-subject": "SMTP Test Email",
"email-smtp-test-text": "You have successfully sent an email",
"error-invitation-code-not-exist": "Invitation code doesn't exist",
"error-notAuthorized": "You are not authorized to view this page.",
"outgoing-webhooks": "Outgoing Webhooks",
"outgoingWebhooksPopup-title": "Outgoing Webhooks",
"boardCardTitlePopup-title": "Card Title Filter",
"new-outgoing-webhook": "New Outgoing Webhook",
"no-name": "(Unknown)",
"Node_version": "Node version",
"OS_Arch": "OS Arch",
"OS_Cpus": "OS CPU Count",
"OS_Freemem": "OS Free Memory",
"OS_Loadavg": "OS Load Average",
"OS_Platform": "OS Platform",
"OS_Release": "OS Release",
"OS_Totalmem": "OS Total Memory",
"OS_Type": "OS Type",
"OS_Uptime": "OS Uptime",
"days": "days",
"hours": "hours",
"minutes": "minutes",
"seconds": "seconds",
"show-field-on-card": "Show this field on card",
"automatically-field-on-card": "Auto create field to all cards",
"showLabel-field-on-card": "Show field label on minicard",
"yes": "Yes",
"no": "No",
"accounts": "Accounts",
"accounts-allowEmailChange": "Allow Email Change",
"accounts-allowUserNameChange": "Allow Username Change",
"createdAt": "Created at",
"verified": "Verified",
"active": "Active",
"card-received": "Received",
"card-received-on": "Received on",
"card-end": "End",
"card-end-on": "Ends on",
"editCardReceivedDatePopup-title": "Change received date",
"editCardEndDatePopup-title": "Change end date",
"setCardColorPopup-title": "Set color",
"setCardActionsColorPopup-title": "Choose a color",
"setSwimlaneColorPopup-title": "Choose a color",
"setListColorPopup-title": "Choose a color",
"assigned-by": "Assigned By",
"requested-by": "Requested By",
"board-delete-notice": "Deleting is permanent. You will lose all lists, cards and actions associated with this board.",
"delete-board-confirm-popup": "All lists, cards, labels, and activities will be deleted and you won't be able to recover the board contents. There is no undo.",
"boardDeletePopup-title": "Delete Board?",
"delete-board": "Delete Board",
"default-subtasks-board": "Subtasks for __board__ board",
"default": "Default",
"queue": "Queue",
"subtask-settings": "Subtasks Settings",
"boardSubtaskSettingsPopup-title": "Board Subtasks Settings",
"show-subtasks-field": "Cards can have subtasks",
"deposit-subtasks-board": "Deposit subtasks to this board:",
"deposit-subtasks-list": "Landing list for subtasks deposited here:",
"show-parent-in-minicard": "Show parent in minicard:",
"prefix-with-full-path": "Prefix with full path",
"prefix-with-parent": "Prefix with parent",
"subtext-with-full-path": "Subtext with full path",
"subtext-with-parent": "Subtext with parent",
"change-card-parent": "Change card's parent",
"parent-card": "Parent card",
"source-board": "Source board",
"no-parent": "Don't show parent",
"activity-added-label": "added label '%s' to %s",
"activity-removed-label": "removed label '%s' from %s",
"activity-delete-attach": "deleted an attachment from %s",
"activity-added-label-card": "added label '%s'",
"activity-removed-label-card": "removed label '%s'",
"activity-delete-attach-card": "deleted an attachment",
"activity-set-customfield": "set custom field '%s' to '%s' in %s",
"activity-unset-customfield": "unset custom field '%s' in %s",
"r-rule": "Rule",
"r-add-trigger": "Add trigger",
"r-add-action": "Add action",
"r-board-rules": "Board rules",
"r-add-rule": "Add rule",
"r-view-rule": "View rule",
"r-delete-rule": "Delete rule",
"r-new-rule-name": "New rule title",
"r-no-rules": "No rules",
"r-when-a-card": "When a card",
"r-is": "is",
"r-is-moved": "is moved",
"r-added-to": "added to",
"r-removed-from": "Removed from",
"r-the-board": "the board",
"r-list": "list",
"set-filter": "Set Filter",
"r-moved-to": "Moved to",
"r-moved-from": "Moved from",
"r-archived": "Moved to Archive",
"r-unarchived": "Restored from Archive",
"r-a-card": "a card",
"r-when-a-label-is": "When a label is",
"r-when-the-label-is": "When the label is",
"r-list-name": "list name",
"r-when-a-member": "When a member is",
"r-when-the-member": "When the member",
"r-name": "name",
"r-when-a-attach": "When an attachment",
"r-when-a-checklist": "When a checklist is",
"r-when-the-checklist": "When the checklist",
"r-completed": "Completed",
"r-made-incomplete": "Made incomplete",
"r-when-a-item": "When a checklist item is",
"r-when-the-item": "When the checklist item",
"r-checked": "Checked",
"r-unchecked": "Unchecked",
"r-move-card-to": "Move card to",
"r-top-of": "Top of",
"r-bottom-of": "Bottom of",
"r-its-list": "its list",
"r-archive": "Move to Archive",
"r-unarchive": "Restore from Archive",
"r-card": "card",
"r-add": "Add",
"r-remove": "Remove",
"r-label": "label",
"r-member": "member",
"r-remove-all": "Remove all members from the card",
"r-set-color": "Set color to",
"r-checklist": "checklist",
"r-check-all": "Check all",
"r-uncheck-all": "Uncheck all",
"r-items-check": "items of checklist",
"r-check": "Check",
"r-uncheck": "Uncheck",
"r-item": "item",
"r-of-checklist": "of checklist",
"r-send-email": "Send an email",
"r-to": "to",
"r-subject": "subject",
"r-rule-details": "Rule details",
"r-d-move-to-top-gen": "Move card to top of its list",
"r-d-move-to-top-spec": "Move card to top of list",
"r-d-move-to-bottom-gen": "Move card to bottom of its list",
"r-d-move-to-bottom-spec": "Move card to bottom of list",
"r-d-send-email": "Send email",
"r-d-send-email-to": "to",
"r-d-send-email-subject": "subject",
"r-d-send-email-message": "message",
"r-d-archive": "Move card to Archive",
"r-d-unarchive": "Restore card from Archive",
"r-d-add-label": "Add label",
"r-d-remove-label": "Remove label",
"r-create-card": "Create new card",
"r-in-list": "in list",
"r-in-swimlane": "in swimlane",
"r-d-add-member": "Add member",
"r-d-remove-member": "Remove member",
"r-d-remove-all-member": "Remove all member",
"r-d-check-all": "Check all items of a list",
"r-d-uncheck-all": "Uncheck all items of a list",
"r-d-check-one": "Check item",
"r-d-uncheck-one": "Uncheck item",
"r-d-check-of-list": "of checklist",
"r-d-add-checklist": "Add checklist",
"r-d-remove-checklist": "Remove checklist",
"r-by": "by",
"r-add-checklist": "Add checklist",
"r-with-items": "with items",
"r-items-list": "item1,item2,item3",
"r-add-swimlane": "Add swimlane",
"r-swimlane-name": "swimlane name",
"r-board-note": "Note: leave a field empty to match every possible value.",
"r-checklist-note": "Note: checklist's items have to be written as comma separated values.",
"r-when-a-card-is-moved": "When a card is moved to another list",
"ldap": "LDAP",
"oauth2": "OAuth2",
"cas": "CAS",
"authentication-method": "Authentication method",
"authentication-type": "Authentication type",
"custom-product-name": "Custom Product Name",
"layout": "Layout",
"hide-logo": "Hide Logo",
"add-custom-html-after-body-start": "Add Custom HTML after <body> start",
"add-custom-html-before-body-end": "Add Custom HTML before </body> end",
"error-undefined": "Something went wrong",
"error-ldap-login": "An error occurred while trying to login",
"display-authentication-method": "Display Authentication Method",
"default-authentication-method": "Default Authentication Method",
"duplicate-board": "Duplicate Board",
"people-number": "The number of people is:",
"swimlaneDeletePopup-title": "Delete Swimlane ?",
"swimlane-delete-pop": "All actions will be removed from the activity feed and you won't be able to recover the swimlane. There is no undo.",
"restore-all": "Restore all",
"delete-all": "Delete all",
"loading": "Loading, please wait."
}
+16
View File
@@ -867,6 +867,22 @@ if (Meteor.isServer) {
} else throw new Meteor.Error('error-board-doesNotExist');
},
});
Meteor.methods({
archiveBoard(boardId) {
check(boardId, String);
const board = Boards.findOne(boardId);
if (board) {
const userId = Meteor.userId();
const index = board.memberIndex(userId);
if (index >= 0) {
board.archive();
return true;
} else throw new Meteor.Error('error-board-notAMember');
} else throw new Meteor.Error('error-board-doesNotExist');
},
});
}
if (Meteor.isServer) {
+17
View File
@@ -1685,6 +1685,7 @@ if (Meteor.isServer) {
* @param {string} boardId the board ID of the new card
* @param {string} listId the list ID of the new card
* @param {string} authorID the user ID of the person owning the card
* @param {string} parentId the parent ID of the new card
* @param {string} title the title of the new card
* @param {string} description the description of the new card
* @param {string} swimlaneId the swimlane ID of the new card
@@ -1695,6 +1696,7 @@ if (Meteor.isServer) {
Authentication.checkUserId(req.userId);
const paramBoardId = req.params.boardId;
const paramListId = req.params.listId;
const paramParentId = req.params.parentId;
const currentCards = Cards.find({
listId: paramListId,
archived: false,
@@ -1708,6 +1710,7 @@ if (Meteor.isServer) {
title: req.body.title,
boardId: paramBoardId,
listId: paramListId,
parentId: paramParentId,
description: req.body.description,
userId: req.body.authorId,
swimlaneId: req.body.swimlaneId,
@@ -1761,6 +1764,7 @@ if (Meteor.isServer) {
* @param {string} [listId] the new list ID of the card (move operation)
* @param {string} [description] the new description of the card
* @param {string} [authorId] change the owner of the card
* @param {string} [parentId] change the parent of the card
* @param {string} [labelIds] the new list of label IDs attached to the card
* @param {string} [swimlaneId] the new swimlane ID of the card
* @param {string} [members] the new list of member IDs attached to the card
@@ -1817,6 +1821,19 @@ if (Meteor.isServer) {
}, paramListId);
}
if (req.body.hasOwnProperty('parentId')) {
const newParentId = req.body.parentId;
Cards.direct.update({
_id: paramCardId,
listId: paramListId,
boardId: paramBoardId,
archived: false,
}, {
$set: {
parentId: newParentId,
},
});
}
if (req.body.hasOwnProperty('description')) {
const newDescription = req.body.description;
Cards.direct.update({
+16 -9
View File
@@ -6,27 +6,34 @@ if (Meteor.isServer) {
// `ApiRoutes.path('boards/export', boardId)``
// on the client instead of copy/pasting the route path manually between the
// client and the server.
/*
* This route is used to export the board FROM THE APPLICATION.
* If user is already logged-in, pass loginToken as param "authToken":
* '/api/boards/:boardId/export?authToken=:token'
/**
* @operation export
* @tag Boards
*
* @summary This route is used to export the board.
*
* @description If user is already logged-in, pass loginToken as param
* "authToken": '/api/boards/:boardId/export?authToken=:token'
*
* See https://blog.kayla.com.au/server-side-route-authentication-in-meteor/
* for detailed explanations
*
* @param {string} boardId the ID of the board we are exporting
* @param {string} authToken the loginToken
*/
JsonRoutes.add('get', '/api/boards/:boardId/export', function(req, res) {
const boardId = req.params.boardId;
let user = null;
// todo XXX for real API, first look for token in Authentication: header
// then fallback to parameter
const loginToken = req.query.authToken;
if (loginToken) {
const hashToken = Accounts._hashLoginToken(loginToken);
user = Meteor.users.findOne({
'services.resume.loginTokens.hashedToken': hashToken,
});
} else if (!Meteor.settings.public.sandstorm) {
Authentication.checkUserId(req.userId);
user = Users.findOne({ _id: req.userId, isAdmin: true });
}
const exporter = new Exporter(boardId);
@@ -172,7 +179,7 @@ export class Exporter {
};
result.users = Users.find(byUserIds, userFields).fetch().map((user) => {
// user avatar is stored as a relative url, we export absolute
if (user.profile.avatarUrl) {
if ((user.profile || {}).avatarUrl) {
user.profile.avatarUrl = FlowRouter.url(user.profile.avatarUrl);
}
return user;
+3 -3
View File
@@ -168,17 +168,17 @@ Swimlanes.helpers({
isListTemplatesSwimlane() {
const user = Users.findOne(Meteor.userId());
return user.profile.listTemplatesSwimlaneId === this._id;
return (user.profile || {}).listTemplatesSwimlaneId === this._id;
},
isCardTemplatesSwimlane() {
const user = Users.findOne(Meteor.userId());
return user.profile.cardTemplatesSwimlaneId === this._id;
return (user.profile || {}).cardTemplatesSwimlaneId === this._id;
},
isBoardTemplatesSwimlane() {
const user = Users.findOne(Meteor.userId());
return user.profile.boardTemplatesSwimlaneId === this._id;
return (user.profile || {}).boardTemplatesSwimlaneId === this._id;
},
remove() {
+43 -9
View File
@@ -238,6 +238,19 @@ Users.allow({
const user = Users.findOne(userId);
return user && Meteor.user().isAdmin;
},
remove(userId, doc) {
const adminsNumber = Users.find({ isAdmin: true }).count();
const { isAdmin } = Users.findOne({ _id: userId }, { fields: { 'isAdmin': 1 } });
// Prevents remove of the only one administrator
if (adminsNumber === 1 && isAdmin && userId === doc._id) {
return false;
}
// If it's the user or an admin
return userId === doc._id || isAdmin;
},
fetch: [],
});
// Search a user in the complete server database by its name or username. This
@@ -288,32 +301,32 @@ Users.helpers({
},
starredBoards() {
const {starredBoards = []} = this.profile;
const {starredBoards = []} = this.profile || {};
return Boards.find({archived: false, _id: {$in: starredBoards}});
},
hasStarred(boardId) {
const {starredBoards = []} = this.profile;
const {starredBoards = []} = this.profile || {};
return _.contains(starredBoards, boardId);
},
invitedBoards() {
const {invitedBoards = []} = this.profile;
const {invitedBoards = []} = this.profile || {};
return Boards.find({archived: false, _id: {$in: invitedBoards}});
},
isInvitedTo(boardId) {
const {invitedBoards = []} = this.profile;
const {invitedBoards = []} = this.profile || {};
return _.contains(invitedBoards, boardId);
},
hasTag(tag) {
const {tags = []} = this.profile;
const {tags = []} = this.profile || {};
return _.contains(tags, tag);
},
hasNotification(activityId) {
const {notifications = []} = this.profile;
const {notifications = []} = this.profile || {};
return _.contains(notifications, activityId);
},
@@ -323,7 +336,7 @@ Users.helpers({
},
getEmailBuffer() {
const {emailBuffer = []} = this.profile;
const {emailBuffer = []} = this.profile || {};
return emailBuffer;
},
@@ -358,11 +371,15 @@ Users.helpers({
},
getTemplatesBoardId() {
return this.profile.templatesBoardId;
return (this.profile || {}).templatesBoardId;
},
getTemplatesBoardSlug() {
return Boards.findOne(this.profile.templatesBoardId).slug;
return (Boards.findOne((this.profile || {}).templatesBoardId) || {}).slug;
},
remove() {
User.remove({ _id: this._id});
},
});
@@ -673,6 +690,23 @@ if (Meteor.isServer) {
}, {unique: true});
});
// OLD WAY THIS CODE DID WORK: When user is last admin of board,
// if admin is removed, board is removed.
// NOW THIS IS COMMENTED OUT, because other board users still need to be able
// to use that board, and not have board deleted.
// Someone can be later changed to be admin of board, by making change to database.
// TODO: Add UI for changing someone as board admin.
//Users.before.remove((userId, doc) => {
// Boards
// .find({members: {$elemMatch: {userId: doc._id, isAdmin: true}}})
// .forEach((board) => {
// // If only one admin for the board
// if (board.members.filter((e) => e.isAdmin).length === 1) {
// Boards.remove(board._id);
// }
// });
//});
// Each board document contains the de-normalized number of users that have
// starred it. If the user star or unstar a board, we need to update this
// counter.
+1 -1
View File
@@ -678,7 +678,7 @@ def parse_schemas(schemas_dir):
data = ''.join(f.readlines())
try:
# if the file failed, it's likely it doesn't contain a schema
program = esprima.parseScript(data, options={'comment': True, 'loc': True})
program = esprima.parseModule(data, options={'comment': True, 'loc': True})
except:
continue
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "wekan",
"version": "v2.65.0",
"version": "v2.73.0",
"description": "Open-Source kanban",
"private": true,
"scripts": {
+105 -77
View File
@@ -1,41 +1,44 @@
import ldapjs from 'ldapjs';
import util from 'util';
import Bunyan from 'bunyan';
import { log_debug, log_info, log_warn, log_error } from './logger';
import {log_debug, log_info, log_warn, log_error} from './logger';
export default class LDAP {
constructor(){
constructor() {
this.ldapjs = ldapjs;
this.connected = false;
this.options = {
host: this.constructor.settings_get('LDAP_HOST'),
port: this.constructor.settings_get('LDAP_PORT'),
Reconnect: this.constructor.settings_get('LDAP_RECONNECT'),
timeout: this.constructor.settings_get('LDAP_TIMEOUT'),
connect_timeout: this.constructor.settings_get('LDAP_CONNECT_TIMEOUT'),
idle_timeout: this.constructor.settings_get('LDAP_IDLE_TIMEOUT'),
encryption: this.constructor.settings_get('LDAP_ENCRYPTION'),
ca_cert: this.constructor.settings_get('LDAP_CA_CERT'),
reject_unauthorized: this.constructor.settings_get('LDAP_REJECT_UNAUTHORIZED') || false,
Authentication: this.constructor.settings_get('LDAP_AUTHENTIFICATION'),
Authentication_UserDN: this.constructor.settings_get('LDAP_AUTHENTIFICATION_USERDN'),
Authentication_Password: this.constructor.settings_get('LDAP_AUTHENTIFICATION_PASSWORD'),
Authentication_Fallback: this.constructor.settings_get('LDAP_LOGIN_FALLBACK'),
BaseDN: this.constructor.settings_get('LDAP_BASEDN'),
Internal_Log_Level: this.constructor.settings_get('INTERNAL_LOG_LEVEL'),
User_Search_Filter: this.constructor.settings_get('LDAP_USER_SEARCH_FILTER'),
User_Search_Scope: this.constructor.settings_get('LDAP_USER_SEARCH_SCOPE'),
User_Search_Field: this.constructor.settings_get('LDAP_USER_SEARCH_FIELD'),
Search_Page_Size: this.constructor.settings_get('LDAP_SEARCH_PAGE_SIZE'),
Search_Size_Limit: this.constructor.settings_get('LDAP_SEARCH_SIZE_LIMIT'),
group_filter_enabled: this.constructor.settings_get('LDAP_GROUP_FILTER_ENABLE'),
group_filter_object_class: this.constructor.settings_get('LDAP_GROUP_FILTER_OBJECTCLASS'),
group_filter_group_id_attribute: this.constructor.settings_get('LDAP_GROUP_FILTER_GROUP_ID_ATTRIBUTE'),
host : this.constructor.settings_get('LDAP_HOST'),
port : this.constructor.settings_get('LDAP_PORT'),
Reconnect : this.constructor.settings_get('LDAP_RECONNECT'),
timeout : this.constructor.settings_get('LDAP_TIMEOUT'),
connect_timeout : this.constructor.settings_get('LDAP_CONNECT_TIMEOUT'),
idle_timeout : this.constructor.settings_get('LDAP_IDLE_TIMEOUT'),
encryption : this.constructor.settings_get('LDAP_ENCRYPTION'),
ca_cert : this.constructor.settings_get('LDAP_CA_CERT'),
reject_unauthorized : this.constructor.settings_get('LDAP_REJECT_UNAUTHORIZED') || false,
Authentication : this.constructor.settings_get('LDAP_AUTHENTIFICATION'),
Authentication_UserDN : this.constructor.settings_get('LDAP_AUTHENTIFICATION_USERDN'),
Authentication_Password : this.constructor.settings_get('LDAP_AUTHENTIFICATION_PASSWORD'),
Authentication_Fallback : this.constructor.settings_get('LDAP_LOGIN_FALLBACK'),
BaseDN : this.constructor.settings_get('LDAP_BASEDN'),
Internal_Log_Level : this.constructor.settings_get('INTERNAL_LOG_LEVEL'),
User_Authentication : this.constructor.settings_get('LDAP_USER_AUTHENTICATION'),
User_Attributes : this.constructor.settings_get('LDAP_USER_ATTRIBUTES'),
User_Search_Filter : this.constructor.settings_get('LDAP_USER_SEARCH_FILTER'),
User_Search_Scope : this.constructor.settings_get('LDAP_USER_SEARCH_SCOPE'),
User_Search_Field : this.constructor.settings_get('LDAP_USER_SEARCH_FIELD'),
Search_Page_Size : this.constructor.settings_get('LDAP_SEARCH_PAGE_SIZE'),
Search_Size_Limit : this.constructor.settings_get('LDAP_SEARCH_SIZE_LIMIT'),
group_filter_enabled : this.constructor.settings_get('LDAP_GROUP_FILTER_ENABLE'),
group_filter_object_class : this.constructor.settings_get('LDAP_GROUP_FILTER_OBJECTCLASS'),
group_filter_group_id_attribute : this.constructor.settings_get('LDAP_GROUP_FILTER_GROUP_ID_ATTRIBUTE'),
group_filter_group_member_attribute: this.constructor.settings_get('LDAP_GROUP_FILTER_GROUP_MEMBER_ATTRIBUTE'),
group_filter_group_member_format: this.constructor.settings_get('LDAP_GROUP_FILTER_GROUP_MEMBER_FORMAT'),
group_filter_group_name: this.constructor.settings_get('LDAP_GROUP_FILTER_GROUP_NAME'),
group_filter_group_member_format : this.constructor.settings_get('LDAP_GROUP_FILTER_GROUP_MEMBER_FORMAT'),
group_filter_group_name : this.constructor.settings_get('LDAP_GROUP_FILTER_GROUP_NAME'),
};
}
@@ -52,14 +55,16 @@ export default class LDAP {
log_warn(`Lookup for unset variable: ${name}`);
}
}
connectSync(...args) {
if (!this._connectSync) {
if (!this._connectSync) {
this._connectSync = Meteor.wrapAsync(this.connectAsync, this);
}
return this._connectSync(...args);
}
searchAllSync(...args) {
if (!this._searchAllSync) {
this._searchAllSync = Meteor.wrapAsync(this.searchAllAsync, this);
}
@@ -72,19 +77,19 @@ export default class LDAP {
let replied = false;
const connectionOptions = {
url: `${ this.options.host }:${ this.options.port }`,
timeout: this.options.timeout,
url : `${this.options.host}:${this.options.port}`,
timeout : this.options.timeout,
connectTimeout: this.options.connect_timeout,
idleTimeout: this.options.idle_timeout,
reconnect: this.options.Reconnect,
idleTimeout : this.options.idle_timeout,
reconnect : this.options.Reconnect,
};
if (this.options.Internal_Log_Level !== 'disabled') {
connectionOptions.log = new Bunyan({
name: 'ldapjs',
name : 'ldapjs',
component: 'client',
stream: process.stderr,
level: this.options.Internal_Log_Level,
stream : process.stderr,
level : this.options.Internal_Log_Level,
});
}
@@ -95,8 +100,8 @@ export default class LDAP {
if (this.options.ca_cert && this.options.ca_cert !== '') {
// Split CA cert into array of strings
const chainLines = this.constructor.settings_get('LDAP_CA_CERT').split('\n');
let cert = [];
const ca = [];
let cert = [];
const ca = [];
chainLines.forEach((line) => {
cert.push(line);
if (line.match(/-END CERTIFICATE-/)) {
@@ -108,14 +113,14 @@ export default class LDAP {
}
if (this.options.encryption === 'ssl') {
connectionOptions.url = `ldaps://${ connectionOptions.url }`;
connectionOptions.url = `ldaps://${connectionOptions.url}`;
connectionOptions.tlsOptions = tlsOptions;
} else {
connectionOptions.url = `ldap://${ connectionOptions.url }`;
connectionOptions.url = `ldap://${connectionOptions.url}`;
}
log_info('Connecting', connectionOptions.url);
log_debug(`connectionOptions${ util.inspect(connectionOptions)}`);
log_debug(`connectionOptions${util.inspect(connectionOptions)}`);
this.client = ldapjs.createClient(connectionOptions);
@@ -189,23 +194,42 @@ export default class LDAP {
if (this.options.User_Search_Filter !== '') {
if (this.options.User_Search_Filter[0] === '(') {
filter.push(`${ this.options.User_Search_Filter }`);
filter.push(`${this.options.User_Search_Filter}`);
} else {
filter.push(`(${ this.options.User_Search_Filter })`);
filter.push(`(${this.options.User_Search_Filter})`);
}
}
const usernameFilter = this.options.User_Search_Field.split(',').map((item) => `(${ item }=${ username })`);
const usernameFilter = this.options.User_Search_Field.split(',').map((item) => `(${item}=${username})`);
if (usernameFilter.length === 0) {
log_error('LDAP_LDAP_User_Search_Field not defined');
} else if (usernameFilter.length === 1) {
filter.push(`${ usernameFilter[0] }`);
filter.push(`${usernameFilter[0]}`);
} else {
filter.push(`(|${ usernameFilter.join('') })`);
filter.push(`(|${usernameFilter.join('')})`);
}
return `(&${ filter.join('') })`;
return `(&${filter.join('')})`;
}
bindUserIfNecessary(username, password) {
if (this.domainBinded === true) {
return;
}
if (!this.options.User_Authentication) {
return;
}
if (!this.options.BaseDN) throw new Error('BaseDN is not provided');
const userDn = `uid=${username},${this.options.BaseDN}`;
this.bindSync(userDn, password);
this.domainBinded = true;
}
bindIfNecessary() {
@@ -218,22 +242,24 @@ export default class LDAP {
}
log_info('Binding UserDN', this.options.Authentication_UserDN);
this.bindSync(this.options.Authentication_UserDN, this.options.Authentication_Password);
this.domainBinded = true;
}
searchUsersSync(username, page) {
this.bindIfNecessary();
const searchOptions = {
filter: this.getUserFilter(username),
scope: this.options.User_Search_Scope || 'sub',
filter : this.getUserFilter(username),
scope : this.options.User_Search_Scope || 'sub',
sizeLimit: this.options.Search_Size_Limit,
};
if (!!this.options.User_Attributes) searchOptions.attributes = this.options.User_Attributes.split(',');
if (this.options.Search_Page_Size > 0) {
searchOptions.paged = {
pageSize: this.options.Search_Page_Size,
pageSize : this.options.Search_Page_Size,
pagePause: !!page,
};
}
@@ -266,11 +292,11 @@ export default class LDAP {
Unique_Identifier_Field.forEach((item) => {
filters.push(new this.ldapjs.filters.EqualityFilter({
attribute: item,
value: new Buffer(id, 'hex'),
value : new Buffer(id, 'hex'),
}));
});
filter = new this.ldapjs.filters.OrFilter({filters});
filter = new this.ldapjs.filters.OrFilter({ filters });
}
const searchOptions = {
@@ -300,7 +326,7 @@ export default class LDAP {
const searchOptions = {
filter: this.getUserFilter(username),
scope: this.options.User_Search_Scope || 'sub',
scope : this.options.User_Search_Scope || 'sub',
};
log_info('Searching user', username);
@@ -320,7 +346,7 @@ export default class LDAP {
return result[0];
}
getUserGroups(username, ldapUser){
getUserGroups(username, ldapUser) {
if (!this.options.group_filter_enabled) {
return true;
}
@@ -328,13 +354,13 @@ export default class LDAP {
const filter = ['(&'];
if (this.options.group_filter_object_class !== '') {
filter.push(`(objectclass=${ this.options.group_filter_object_class })`);
filter.push(`(objectclass=${this.options.group_filter_object_class})`);
}
if (this.options.group_filter_group_member_attribute !== '') {
const format_value = ldapUser[this.options.group_filter_group_member_format];
if( format_value ) {
filter.push(`(${ this.options.group_filter_group_member_attribute }=${ format_value })`);
if (format_value) {
filter.push(`(${this.options.group_filter_group_member_attribute}=${format_value})`);
}
}
@@ -342,7 +368,7 @@ export default class LDAP {
const searchOptions = {
filter: filter.join('').replace(/#{username}/g, username),
scope: 'sub',
scope : 'sub',
};
log_debug('Group list filter LDAP:', searchOptions.filter);
@@ -354,11 +380,11 @@ export default class LDAP {
}
const grp_identifier = this.options.group_filter_group_id_attribute || 'cn';
const groups = [];
const groups = [];
result.map((item) => {
groups.push( item[ grp_identifier ] );
groups.push(item[grp_identifier]);
});
log_debug(`Groups: ${ groups.join(', ')}`);
log_debug(`Groups: ${groups.join(', ')}`);
return groups;
}
@@ -373,24 +399,24 @@ export default class LDAP {
const filter = ['(&'];
if (this.options.group_filter_object_class !== '') {
filter.push(`(objectclass=${ this.options.group_filter_object_class })`);
filter.push(`(objectclass=${this.options.group_filter_object_class})`);
}
if (this.options.group_filter_group_member_attribute !== '') {
const format_value = ldapUser[this.options.group_filter_group_member_format];
if( format_value ) {
filter.push(`(${ this.options.group_filter_group_member_attribute }=${ format_value })`);
if (format_value) {
filter.push(`(${this.options.group_filter_group_member_attribute}=${format_value})`);
}
}
if (this.options.group_filter_group_id_attribute !== '') {
filter.push(`(${ this.options.group_filter_group_id_attribute }=${ this.options.group_filter_group_name })`);
filter.push(`(${this.options.group_filter_group_id_attribute}=${this.options.group_filter_group_name})`);
}
filter.push(')');
const searchOptions = {
filter: filter.join('').replace(/#{username}/g, username),
scope: 'sub',
scope : 'sub',
};
log_debug('Group filter LDAP:', searchOptions.filter);
@@ -426,15 +452,17 @@ export default class LDAP {
searchAllPaged(BaseDN, options, page) {
this.bindIfNecessary();
const processPage = ({entries, title, end, next}) => {
const processPage = ({ entries, title, end, next }) => {
log_info(title);
// Force LDAP idle to wait the record processing
this.client._updateIdle(true);
page(null, entries, {end, next: () => {
// Reset idle timer
this.client._updateIdle();
next && next();
}});
page(null, entries, {
end, next: () => {
// Reset idle timer
this.client._updateIdle();
next && next();
}
});
};
this.client.search(BaseDN, options, (error, res) => {
@@ -461,7 +489,7 @@ export default class LDAP {
processPage({
entries,
title: 'Internal Page',
end: false,
end : false,
});
entries = [];
}
@@ -473,14 +501,14 @@ export default class LDAP {
processPage({
entries,
title: 'Final Page',
end: true,
end : true,
});
} else if (entries.length) {
log_info('Page');
processPage({
entries,
title: 'Page',
end: false,
end : false,
next,
});
entries = [];
@@ -492,7 +520,7 @@ export default class LDAP {
processPage({
entries,
title: 'Final Page',
end: true,
end : true,
});
entries = [];
}
@@ -547,7 +575,7 @@ export default class LDAP {
}
disconnect() {
this.connected = false;
this.connected = false;
this.domainBinded = false;
log_info('Disconecting');
this.client.unbind();
+31 -21
View File
@@ -41,28 +41,38 @@ Accounts.registerLoginHandler('ldap', function(loginRequest) {
let ldapUser;
try {
ldap.connectSync();
const users = ldap.searchUsersSync(loginRequest.username);
if (users.length !== 1) {
log_info('Search returned', users.length, 'record(s) for', loginRequest.username);
throw new Error('User not Found');
}
ldap.connectSync();
if (!!LDAP.settings_get('LDAP_USER_AUTHENTICATION')) {
ldap.bindUserIfNecessary(loginRequest.username, loginRequest.ldapPass);
ldapUser = ldap.searchUsersSync(loginRequest.username)[0];
} else {
const users = ldap.searchUsersSync(loginRequest.username);
if (users.length !== 1) {
log_info('Search returned', users.length, 'record(s) for', loginRequest.username);
throw new Error('User not Found');
}
if (ldap.authSync(users[0].dn, loginRequest.ldapPass) === true) {
if (ldap.isUserInGroup(loginRequest.username, users[0])) {
ldapUser = users[0];
} else {
throw new Error('User not in a valid group');
}
} else {
log_info('Wrong password for', loginRequest.username);
}
}
if (ldap.authSync(users[0].dn, loginRequest.ldapPass) === true) {
if (ldap.isUserInGroup(loginRequest.username, users[0])) {
ldapUser = users[0];
} else {
throw new Error('User not in a valid group');
}
} else {
log_info('Wrong password for', loginRequest.username);
}
} catch (error) {
log_error(error);
log_error(error);
}
if (ldapUser === undefined) {
if (!ldapUser) {
if (LDAP.settings_get('LDAP_LOGIN_FALLBACK') === true) {
return fallbackDefaultAccountSystem(self, loginRequest.username, loginRequest.ldapPass);
}
@@ -76,8 +86,7 @@ Accounts.registerLoginHandler('ldap', function(loginRequest) {
const Unique_Identifier_Field = getLdapUserUniqueID(ldapUser);
let user;
// Attempt to find user by unique identifier
// Attempt to find user by unique identifier
if (Unique_Identifier_Field) {
userQuery = {
@@ -88,14 +97,14 @@ Accounts.registerLoginHandler('ldap', function(loginRequest) {
log_debug('userQuery', userQuery);
user = Meteor.users.findOne(userQuery);
}
}
// Attempt to find user by username
let username;
let email;
if (LDAP.settings_get('LDAP_USERNAME_FIELD') !== '') {
if (LDAP.settings_get('LDAP_USERNAME_FIELD') !== '') {
username = slug(getLdapUsername(ldapUser));
} else {
username = slug(loginRequest.username);
@@ -105,6 +114,7 @@ Accounts.registerLoginHandler('ldap', function(loginRequest) {
email = getLdapEmail(ldapUser);
}
if (!user) {
if(email && LDAP.settings_get('LDAP_EMAIL_MATCH_REQUIRE') === true) {
if(LDAP.settings_get('LDAP_EMAIL_MATCH_VERIFIED') === true) {
+6 -6
View File
@@ -13,12 +13,12 @@ OAuth.registerService('oidc', 2, null, function (query) {
if (debug) console.log('XXX: userinfo:', userinfo);
var serviceData = {};
serviceData.id = userinfo[process.env.OAUTH2_ID_MAP] || userinfo[id];
serviceData.username = userinfo[process.env.OAUTH2_USERNAME_MAP] || userinfo[uid];
serviceData.fullname = userinfo[process.env.OAUTH2_FULLNAME_MAP] || userinfo[displayName];
serviceData.id = userinfo[process.env.OAUTH2_ID_MAP] || userinfo["id"];
serviceData.username = userinfo[process.env.OAUTH2_USERNAME_MAP] || userinfo["uid"];
serviceData.fullname = userinfo[process.env.OAUTH2_FULLNAME_MAP] || userinfo["displayName"];
serviceData.accessToken = accessToken;
serviceData.expiresAt = expiresAt;
serviceData.email = userinfo[process.env.OAUTH2_EMAIL_MAP] || userinfo[email];
serviceData.email = userinfo[process.env.OAUTH2_EMAIL_MAP] || userinfo["email"];
if (accessToken) {
var tokenContent = getTokenContent(accessToken);
@@ -31,8 +31,8 @@ OAuth.registerService('oidc', 2, null, function (query) {
if (debug) console.log('XXX: serviceData:', serviceData);
var profile = {};
profile.name = userinfo[process.env.OAUTH2_FULLNAME_MAP] || userinfo[displayName];
profile.email = userinfo[process.env.OAUTH2_EMAIL_MAP] || userinfo[email];
profile.name = userinfo[process.env.OAUTH2_FULLNAME_MAP] || userinfo["displayName"];
profile.email = userinfo[process.env.OAUTH2_EMAIL_MAP] || userinfo["email"];
if (debug) console.log('XXX: profile:', profile);
return {
@@ -146,3 +146,6 @@ tx pull -f -l zh_CN
echo "Chinese (Taiwan)"
tx pull -f -l zh_TW
echo "Chinese (Hong Kong)"
tx pull -f -l zh_HK
+2
View File
@@ -191,6 +191,8 @@
# LDAP_REJECT_UNAUTHORIZED : Reject Unauthorized Certificate
# example : export LDAP_REJECT_UNAUTHORIZED=true
#export LDAP_REJECT_UNAUTHORIZED=false
# Option to login to the LDAP server with the user's own username and password, instead of an administrator key. Default: false (use administrator key).
#export LDAP_USER_AUTHENTICATION=true
# LDAP_USER_SEARCH_FILTER : Optional extra LDAP filters. Don't forget the outmost enclosing parentheses if needed
# example : export LDAP_USER_SEARCH_FILTER=
#export LDAP_USER_SEARCH_FILTER=
+2 -2
View File
@@ -22,10 +22,10 @@ const pkgdef :Spk.PackageDefinition = (
appTitle = (defaultText = "Wekan"),
# The name of the app as it is displayed to the user.
appVersion = 267,
appVersion = 275,
# Increment this for every release.
appMarketingVersion = (defaultText = "2.65.0~2019-04-24"),
appMarketingVersion = (defaultText = "2.73.0~2019-05-14"),
# Human-readable presentation of the app version.
minUpgradableAppVersion = 0,
+9 -5
View File
@@ -10,7 +10,7 @@ Meteor.publish('boards', function() {
// Defensive programming to verify that starredBoards has the expected
// format -- since the field is in the `profile` a user can modify it.
const {starredBoards = []} = Users.findOne(this.userId).profile;
const {starredBoards = []} = Users.findOne(this.userId).profile || {};
check(starredBoards, [String]);
return Boards.find({
@@ -59,9 +59,12 @@ Meteor.publish('archivedBoards', function() {
});
});
Meteor.publishRelations('board', function(boardId) {
// If isArchived = false, this will only return board elements which are not archived.
// If isArchived = true, this will only return board elements which are archived.
Meteor.publishRelations('board', function(boardId, isArchived) {
this.unblock();
check(boardId, String);
check(isArchived, Boolean);
const thisUserId = this.userId;
this.cursor(Boards.find({
@@ -75,8 +78,8 @@ Meteor.publishRelations('board', function(boardId) {
],
// Sort required to ensure oplog usage
}, { limit: 1, sort: { _id: 1 } }), function(boardId, board) {
this.cursor(Lists.find({ boardId }));
this.cursor(Swimlanes.find({ boardId }));
this.cursor(Lists.find({ boardId, archived: isArchived }));
this.cursor(Swimlanes.find({ boardId, archived: isArchived }));
this.cursor(Integrations.find({ boardId }));
this.cursor(CustomFields.find({ boardIds: {$in: [boardId]} }, { sort: { name: 1 } }));
@@ -115,8 +118,9 @@ Meteor.publishRelations('board', function(boardId) {
parentCards.selector = (_ids) => ({ parentId: _ids });
const boards = this.join(Boards);
const subCards = this.join(Cards);
subCards.selector = (_ids) => ({ archived: isArchived });
this.cursor(Cards.find({ boardId: {$in: [boardId, board.subtasksDefaultBoardId]}}), function(cardId, card) {
this.cursor(Cards.find({ boardId: {$in: [boardId, board.subtasksDefaultBoardId]}, archived: isArchived }), function(cardId, card) {
if (card.type === 'cardType-linkedCard') {
const impCardId = card.linkedId;
subCards.push(impCardId);
+3 -1
View File
@@ -1,7 +1,9 @@
import { FastRender } from 'meteor/staringatlights:fast-render';
FastRender.onAllRoutes(function() {
this.subscribe('boards');
});
FastRender.route('/b/:id/:slug', function({ id }) {
this.subscribe('board', id);
this.subscribe('board', id, false);
});
+5 -1
View File
@@ -3,7 +3,7 @@
# All supported keys are defined here together with descriptions and default values
# list of supported keys
keys="DEBUG MONGODB_BIND_UNIX_SOCKET MONGODB_BIND_IP MONGODB_PORT MAIL_URL MAIL_FROM ROOT_URL PORT DISABLE_MONGODB CADDY_ENABLED CADDY_BIND_PORT WITH_API ACCOUNTS_LOCKOUT_KNOWN_USERS_FAILURES_BEFORE ACCOUNTS_LOCKOUT_KNOWN_USERS_PERIOD ACCOUNTS_LOCKOUT_KNOWN_USERS_FAILURE_WINDOW ACCOUNTS_LOCKOUT_UNKNOWN_USERS_FAILURES_BERORE ACCOUNTS_LOCKOUT_UNKNOWN_USERS_LOCKOUT_PERIOD ACCOUNTS_LOCKOUT_UNKNOWN_USERS_FAILURE_WINDOW EMAIL_NOTIFICATION_TIMEOUT CORS MATOMO_ADDRESS MATOMO_SITE_ID MATOMO_DO_NOT_TRACK MATOMO_WITH_USERNAME BROWSER_POLICY_ENABLED TRUSTED_URL WEBHOOKS_ATTRIBUTES OAUTH2_ENABLED OAUTH2_LOGIN_STYLE OAUTH2_CLIENT_ID OAUTH2_SECRET OAUTH2_SERVER_URL OAUTH2_AUTH_ENDPOINT OAUTH2_USERINFO_ENDPOINT OAUTH2_TOKEN_ENDPOINT OAUTH2_ID_MAP OAUTH2_USERNAME_MAP OAUTH2_FULLNAME_MAP OAUTH2_EMAIL_MAP LDAP_ENABLE LDAP_PORT LDAP_HOST LDAP_BASEDN LDAP_LOGIN_FALLBACK LDAP_RECONNECT LDAP_TIMEOUT LDAP_IDLE_TIMEOUT LDAP_CONNECT_TIMEOUT LDAP_AUTHENTIFICATION LDAP_AUTHENTIFICATION_USERDN LDAP_AUTHENTIFICATION_PASSWORD LDAP_LOG_ENABLED LDAP_BACKGROUND_SYNC LDAP_BACKGROUND_SYNC_INTERVAL LDAP_BACKGROUND_SYNC_KEEP_EXISTANT_USERS_UPDATED LDAP_BACKGROUND_SYNC_IMPORT_NEW_USERS LDAP_ENCRYPTION LDAP_CA_CERT LDAP_REJECT_UNAUTHORIZED LDAP_USER_SEARCH_FILTER LDAP_USER_SEARCH_SCOPE LDAP_USER_SEARCH_FIELD LDAP_SEARCH_PAGE_SIZE LDAP_SEARCH_SIZE_LIMIT LDAP_GROUP_FILTER_ENABLE LDAP_GROUP_FILTER_OBJECTCLASS LDAP_GROUP_FILTER_GROUP_ID_ATTRIBUTE LDAP_GROUP_FILTER_GROUP_MEMBER_ATTRIBUTE LDAP_GROUP_FILTER_GROUP_MEMBER_FORMAT LDAP_GROUP_FILTER_GROUP_NAME LDAP_UNIQUE_IDENTIFIER_FIELD LDAP_UTF8_NAMES_SLUGIFY LDAP_USERNAME_FIELD LDAP_FULLNAME_FIELD LDAP_MERGE_EXISTING_USERS LDAP_SYNC_USER_DATA LDAP_SYNC_USER_DATA_FIELDMAP LDAP_SYNC_GROUP_ROLES LDAP_DEFAULT_DOMAIN LDAP_EMAIL_MATCH_ENABLE LDAP_EMAIL_MATCH_REQUIRE LDAP_EMAIL_MATCH_VERIFIED LDAP_EMAIL_FIELD LDAP_SYNC_ADMIN_STATUS LDAP_SYNC_ADMIN_GROUPS HEADER_LOGIN_ID HEADER_LOGIN_FIRSTNAME HEADER_LOGIN_LASTNAME HEADER_LOGIN_EMAIL LOGOUT_WITH_TIMER LOGOUT_IN LOGOUT_ON_HOURS LOGOUT_ON_MINUTES DEFAULT_AUTHENTICATION_METHOD"
keys="DEBUG MONGODB_BIND_UNIX_SOCKET MONGODB_BIND_IP MONGODB_PORT MAIL_URL MAIL_FROM ROOT_URL PORT DISABLE_MONGODB CADDY_ENABLED CADDY_BIND_PORT WITH_API ACCOUNTS_LOCKOUT_KNOWN_USERS_FAILURES_BEFORE ACCOUNTS_LOCKOUT_KNOWN_USERS_PERIOD ACCOUNTS_LOCKOUT_KNOWN_USERS_FAILURE_WINDOW ACCOUNTS_LOCKOUT_UNKNOWN_USERS_FAILURES_BERORE ACCOUNTS_LOCKOUT_UNKNOWN_USERS_LOCKOUT_PERIOD ACCOUNTS_LOCKOUT_UNKNOWN_USERS_FAILURE_WINDOW EMAIL_NOTIFICATION_TIMEOUT CORS MATOMO_ADDRESS MATOMO_SITE_ID MATOMO_DO_NOT_TRACK MATOMO_WITH_USERNAME BROWSER_POLICY_ENABLED TRUSTED_URL WEBHOOKS_ATTRIBUTES OAUTH2_ENABLED OAUTH2_LOGIN_STYLE OAUTH2_CLIENT_ID OAUTH2_SECRET OAUTH2_SERVER_URL OAUTH2_AUTH_ENDPOINT OAUTH2_USERINFO_ENDPOINT OAUTH2_TOKEN_ENDPOINT OAUTH2_ID_MAP OAUTH2_USERNAME_MAP OAUTH2_FULLNAME_MAP OAUTH2_EMAIL_MAP LDAP_ENABLE LDAP_PORT LDAP_HOST LDAP_BASEDN LDAP_LOGIN_FALLBACK LDAP_RECONNECT LDAP_TIMEOUT LDAP_IDLE_TIMEOUT LDAP_CONNECT_TIMEOUT LDAP_AUTHENTIFICATION LDAP_AUTHENTIFICATION_USERDN LDAP_AUTHENTIFICATION_PASSWORD LDAP_LOG_ENABLED LDAP_BACKGROUND_SYNC LDAP_BACKGROUND_SYNC_INTERVAL LDAP_BACKGROUND_SYNC_KEEP_EXISTANT_USERS_UPDATED LDAP_BACKGROUND_SYNC_IMPORT_NEW_USERS LDAP_ENCRYPTION LDAP_CA_CERT LDAP_REJECT_UNAUTHORIZED LDAP_USER_AUTHENTICATION LDAP_USER_SEARCH_FILTER LDAP_USER_SEARCH_SCOPE LDAP_USER_SEARCH_FIELD LDAP_SEARCH_PAGE_SIZE LDAP_SEARCH_SIZE_LIMIT LDAP_GROUP_FILTER_ENABLE LDAP_GROUP_FILTER_OBJECTCLASS LDAP_GROUP_FILTER_GROUP_ID_ATTRIBUTE LDAP_GROUP_FILTER_GROUP_MEMBER_ATTRIBUTE LDAP_GROUP_FILTER_GROUP_MEMBER_FORMAT LDAP_GROUP_FILTER_GROUP_NAME LDAP_UNIQUE_IDENTIFIER_FIELD LDAP_UTF8_NAMES_SLUGIFY LDAP_USERNAME_FIELD LDAP_FULLNAME_FIELD LDAP_MERGE_EXISTING_USERS LDAP_SYNC_USER_DATA LDAP_SYNC_USER_DATA_FIELDMAP LDAP_SYNC_GROUP_ROLES LDAP_DEFAULT_DOMAIN LDAP_EMAIL_MATCH_ENABLE LDAP_EMAIL_MATCH_REQUIRE LDAP_EMAIL_MATCH_VERIFIED LDAP_EMAIL_FIELD LDAP_SYNC_ADMIN_STATUS LDAP_SYNC_ADMIN_GROUPS HEADER_LOGIN_ID HEADER_LOGIN_FIRSTNAME HEADER_LOGIN_LASTNAME HEADER_LOGIN_EMAIL LOGOUT_WITH_TIMER LOGOUT_IN LOGOUT_ON_HOURS LOGOUT_ON_MINUTES DEFAULT_AUTHENTICATION_METHOD"
# default values
DESCRIPTION_DEBUG="Debug OIDC OAuth2 etc. Example: sudo snap set wekan debug='true'"
@@ -250,6 +250,10 @@ DESCRIPTION_LDAP_REJECT_UNAUTHORIZED="Reject Unauthorized Certificate"
DEFAULT_LDAP_REJECT_UNAUTHORIZED="false"
KEY_LDAP_REJECT_UNAUTHORIZED="ldap-reject-unauthorized"
DESCRIPTION_LDAP_USER_AUTHENTICATION="Option to login to the LDAP server with the user's own username and password, instead of an administrator key. Default: false (use administrator key)."
DEFAULT_LDAP_USER_AUTHENTICATION="false"
KEY_LDAP_USER_AUTHENTICATION="ldap-user-authentication"
DESCRIPTION_LDAP_USER_SEARCH_FILTER="Optional extra LDAP filters. Don't forget the outmost enclosing parentheses if needed"
DEFAULT_LDAP_USER_SEARCH_FILTER=""
KEY_LDAP_USER_SEARCH_FILTER="ldap-user-search-filter"
+3
View File
@@ -234,6 +234,9 @@ echo -e "Ldap Reject Unauthorized."
echo -e "Reject Unauthorized Certificate:"
echo -e "\t$ snap set $SNAP_NAME ldap-reject-unauthorized='true'"
echo -e "\n"
echo -e "Option to login to the LDAP server with the user's own username and password, instead of an administrator key. Default: false (use administrator key)."
echo -e "\t$ snap set $SNAP_NAME ldap-user-authentication='true'"
echo -e "\n"
echo -e "Ldap User Search Filter."
echo -e "Optional extra LDAP filters. Don't forget the outmost enclosing parentheses if needed:"
echo -e "\t$ snap set $SNAP_NAME ldap-user-search-filter=''"
+3
View File
@@ -173,6 +173,9 @@ REM # LDAP_REJECT_UNAUTHORIZED : Reject Unauthorized Certificate
REM # example : LDAP_REJECT_UNAUTHORIZED=true
REM SET LDAP_REJECT_UNAUTHORIZED=false
REM # Option to login to the LDAP server with the user's own username and password, instead of an administrator key. Default: false (use administrator key).
REM SET LDAP_USER_AUTHENTICATION=true
REM # LDAP_USER_SEARCH_FILTER : Optional extra LDAP filters. Don't forget the outmost enclosing parentheses if needed
REM # example : LDAP_USER_SEARCH_FILTER=
REM SET LDAP_USER_SEARCH_FILTER=
+2
View File
@@ -210,6 +210,8 @@ function wekan_repo_check(){
# LDAP_REJECT_UNAUTHORIZED : Reject Unauthorized Certificate
# example : export LDAP_REJECT_UNAUTHORIZED=true
#export LDAP_REJECT_UNAUTHORIZED=false
# Option to login to the LDAP server with the user's own username and password, instead of an administrator key. Default: false (use administrator key).
#export LDAP_USER_AUTHENTICATION=true
# LDAP_USER_SEARCH_FILTER : Optional extra LDAP filters. Don't forget the outmost enclosing parentheses if needed
# example : export LDAP_USER_SEARCH_FILTER=
#export LDAP_USER_SEARCH_FILTER=