mirror of
https://github.com/wekan/wekan.git
synced 2026-11-05 09:40:20 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c62396e389 | ||
|
|
d52e85f298 | ||
|
|
05ebae7329 | ||
|
|
b697bb656e | ||
|
|
4d7de2adce | ||
|
|
8a9528e787 | ||
|
|
6c6cba51fa | ||
|
|
28e23f9d87 | ||
|
|
e31192e97e | ||
|
|
26b7137b5c | ||
|
|
912200a2ec | ||
|
|
c42d0d7423 | ||
|
|
3da66a0fe3 | ||
|
|
41e1f8fbc3 | ||
|
|
130ac3c917 | ||
|
|
3774060d32 | ||
|
|
d8c8856548 | ||
|
|
efec00a550 | ||
|
|
3d3cf1d551 | ||
|
|
c52d17b6fb | ||
|
|
c0b9ef5990 | ||
|
|
e303159b98 | ||
|
|
f274b3c26b | ||
|
|
81fdc9a865 | ||
|
|
f40c9804f8 | ||
|
|
4d13d51038 | ||
|
|
5c4421dc38 | ||
|
|
76ef6a81ab | ||
|
|
a7b43d5b57 | ||
|
|
e4f50d4713 | ||
|
|
1e71237627 | ||
|
|
678c8f6bf6 | ||
|
|
786c27bbec | ||
|
|
710643d8cb | ||
|
|
e595aba189 | ||
|
|
ea67e94c47 | ||
|
|
b2c2067f7d | ||
|
|
4fc2d7b935 | ||
|
|
b1b9dd208b | ||
|
|
ee2f7c077f | ||
|
|
a385d6f4fd | ||
|
|
7031b7a3c7 | ||
|
|
0f0a5fba1f | ||
|
|
1d7af3f011 | ||
|
|
6fd85f97b3 | ||
|
|
a6d17f3813 | ||
|
|
4e830ea416 | ||
|
|
fc5c936272 | ||
|
|
b2af684c4d | ||
|
|
0446999c63 | ||
|
|
6920c39752 | ||
|
|
62ba8ed8d8 | ||
|
|
6eeef96886 | ||
|
|
4acf852650 | ||
|
|
9b3f1562a5 | ||
|
|
49774e46a3 | ||
|
|
ae2447393d | ||
|
|
3435192640 | ||
|
|
6ba4da9711 | ||
|
|
010a1d07d9 | ||
|
|
94d09b0014 | ||
|
|
d6ff442622 | ||
|
|
f7cc1abc8e | ||
|
|
bf7b1789ec | ||
|
|
cf9b482546 | ||
|
|
ad6da9bf37 | ||
|
|
d647884b91 | ||
|
|
0adde3e06d |
No files matched your search
@@ -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:
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
[](https://david-dm.org/wekan/wekan)
|
||||
[](https://www.openhub.net/p/wekan)
|
||||
[](https://app.fossa.io/projects/git%2Bgithub.com%2Fwekan%2Fwekan?ref=badge_shield)
|
||||
[](https://bestpractices.coreinfrastructure.org/projects/4619)
|
||||
|
||||
## [Translate Wekan at Transifex](https://transifex.com/wekan/wekan)
|
||||
|
||||
|
||||
+3
-3
@@ -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
@@ -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
|
||||
|
||||
@@ -11,7 +11,7 @@ BlazeComponent.extendComponent({
|
||||
return Boards.find(
|
||||
{ archived: true },
|
||||
{
|
||||
sort: { sort: 1 /* boards default sorting */ },
|
||||
sort: { archivedAt: -1, modifiedAt: -1 },
|
||||
},
|
||||
);
|
||||
},
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -176,6 +176,7 @@
|
||||
border-radius: 50%
|
||||
height: 28px
|
||||
width: @height
|
||||
margin: 0px 0px 4px 0px
|
||||
|
||||
.assignee
|
||||
float: right
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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());
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
Vendored
+4
@@ -47,3 +47,7 @@
|
||||
|
||||
a.show-mapping
|
||||
text-decoration underline
|
||||
|
||||
.import-members-map-note
|
||||
font-size: 90%
|
||||
font-weight: bold
|
||||
@@ -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();
|
||||
},
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
});
|
||||
@@ -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
@@ -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
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+4
-1
@@ -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
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+43
-15
@@ -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,
|
||||
|
||||
@@ -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
@@ -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(),
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
@@ -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
@@ -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() {
|
||||
|
||||
@@ -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
@@ -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;
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
Generated
+7
-7
@@ -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
@@ -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
File diff suppressed because it is too large.
Load diff
+683
-1
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 },
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
@@ -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 });
|
||||
|
||||
@@ -20,6 +20,7 @@ Meteor.publish('people', function(query, limit) {
|
||||
createdAt: 1,
|
||||
loginDisabled: 1,
|
||||
authenticationMethod: 1,
|
||||
importUsernames: 1,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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
Reference in new issue
Block a user