mirror of
https://github.com/wekan/wekan.git
synced 2026-03-07 22:22:33 +01:00
Merge branch 'master' of https://github.com/wekan/wekan into lib-change
This commit is contained in:
commit
4b196d5378
175 changed files with 13493 additions and 1971 deletions
|
|
@ -82,4 +82,16 @@ if (Meteor.isServer) {
|
|||
});
|
||||
}
|
||||
|
||||
AccountSettings.helpers({
|
||||
allowEmailChange() {
|
||||
return AccountSettings.findOne('accounts-allowEmailChange').booleanValue;
|
||||
},
|
||||
allowUserNameChange() {
|
||||
return AccountSettings.findOne('accounts-allowUserNameChange').booleanValue;
|
||||
},
|
||||
allowUserDelete() {
|
||||
return AccountSettings.findOne('accounts-allowUserDelete').booleanValue;
|
||||
},
|
||||
});
|
||||
|
||||
export default AccountSettings;
|
||||
|
|
|
|||
283
models/boards.js
283
models/boards.js
|
|
@ -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
|
||||
|
|
@ -270,6 +278,7 @@ Boards.attachSchema(
|
|||
optional: true,
|
||||
defaultValue: null,
|
||||
},
|
||||
|
||||
subtasksDefaultListId: {
|
||||
/**
|
||||
* The default List ID assigned to subtasks.
|
||||
|
|
@ -278,6 +287,19 @@ Boards.attachSchema(
|
|||
optional: true,
|
||||
defaultValue: null,
|
||||
},
|
||||
|
||||
dateSettingsDefaultBoardId: {
|
||||
type: String,
|
||||
optional: true,
|
||||
defaultValue: null,
|
||||
},
|
||||
|
||||
dateSettingsDefaultListId: {
|
||||
type: String,
|
||||
optional: true,
|
||||
defaultValue: null,
|
||||
},
|
||||
|
||||
allowsSubtasks: {
|
||||
/**
|
||||
* Does the board allows subtasks?
|
||||
|
|
@ -285,6 +307,127 @@ Boards.attachSchema(
|
|||
type: Boolean,
|
||||
defaultValue: true,
|
||||
},
|
||||
|
||||
allowsAttachments: {
|
||||
/**
|
||||
* Does the board allows attachments?
|
||||
*/
|
||||
type: Boolean,
|
||||
defaultValue: true,
|
||||
},
|
||||
|
||||
allowsChecklists: {
|
||||
/**
|
||||
* Does the board allows checklists?
|
||||
*/
|
||||
type: Boolean,
|
||||
defaultValue: true,
|
||||
},
|
||||
|
||||
allowsComments: {
|
||||
/**
|
||||
* Does the board allows comments?
|
||||
*/
|
||||
type: Boolean,
|
||||
defaultValue: true,
|
||||
},
|
||||
|
||||
allowsDescriptionTitle: {
|
||||
/**
|
||||
* Does the board allows description title?
|
||||
*/
|
||||
type: Boolean,
|
||||
defaultValue: true,
|
||||
},
|
||||
|
||||
allowsDescriptionText: {
|
||||
/**
|
||||
* Does the board allows description text?
|
||||
*/
|
||||
type: Boolean,
|
||||
defaultValue: true,
|
||||
},
|
||||
|
||||
allowsActivities: {
|
||||
/**
|
||||
* Does the board allows comments?
|
||||
*/
|
||||
type: Boolean,
|
||||
defaultValue: true,
|
||||
},
|
||||
|
||||
allowsLabels: {
|
||||
/**
|
||||
* Does the board allows labels?
|
||||
*/
|
||||
type: Boolean,
|
||||
defaultValue: true,
|
||||
},
|
||||
|
||||
allowsAssignee: {
|
||||
/**
|
||||
* Does the board allows assignee?
|
||||
*/
|
||||
type: Boolean,
|
||||
defaultValue: true,
|
||||
},
|
||||
|
||||
allowsMembers: {
|
||||
/**
|
||||
* Does the board allows members?
|
||||
*/
|
||||
type: Boolean,
|
||||
defaultValue: true,
|
||||
},
|
||||
|
||||
allowsRequestedBy: {
|
||||
/**
|
||||
* Does the board allows requested by?
|
||||
*/
|
||||
type: Boolean,
|
||||
defaultValue: true,
|
||||
},
|
||||
|
||||
allowsAssignedBy: {
|
||||
/**
|
||||
* Does the board allows requested by?
|
||||
*/
|
||||
type: Boolean,
|
||||
defaultValue: true,
|
||||
},
|
||||
|
||||
allowsReceivedDate: {
|
||||
/**
|
||||
* Does the board allows received date?
|
||||
*/
|
||||
type: Boolean,
|
||||
defaultValue: true,
|
||||
},
|
||||
|
||||
allowsStartDate: {
|
||||
/**
|
||||
* Does the board allows start date?
|
||||
*/
|
||||
type: Boolean,
|
||||
defaultValue: true,
|
||||
},
|
||||
|
||||
allowsEndDate: {
|
||||
/**
|
||||
* Does the board allows end date?
|
||||
*/
|
||||
type: Boolean,
|
||||
defaultValue: true,
|
||||
},
|
||||
|
||||
allowsDueDate: {
|
||||
/**
|
||||
* Does the board allows due date?
|
||||
*/
|
||||
type: Boolean,
|
||||
defaultValue: true,
|
||||
},
|
||||
|
||||
presentParentTask: {
|
||||
/**
|
||||
* Controls how to present the parent task:
|
||||
|
|
@ -409,8 +552,12 @@ Boards.helpers({
|
|||
},
|
||||
|
||||
lists() {
|
||||
const enabled = Meteor.user().hasSortBy();
|
||||
return enabled ? this.newestLists() : this.draggableLists();
|
||||
//currentUser = Meteor.user();
|
||||
//if (currentUser) {
|
||||
// enabled = Meteor.user().hasSortBy();
|
||||
//}
|
||||
//return enabled ? this.newestLists() : this.draggableLists();
|
||||
return this.draggableLists();
|
||||
},
|
||||
|
||||
newestLists() {
|
||||
|
|
@ -534,6 +681,7 @@ Boards.helpers({
|
|||
isActive: true,
|
||||
isAdmin: false,
|
||||
isNoComments: true,
|
||||
isWorker: false,
|
||||
});
|
||||
},
|
||||
|
||||
|
|
@ -543,6 +691,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,
|
||||
});
|
||||
},
|
||||
|
||||
|
|
@ -686,6 +845,39 @@ Boards.helpers({
|
|||
return Boards.findOne(this.getDefaultSubtasksBoardId());
|
||||
},
|
||||
|
||||
//Date Settings option such as received date, start date and so on.
|
||||
getDefaultDateSettingsBoardId() {
|
||||
if (
|
||||
this.dateSettingsDefaultBoardId === null ||
|
||||
this.dateSettingsDefaultBoardId === undefined
|
||||
) {
|
||||
this.dateSettingsDefaultBoardId = Boards.insert({
|
||||
title: `^${this.title}^`,
|
||||
permission: this.permission,
|
||||
members: this.members,
|
||||
color: this.color,
|
||||
description: TAPi18n.__('default-dates-board', {
|
||||
board: this.title,
|
||||
}),
|
||||
});
|
||||
|
||||
Swimlanes.insert({
|
||||
title: TAPi18n.__('default'),
|
||||
boardId: this.dateSettingsDefaultBoardId,
|
||||
});
|
||||
Boards.update(this._id, {
|
||||
$set: {
|
||||
dateSettingsDefaultBoardId: this.dateSettingsDefaultBoardId,
|
||||
},
|
||||
});
|
||||
}
|
||||
return this.dateSettingsDefaultBoardId;
|
||||
},
|
||||
|
||||
getDefaultDateSettingsBoard() {
|
||||
return Boards.findOne(this.getDefaultDateSettingsBoardId());
|
||||
},
|
||||
|
||||
getDefaultSubtasksListId() {
|
||||
if (
|
||||
this.subtasksDefaultListId === null ||
|
||||
|
|
@ -704,6 +896,24 @@ Boards.helpers({
|
|||
return Lists.findOne(this.getDefaultSubtasksListId());
|
||||
},
|
||||
|
||||
getDefaultDateSettingsListId() {
|
||||
if (
|
||||
this.dateSettingsDefaultListId === null ||
|
||||
this.dateSettingsDefaultListId === undefined
|
||||
) {
|
||||
this.dateSettingsDefaultListId = Lists.insert({
|
||||
title: TAPi18n.__('queue'),
|
||||
boardId: this._id,
|
||||
});
|
||||
this.setDateSettingsDefaultListId(this.dateSettingsDefaultListId);
|
||||
}
|
||||
return this.dateSettingsDefaultListId;
|
||||
},
|
||||
|
||||
getDefaultDateSettingsList() {
|
||||
return Lists.findOne(this.getDefaultDateSettingsListId());
|
||||
},
|
||||
|
||||
getDefaultSwimline() {
|
||||
let result = Swimlanes.findOne({ boardId: this._id });
|
||||
if (result === undefined) {
|
||||
|
|
@ -845,6 +1055,7 @@ Boards.mutations({
|
|||
isActive: true,
|
||||
isNoComments: false,
|
||||
isCommentOnly: false,
|
||||
isWorker: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
@ -877,6 +1088,7 @@ Boards.mutations({
|
|||
isAdmin,
|
||||
isNoComments,
|
||||
isCommentOnly,
|
||||
isWorker,
|
||||
currentUserId = Meteor.userId(),
|
||||
) {
|
||||
const memberIndex = this.memberIndex(memberId);
|
||||
|
|
@ -890,6 +1102,7 @@ Boards.mutations({
|
|||
[`members.${memberIndex}.isAdmin`]: isAdmin,
|
||||
[`members.${memberIndex}.isNoComments`]: isNoComments,
|
||||
[`members.${memberIndex}.isCommentOnly`]: isCommentOnly,
|
||||
[`members.${memberIndex}.isWorker`]: isWorker,
|
||||
},
|
||||
};
|
||||
},
|
||||
|
|
@ -898,6 +1111,66 @@ Boards.mutations({
|
|||
return { $set: { allowsSubtasks } };
|
||||
},
|
||||
|
||||
setAllowsMembers(allowsMembers) {
|
||||
return { $set: { allowsMembers } };
|
||||
},
|
||||
|
||||
setAllowsChecklists(allowsChecklists) {
|
||||
return { $set: { allowsChecklists } };
|
||||
},
|
||||
|
||||
setAllowsAssignee(allowsAssignee) {
|
||||
return { $set: { allowsAssignee } };
|
||||
},
|
||||
|
||||
setAllowsAssignedBy(allowsAssignedBy) {
|
||||
return { $set: { allowsAssignedBy } };
|
||||
},
|
||||
|
||||
setAllowsRequestedBy(allowsRequestedBy) {
|
||||
return { $set: { allowsRequestedBy } };
|
||||
},
|
||||
|
||||
setAllowsAttachments(allowsAttachments) {
|
||||
return { $set: { allowsAttachments } };
|
||||
},
|
||||
|
||||
setAllowsLabels(allowsLabels) {
|
||||
return { $set: { allowsLabels } };
|
||||
},
|
||||
|
||||
setAllowsComments(allowsComments) {
|
||||
return { $set: { allowsComments } };
|
||||
},
|
||||
|
||||
setAllowsDescriptionTitle(allowsDescriptionTitle) {
|
||||
return { $set: { allowsDescriptionTitle } };
|
||||
},
|
||||
|
||||
setAllowsDescriptionText(allowsDescriptionText) {
|
||||
return { $set: { allowsDescriptionText } };
|
||||
},
|
||||
|
||||
setAllowsActivities(allowsActivities) {
|
||||
return { $set: { allowsActivities } };
|
||||
},
|
||||
|
||||
setAllowsReceivedDate(allowsReceivedDate) {
|
||||
return { $set: { allowsReceivedDate } };
|
||||
},
|
||||
|
||||
setAllowsStartDate(allowsStartDate) {
|
||||
return { $set: { allowsStartDate } };
|
||||
},
|
||||
|
||||
setAllowsEndDate(allowsEndDate) {
|
||||
return { $set: { allowsEndDate } };
|
||||
},
|
||||
|
||||
setAllowsDueDate(allowsDueDate) {
|
||||
return { $set: { allowsDueDate } };
|
||||
},
|
||||
|
||||
setSubtasksDefaultBoardId(subtasksDefaultBoardId) {
|
||||
return { $set: { subtasksDefaultBoardId } };
|
||||
},
|
||||
|
|
@ -1277,6 +1550,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
|
||||
|
|
@ -1296,6 +1570,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',
|
||||
|
|
@ -1399,6 +1674,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,
|
||||
|
|
@ -1407,7 +1683,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) {
|
||||
|
|
@ -1422,6 +1698,7 @@ if (Meteor.isServer) {
|
|||
isTrue(isAdmin),
|
||||
isTrue(isNoComments),
|
||||
isTrue(isCommentOnly),
|
||||
isTrue(isWorker),
|
||||
req.userId,
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -205,7 +205,8 @@ Cards.attachSchema(
|
|||
},
|
||||
assignees: {
|
||||
/**
|
||||
* who assignees of the card (user IDs)
|
||||
* who is assignee of the card (user ID),
|
||||
* maximum one ID of assignee in array.
|
||||
*/
|
||||
type: [String],
|
||||
optional: true,
|
||||
|
|
@ -1996,15 +1997,22 @@ if (Meteor.isServer) {
|
|||
* @param {string} description the description of the new card
|
||||
* @param {string} swimlaneId the swimlane ID of the new card
|
||||
* @param {string} [members] the member IDs list of the new card
|
||||
* @param {string} [assignees] the assignee IDs list of the new card
|
||||
* @param {string} [assignees] the array of maximum one ID of assignee of the new card
|
||||
* @return_type {_id: string}
|
||||
*/
|
||||
JsonRoutes.add('POST', '/api/boards/:boardId/lists/:listId/cards', function(
|
||||
req,
|
||||
res,
|
||||
) {
|
||||
Authentication.checkUserId(req.userId);
|
||||
// Check user is logged in
|
||||
Authentication.checkLoggedIn(req.userId);
|
||||
const paramBoardId = req.params.boardId;
|
||||
// Check user has permission to add card to the board
|
||||
const board = Boards.findOne({
|
||||
_id: paramBoardId,
|
||||
});
|
||||
const addPermission = allowIsBoardMemberCommentOnly(req.userId, board);
|
||||
Authentication.checkAdminOrCondition(req.userId, addPermission);
|
||||
const paramListId = req.params.listId;
|
||||
const paramParentId = req.params.parentId;
|
||||
const currentCards = Cards.find(
|
||||
|
|
@ -2082,7 +2090,7 @@ if (Meteor.isServer) {
|
|||
* @param {string} [labelIds] the new list of label IDs attached to the card
|
||||
* @param {string} [swimlaneId] the new swimlane ID of the card
|
||||
* @param {string} [members] the new list of member IDs attached to the card
|
||||
* @param {string} [assignees] the new list of assignee IDs attached to the card
|
||||
* @param {string} [assignees] the array of maximum one ID of assignee attached to the card
|
||||
* @param {string} [requestedBy] the new requestedBy field of the card
|
||||
* @param {string} [assignedBy] the new assignedBy field of the card
|
||||
* @param {string} [receivedAt] the new receivedAt field of the card
|
||||
|
|
|
|||
|
|
@ -283,8 +283,15 @@ if (Meteor.isServer) {
|
|||
'POST',
|
||||
'/api/boards/:boardId/cards/:cardId/checklists',
|
||||
function(req, res) {
|
||||
Authentication.checkUserId(req.userId);
|
||||
|
||||
// Check user is logged in
|
||||
Authentication.checkLoggedIn(req.userId);
|
||||
const paramBoardId = req.params.boardId;
|
||||
// Check user has permission to add checklist to the card
|
||||
const board = Boards.findOne({
|
||||
_id: paramBoardId,
|
||||
});
|
||||
const addPermission = allowIsBoardMemberCommentOnly(req.userId, board);
|
||||
Authentication.checkAdminOrCondition(req.userId, addPermission);
|
||||
const paramCardId = req.params.cardId;
|
||||
const id = Checklists.insert({
|
||||
title: req.body.title,
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ if (Meteor.isServer) {
|
|||
JsonRoutes.add('get', '/api/boards/:boardId/export', function(req, res) {
|
||||
const boardId = req.params.boardId;
|
||||
let user = null;
|
||||
|
||||
const loginToken = req.query.authToken;
|
||||
if (loginToken) {
|
||||
const hashToken = Accounts._hashLoginToken(loginToken);
|
||||
|
|
@ -35,7 +34,6 @@ if (Meteor.isServer) {
|
|||
Authentication.checkUserId(req.userId);
|
||||
user = Users.findOne({ _id: req.userId, isAdmin: true });
|
||||
}
|
||||
|
||||
const exporter = new Exporter(boardId);
|
||||
if (exporter.canExport(user)) {
|
||||
JsonRoutes.sendResult(res, {
|
||||
|
|
@ -137,8 +135,11 @@ export class Exporter {
|
|||
|
||||
// [Old] for attachments we only export IDs and absolute url to original doc
|
||||
// [New] Encode attachment to base64
|
||||
|
||||
const getBase64Data = function(doc, callback) {
|
||||
let buffer = new Buffer(0);
|
||||
let buffer = Buffer.allocUnsafe(0);
|
||||
buffer.fill(0);
|
||||
|
||||
// callback has the form function (err, res) {}
|
||||
const tmpFile = path.join(
|
||||
os.tmpdir(),
|
||||
|
|
@ -149,14 +150,16 @@ export class Exporter {
|
|||
readStream.on('data', function(chunk) {
|
||||
buffer = Buffer.concat([buffer, chunk]);
|
||||
});
|
||||
|
||||
readStream.on('error', function(err) {
|
||||
callback(err, null);
|
||||
callback(null, null);
|
||||
});
|
||||
readStream.on('end', function() {
|
||||
// done
|
||||
fs.unlink(tmpFile, () => {
|
||||
//ignored
|
||||
});
|
||||
|
||||
callback(null, buffer.toString('base64'));
|
||||
});
|
||||
readStream.pipe(tmpWriteable);
|
||||
|
|
@ -165,11 +168,14 @@ export class Exporter {
|
|||
result.attachments = Attachments.find({ 'meta.boardId': byBoard.boardId })
|
||||
.fetch()
|
||||
.map(attachment => {
|
||||
let filebase64 = null;
|
||||
filebase64 = getBase64DataSync(attachment);
|
||||
|
||||
return {
|
||||
_id: attachment._id,
|
||||
cardId: attachment.cardId,
|
||||
// url: FlowRouter.url(attachment.url()),
|
||||
file: getBase64DataSync(attachment),
|
||||
//url: FlowRouter.url(attachment.url()),
|
||||
file: filebase64,
|
||||
name: attachment.original.name,
|
||||
type: attachment.original.type,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -174,8 +174,12 @@ Swimlanes.helpers({
|
|||
},
|
||||
|
||||
lists() {
|
||||
const enabled = Meteor.user().hasSortBy();
|
||||
return enabled ? this.newestLists() : this.draggableLists();
|
||||
//currentUser = Meteor.user();
|
||||
//if (currentUser) {
|
||||
// enabled = Meteor.user().hasSortBy();
|
||||
//}
|
||||
//return enabled ? this.newestLists() : this.draggableLists();
|
||||
return this.draggableLists();
|
||||
},
|
||||
newestLists() {
|
||||
// sorted lists from newest to the oldest, by its creation date or its cards' last modification date
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -443,7 +443,7 @@ export class WekanCreator {
|
|||
} else if (att.file) {
|
||||
// FIXME: Change to new file library
|
||||
file.attachData(
|
||||
new Buffer(att.file, 'base64'),
|
||||
Buffer.from(att.file, 'base64'),
|
||||
{
|
||||
type: att.type,
|
||||
},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue