Compare commits

...
16 Commits
Author SHA1 Message Date
Lauri Ojansivu ba0068598c v3.64 2020-01-06 20:33:01 +02:00
Lauri Ojansivu 8f16c8bf8e Update translations. 2020-01-06 20:27:38 +02:00
Lauri Ojansivu 29726453a0 Update ChangeLog. 2020-01-06 20:19:56 +02:00
Lauri Ojansivu 5058233509 Wider sidebar.
Thanks to vjrj !

Closes #2218
2020-01-06 20:12:35 +02:00
Lauri Ojansivu 8442e1e83b Fix typo. 2020-01-06 11:20:11 +02:00
Lauri Ojansivu ef0689baf7 Update ChangeLog. 2020-01-06 11:04:58 +02:00
Lauri Ojansivu ddce0ada09 Removed Custom HTML feature that does not work.
Thanks to xet7 !

Closes #2218
2020-01-06 11:01:38 +02:00
Lauri Ojansivu 60df1fa1ee v3.63 2020-01-06 10:14:00 +02:00
Lauri Ojansivu 8e93912389 Update translations. 2020-01-06 10:09:14 +02:00
Lauri Ojansivu 064e4a2cf9 Update ChangeLog. 2020-01-06 10:07:02 +02:00
Lauri Ojansivu 8ce9939217 Fix: Unable to find Archive Card/List/Swimlane in board settings.
Thanks to neobradley and xet7 !

Closes #2872
2020-01-06 10:02:37 +02:00
Lauri Ojansivu 41a28df430 v3.62 2020-01-05 21:43:44 +02:00
Lauri Ojansivu c36a74b956 Update ChangeLog. 2020-01-05 21:36:28 +02:00
Lauri Ojansivu f6f7705f23 Add Worker role.
This was originally added at Wekan v3.58,
reverted at Wekan v3.60 because of bugs,
and now after fixes added back.

Thanks to xet7 !

Closes #2788
2020-01-05 21:28:14 +02:00
Lauri Ojansivu 6209b792aa Update translations. 2020-01-05 19:48:11 +02:00
Lauri Ojansivu f8873b009b Fix typo. 2020-01-03 17:20:04 +02:00
31 changed files with 438 additions and 268 deletions

No files matched your search

