Compare commits

...
68 Commits
Author SHA1 Message Date
Lauri Ojansivu c62396e389 v4.92 2021-02-03 02:32:00 +02:00
Lauri Ojansivu d52e85f298 Updated ChangeLog. 2021-02-03 02:27:18 +02:00
Lauri Ojansivu 05ebae7329 Updated dependencies.
Thanks to developers of dependencies !
2021-02-03 02:25:37 +02:00
Lauri Ojansivu b697bb656e Updated ChangeLog. 2021-02-03 01:50:52 +02:00
Lauri Ojansivu 4d7de2adce Merge pull request #3523 from mfilser/notifications_overlap_avatar_mobile_view
Notifications avatar overlaped at mobile view
2021-02-03 01:49:32 +02:00
Lauri Ojansivu 8a9528e787 Updated README 2021-02-03 01:45:52 +02:00
Martin Filser 6c6cba51fa Notification trash link was not visible if actifity text is too long 2021-02-03 00:20:56 +01:00
Martin Filser 28e23f9d87 Notification, each notification has now more space at top 2021-02-02 23:07:28 +01:00
Martin Filser e31192e97e Notification, split line was missing at mobile view 2021-02-02 23:02:45 +01:00
Martin Filser 26b7137b5c Notification, Avatar overlaped at mobile view 2021-02-02 23:02:33 +01:00
Lauri Ojansivu 912200a2ec Updated ChangeLog.
Related https://github.com/wekan/wekan/discussions/3496
2021-02-02 21:12:56 +02:00
Lauri Ojansivu c42d0d7423 Merge branch 'bronger-sorted-archives' 2021-02-02 21:09:41 +02:00
Lauri Ojansivu 3da66a0fe3 Sorted archives Part 2.
Thanks to xet7 !
2021-02-02 21:08:34 +02:00
Lauri Ojansivu 41e1f8fbc3 Merge branch 'sorted-archives' of https://github.com/bronger/wekan into bronger-sorted-archives 2021-02-02 20:56:09 +02:00
Lauri Ojansivu 130ac3c917 Updated ChangeLog. 2021-02-02 20:55:25 +02:00
Lauri Ojansivu 3774060d32 Createtoken API: Added better description and deleted extra file.
Thanks to magicbelette and xet7 !

Fixes #2887
2021-02-02 20:51:41 +02:00
Lauri Ojansivu d8c8856548 Merge pull request #3520 from messagerie-melanie2/master
Add createtoken API
2021-02-02 20:48:00 +02:00
Lauri Ojansivu efec00a550 Updated ChangeLog. 2021-02-02 20:30:22 +02:00
Lauri Ojansivu 3d3cf1d551 Merge pull request #3521 from mfilser/master
Cards, CustomFields sorted alphabetically, fixes #3517
2021-02-02 20:28:35 +02:00
Lauri Ojansivu c52d17b6fb Updated translations. 2021-02-02 18:47:08 +02:00
Martin Filser c0b9ef5990 Cards, CustomFields sorted alphabetically #3517
- last fix didn't work and disabled alphabetic sorting
- also works with linked cards
2021-02-02 17:45:43 +01:00
Lauri Ojansivu e303159b98 Updated ChangeLog. 2021-02-02 18:40:12 +02:00
Lauri Ojansivu f274b3c26b Try fix removed nonexistent document error.
Thanks to xet7 !

Related #3203,
related #3252,
related #2230
related #1629
2021-02-02 18:36:21 +02:00
Lauri Ojansivu 81fdc9a865 Updated ChangeLog. 2021-02-02 18:33:23 +02:00
Lauri Ojansivu f40c9804f8 Disable some console.log code, that is only needed while developing.
Thanks to xet7 !
2021-02-02 18:31:13 +02:00
Lauri Ojansivu 4d13d51038 Updated ChangeLog. 2021-02-02 18:14:18 +02:00
magicbelette 5c4421dc38 Delete test file 2021-02-02 17:12:57 +01:00
Lauri Ojansivu 76ef6a81ab Merge pull request #3519 from jrsupplee/issue-2074
Hopeful fix for i18n not working in `onRendered()`
2021-02-02 18:07:25 +02:00
magicbelette a7b43d5b57 Add createtoken API 2021-02-02 17:06:06 +01:00
John R. Supplee e4f50d4713 Hopeful fix for i18n not working in onRendered()
* Remove the i18n initialization code from an `autorun()` block
* Add some console statements to help with debugging production.
* Add functions to `Boards` for label colors and color mapping
2021-02-02 17:56:18 +02:00
Lauri Ojansivu 1e71237627 Merge pull request #3516 from mfilser/notifications_overlap_avatar
Avatar overlaped notifications
2021-02-02 16:50:24 +02:00
Torsten Bronger 678c8f6bf6 Printed archivedAt under every item in the archive. 2021-02-02 14:52:14 +01:00
Torsten Bronger 786c27bbec Added sorting by archivedAt in the archive.
I use modifiedAt as a fall back for legacy cards which don't have archivedAt
set yet.
2021-02-02 14:52:12 +01:00
Torsten Bronger 710643d8cb Added field archivedAt to cards, lists, swimlanes, and boards. 2021-02-02 14:52:08 +01:00
Martin Filser e595aba189 Minicard, assignee and red line now aligned again 2021-02-02 09:24:26 +01:00
Martin Filser ea67e94c47 Notification, fixed avatar icon (was an ellipse) 2021-02-02 08:45:37 +01:00
Martin Filser b2c2067f7d Avatar overlaped notifications #3515 2021-02-01 18:26:18 +01:00
Lauri Ojansivu 4fc2d7b935 Updated translations. 2021-01-31 01:26:51 +02:00
Lauri Ojansivu b1b9dd208b Updated ChangeLog. 2021-01-30 20:54:54 +02:00
Lauri Ojansivu ee2f7c077f Added badge for CII Best Practices.
Thanks to CII and xet7 !
2021-01-30 20:51:36 +02:00
Lauri Ojansivu a385d6f4fd Added PGP public key for sending security vulnerability reports. 2021-01-30 20:15:52 +02:00
Lauri Ojansivu 7031b7a3c7 Updated security report email address. 2021-01-30 20:07:03 +02:00
Lauri Ojansivu 0f0a5fba1f Merge branch 'master' of github.com:wekan/wekan 2021-01-30 18:23:00 +02:00
Lauri Ojansivu 1d7af3f011 Updated translations. 2021-01-30 18:22:40 +02:00
Lauri Ojansivu 6fd85f97b3 Updated ChangeLog. 2021-01-30 18:18:54 +02:00
Lauri Ojansivu a6d17f3813 Merge pull request #3509 from jrsupplee/fix-2
Don't reload page when returning default sort
2021-01-30 18:17:39 +02:00
Lauri Ojansivu 4e830ea416 Updated ChangeLog. 2021-01-30 18:15:48 +02:00
Lauri Ojansivu fc5c936272 Merge pull request #3510 from jrsupplee/import-user-mapping
Import user mapping
2021-01-30 18:04:30 +02:00
John R. Supplee b2af684c4d JSON import: add note about unmapped members 2021-01-30 11:44:53 +02:00
John R. Supplee 0446999c63 Add new importUsernames field for import user mapping 2021-01-30 02:35:29 +02:00
John R. Supplee 6920c39752 Don't reload page when returning default sort 2021-01-29 21:09:28 +02:00
Lauri Ojansivu 62ba8ed8d8 v4.91 2021-01-29 15:16:35 +02:00
Lauri Ojansivu 6eeef96886 Updated ChangeLog. 2021-01-29 15:11:02 +02:00
Lauri Ojansivu 4acf852650 Fixed typos in docker-compose.yml.
Thanks to farfoodyou and xet7 !