+41 -1
View File
@@ -1,3 +1,43 @@
# v3.64 2020-01-06 Wekan release
This release adds the following warning for CentOS 7 users:
- [WARNING: DO NOT USE SNAP ON CENTOS 7, THERE IS UPDATE BUG](https://github.com/wekan/wekan-snap/wiki/CentOS-7).
Thanks to andy-twosticks and xet7.
and adds the following features:
- [Wider sidebar](https://github.com/wekan/wekan/commit/5058233509e44916296e38fb8a6c5dd591c46d8b).
Thanks to vjrj.
and removes the following features:
- [Removed Custom HTML feature that does not work](https://github.com/wekan/wekan/commit/ddce0ada094e6450be260b4cda21fdfa09ae0133).
Thanks to xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v3.63 2020-01-06 Wekan release
This release fixes the following bugs:
- [Fix: Unable to find Archive Card/List/Swimlane in board
settings](https://github.com/wekan/wekan/commit/8ce993921718f3e10c2daa5fabb145b939d789dd).
Thanks to neobradley and xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v3.62 2020-01-05 Wekan release
This release adds the following features:
- [Add Worker role](https://github.com/wekan/wekan/issues/2788).
This was originally added at Wekan v3.58, reverted at Wekan v3.60 because of bugs,
and now after fixes added back.
Thanks to xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v3.61 2020-01-03 Wekan release
This release adds the following features:
@@ -22,7 +62,7 @@ This release fixes the following bugs:
- [Revert to Wekan v3.57 version of client and models directories,
removing Worker role temporarily, because Worker role changes
broke saving card](https://github.com/wekan/wekan/commit/27943796ade78ca3c503637a1340918bf06a1267).
Thanks to xet7 !
Thanks to xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
+1 -1
View File
@@ -1,5 +1,5 @@
appId: wekan-public/apps/77b94f60-dec9-0136-304e-16ff53095928
appVersion: "v3.61.0"
appVersion: "v3.64.0"
files:
userUploads:
- README.md
+14 -12
View File
@@ -38,18 +38,20 @@ template(name="attachmentsGalery")
| {{_ 'download'}}
if currentUser.isBoardMember
unless currentUser.isCommentOnly
if isImage
a(class="{{#if $eq ../coverId _id}}js-remove-cover{{else}}js-add-cover{{/if}}")
i.fa.fa-thumb-tack
if($eq ../coverId _id)
| {{_ 'remove-cover'}}
else
| {{_ 'add-cover'}}
a.js-confirm-delete
i.fa.fa-close
| {{_ 'delete'}}
unless currentUser.isWorker
if isImage
a(class="{{#if $eq ../coverId _id}}js-remove-cover{{else}}js-add-cover{{/if}}")
i.fa.fa-thumb-tack
if($eq ../coverId _id)
| {{_ 'remove-cover'}}
else
| {{_ 'add-cover'}}
a.js-confirm-delete
i.fa.fa-close
| {{_ 'delete'}}
if currentUser.isBoardMember
unless currentUser.isCommentOnly
li.attachment-item.add-attachment
a.js-add-attachment {{_ 'add-attachment' }}
unless currentUser.isWorker
li.attachment-item.add-attachment
a.js-add-attachment {{_ 'add-attachment' }}
+2 -1
View File
@@ -97,7 +97,8 @@ Template.dateBadge.helpers({
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly()
!Meteor.user().isCommentOnly() &&
!Meteor.user().isWorker()
);
},
});
+122 -94
View File
@@ -44,7 +44,8 @@ template(name="cardDetails")
+cardReceivedDate
else
if canModifyCard
a.js-received-date {{_ 'add'}}
unless currentUser.isWorker
a.js-received-date {{_ 'add'}}
.card-details-item.card-details-item-start
h3
@@ -54,7 +55,8 @@ template(name="cardDetails")
+cardStartDate
else
if canModifyCard
a.js-start-date {{_ 'add'}}
unless currentUser.isWorker
a.js-start-date {{_ 'add'}}
.card-details-item.card-details-item-due
h3
@@ -64,7 +66,8 @@ template(name="cardDetails")
+cardDueDate
else
if canModifyCard
a.js-due-date {{_ 'add'}}
unless currentUser.isWorker
a.js-due-date {{_ 'add'}}
.card-details-item.card-details-item-end
h3
@@ -74,7 +77,8 @@ template(name="cardDetails")
+cardEndDate
else
if canModifyCard
a.js-end-date {{_ 'add'}}
unless currentUser.isWorker
a.js-end-date {{_ 'add'}}
.card-details-items
.card-details-item.card-details-item-members
@@ -85,8 +89,9 @@ template(name="cardDetails")
+userAvatar(userId=this cardId=../_id)
| {{! XXX Hack to hide syntaxic coloration /// }}
if canModifyCard
a.member.add-member.card-details-item-add-button.js-add-members(title="{{_ 'card-members-title'}}")
i.fa.fa-plus
unless currentUser.isWorker
a.member.add-member.card-details-item-add-button.js-add-members(title="{{_ 'card-members-title'}}")
i.fa.fa-plus
.card-details-item.card-details-item-assignees
h3
@@ -96,10 +101,14 @@ template(name="cardDetails")
+userAvatarAssignee(userId=this cardId=../_id)
| {{! XXX Hack to hide syntaxic coloration /// }}
if canModifyCard
a.assignee.add-assignee.card-details-item-add-button.js-add-assignees(title="{{_ 'assignee'}}")
i.fa.fa-plus
if currentUser.isWorker
unless assigneeSelected
a.assignee.add-assignee.card-details-item-add-button.js-add-assignees(title="{{_ 'assignee'}}")
i.fa.fa-plus
.card-details-item.card-details-item-labels
h3
i.fa.fa-tags
@@ -110,8 +119,9 @@ template(name="cardDetails")
+viewer
= name
if canModifyCard
a.card-label.add-label.js-add-labels(title="{{_ 'card-labels-title'}}")
i.fa.fa-plus
unless currentUser.isWorker
a.card-label.add-label.js-add-labels(title="{{_ 'card-labels-title'}}")
i.fa.fa-plus
.card-details-items
each customFieldsWD
@@ -132,28 +142,29 @@ template(name="cardDetails")
//- XXX We should use "editable" to avoid repetiting ourselves
if canModifyCard
h3
i.fa.fa-align-left
card-details-item-title {{_ 'description'}}
+inlinedCardDescription(classNames="card-description js-card-description")
+editor(autofocus=true)
| {{getUnsavedValue 'cardDescription' _id getDescription}}
.edit-controls.clearfix
button.primary(type="submit") {{_ 'save'}}
a.fa.fa-times-thin.js-close-inlined-form
else
a.js-open-inlined-form
if getDescription
+viewer
= getDescription
else
| {{_ 'edit'}}
if (hasUnsavedValue 'cardDescription' _id)
p.quiet
| {{_ 'unsaved-description'}}
a.js-open-inlined-form {{_ 'view-it'}}
= ' - '
a.js-close-inlined-form {{_ 'discard'}}
unless currentUser.isWorker
h3
i.fa.fa-align-left
card-details-item-title {{_ 'description'}}
+inlinedCardDescription(classNames="card-description js-card-description")
+editor(autofocus=true)
| {{getUnsavedValue 'cardDescription' _id getDescription}}
.edit-controls.clearfix
button.primary(type="submit") {{_ 'save'}}
a.fa.fa-times-thin.js-close-inlined-form
else
a.js-open-inlined-form
if getDescription
+viewer
= getDescription
else
| {{_ 'edit'}}
if (hasUnsavedValue 'cardDescription' _id)
p.quiet
| {{_ 'unsaved-description'}}
a.js-open-inlined-form {{_ 'view-it'}}
= ' - '
a.js-close-inlined-form {{_ 'discard'}}
else if getDescription
h3.card-details-item-title {{_ 'description'}}
+viewer
@@ -165,15 +176,16 @@ template(name="cardDetails")
i.fa.fa-shopping-cart
card-details-item-title {{_ 'requested-by'}}
if canModifyCard
+inlinedForm(classNames="js-card-details-requester")
+editCardRequesterForm
else
a.js-open-inlined-form
if getRequestedBy
+viewer
= getRequestedBy
else
| {{_ 'add'}}
unless currentUser.isWorker
+inlinedForm(classNames="js-card-details-requester")
+editCardRequesterForm
else
a.js-open-inlined-form
if getRequestedBy
+viewer
= getRequestedBy
else
| {{_ 'add'}}
else if getRequestedBy
+viewer
= getRequestedBy
@@ -183,15 +195,16 @@ template(name="cardDetails")
i.fa.fa-user-plus
card-details-item-title {{_ 'assigned-by'}}
if canModifyCard
+inlinedForm(classNames="js-card-details-assigner")
+editCardAssignerForm
else
a.js-open-inlined-form
if getAssignedBy
+viewer
= getAssignedBy
else
| {{_ 'add'}}
unless currentUser.isWorker
+inlinedForm(classNames="js-card-details-assigner")
+editCardAssignerForm
else
a.js-open-inlined-form
if getAssignedBy
+viewer
= getAssignedBy
else
| {{_ 'add'}}
else if getRequestedBy
+viewer
= getAssignedBy
@@ -266,28 +279,29 @@ template(name="cardDetailsActionsPopup")
i.fa.fa-eye-slash
| {{_ 'watch'}}
if canModifyCard
hr
ul.pop-over-list
//li: a.js-members {{_ 'card-edit-members'}}
//li: a.js-labels {{_ 'card-edit-labels'}}
//li: a.js-attachments {{_ 'card-edit-attachments'}}
li
a.js-custom-fields
i.fa.fa-list-alt
| {{_ 'card-edit-custom-fields'}}
//li: a.js-received-date {{_ 'editCardReceivedDatePopup-title'}}
//li: a.js-start-date {{_ 'editCardStartDatePopup-title'}}
//li: a.js-due-date {{_ 'editCardDueDatePopup-title'}}
//li: a.js-end-date {{_ 'editCardEndDatePopup-title'}}
li
a.js-spent-time
i.fa.fa-clock-o
| {{_ 'editCardSpentTimePopup-title'}}
li
a.js-set-card-color
i.fa.fa-paint-brush
| {{_ 'setCardColorPopup-title'}}
hr
unless currentUser.isWorker
hr
ul.pop-over-list
//li: a.js-members {{_ 'card-edit-members'}}
//li: a.js-labels {{_ 'card-edit-labels'}}
//li: a.js-attachments {{_ 'card-edit-attachments'}}
li
a.js-custom-fields
i.fa.fa-list-alt
| {{_ 'card-edit-custom-fields'}}
//li: a.js-received-date {{_ 'editCardReceivedDatePopup-title'}}
//li: a.js-start-date {{_ 'editCardStartDatePopup-title'}}
//li: a.js-due-date {{_ 'editCardDueDatePopup-title'}}
//li: a.js-end-date {{_ 'editCardEndDatePopup-title'}}
li
a.js-spent-time
i.fa.fa-clock-o
| {{_ 'editCardSpentTimePopup-title'}}
li
a.js-set-card-color
i.fa.fa-paint-brush
| {{_ 'setCardColorPopup-title'}}
hr
ul.pop-over-list
li
a.js-move-card-to-top
@@ -297,16 +311,17 @@ template(name="cardDetailsActionsPopup")
a.js-move-card-to-bottom
i.fa.fa-arrow-down
| {{_ 'moveCardToBottom-title'}}
hr
ul.pop-over-list
li
a.js-move-card
i.fa.fa-arrow-right
| {{_ 'moveCardPopup-title'}}
li
a.js-copy-card
i.fa.fa-copy
| {{_ 'copyCardPopup-title'}}
unless currentUser.isWorker
hr
ul.pop-over-list
li
a.js-move-card
i.fa.fa-arrow-right
| {{_ 'moveCardPopup-title'}}
li
a.js-copy-card
i.fa.fa-copy
| {{_ 'copyCardPopup-title'}}
hr
ul.pop-over-list
li
@@ -379,16 +394,27 @@ template(name="cardMembersPopup")
i.fa.fa-check
template(name="cardAssigneesPopup")
ul.pop-over-list.js-card-assignee-list
each board.activeMembers
li.item(class="{{#if isCardAssignee}}active{{/if}}")
a.name.js-select-assignee(href="#")
+userAvatar(userId=user._id)
span.full-name
= user.profile.fullname
| (<span class="username">{{ user.username }}</span>)
if isCardAssignee
i.fa.fa-check
unless currentUser.isWorker
ul.pop-over-list.js-card-assignee-list
each board.activeMembers
li.item(class="{{#if isCardAssignee}}active{{/if}}")
a.name.js-select-assignee(href="#")
+userAvatar(userId=user._id)
span.full-name
= user.profile.fullname
| (<span class="username">{{ user.username }}</span>)
if isCardAssignee
i.fa.fa-check
if currentUser.isWorker
ul.pop-over-list.js-card-assignee-list
li.item(class="{{#if currentUser.isCardAssignee}}active{{/if}}")
a.name.js-select-assignee(href="#")
+userAvatar(userId=currentUser._id)
span.full-name
= currentUser.profile.fullname
| (<span class="username">{{ currentUser.username }}</span>)
if currentUser.isCardAssignee
i.fa.fa-check
template(name="userAvatarAssignee")
a.assignee.js-assignee(title="{{userData.profile.fullname}} ({{userData.username}})")
@@ -416,11 +442,13 @@ template(name="cardAssigneePopup")
p.quiet @{{ user.username }}
ul.pop-over-list
if currentUser.isNotCommentOnly
li: a.js-remove-assignee {{_ 'remove-member-from-card'}}
unless currentUser.isWorker
li: a.js-remove-assignee {{_ 'remove-member-from-card'}}
if $eq currentUser._id user._id
with currentUser
li: a.js-edit-profile {{_ 'edit-profile'}}
unless currentUser.isWorker
if $eq currentUser._id user._id
with currentUser
li: a.js-edit-profile {{_ 'edit-profile'}}
template(name="userAvatarAssigneeInitials")
svg.avatar.avatar-assignee-initials(viewBox="0 0 {{viewPortWidth}} 15")
+2 -1
View File
@@ -51,7 +51,8 @@ BlazeComponent.extendComponent({
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly()
!Meteor.user().isCommentOnly() &&
!Meteor.user().isWorker()
);
},
+6 -3
View File
@@ -67,7 +67,8 @@ BlazeComponent.extendComponent({
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly()
!Meteor.user().isCommentOnly() &&
!Meteor.user().isWorker()
);
},
}).register('checklistDetail');
@@ -120,7 +121,8 @@ BlazeComponent.extendComponent({
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly()
!Meteor.user().isCommentOnly() &&
!Meteor.user().isWorker()
);
},
@@ -228,7 +230,8 @@ Template.checklistItemDetail.helpers({
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly()
!Meteor.user().isCommentOnly() &&
!Meteor.user().isWorker()
);
},
});
+6 -3
View File
@@ -3,7 +3,8 @@ BlazeComponent.extendComponent({
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly()
!Meteor.user().isCommentOnly() &&
!Meteor.user().isWorker()
);
},
}).register('subtaskDetail');
@@ -55,7 +56,8 @@ BlazeComponent.extendComponent({
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly()
!Meteor.user().isCommentOnly() &&
!Meteor.user().isWorker()
);
},
@@ -154,7 +156,8 @@ Template.subtaskItemDetail.helpers({
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly()
!Meteor.user().isCommentOnly() &&
!Meteor.user().isWorker()
);
},
});
+2 -1
View File
@@ -189,7 +189,8 @@ BlazeComponent.extendComponent({
!this.reachedWipLimit() &&
Meteor.user() &&
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly()
!Meteor.user().isCommentOnly() &&
!Meteor.user().isWorker()
);
},
+17 -14
View File
@@ -10,7 +10,7 @@ template(name="listHeader")
a.list-header-left-icon.fa.fa-angle-left.js-unselect-list
h2.list-header-name(
title="{{ moment modifiedAt 'LLL' }}"
class="{{#if currentUser.isBoardMember}}{{#unless currentUser.isCommentOnly}}js-open-inlined-form is-editable{{/unless}}{{/if}}")
class="{{#if currentUser.isBoardMember}}{{#unless currentUser.isCommentOnly}}{{#unless currentUser.isWorker}}js-open-inlined-form is-editable{{/unless}}{{/unless}}{{/if}}")
+viewer
= title
if wipLimit.enabled
@@ -65,11 +65,12 @@ template(name="listActionPopup")
i.fa.fa-eye-slash
| {{_ 'watch'}}
unless currentUser.isCommentOnly
ul.pop-over-list
li
a.js-set-color-list
i.fa.fa-paint-brush
| {{_ 'set-color-list'}}
unless currentUser.isWorker
ul.pop-over-list
li
a.js-set-color-list
i.fa.fa-paint-brush
| {{_ 'set-color-list'}}
ul.pop-over-list
if cards.count
li
@@ -82,13 +83,14 @@ template(name="listActionPopup")
a.js-set-wip-limit
i.fa.fa-ban
| {{#if isWipLimitEnabled }}{{_ 'edit-wip-limit'}}{{else}}{{_ 'setWipLimitPopup-title'}}{{/if}}
hr
ul.pop-over-list
li
a.js-close-list
i.fa.fa-arrow-right
i.fa.fa-archive
| {{_ 'archive-list'}}
unless currentUser.isWorker
hr
ul.pop-over-list
li
a.js-close-list
i.fa.fa-arrow-right
i.fa.fa-archive
| {{_ 'archive-list'}}
hr
ul.pop-over-list
li
@@ -114,7 +116,8 @@ template(name="listMorePopup")
input.inline-input(type="text" readonly value="{{ rootUrl }}")
| {{_ 'added'}}
span.date(title=list.createdAt) {{ moment createdAt 'LLL' }}
a.js-delete {{_ 'delete'}}
unless currentUser.isWorker
a.js-delete {{_ 'delete'}}
template(name="listDeletePopup")
p {{_ "list-delete-pop"}}
+4 -3
View File
@@ -9,9 +9,10 @@ BlazeComponent.extendComponent({
canSeeAddCard() {
const list = Template.currentData();
return (
!list.getWipLimit('enabled') ||
list.getWipLimit('soft') ||
!this.reachedWipLimit()
(!list.getWipLimit('enabled') ||
list.getWipLimit('soft') ||
!this.reachedWipLimit()) &&
!Meteor.user().isWorker()
);
},
@@ -184,12 +184,6 @@ template(name='layoutSettings')
.title {{_ 'custom-product-name'}}
.form-group
input.wekan-form-control#product-name(type="text", placeholder="" value="{{currentSetting.productName}}")
li.layout-form
.title {{_ 'add-custom-html-after-body-start'}}
textarea#customHTMLafterBodyStart.wekan-form-control= currentSetting.customHTMLafterBodyStart
li.layout-form
.title {{_ 'add-custom-html-before-body-end'}}
textarea#customHTMLbeforeBodyEnd.wekan-form-control= currentSetting.customHTMLbeforeBodyEnd
li
button.js-save-layout.primary {{_ 'save'}}
@@ -171,20 +171,12 @@ BlazeComponent.extendComponent({
const displayAuthenticationMethod =
$('input[name=displayAuthenticationMethod]:checked').val() === 'true';
const defaultAuthenticationMethod = $('#defaultAuthenticationMethod').val();
const customHTMLafterBodyStart = $('#customHTMLafterBodyStart')
.val()
.trim();
const customHTMLbeforeBodyEnd = $('#customHTMLbeforeBodyEnd')
.val()
.trim();
try {
Settings.update(Settings.findOne()._id, {
$set: {
productName,
hideLogo: hideLogoChange,
customHTMLafterBodyStart,
customHTMLbeforeBodyEnd,
displayAuthenticationMethod,
defaultAuthenticationMethod,
},
+16 -8
View File
@@ -40,8 +40,9 @@ template(name="membersWidget")
i.fa.fa-users
| {{_ 'members'}}
unless currentUser.isCommentOnly
a.board-header-btn.js-open-board-menu(title="{{_ 'boardMenuPopup-title'}}").right
i.board-header-btn-icon.fa.fa-cog
unless currentUser.isWorker
a.board-header-btn.js-open-board-menu(title="{{_ 'boardMenuPopup-title'}}").right
i.board-header-btn-icon.fa.fa-cog
.board-widget-content
each currentBoard.activeMembers
@@ -246,7 +247,7 @@ template(name="labelsWidget")
.board-widget-content
each currentBoard.labels
a.card-label(class="card-label-{{color}}"
class="{{#if currentUser.isNotCommentOnly}}js-label{{/if}}")
class="{{#if currentUser.isNotCommentOnly}}{{#if currentUser.isNotWorker}}js-label{{/if}}{{/if}}")
span.card-label-name
+viewer
= name
@@ -275,11 +276,12 @@ template(name="memberPopup")
a.js-change-role
| {{_ 'change-permissions'}}
span.quiet (#{memberType})
li
if $eq currentUser._id userId
a.js-leave-member {{_ 'leave-board'}}
else if currentUser.isBoardAdmin
a.js-remove-member {{_ 'remove-from-board'}}
unless currentUser.isWorker
li
if $eq currentUser._id userId
a.js-leave-member {{_ 'leave-board'}}
else if currentUser.isBoardAdmin
a.js-remove-member {{_ 'remove-from-board'}}
template(name="removeMemberPopup")
p {{_ 'remove-member-pop' name=user.profile.fullname username=user.username boardTitle=board.title}}
@@ -343,6 +345,12 @@ template(name="changePermissionsPopup")
if isCommentOnly
i.fa.fa-check
span.sub-name {{_ 'comment-only-desc'}}
li
a(class="{{#if isLastAdmin}}disabled{{else}}js-set-worker{{/if}}")
| {{_ 'worker'}}
if isWorker
i.fa.fa-check
span.sub-name {{_ 'worker-desc'}}
if isLastAdmin
hr
p.quiet.bottom {{_ 'last-admin-desc'}}
+23 -2
View File
@@ -161,10 +161,13 @@ Template.memberPopup.helpers({
const currentBoard = Boards.findOne(Session.get('currentBoard'));
const commentOnly = currentBoard.hasCommentOnly(this.userId);
const noComments = currentBoard.hasNoComments(this.userId);
const worker = currentBoard.hasWorker(this.userId);
if (commentOnly) {
return TAPi18n.__('comment-only').toLowerCase();
} else if (noComments) {
return TAPi18n.__('no-comments').toLowerCase();
} else if (worker) {
return TAPi18n.__('worker').toLowerCase();
} else {
return TAPi18n.__(type).toLowerCase();
}
@@ -267,6 +270,14 @@ Template.membersWidget.helpers({
const user = Meteor.user();
return user && user.isInvitedTo(Session.get('currentBoard'));
},
isWorker() {
const user = Meteor.user();
if (user) {
return Meteor.call(Boards.hasWorker(user.memberId));
} else {
return false;
}
},
});
Template.membersWidget.events({
@@ -644,7 +655,7 @@ BlazeComponent.extendComponent({
}).register('addMemberPopup');
Template.changePermissionsPopup.events({
'click .js-set-admin, click .js-set-normal, click .js-set-no-comments, click .js-set-comment-only'(
'click .js-set-admin, click .js-set-normal, click .js-set-no-comments, click .js-set-comment-only, click .js-set-worker'(
event,
) {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
@@ -654,11 +665,13 @@ Template.changePermissionsPopup.events({
'js-set-comment-only',
);
const isNoComments = $(event.currentTarget).hasClass('js-set-no-comments');
const isWorker = $(event.currentTarget).hasClass('js-set-worker');
currentBoard.setMemberPermission(
memberId,
isAdmin,
isNoComments,
isCommentOnly,
isWorker,
);
Popup.back(1);
},
@@ -675,7 +688,8 @@ Template.changePermissionsPopup.helpers({
return (
!currentBoard.hasAdmin(this.userId) &&
!currentBoard.hasNoComments(this.userId) &&
!currentBoard.hasCommentOnly(this.userId)
!currentBoard.hasCommentOnly(this.userId) &&
!currentBoard.hasWorker(this.userId)
);
},
@@ -695,6 +709,13 @@ Template.changePermissionsPopup.helpers({
);
},
isWorker() {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
return (
!currentBoard.hasAdmin(this.userId) && currentBoard.hasWorker(this.userId)
);
},
isLastAdmin() {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
return (
+1 -1
View File
@@ -109,7 +109,7 @@
color: darken(white, 40%)
.board-sidebar
width: 248px
width: 548px
right: -@width
transition: top .1s, right .1s, width .1s
+30 -24
View File
@@ -2,54 +2,60 @@ template(name="archivesSidebar")
if isArchiveReady.get
+basicTabs(tabs=tabs)
+tabContent(slug="cards")
p.quiet
a.js-restore-all-cards {{_ 'restore-all'}}
| -
a.js-delete-all-cards {{_ 'delete-all'}}
unless isWorker
p.quiet
a.js-restore-all-cards {{_ 'restore-all'}}
| -
a.js-delete-all-cards {{_ 'delete-all'}}
each archivedCards
.minicard-wrapper.js-minicard
+minicard(this)
if currentUser.isBoardMember
p.quiet
a.js-restore-card {{_ 'restore'}}
| -
a.js-delete-card {{_ 'delete'}}
unless isWorker
p.quiet
a.js-restore-card {{_ 'restore'}}
| -
a.js-delete-card {{_ 'delete'}}
if cardIsInArchivedList
p.quiet.small ({{_ 'warn-list-archived'}})
else
p.no-items-message {{_ 'no-archived-cards'}}
+tabContent(slug="lists")
p.quiet
a.js-restore-all-lists {{_ 'restore-all'}}
| -
a.js-delete-all-lists {{_ 'delete-all'}}
unless isWorker
p.quiet
a.js-restore-all-lists {{_ 'restore-all'}}
| -
a.js-delete-all-lists {{_ 'delete-all'}}
ul.archived-lists
each archivedLists
li.archived-lists-item
= title
if currentUser.isBoardMember
p.quiet
a.js-restore-list {{_ 'restore'}}
| -
a.js-delete-list {{_ 'delete'}}
unless isWorker
p.quiet
a.js-restore-list {{_ 'restore'}}
| -
a.js-delete-list {{_ 'delete'}}
else
li.no-items-message {{_ 'no-archived-lists'}}
+tabContent(slug="swimlanes")
p.quiet
a.js-restore-all-swimlanes {{_ 'restore-all'}}
| -
a.js-delete-all-swimlanes {{_ 'delete-all'}}
unless isWorker
p.quiet
a.js-restore-all-swimlanes {{_ 'restore-all'}}
| -
a.js-delete-all-swimlanes {{_ 'delete-all'}}
ul.archived-lists
each archivedSwimlanes
li.archived-lists-item
= title
if currentUser.isBoardMember
p.quiet
a.js-restore-swimlane {{_ 'restore'}}
| -
a.js-delete-swimlane {{_ 'delete'}}
unless isWorker
p.quiet
a.js-restore-swimlane {{_ 'restore'}}
| -
a.js-delete-swimlane {{_ 'delete'}}
else
li.no-items-message {{_ 'no-archived-swimlanes'}}
else
@@ -139,3 +139,12 @@ BlazeComponent.extendComponent({
];
},
}).register('archivesSidebar');
Template.archivesSidebar.helpers({
isWorker() {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
return (
!currentBoard.hasAdmin(this.userId) && currentBoard.hasWorker(this.userId)
);
},
});
+17 -16
View File
@@ -43,19 +43,20 @@ template(name="listsGroup")
+addListForm
template(name="addListForm")
.list.list-composer.js-list-composer(class="{{#if isMiniScreen}}mini-list{{/if}}")
.list-header-add
+inlinedForm(autoclose=false)
input.list-name-input.full-line(type="text" placeholder="{{_ 'add-list'}}"
autocomplete="off" autofocus)
.edit-controls.clearfix
button.primary.confirm(type="submit") {{_ 'save'}}
unless currentBoard.isTemplatesBoard
unless currentBoard.isTemplateBoard
span.quiet
| {{_ 'or'}}
a.js-list-template {{_ 'template'}}
else
a.open-list-composer.js-open-inlined-form
i.fa.fa-plus
| {{_ 'add-list'}}
unless currentUser.isWorker
.list.list-composer.js-list-composer(class="{{#if isMiniScreen}}mini-list{{/if}}")
.list-header-add
+inlinedForm(autoclose=false)
input.list-name-input.full-line(type="text" placeholder="{{_ 'add-list'}}"
autocomplete="off" autofocus)
.edit-controls.clearfix
button.primary.confirm(type="submit") {{_ 'save'}}
unless currentBoard.isTemplatesBoard
unless currentBoard.isTemplateBoard
span.quiet
| {{_ 'or'}}
a.js-list-template {{_ 'template'}}
else
a.open-list-composer.js-open-inlined-form
i.fa.fa-plus
| {{_ 'add-list'}}
+13 -2
View File
@@ -94,7 +94,8 @@ function initSortable(boardComponent, $listsDom) {
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly()
!Meteor.user().isCommentOnly() &&
!Meteor.user().isWorker()
);
}
@@ -131,6 +132,15 @@ function initSortable(boardComponent, $listsDom) {
// MultiSelection.isActive() || !userIsMember(),
);
}
$listsDom.sortable(
'option',
'disabled',
// Disable drag-dropping when user is not member
Meteor.user().isWorker(),
// Not disable drag-dropping while in multi-selection mode
// MultiSelection.isActive() || !userIsMember(),
);
});
}
@@ -282,7 +292,8 @@ Template.swimlane.helpers({
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly()
!Meteor.user().isCommentOnly() &&
!Meteor.user().isWorker()
);
},
});
+2 -1
View File
@@ -73,7 +73,8 @@ template(name="cardMemberPopup")
p.quiet @{{ user.username }}
ul.pop-over-list
if currentUser.isNotCommentOnly
li: a.js-remove-member {{_ 'remove-member-from-card'}}
if currentUser.isNotWorker
li: a.js-remove-member {{_ 'remove-member-from-card'}}
if $eq currentUser._id user._id
with currentUser
+17 -14
View File
@@ -39,12 +39,13 @@ template(name="memberMenuPopup")
a.js-go-setting(href="{{pathFor 'setting'}}")
i.fa.fa-lock
| {{_ 'admin-panel'}}
hr
ul.pop-over-list
li
a(href="{{pathFor 'board' id=templatesBoardId slug=templatesBoardSlug}}")
i.fa.fa-clone
| {{_ 'templates'}}
unless currentUser.isWorker
hr
ul.pop-over-list
li
a(href="{{pathFor 'board' id=templatesBoardId slug=templatesBoardSlug}}")
i.fa.fa-clone
| {{_ 'templates'}}
unless isSandstorm
hr
ul.pop-over-list
@@ -109,13 +110,15 @@ template(name="changeSettingsPopup")
| {{_ 'show-desktop-drag-handles'}}
if showDesktopDragHandles
i.fa.fa-check
li
label.bold
i.fa.fa-sort-numeric-asc
| {{_ 'show-cards-minimum-count'}}
input#show-cards-count-at.inline-input.left(type="number" value="#{showCardsCountAt}" min="0" max="99" onkeydown="return false")
input.js-apply-show-cards-at.left(type="submit" value="{{_ 'apply'}}")
unless currentUser.isWorker
li
label.bold
i.fa.fa-sort-numeric-asc
| {{_ 'show-cards-minimum-count'}}
input#show-cards-count-at.inline-input.left(type="number" value="#{showCardsCountAt}" min="0" max="99" onkeydown="return false")
input.js-apply-show-cards-at.left(type="submit" value="{{_ 'apply'}}")
template(name="userDeletePopup")
p {{_ 'delete-user-confirm-popup'}}
button.js-confirm.negate.full(type="submit") {{_ 'delete'}}
unless currentUser.isWorker
p {{_ 'delete-user-confirm-popup'}}
button.js-confirm.negate.full(type="submit") {{_ 'delete'}}
+28 -1
View File
@@ -185,6 +185,7 @@ Boards.attachSchema(
isActive: true,
isNoComments: false,
isCommentOnly: false,
isWorker: false,
},
];
}
@@ -222,6 +223,13 @@ Boards.attachSchema(
type: Boolean,
optional: true,
},
'members.$.isWorker': {
/**
* Is the member only allowed to move card, assign himself to card and comment
*/
type: Boolean,
optional: true,
},
permission: {
/**
* visibility of the board
@@ -538,6 +546,7 @@ Boards.helpers({
isActive: true,
isAdmin: false,
isNoComments: true,
isWorker: false,
});
},
@@ -547,6 +556,17 @@ Boards.helpers({
isActive: true,
isAdmin: false,
isCommentOnly: true,
isWorker: false,
});
},
hasWorker(memberId) {
return !!_.findWhere(this.members, {
userId: memberId,
isActive: true,
isAdmin: false,
isCommentOnly: false,
isWorker: true,
});
},
@@ -849,6 +869,7 @@ Boards.mutations({
isActive: true,
isNoComments: false,
isCommentOnly: false,
isWorker: false,
},
},
};
@@ -881,6 +902,7 @@ Boards.mutations({
isAdmin,
isNoComments,
isCommentOnly,
isWorker,
currentUserId = Meteor.userId(),
) {
const memberIndex = this.memberIndex(memberId);
@@ -894,6 +916,7 @@ Boards.mutations({
[`members.${memberIndex}.isAdmin`]: isAdmin,
[`members.${memberIndex}.isNoComments`]: isNoComments,
[`members.${memberIndex}.isCommentOnly`]: isCommentOnly,
[`members.${memberIndex}.isWorker`]: isWorker,
},
};
},
@@ -1281,6 +1304,7 @@ if (Meteor.isServer) {
* @param {boolean} [isActive] is the board active (default true)
* @param {boolean} [isNoComments] disable comments (default false)
* @param {boolean} [isCommentOnly] only enable comments (default false)
* @param {boolean} [isWorker] only move cards, assign himself to card and comment (default false)
* @param {string} [permission] "private" board <== Set to "public" if you
* want public Wekan board
* @param {string} [color] the color of the board
@@ -1300,6 +1324,7 @@ if (Meteor.isServer) {
isActive: req.body.isActive || true,
isNoComments: req.body.isNoComments || false,
isCommentOnly: req.body.isCommentOnly || false,
isWorker: req.body.isWorker || false,
},
],
permission: req.body.permission || 'private',
@@ -1403,6 +1428,7 @@ if (Meteor.isServer) {
* @param {boolean} isAdmin admin capability
* @param {boolean} isNoComments NoComments capability
* @param {boolean} isCommentOnly CommentsOnly capability
* @param {boolean} isWorker Worker capability
*/
JsonRoutes.add('POST', '/api/boards/:boardId/members/:memberId', function(
req,
@@ -1411,7 +1437,7 @@ if (Meteor.isServer) {
try {
const boardId = req.params.boardId;
const memberId = req.params.memberId;
const { isAdmin, isNoComments, isCommentOnly } = req.body;
const { isAdmin, isNoComments, isCommentOnly, isWorker } = req.body;
Authentication.checkBoardAccess(req.userId, boardId);
const board = Boards.findOne({ _id: boardId });
function isTrue(data) {
@@ -1426,6 +1452,7 @@ if (Meteor.isServer) {
isTrue(isAdmin),
isTrue(isNoComments),
isTrue(isCommentOnly),
isTrue(isWorker),
req.userId,
);
-8
View File
@@ -33,14 +33,6 @@ Settings.attachSchema(
type: String,
optional: true,
},
customHTMLafterBodyStart: {
type: String,
optional: true,
},
customHTMLbeforeBodyEnd: {
type: String,
optional: true,
},
displayAuthenticationMethod: {
type: Boolean,
optional: true,
+10
View File
@@ -352,6 +352,16 @@ if (Meteor.isClient) {
return board && board.hasCommentOnly(this._id);
},
isNotWorker() {
const board = Boards.findOne(Session.get('currentBoard'));
return board && board.hasMember(this._id) && !board.hasWorker(this._id);
},
isWorker() {
const board = Boards.findOne(Session.get('currentBoard'));
return board && board.hasWorker(this._id);
},
isBoardAdmin() {
const board = Boards.findOne(Session.get('currentBoard'));
return board && board.hasAdmin(this._id);
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "wekan",
"version": "v3.61.0",
"version": "v3.64.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "wekan",
"version": "v3.61.0",
"version": "v3.64.0",
"description": "Open-Source kanban",
"private": true,
"scripts": {
+34 -6
View File
@@ -1524,7 +1524,7 @@ var n=this.pipeline.run(e.tokenizer(t)),r=new e.Vector,i=[],o=this._fields.reduc
<ul class="toc-list-h1">
<li>
<a href="#wekan-rest-api" class="toc-h1 toc-link" data-title="Wekan REST API v3.61">Wekan REST API v3.61</a>
<a href="#wekan-rest-api" class="toc-h1 toc-link" data-title="Wekan REST API v3.64">Wekan REST API v3.64</a>
</li>
@@ -2017,7 +2017,7 @@ var n=this.pipeline.run(e.tokenizer(t)),r=new e.Vector,i=[],o=this._fields.reduc
<div class="page-wrapper">
<div class="dark-box"></div>
<div class="content">
<h1 id="wekan-rest-api">Wekan REST API v3.61</h1>
<h1 id="wekan-rest-api">Wekan REST API v3.64</h1>
<blockquote>
<p>Scroll down for code samples, example requests and responses. Select a language for code samples from the tabs above or the mobile navigation menu.</p>
</blockquote>
@@ -2837,6 +2837,7 @@ $.ajax({
"isActive": true,
"isNoComments": true,
"isCommentOnly": true,
"isWorker": true,
"permission": "string",
"color": "string"
}'</span>;
@@ -2947,6 +2948,7 @@ System.out.println(response.toString());
<span class="hljs-attr">isActive:</span> <span class="hljs-literal">true</span>
<span class="hljs-attr">isNoComments:</span> <span class="hljs-literal">true</span>
<span class="hljs-attr">isCommentOnly:</span> <span class="hljs-literal">true</span>
<span class="hljs-attr">isWorker:</span> <span class="hljs-literal">true</span>
<span class="hljs-attr">permission:</span> <span class="hljs-string">string</span>
<span class="hljs-attr">color:</span> <span class="hljs-string">string</span>
@@ -3013,6 +3015,13 @@ System.out.println(response.toString());
<td>only enable comments (default false)</td>
</tr>
<tr>
<td>» isWorker</td>
<td>body</td>
<td>boolean</td>
<td>false</td>
<td>only move cards, assign himself to card and comment (default false)</td>
</tr>
<tr>
<td>» permission</td>
<td>body</td>
<td>string</td>
@@ -3269,7 +3278,8 @@ System.out.println(response.toString());
<span class="hljs-attr">"isAdmin"</span>: <span class="hljs-literal">true</span>,
<span class="hljs-attr">"isActive"</span>: <span class="hljs-literal">true</span>,
<span class="hljs-attr">"isNoComments"</span>: <span class="hljs-literal">true</span>,
<span class="hljs-attr">"isCommentOnly"</span>: <span class="hljs-literal">true</span>
<span class="hljs-attr">"isCommentOnly"</span>: <span class="hljs-literal">true</span>,
<span class="hljs-attr">"isWorker"</span>: <span class="hljs-literal">true</span>
}
],
<span class="hljs-attr">"permission"</span>: <span class="hljs-string">"public"</span>,
@@ -3884,7 +3894,8 @@ $.ajax({
<span class="hljs-keyword">const</span> inputBody = <span class="hljs-string">'{
"isAdmin": true,
"isNoComments": true,
"isCommentOnly": true
"isCommentOnly": true,
"isWorker": true
}'</span>;
<span class="hljs-keyword">const</span> headers = {
<span class="hljs-string">'Content-Type'</span>:<span class="hljs-string">'multipart/form-data'</span>,
@@ -3981,6 +3992,7 @@ System.out.println(response.toString());
<pre class="highlight tab tab-yaml"><code><span class="hljs-attr">isAdmin:</span> <span class="hljs-literal">true</span>
<span class="hljs-attr">isNoComments:</span> <span class="hljs-literal">true</span>
<span class="hljs-attr">isCommentOnly:</span> <span class="hljs-literal">true</span>
<span class="hljs-attr">isWorker:</span> <span class="hljs-literal">true</span>
</code></pre>
<h3 id="set_board_member_permission-parameters">Parameters</h3>
@@ -4037,6 +4049,13 @@ System.out.println(response.toString());
<td>true</td>
<td>CommentsOnly capability</td>
</tr>
<tr>
<td>» isWorker</td>
<td>body</td>
<td>boolean</td>
<td>true</td>
<td>Worker capability</td>
</tr>
</tbody>
</table>
<h4 id="detailed-descriptions">Detailed descriptions</h4>
@@ -13608,7 +13627,8 @@ UserSecurity
<span class="hljs-attr">"isAdmin"</span>: <span class="hljs-literal">true</span>,
<span class="hljs-attr">"isActive"</span>: <span class="hljs-literal">true</span>,
<span class="hljs-attr">"isNoComments"</span>: <span class="hljs-literal">true</span>,
<span class="hljs-attr">"isCommentOnly"</span>: <span class="hljs-literal">true</span>
<span class="hljs-attr">"isCommentOnly"</span>: <span class="hljs-literal">true</span>,
<span class="hljs-attr">"isWorker"</span>: <span class="hljs-literal">true</span>
}
],
<span class="hljs-attr">"permission"</span>: <span class="hljs-string">"public"</span>,
@@ -14034,7 +14054,8 @@ UserSecurity
<span class="hljs-attr">"isAdmin"</span>: <span class="hljs-literal">true</span>,
<span class="hljs-attr">"isActive"</span>: <span class="hljs-literal">true</span>,
<span class="hljs-attr">"isNoComments"</span>: <span class="hljs-literal">true</span>,
<span class="hljs-attr">"isCommentOnly"</span>: <span class="hljs-literal">true</span>
<span class="hljs-attr">"isCommentOnly"</span>: <span class="hljs-literal">true</span>,
<span class="hljs-attr">"isWorker"</span>: <span class="hljs-literal">true</span>
}
</code></pre>
@@ -14085,6 +14106,13 @@ UserSecurity
<td>none</td>
<td>Is the member only allowed to comment on the board</td>
</tr>
<tr>
<td>isWorker</td>
<td>boolean</td>
<td>false</td>
<td>none</td>
<td>Is the member only allowed to move card, assign himself to card and comment</td>
</tr>
</tbody>
</table>
<h2 id="tocscardcomments">CardComments</h2>
+17 -1
View File
@@ -1,7 +1,7 @@
swagger: '2.0'
info:
title: Wekan REST API
version: v3.61
version: v3.64
description: |
The REST API allows you to control and extend Wekan with ease.
@@ -211,6 +211,12 @@ paths:
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: |
@@ -1534,6 +1540,12 @@ paths:
CommentsOnly capability
type: boolean
required: true
- name: isWorker
in: formData
description: |
Worker capability
type: boolean
required: true
- name: board
in: path
description: |
@@ -2215,6 +2227,10 @@ definitions:
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
+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 = 363,
appVersion = 366,
# Increment this for every release.
appMarketingVersion = (defaultText = "3.61.0~2020-01-03"),
appMarketingVersion = (defaultText = "3.64.0~2020-01-06"),
# Human-readable presentation of the app version.
minUpgradableAppVersion = 0,
-32
View File
@@ -472,38 +472,6 @@ Migrations.add('add-hide-logo', () => {
);
});
Migrations.add('add-custom-html-after-body-start', () => {
Settings.update(
{
customHTMLafterBodyStart: {
$exists: false,
},
},
{
$set: {
customHTMLafterBodyStart: '',
},
},
noValidateMulti,
);
});
Migrations.add('add-custom-html-before-body-end', () => {
Settings.update(
{
customHTMLbeforeBodyEnd: {
$exists: false,
},
},
{
$set: {
customHTMLbeforeBodyEnd: '',
},
},
noValidateMulti,
);
});
Migrations.add('add-displayAuthenticationMethod', () => {
Settings.update(
{