Fixes #3506
2021-01-29 15:09:11 +02:00
Lauri Ojansivu 9b3f1562a5 Updated translations. 2021-01-29 14:59:37 +02:00
Lauri Ojansivu 49774e46a3 Updated ChangeLog. 2021-01-29 14:57:02 +02:00
Lauri Ojansivu ae2447393d Merge pull request #3505 from jrsupplee/new-search
Use `new RegExp(...)` to define a regex
2021-01-29 13:55:01 +02:00
John R. Supplee 3435192640 only use new RegExp(...) to define regex (not slashes) 2021-01-29 13:15:53 +02:00
John R. Supplee 6ba4da9711 Remove added backticks from regex 2021-01-28 23:42:47 +02:00
Lauri Ojansivu 010a1d07d9 v4.90 2021-01-28 19:24:10 +02:00
Lauri Ojansivu 94d09b0014 Updated translations. 2021-01-28 19:16:53 +02:00
Lauri Ojansivu d6ff442622 Updated ChangeLog. 2021-01-28 19:11:01 +02:00
Lauri Ojansivu f7cc1abc8e Merge pull request #3500 from jrsupplee/patch-5
Fix some bugs when importing Wekan JSON
2021-01-28 19:08:34 +02:00
Lauri Ojansivu bf7b1789ec Added missing backtick quotes.
Thanks to xet7 !
2021-01-28 19:01:30 +02:00
Lauri Ojansivu cf9b482546 Merge pull request #3499 from jrsupplee/patch-6
Create unique board names when importing
2021-01-28 18:58:41 +02:00
John R. Supplee ad6da9bf37 Create unique board names when importing 2021-01-28 18:21:56 +02:00
John R. Supplee d647884b91 Make sure user data is retrieved before proceeding with import 2021-01-28 18:18:31 +02:00
John R. Supplee 0adde3e06d Fix Wekan JSON import bug
If not all users are mapped the import crashes.
2021-01-28 00:44:48 +02:00
101 changed files with 60338 additions and 56443 deletions

No files matched your search

+75
View File
@@ -1,3 +1,78 @@
# v4.92 2021-02-03 Wekan release
This release adds the following improvements:
- [Import user mapping improvements](https://github.com/wekan/wekan/pull/3510).
Thanks to jrsupplee.
- Added Createtoken API.
[Part 1](https://github.com/wekan/wekan/pull/3520),
[Part 2](https://github.com/wekan/wekan/commit/3774060d32abcfee17dc1c31958d4673794d8619).
Thanks to magicbelette and xet7.
- Sorted archives.
[Part 1](https://github.com/wekan/wekan/pull/3518),
[Part 2](https://github.com/wekan/wekan/commit/3da66a0fe30c2b54b63e5d098232b375d899925e).
Thanks to bronger, jrsupplee and xet7.
and adds the following updates:
- [Updated dependencies](https://github.com/wekan/wekan/commit/05ebae7329ba0dd3fe9b04cd63b1f983830cdeee).
Thanks to developers of dependencies.
and fixes the following bugs:
- [Don't reload page when returning default sort](https://github.com/wekan/wekan/pull/3509).
Thanks to jrsupplee.
- [Avatar overlaped notifications](https://github.com/wekan/wekan/pull/3516).
Thanks to mfilser.
- [Hopeful fix for i18n not working in `onRendered()`](https://github.com/wekan/wekan/pull/3519).
Thanks to jrsupplee.
- [Disable some console.log code, that is only needed while developing](https://github.com/wekan/wekan/commit/f40c9804f848fdb91229c5718ad97495337109ba).
Thanks to xet7.
- [Try fix removed nonexistent document error](https://github.com/wekan/wekan/commit/f274b3c26be60813829dcf2b0e68a8dd876ff614).
Thanks to Brulf, TheMasterFX and xet7.
- [Fixed Cards and CustomFields sorted alphabetically](https://github.com/wekan/wekan/pull/3521).
Thanks to mfilser.
- [Notifications avatar overlaped at mobile view](https://github.com/wekan/wekan/pull/3523).
Thanks to mfilser.
and improves some security related info:
- [Added badge for CII Best Practices](https://github.com/wekan/wekan/commit/ee2f7c077fe56d6fedb8b75ae3cba6bab56f9363).
Thanks to CII and xet7.
- [Added PGP public key for sending security vulnerability reports](https://github.com/wekan/wekan/commit/a385d6f4fd76e2bb0f374963848513b9373d6b5a).
Thanks to xet7.
- [Updated security report email address](https://github.com/wekan/wekan/commit/7031b7a3c77acc0ddeabe436572dd4057001e9f5).
Thanks to xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v4.91 2021-01-29 Wekan release
This release fixes the following bugs:
- [Use `new RegExp(...)` to define a regex](https://github.com/wekan/wekan/pull/3505).
Thanks to jrsupplee.
- [Fixed typos in docker-compose.yml](https://github.com/wekan/wekan/commit/4acf8526509ffe852e6e48e3503560448239d8cd).
Thanks to farfoodyou and xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v4.90 2021-01-28 Wekan release
This release adds the following new features:
- [Create unique board names when importing](https://github.com/wekan/wekan/pull/3499).
Thanks to jrsupplee.
and fixes the following bugs:
- [Added missing backtick quotes](https://github.com/wekan/wekan/commit/bf7b1789ec16e3c52397318c799ec5a0fc2de3a5).
Thanks to xet7.
- [Fix some bugs when importing Wekan JSON](https://github.com/wekan/wekan/pull/3500).
Thanks to jrsupplee.
Thanks to above GitHub users for their contributions and translators for their translations.
# v4.89 2021-01-28 Wekan release
This release fixes the following bugs:
+1
View File
@@ -12,6 +12,7 @@
[![Project Dependencies](https://david-dm.org/wekan/wekan.svg "Project Dependencies")](https://david-dm.org/wekan/wekan)
[![Code analysis at Open Hub](https://img.shields.io/badge/code%20analysis-at%20Open%20Hub-brightgreen.svg "Code analysis at Open Hub")](https://www.openhub.net/p/wekan)
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fwekan%2Fwekan.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fwekan%2Fwekan?ref=badge_shield)
[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/4619/badge)](https://bestpractices.coreinfrastructure.org/projects/4619)
## [Translate Wekan at Transifex](https://transifex.com/wekan/wekan)
+3 -3
View File
@@ -1,10 +1,10 @@
Security is very important to us. If you discover any issue regarding security, please disclose
the information responsibly by sending an email to security (at) wekan.team and not by
the information responsibly by sending an email to support (at) wekan.team using
[this PGP public key](support-at-wekan.team_pgp-publickey.asc) and not by
creating a GitHub issue. We will respond swiftly to fix verifiable security issues.
We thank you with a place at our hall of fame page, that is
at https://wekan.github.io/hall-of-fame . Others have just posted public GitHub issue,
so they are not at that hall-of-fame page.
at https://wekan.github.io/hall-of-fame
## How should reports be formatted?
+1 -1
View File
@@ -1,5 +1,5 @@
appId: wekan-public/apps/77b94f60-dec9-0136-304e-16ff53095928
appVersion: "v4.89.0"
appVersion: "v4.92.0"
files:
userUploads:
- README.md
+1 -1
View File
@@ -11,7 +11,7 @@ BlazeComponent.extendComponent({
return Boards.find(
{ archived: true },
{
sort: { sort: 1 /* boards default sorting */ },
sort: { archivedAt: -1, modifiedAt: -1 },
},
);
},
+1 -1
View File
@@ -129,7 +129,7 @@ BlazeComponent.extendComponent({
{
sort: Boards.find({ archived: false }).count(),
type: 'board',
title: Boards.findOne(this.currentData()._id).copyTitle(),
title: Boards.findOne(this.currentData()._id).title,
},
(err, res) => {
if (err) {
+1
View File
@@ -176,6 +176,7 @@
border-radius: 50%
height: 28px
width: @height
margin: 0px 0px 4px 0px
.assignee
float: right
+32 -27
View File
@@ -13,38 +13,43 @@ template(name="import")
template(name="importTextarea")
form
p: label(for='import-textarea') {{_ instruction}} {{_ 'import-board-instruction-about-errors'}}
textarea.js-import-json(placeholder="{{_ importPlaceHolder}}" autofocus)
textarea.js-import-json(id='import-textarea' placeholder="{{_ importPlaceHolder}}" autofocus)
| {{jsonText}}
input.primary.wide(type="submit" value="{{_ 'import'}}")
template(name="importMapMembers")
h2 {{_ 'import-map-members'}}
.map-members
p {{_ 'import-members-map'}}
.mapping-list
each members
a.mapping-item.js-select-member(class="{{#if wekanId}}filled{{/if}}")
.profile-source
.full-name= fullName
.username
| ({{username}})
.wekan
if wekanId
+userAvatar(userId=wekanId)
else
a.member.add-member
i.fa.fa-plus
//-
Due to the way the flewbox layout is working, we need to set some
invisible items so that the last row items have a consistent width.
See http://jsfiddle.net/Ln4h3c4n/ for an minimal example of the issue.
.mapping-item.ghost-item
.mapping-item.ghost-item
.mapping-item.ghost-item
.mapping-item.ghost-item
.mapping-item.ghost-item
form
input.primary.wide(type="submit" value="{{_ 'done'}}")
if usersLoaded.get
.map-members
p {{_ 'import-members-map'}}
p.import-members-map-note
| {{_ 'import-members-map-note' }}
.mapping-list
each members
a.mapping-item.js-select-member(class="{{#if wekanId}}filled{{/if}}")
.profile-source
.full-name= fullName
.username
| ({{username}})
.wekan
if wekanId
+userAvatar(userId=wekanId)
else
a.member.add-member
i.fa.fa-plus
//-
Due to the way the flewbox layout is working, we need to set some
invisible items so that the last row items have a consistent width.
See http://jsfiddle.net/Ln4h3c4n/ for an minimal example of the issue.
.mapping-item.ghost-item
.mapping-item.ghost-item
.mapping-item.ghost-item
.mapping-item.ghost-item
.mapping-item.ghost-item
form
input.primary.wide(type="submit" value="{{_ 'done'}}")
else
+spinner
template(name="importMapMembersAddPopup")
.select-member
+33 -5
View File
@@ -150,14 +150,42 @@ BlazeComponent.extendComponent({
BlazeComponent.extendComponent({
onCreated() {
this.usersLoaded = new ReactiveVar(false);
this.autorun(() => {
this.parentComponent()
.membersToMap.get()
.forEach(({ wekanId }) => {
if (wekanId) {
this.subscribe('user-miniprofile', wekanId);
const handle = this.subscribe(
'user-miniprofile',
this.members().map(member => {
return member.username;
}),
);
Tracker.nonreactive(() => {
Tracker.autorun(() => {
if (
handle.ready() &&
!this.usersLoaded.get() &&
this.members().length
) {
this._refreshMembers(
this.members().map(member => {
if (!member.wekanId) {
let user = Users.findOne({ username: member.username });
if (!user) {
user = Users.findOne({ importUsernames: member.username });
}
if (user) {
// eslint-disable-next-line no-console
// console.log('found username:', user.username);
member.wekanId = user._id;
}
}
return member;
}),
);
}
this.usersLoaded.set(handle.ready());
});
});
});
},
+4
View File
@@ -47,3 +47,7 @@
a.show-mapping
text-decoration underline
.import-members-map-note
font-size: 90%
font-weight: bold
+1 -1
View File
@@ -60,7 +60,7 @@ BlazeComponent.extendComponent({
dueCardsView() {
// eslint-disable-next-line no-console
console.log('sort:', Utils.dueCardsView());
//console.log('sort:', Utils.dueCardsView());
return Utils.dueCardsView();
},
+22 -14
View File
@@ -78,12 +78,10 @@ BlazeComponent.extendComponent({
onRendered() {
Meteor.subscribe('setting');
this.colorMap = {};
for (const color of Boards.simpleSchema()._schema['labels.$.color']
.allowedValues) {
this.colorMap[TAPi18n.__(`color-${color}`)] = color;
}
// // eslint-disable-next-line no-console
// eslint-disable-next-line no-console
//console.log('lang:', TAPi18n.getLanguage());
this.colorMap = Boards.colorMap();
// eslint-disable-next-line no-console
// console.log('colorMap:', this.colorMap);
if (Session.get('globalQuery')) {
@@ -116,7 +114,7 @@ BlazeComponent.extendComponent({
if (this.queryParams) {
const sessionData = this.getSessionData();
// eslint-disable-next-line no-console
console.log('selector:', sessionData.getSelector());
// console.log('selector:', sessionData.getSelector());
// console.log('session data:', sessionData);
const cards = Cards.find({ _id: { $in: sessionData.cards } });
this.queryErrors = sessionData.errors;
@@ -178,7 +176,7 @@ BlazeComponent.extendComponent({
searchAllBoards(query) {
query = query.trim();
// eslint-disable-next-line no-console
console.log('query:', query);
//console.log('query:', query);
this.query.set(query);
@@ -190,10 +188,19 @@ BlazeComponent.extendComponent({
this.searching.set(true);
const reOperator1 = `/^((?<operator>[\p{Letter}\p{Mark}]+):|(?<abbrev>[#@]))(?<value>[\p{Letter}\p{Mark}]+)(\s+|$)/iu`;
const reOperator2 = `/^((?<operator>[\p{Letter}\p{Mark}]+):|(?<abbrev>[#@]))(?<quote>["']*)(?<value>.*?)\k<quote>(\s+|$)/iu`;
const reText = `/^(?<text>\S+)(\s+|$)/u`;
const reQuotedText = `/^(?<quote>["'])(?<text>[\w\p{L}]+)\k<quote>(\s+|$)/u`;
const reOperator1 = new RegExp(
'^((?<operator>[\\p{Letter}\\p{Mark}]+):|(?<abbrev>[#@]))(?<value>[\\p{Letter}\\p{Mark}]+)(\\s+|$)',
'iu',
);
const reOperator2 = new RegExp(
'^((?<operator>[\\p{Letter}\\p{Mark}]+):|(?<abbrev>[#@]))(?<quote>["\']*)(?<value>.*?)\\k<quote>(\\s+|$)',
'iu',
);
const reText = new RegExp('^(?<text>\\S+)(\\s+|$)', 'u');
const reQuotedText = new RegExp(
'^(?<quote>["\'])(?<text>.*?)\\k<quote>(\\s+|$)',
'u',
);
const operators = {
'operator-board': 'boards',
@@ -287,13 +294,14 @@ BlazeComponent.extendComponent({
if (m.groups.operator) {
op = m.groups.operator.toLowerCase();
} else {
op = m.groups.abbrev;
op = m.groups.abbrev.toLowerCase();
}
if (operatorMap.hasOwnProperty(op)) {
let value = m.groups.value;
if (operatorMap[op] === 'labels') {
if (value in this.colorMap) {
value = this.colorMap[value];
// console.log('found color:', value);
}
} else if (
['dueAt', 'createdAt', 'modifiedAt'].includes(operatorMap[op])
@@ -379,7 +387,7 @@ BlazeComponent.extendComponent({
params.text = text;
// eslint-disable-next-line no-console
// console.log('params:', params);
console.log('params:', params);
this.queryParams = params;
@@ -5,7 +5,7 @@
.notification
display: flex
float: none
padding: 12px 8px 8px
padding: 15px 8px 8px
color: black
border-bottom: 1px solid #dbdbdb
@@ -14,6 +14,7 @@
.read-status
width: 30px
padding: 0px 10px 0px 0px
input
width: 24px
@@ -28,13 +29,19 @@
color: #bbb
.details
width: calc(100% - 30px)
.activity
display: flex
a.member
margin: 0px 0px 0px 0px
padding: 0px
svg
padding: 3px
.activity-desc
width: 100%;
margin: 0px 0px 0px 5px
.activity-comment
display: block
@@ -55,3 +62,14 @@
.remove
a:hover
color #eb4646 !important
@media screen and (max-width: 800px)
#notifications-drawer
.notification
height: auto
.details
.activity
a.member
height: 36px
width: 36px
@@ -2,7 +2,7 @@ belize = #2980b9
section#notifications-drawer
position: fixed
top: 28px
top: 48px
right: 0
width: 400px
background-color: #fafafa
@@ -17,7 +17,7 @@ section#notifications-drawer
.header
position: fixed
top 28px
top 48px
right 0
width calc(400px - 32px)
padding: 8px 16px
@@ -63,7 +63,7 @@ section#notifications-drawer
ul.notifications
display: block
padding: 0px 16px
padding: 0px 16px 0px 16px
margin: 0
height: calc(100vh - 102px)
height: calc(100vh - 122px)
overflow-y: scroll
@@ -110,6 +110,7 @@ template(name="peopleGeneral")
th {{_ 'createdAt'}}
th {{_ 'active'}}
th {{_ 'authentication-method'}}
th {{_ 'import-usernames'}}
th
+newUserRow
each user in peopleList
@@ -257,6 +258,10 @@ template(name="peopleRow")
td <s>{{_ userData.authenticationMethod }}</s>
else
td {{_ userData.authenticationMethod }}
if userData.loginDisabled
td <s>{{ userData.importUsernamesString }}</s>
else
td {{ userData.importUsernamesString }}
td
a.edit-user
i.fa.fa-edit
@@ -346,6 +351,9 @@ template(name="editUserPopup")
input.js-profile-email(type="email" value="{{user.emails.[0].address}}" readonly)
else
input.js-profile-email(type="email" value="{{user.emails.[0].address}}" required)
label
| {{_ 'import-usernames'}}
input.js-import-usernames(type="text" value=user.importUsernames)
label
| {{_ 'verified'}}
select.select-verified.js-profile-email-verified
@@ -444,6 +452,9 @@ template(name="newUserPopup")
// input.js-profile-email(type="email" value="{{user.emails.[0].address}}" readonly)
//else
input.js-profile-email(type="email" value="" required)
label
| {{_ 'import-usernames'}}
input.js-import-usernames(type="text" value="")
label
| {{_ 'admin'}}
select.select-role.js-profile-isadmin
+9 -1
View File
@@ -143,7 +143,7 @@ BlazeComponent.extendComponent({
const orgs = Org.find(this.findOrgsOptions.get(), {
fields: { _id: true },
});
this.numberOrgs.set(org.count(false));
this.numberOrgs.set(orgs.count(false));
return orgs;
},
teamList() {
@@ -421,6 +421,9 @@ Template.editUserPopup.events({
const authentication = templateInstance
.find('.js-authenticationMethod')
.value.trim();
const importUsernames = templateInstance
.find('.js-import-usernames')
.value.trim();
const isChangePassword = password.length > 0;
const isChangeUserName = username !== user.username;
@@ -441,6 +444,7 @@ Template.editUserPopup.events({
isAdmin: isAdmin === 'true',
loginDisabled: isActive === 'true',
authenticationMethod: authentication,
importUsernames: Users.parseImportUsernames(importUsernames),
},
});
@@ -563,6 +567,9 @@ Template.newUserPopup.events({
const isAdmin = templateInstance.find('.js-profile-isadmin').value.trim();
const isActive = templateInstance.find('.js-profile-isactive').value.trim();
const email = templateInstance.find('.js-profile-email').value.trim();
const importUsernames = templateInstance
.find('.js-import-usernames')
.value.trim();
Meteor.call(
'setCreateUser',
@@ -572,6 +579,7 @@ Template.newUserPopup.events({
isAdmin,
isActive,
email.toLowerCase(),
importUsernames,
function(error) {
const usernameMessageElement = templateInstance.$('.username-taken');
const emailMessageElement = templateInstance.$('.email-taken');
@@ -14,6 +14,11 @@ template(name="archivesSidebar")
if currentUser.isBoardMember
unless isWorker
p.quiet
if this.archivedAt
| {{_ 'archived-at' }}
|
| {{ moment this.archivedAt 'LLL' }}
br
a.js-restore-card {{_ 'restore'}}
if currentUser.isBoardAdmin
| -
@@ -37,6 +42,11 @@ template(name="archivesSidebar")
if currentUser.isBoardMember
unless isWorker
p.quiet
if this.archivedAt
| {{_ 'archived-at' }}
|
| {{ moment this.archivedAt 'LLL' }}
br
a.js-restore-list {{_ 'restore'}}
if currentUser.isBoardAdmin
| -
@@ -58,6 +68,11 @@ template(name="archivesSidebar")
if currentUser.isBoardMember
unless isWorker
p.quiet
if this.archivedAt
| {{_ 'archived-at' }}
|
| {{ moment this.archivedAt 'LLL' }}
br
a.js-restore-swimlane {{_ 'restore'}}
if currentUser.isBoardAdmin
| -
@@ -34,6 +34,8 @@ BlazeComponent.extendComponent({
return Cards.find({
archived: true,
boardId: Session.get('currentBoard'),
}, {
sort: { archivedAt: -1, modifiedAt: -1 },
});
},
@@ -41,6 +43,8 @@ BlazeComponent.extendComponent({
return Lists.find({
archived: true,
boardId: Session.get('currentBoard'),
}, {
sort: { archivedAt: -1, modifiedAt: -1 },
});
},
@@ -48,6 +52,8 @@ BlazeComponent.extendComponent({
return Swimlanes.find({
archived: true,
boardId: Session.get('currentBoard'),
}, {
sort: { archivedAt: -1, modifiedAt: -1 },
});
},
+17 -17
View File
@@ -4,24 +4,24 @@
Meteor.startup(() => {
TAPi18n.conf.i18n_files_route = Meteor._relativeToSiteRootUrl('/tap-i18n');
Tracker.autorun(() => {
const currentUser = Meteor.user();
let language;
if (currentUser) {
language = currentUser.profile && currentUser.profile.language;
}
const currentUser = Meteor.user();
let language;
if (currentUser) {
language = currentUser.profile && currentUser.profile.language;
}
if (!language) {
if (navigator.languages) {
language = navigator.languages[0];
} else {
language = navigator.language || navigator.userLanguage;
}
if (!language) {
if (navigator.languages) {
language = navigator.languages[0];
} else {
language = navigator.language || navigator.userLanguage;
}
}
if (language) {
TAPi18n.setLanguage(language);
T9n.setLanguage(language);
}
});
if (language) {
TAPi18n.setLanguage(language);
// eslint-disable-next-line no-console
// console.log('language set!');
T9n.setLanguage(language);
}
});
-4
View File
@@ -48,8 +48,6 @@ Utils = {
let sort = window.localStorage.getItem('myCardsSort');
if (!sort || !['board', 'dueAt'].includes(sort)) {
window.localStorage.setItem('myCardsSort', 'board');
location.reload();
sort = 'board';
}
@@ -81,8 +79,6 @@ Utils = {
let view = window.localStorage.getItem('dueCardsView');
if (!view || !['me', 'all'].includes(view)) {
window.localStorage.setItem('dueCardsView', 'me');
location.reload();
view = 'me';
}
+5 -5
View File
@@ -95,9 +95,9 @@ services:
# 2020-12-03:
# - Mongo image copied from Docker Hub mongo:4.4.2-bionic to Quay
# to avoid Docker Hub rate limits.
# Quay image
# Quay image does work:
# image: quay.io/wekan/mongo:4.4.2-bionic
# Docker Hub MongoDB image works:
# Docker Hub MongoDB image does work:
image: mongo:4.4
#-------------------------------------------------------------------------------------
container_name: wekan-db
@@ -117,12 +117,12 @@ services:
wekan:
#-------------------------------------------------------------------------------------
# ==== MONGODB AND METEOR VERSION ====
# a) Quay automatic builds do not currently work, https://quay.io/wekan/wekan
# a) Quay automatic builds do work work, https://quay.io/wekan/wekan
# image: quay.io/wekan/wekan
# b) Using specific version tag:
# image: quay.io/wekan/wekan:v4.52
c) Docker Hub builds do work https://hub.docker.com/r/wekanteam/wekan
# image: wekanteam/wekan
# c) Docker Hub builds do work https://hub.docker.com/r/wekanteam/wekan
image: wekanteam/wekan
#-------------------------------------------------------------------------------------
container_name: wekan-app
restart: always
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+4 -1
View File
@@ -384,6 +384,7 @@
"import-csv-placeholder": "Paste your valid CSV/TSV 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-members-map-note": "Note: Unmapped members will be assigned to the current user.",
"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",
@@ -530,6 +531,7 @@
"custom-login-logo-link-url": "Custom Login Logo Link URL",
"text-below-custom-login-logo": "Text below Custom Login Logo",
"username": "Username",
"import-usernames": "Import Usernames",
"view-it": "View it",
"warn-list-archived": "warning: this card is in an list at Archive",
"watch": "Watch",
@@ -949,5 +951,6 @@
"excel-font": "Arial",
"number": "Number",
"label-colors": "Label Colors",
"label-names": "Label Names"
"label-names": "Label Names",
"archived-at": "archived at"
}
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+953 -951
View File
File diff suppressed because it is too large. Load diff
+43 -15
View File
@@ -43,6 +43,13 @@ Boards.attachSchema(
}
},
},
archivedAt: {
/**
* Latest archiving time of the board
*/
type: Date,
optional: true,
},
createdAt: {
/**
* Creation time of the board
@@ -510,6 +517,7 @@ Boards.helpers({
const oldId = this._id;
delete this._id;
delete this.slug;
this.title = this.copyTitle();
const _id = Boards.insert(this);
// Copy all swimlanes in board
@@ -569,20 +577,7 @@ Boards.helpers({
* @returns {string|null}
*/
copyTitle() {
const m = this.title.match(/^(?<title>.*?)\s*(\[(?<num>\d+)]\s*$|\s*$)/);
const title = escapeForRegex(m.groups.title);
let num = 0;
Boards.find({ title: new RegExp(`^${title}\\s*\\[\\d+]\\s*$`) }).forEach(
board => {
const m = board.title.match(/^(?<title>.*?)\s*\[(?<num>\d+)]\s*$/);
if (m) {
const n = parseInt(m.groups.num, 10);
num = num < n ? n : num;
}
},
);
return `${title} [${num + 1}]`;
return Boards.uniqueTitle(this.title);
},
/**
@@ -1054,7 +1049,7 @@ Boards.helpers({
Boards.mutations({
archive() {
return { $set: { archived: true } };
return { $set: { archived: true, archivedAt: new Date() } };
},
restore() {
@@ -1274,6 +1269,27 @@ function boardRemover(userId, doc) {
);
}
Boards.uniqueTitle = title => {
const m = title.match(
new RegExp('^(?<title>.*?)\\s*(\\[(?<num>\\d+)]\\s*$|\\s*$)'),
);
const base = escapeForRegex(m.groups.title);
let num = 0;
Boards.find({ title: new RegExp(`^${base}\\s*\\[\\d+]\\s*$`) }).forEach(
board => {
const m = board.title.match(
new RegExp('^(?<title>.*?)\\s*\\[(?<num>\\d+)]\\s*$'),
);
if (m) {
const n = parseInt(m.groups.num, 10);
num = num < n ? n : num;
}
},
);
return `${base} [${num + 1}]`;
};
Boards.userSearch = (
userId,
selector = {},
@@ -1309,6 +1325,18 @@ Boards.userBoardIds = (userId, archived = false, selector = {}) => {
});
};
Boards.colorMap = () => {
const colors = {};
for (const color of Boards.labelColors()) {
colors[TAPi18n.__(`color-${color}`)] = color;
}
return colors;
};
Boards.labelColors = () => {
return _.clone(Boards.simpleSchema()._schema['labels.$.color'].allowedValues);
};
if (Meteor.isServer) {
Boards.allow({
insert: Meteor.userId,
-3
View File
@@ -168,9 +168,6 @@ if (Meteor.isServer) {
listId: card.listId,
swimlaneId: card.swimlaneId,
});
});
CardComments.after.remove((userId, doc) => {
const activity = Activities.findOne({ commentId: doc._id });
if (activity) {
Activities.remove(activity._id);
+14 -3
View File
@@ -26,6 +26,13 @@ Cards.attachSchema(
}
},
},
archivedAt: {
/**
* latest archiving date
*/
type: Date,
optional: true,
},
parentId: {
/**
* ID of the parent card
@@ -724,9 +731,12 @@ Cards.helpers({
definition,
};
});
if (ret.definition !== undefined) {
ret.sort((a, b) => a.definition.name.localeCompare(b.definition.name));
}
ret.sort(
(a, b) =>
a.definition.name !== undefined &&
b.definition.name !== undefined &&
a.definition.name.localeCompare(b.definition.name),
);
return ret;
},
@@ -1446,6 +1456,7 @@ Cards.mutations({
return {
$set: {
archived: true,
archivedAt: new Date(),
},
};
},
+4
View File
@@ -69,24 +69,28 @@ CustomFields.attachSchema(
* should we show on the cards this custom field
*/
type: Boolean,
defaultValue: false,
},
automaticallyOnCard: {
/**
* should the custom fields automatically be added on cards?
*/
type: Boolean,
defaultValue: false,
},
alwaysOnCard: {
/**
* should the custom field be automatically added to all cards?
*/
type: Boolean,
defaultValue: false,
},
showLabelOnMiniCard: {
/**
* should the label of the custom field be shown on minicards?
*/
type: Boolean,
defaultValue: false,
},
createdAt: {
type: Date,
+2 -2
View File
@@ -385,8 +385,8 @@ export class ExporterExcel {
}
//add data +8 hours
function addTZhours(jdate) {
let curdate = new Date(jdate);
let checkCorrectDate = moment(curdate);
const curdate = new Date(jdate);
const checkCorrectDate = moment(curdate);
if (checkCorrectDate.isValid()) {
return curdate;
} else {
+9 -1
View File
@@ -32,6 +32,13 @@ Lists.attachSchema(
}
},
},
archivedAt: {
/**
* latest archiving date
*/
type: Date,
optional: true,
},
boardId: {
/**
* the board associated to this list
@@ -292,7 +299,7 @@ Lists.mutations({
return card.archive();
});
}
return { $set: { archived: true } };
return { $set: { archived: true, archivedAt: new Date() } };
},
restore() {
@@ -384,6 +391,7 @@ if (Meteor.isServer) {
Meteor.startup(() => {
Lists._collection._ensureIndex({ modifiedAt: -1 });
Lists._collection._ensureIndex({ boardId: 1 });
Lists._collection._ensureIndex({ archivedAt: -1 });
});
Lists.after.insert((userId, doc) => {
+8 -1
View File
@@ -23,6 +23,13 @@ Swimlanes.attachSchema(
}
},
},
archivedAt: {
/**
* latest archiving date of the swimlane
*/
type: Date,
optional: true,
},
boardId: {
/**
* the ID of the board the swimlane is attached to
@@ -259,7 +266,7 @@ Swimlanes.mutations({
return list.archive();
});
}
return { $set: { archived: true } };
return { $set: { archived: true, archivedAt: new Date() } };
},
restore() {
+1 -1
View File
@@ -177,7 +177,7 @@ export class TrelloCreator {
permission: this.getPermission(trelloBoard.prefs.permissionLevel),
slug: getSlug(trelloBoard.name) || 'board',
stars: 0,
title: trelloBoard.name,
title: Boards.uniqueTitle(trelloBoard.name),
};
// now add other members
if (trelloBoard.memberships) {
+62 -3
View File
@@ -338,6 +338,13 @@ Users.attachSchema(
type: Number,
optional: true,
},
importUsernames: {
/**
* username for imported
*/
type: [String],
optional: true,
},
}),
);
@@ -433,7 +440,18 @@ if (Meteor.isClient) {
});
}
Users.parseImportUsernames = usernamesString => {
return usernamesString.trim().split(new RegExp('\\s*[,;]\\s*'));
};
Users.helpers({
importUsernamesString() {
if (this.importUsernames) {
return this.importUsernames.join(', ');
}
return '';
},
boards() {
return Boards.find(
{ 'members.userId': this._id },
@@ -779,7 +797,15 @@ Meteor.methods({
if (Meteor.isServer) {
Meteor.methods({
setCreateUser(fullname, username, password, isAdmin, isActive, email) {
setCreateUser(
fullname,
username,
password,
isAdmin,
isActive,
email,
importUsernames,
) {
if (Meteor.user() && Meteor.user().isAdmin) {
check(fullname, String);
check(username, String);
@@ -787,6 +813,7 @@ if (Meteor.isServer) {
check(isAdmin, String);
check(isActive, String);
check(email, String);
check(importUsernames, Array);
const nUsersWithUsername = Users.find({ username }).count();
const nUsersWithEmail = Users.find({ email }).count();
@@ -803,10 +830,10 @@ if (Meteor.isServer) {
email: email.toLowerCase(),
from: 'admin',
});
user = Users.findOne(username) || Users.findOne({ username });
const user = Users.findOne(username) || Users.findOne({ username });
if (user) {
Users.update(user._id, {
$set: { 'profile.fullname': fullname },
$set: { 'profile.fullname': fullname, importUsernames },
});
}
}
@@ -1733,6 +1760,38 @@ if (Meteor.isServer) {
});
}
});
/**
* @operation create_user_token
*
* @summary Create a user token
*
* @description Only the admin user (the first user) can call the REST API.
*
* @param {string} userId the ID of the user to create token for.
* @return_type {_id: string}
*/
JsonRoutes.add('POST', '/api/createtoken/:userId', function(req, res) {
try {
Authentication.checkUserId(req.userId);
const id = req.params.userId;
const token = Accounts._generateStampedLoginToken();
Accounts._insertLoginToken(id, token);
JsonRoutes.sendResult(res, {
code: 200,
data: {
_id: id,
authToken: token.token,
},
});
} catch (error) {
JsonRoutes.sendResult(res, {
code: 200,
data: error,
});
}
});
}
export default Users;
+3 -2
View File
@@ -253,13 +253,14 @@ export class WekanCreator {
permission: boardToImport.permission,
slug: getSlug(boardToImport.title) || 'board',
stars: 0,
title: boardToImport.title,
title: Boards.uniqueTitle(boardToImport.title),
};
// now add other members
if (boardToImport.members) {
boardToImport.members.forEach(wekanMember => {
// do we already have it in our list?
// is it defined and do we already have it in our list?
if (
wekanMember.wekanId &&
!boardToCreate.members.some(
member => member.wekanId === wekanMember.wekanId,
)
+7 -7
View File
@@ -1,6 +1,6 @@
{
"name": "wekan",
"version": "v4.89.0",
"version": "v4.92.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -819,9 +819,9 @@
"dev": true
},
"ajv": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-7.0.3.tgz",
"integrity": "sha512-R50QRlXSxqXcQP5SvKUrw8VZeypvo12i2IX0EeR5PiZ7bEKeHWgzgo264LDadUsCU42lTJVhFikTqJwNeH34gQ==",
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-7.0.4.tgz",
"integrity": "sha512-xzzzaqgEQfmuhbhAoqjJ8T/1okb6gAzXn/eQRNpAN1AEUoHJTNF9xCDRTtf/s3SKldtZfa+RJeTs+BQq+eZ/sw==",
"requires": {
"fast-deep-equal": "^3.1.1",
"json-schema-traverse": "^1.0.0",
@@ -4324,9 +4324,9 @@
"optional": true
},
"mongodb": {
"version": "3.6.3",
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.3.tgz",
"integrity": "sha512-rOZuR0QkodZiM+UbQE5kDsJykBqWi0CL4Ec2i1nrGrUI3KO11r6Fbxskqmq3JK2NH7aW4dcccBuUujAP0ERl5w==",
"version": "3.6.4",
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.4.tgz",
"integrity": "sha512-Y+Ki9iXE9jI+n9bVtbTOOdK0B95d6wVGSucwtBkvQ+HIvVdTCfpVRp01FDC24uhC/Q2WXQ8Lpq3/zwtB5Op9Qw==",
"requires": {
"bl": "^2.2.1",
"bson": "^1.1.4",
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "wekan",
"version": "v4.89.0",
"version": "v4.92.0",
"description": "Open-Source kanban",
"private": true,
"scripts": {
@@ -57,7 +57,7 @@
"@babel/core": "^7.12.10",
"@babel/runtime": "^7.12.5",
"@root/request": "^1.7.0",
"ajv": "^7.0.3",
"ajv": "^7.0.4",
"babel-runtime": "^6.26.0",
"bcrypt": "^5.0.0",
"bson": "^4.2.2",
@@ -72,7 +72,7 @@
"markdown-it": "^12.0.4",
"markdown-it-emoji": "^2.0.0",
"meteor-node-stubs": "^1.0.1",
"mongodb": "^3.6.3",
"mongodb": "^3.6.4",
"os": "^0.1.1",
"page": "^1.11.5",
"papaparse": "^5.3.0",
+2959 -186
View File
File diff suppressed because it is too large. Load diff
+683 -1
View File
@@ -1,7 +1,7 @@
swagger: '2.0'
info:
title: Wekan REST API
version: v4.89
version: v4.92
description: |
The REST API allows you to control and extend Wekan with ease.
@@ -134,6 +134,198 @@ paths:
description: |
Error in registration
/api/boards:
get:
operationId: get_public_boards
summary: Get all public boards
tags:
- Boards
produces:
- application/json
security:
- UserSecurity: []
responses:
'200':
description: |-
200 response
schema:
type: array
items:
type: object
properties:
_id:
type: string
title:
type: string
post:
operationId: new_board
summary: Create a board
description: |
This allows to create a board.
The color has to be chosen between `belize`, `nephritis`, `pomegranate`,
`pumpkin`, `wisteria`, `moderatepink`, `strongcyan`,
`limegreen`, `midnight`, `dark`, `relax`, `corteza`:
<img src="https://wekan.github.io/board-colors.png" width="40%" alt="Wekan logo" />
tags:
- Boards
consumes:
- multipart/form-data
- application/json
parameters:
- name: title
in: formData
description: |
the new title of the board
type: string
required: true
- name: owner
in: formData
description: |
"ABCDE12345" <= User ID in Wekan.
(Not username or email)
type: string
required: true
- name: isAdmin
in: formData
description: |
is the owner an admin of the board (default true)
type: boolean
required: false
- name: isActive
in: formData
description: |
is the board active (default true)
type: boolean
required: false
- name: isNoComments
in: formData
description: |
disable comments (default false)
type: boolean
required: false
- name: isCommentOnly
in: formData
description: |
only enable comments (default false)
type: boolean
required: false
- name: isWorker
in: formData
description: |
only move cards, assign himself to card and comment (default false)
type: boolean
required: false
- name: permission
in: formData
description: |
"private" board <== Set to "public" if you
want public Wekan board
type: string
required: false
- name: color
in: formData
description: |
the color of the board
type: string
required: false
produces:
- application/json
security:
- UserSecurity: []
responses:
'200':
description: |-
200 response
schema:
type: object
properties:
_id:
type: string
defaultSwimlaneId:
type: string
/api/boards/{board}:
get:
operationId: get_board
summary: Get the board with that particular ID
tags:
- Boards
parameters:
- name: board
in: path
description: |
the ID of the board to retrieve the data
type: string
required: true
produces:
- application/json
security:
- UserSecurity: []
responses:
'200':
description: |-
200 response
schema:
$ref: "#/definitions/Boards"
delete:
operationId: delete_board
summary: Delete a board
tags:
- Boards
parameters:
- name: board
in: path
description: |
the ID of the board
type: string
required: true
produces:
- application/json
security:
- UserSecurity: []
responses:
'200':
description: |-
200 response
/api/boards/{board}/attachments:
get:
operationId: get_board_attachments
summary: Get the list of attachments of a board
tags:
- Boards
parameters:
- name: board
in: path
description: |
the board ID
type: string
required: true
produces:
- application/json
security:
- UserSecurity: []
responses:
'200':
description: |-
200 response
schema:
type: array
items:
type: object
properties:
attachmentId:
type: string
attachmentName:
type: string
attachmentType:
type: string
cardId:
type: string
listId:
type: string
swimlaneId:
type: string
/api/boards/{board}/cards/{card}/checklists:
get:
operationId: get_all_checklists
@@ -1096,6 +1288,40 @@ paths:
200 response
schema:
$ref: "#/definitions/Integrations"
/api/boards/{board}/labels:
put:
operationId: add_board_label
summary: Add a label to a board
description: |
If the board doesn't have the name/color label, this function
adds the label to the board.
tags:
- Boards
consumes:
- multipart/form-data
- application/json
parameters:
- name: label
in: formData
description: the label value
type: string
required: true
- name: board
in: path
description: |
the board
type: string
required: true
produces:
- application/json
security:
- UserSecurity: []
responses:
'200':
description: |-
200 response
schema:
type: string
/api/boards/{board}/lists:
get:
operationId: get_all_lists
@@ -1577,6 +1803,61 @@ paths:
properties:
_id:
type: string
/api/boards/{board}/members/{member}:
post:
operationId: set_board_member_permission
summary: Change the permission of a member of a board
tags:
- Boards
- Users
consumes:
- multipart/form-data
- application/json
parameters:
- name: isAdmin
in: formData
description: |
admin capability
type: boolean
required: true
- name: isNoComments
in: formData
description: |
NoComments capability
type: boolean
required: true
- name: isCommentOnly
in: formData
description: |
CommentsOnly capability
type: boolean
required: true
- name: isWorker
in: formData
description: |
Worker capability
type: boolean
required: true
- name: board
in: path
description: |
the ID of the board that we are changing
type: string
required: true
- name: member
in: path
description: |
the ID of the user to change permissions
type: string
required: true
produces:
- application/json
security:
- UserSecurity: []
responses:
'200':
description: |-
200 response
/api/boards/{board}/members/{user}/add:
post:
operationId: add_board_member
@@ -1855,6 +2136,37 @@ paths:
type: string
listId:
type: string
/api/createtoken/{user}:
post:
operationId: create_user_token
summary: Create a user token
description: |
Only the admin user (the first user) can call the REST API.
tags:
- Users
consumes:
- multipart/form-data
- application/json
parameters:
- name: user
in: path
description: |
the ID of the user to create token for.
type: string
required: true
produces:
- application/json
security:
- UserSecurity: []
responses:
'200':
description: |-
200 response
schema:
type: object
properties:
_id:
type: string
/api/user:
get:
operationId: get_current_user
@@ -2033,7 +2345,354 @@ paths:
properties:
_id:
type: string
/api/users/{user}/boards:
get:
operationId: get_boards_from_user
summary: Get all boards attached to a user
tags:
- Boards
parameters:
- name: user
in: path
description: |
the ID of the user to retrieve the data
type: string
required: true
produces:
- application/json
security:
- UserSecurity: []
responses:
'200':
description: |-
200 response
schema:
type: array
items:
type: object
properties:
_id:
type: string
title:
type: string
definitions:
Boards:
type: object
description: This is a Board.
properties:
title:
description: |
The title of the board
type: string
slug:
description: |
The title slugified.
type: string
archived:
description: |
Is the board archived?
type: boolean
archivedAt:
description: |
Latest archiving time of the board
type: string
x-nullable: true
createdAt:
description: |
Creation time of the board
type: string
modifiedAt:
description: |
Last modification time of the board
type: string
x-nullable: true
stars:
description: |
How many stars the board has
type: number
labels:
description: |
List of labels attached to a board
type: array
items:
$ref: "#/definitions/BoardsLabels"
members:
description: |
List of members of a board
type: array
items:
$ref: "#/definitions/BoardsMembers"
permission:
description: |
visibility of the board
type: string
enum:
- public
- private
color:
description: |
The color of the board.
type: string
enum:
- belize
- nephritis
- pomegranate
- pumpkin
- wisteria
- moderatepink
- strongcyan
- limegreen
- midnight
- dark
- relax
- corteza
- clearblue
- natural
- modern
- moderndark
description:
description: |
The description of the board
type: string
x-nullable: true
subtasksDefaultBoardId:
description: |
The default board ID assigned to subtasks.
type: string
x-nullable: true
subtasksDefaultListId:
description: |
The default List ID assigned to subtasks.
type: string
x-nullable: true
dateSettingsDefaultBoardId:
type: string
x-nullable: true
dateSettingsDefaultListId:
type: string
x-nullable: true
allowsSubtasks:
description: |
Does the board allows subtasks?
type: boolean
allowsAttachments:
description: |
Does the board allows attachments?
type: boolean
allowsChecklists:
description: |
Does the board allows checklists?
type: boolean
allowsComments:
description: |
Does the board allows comments?
type: boolean
allowsDescriptionTitle:
description: |
Does the board allows description title?
type: boolean
allowsDescriptionText:
description: |
Does the board allows description text?
type: boolean
allowsActivities:
description: |
Does the board allows comments?
type: boolean
allowsLabels:
description: |
Does the board allows labels?
type: boolean
allowsAssignee:
description: |
Does the board allows assignee?
type: boolean
allowsMembers:
description: |
Does the board allows members?
type: boolean
allowsRequestedBy:
description: |
Does the board allows requested by?
type: boolean
allowsAssignedBy:
description: |
Does the board allows requested by?
type: boolean
allowsReceivedDate:
description: |
Does the board allows received date?
type: boolean
allowsStartDate:
description: |
Does the board allows start date?
type: boolean
allowsEndDate:
description: |
Does the board allows end date?
type: boolean
allowsDueDate:
description: |
Does the board allows due date?
type: boolean
presentParentTask:
description: |
Controls how to present the parent task:
- `prefix-with-full-path`: add a prefix with the full path
- `prefix-with-parent`: add a prefisx with the parent name
- `subtext-with-full-path`: add a subtext with the full path
- `subtext-with-parent`: add a subtext with the parent name
- `no-parent`: does not show the parent at all
type: string
enum:
- prefix-with-full-path
- prefix-with-parent
- subtext-with-full-path
- subtext-with-parent
- no-parent
x-nullable: true
startAt:
description: |
Starting date of the board.
type: string
x-nullable: true
dueAt:
description: |
Due date of the board.
type: string
x-nullable: true
endAt:
description: |
End date of the board.
type: string
x-nullable: true
spentTime:
description: |
Time spent in the board.
type: number
x-nullable: true
isOvertime:
description: |
Is the board overtimed?
type: boolean
x-nullable: true
type:
description: |
The type of board
type: string
sort:
description: |
Sort value
type: number
required:
- title
- slug
- archived
- createdAt
- stars
- labels
- members
- permission
- color
- allowsSubtasks
- allowsAttachments
- allowsChecklists
- allowsComments
- allowsDescriptionTitle
- allowsDescriptionText
- allowsActivities
- allowsLabels
- allowsAssignee
- allowsMembers
- allowsRequestedBy
- allowsAssignedBy
- allowsReceivedDate
- allowsStartDate
- allowsEndDate
- allowsDueDate
- type
- sort
BoardsLabels:
type: object
properties:
_id:
description: |
Unique id of a label
type: string
name:
description: |
Name of a label
type: string
color:
description: |
color of a label.
Can be amongst `green`, `yellow`, `orange`, `red`, `purple`,
`blue`, `sky`, `lime`, `pink`, `black`,
`silver`, `peachpuff`, `crimson`, `plum`, `darkgreen`,
`slateblue`, `magenta`, `gold`, `navy`, `gray`,
`saddlebrown`, `paleturquoise`, `mistyrose`, `indigo`
type: string
enum:
- green
- yellow
- orange
- red
- purple
- blue
- sky
- lime
- pink
- black
- silver
- peachpuff
- crimson
- plum
- darkgreen
- slateblue
- magenta
- gold
- navy
- gray
- saddlebrown
- paleturquoise
- mistyrose
- indigo
required:
- _id
- color
BoardsMembers:
type: object
properties:
userId:
description: |
The uniq ID of the member
type: string
isAdmin:
description: |
Is the member an admin of the board?
type: boolean
isActive:
description: |
Is the member active?
type: boolean
isNoComments:
description: |
Is the member not allowed to make comments
type: boolean
isCommentOnly:
description: |
Is the member only allowed to comment on the board
type: boolean
isWorker:
description: |
Is the member only allowed to move card, assign himself to card and comment
type: boolean
required:
- userId
- isAdmin
- isActive
CardComments:
type: object
description: A comment on a card
@@ -2079,6 +2738,11 @@ definitions:
description: |
is the card archived
type: boolean
archivedAt:
description: |
latest archiving date
type: string
x-nullable: true
parentId:
description: |
ID of the parent card
@@ -2499,6 +3163,11 @@ definitions:
description: |
is the list archived
type: boolean
archivedAt:
description: |
latest archiving date
type: string
x-nullable: true
boardId:
description: |
the board associated to this list
@@ -2601,6 +3270,11 @@ definitions:
description: |
is the swimlane archived?
type: boolean
archivedAt:
description: |
latest archiving date of the swimlane
type: string
x-nullable: true
boardId:
description: |
the ID of the board the swimlane is attached to
@@ -2723,6 +3397,14 @@ definitions:
profile settings
$ref: "#/definitions/UsersSessiondata"
x-nullable: true
importUsernames:
description: |
username for imported
type: array
items:
type: string
x-nullable: true
x-nullable: true
required:
- createdAt
- modifiedAt
+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 = 489,
appVersion = 492,
# Increment this for every release.
appMarketingVersion = (defaultText = "4.89.0~2021-01-28"),
appMarketingVersion = (defaultText = "4.92.0~2021-02-03"),
# Human-readable presentation of the app version.
minUpgradableAppVersion = 0,
+4 -1
View File
@@ -63,8 +63,11 @@ Meteor.publish('archivedBoards', function() {
archived: 1,
slug: 1,
title: 1,
createdAt: 1,
modifiedAt: 1,
archivedAt: 1,
},
sort: { sort: 1 /* boards default sorting */ },
sort: { archivedAt: -1, modifiedAt: -1 },
},
);
});
+6 -6
View File
@@ -200,11 +200,7 @@ Meteor.publish('globalSearch', function(sessionId, queryParams) {
comments: [],
};
this.colorMap = {};
for (const color of Boards.simpleSchema()._schema['labels.$.color']
.allowedValues) {
this.colorMap[TAPi18n.__(`color-${color}`)] = color;
}
this.colorMap = Boards.colorMap();
}
hasErrors() {
@@ -234,7 +230,11 @@ Meteor.publish('globalSearch', function(sessionId, queryParams) {
});
});
this.notFound.labels.forEach(label => {
messages.push({ tag: 'label-not-found', value: label, color: true });
messages.push({
tag: 'label-not-found',
value: label,
color: Boards.labelColors().includes(label),
});
});
this.notFound.users.forEach(user => {
messages.push({ tag: 'user-username-not-found', value: user });
+1
View File
@@ -20,6 +20,7 @@ Meteor.publish('people', function(query, limit) {
createdAt: 1,
loginDisabled: 1,
authenticationMethod: 1,
importUsernames: 1,
},
});
}
+17 -9
View File
@@ -1,14 +1,22 @@
Meteor.publish('user-miniprofile', function(userId) {
check(userId, String);
Meteor.publish('user-miniprofile', function(usernames) {
check(usernames, Array);
return Users.find(userId, {
fields: {
username: 1,
'profile.fullname': 1,
'profile.avatarUrl': 1,
'profile.initials': 1,
// eslint-disable-next-line no-console
// console.log('usernames:', usernames);
return Users.find(
{
$or: [
{ username: { $in: usernames } },
{ importUsernames: { $in: usernames } },
],
},
});
{
fields: {
...Users.safeFields,
importUsernames: 1,
},
},
);
});
Meteor.publish('user-admin', function() {
Loaded 100 of 101 files, more files were not shown because too many files have changed in this diff. Show more