mirror of
https://github.com/wekan/wekan.git
synced 2025-04-22 21:17:18 -04:00
RESTAPI: Add some JSDoc
So we can have a decent REST API documentation generated.
This commit is contained in:
parent
49d3eb5a3f
commit
ff467402c0
11 changed files with 994 additions and 11 deletions
176
models/boards.js
176
models/boards.js
|
@ -1,10 +1,19 @@
|
|||
Boards = new Mongo.Collection('boards');
|
||||
|
||||
/**
|
||||
* This is a Board.
|
||||
*/
|
||||
Boards.attachSchema(new SimpleSchema({
|
||||
title: {
|
||||
/**
|
||||
* The title of the board
|
||||
*/
|
||||
type: String,
|
||||
},
|
||||
slug: {
|
||||
/**
|
||||
* The title slugified.
|
||||
*/
|
||||
type: String,
|
||||
autoValue() { // eslint-disable-line consistent-return
|
||||
// XXX We need to improve slug management. Only the id should be necessary
|
||||
|
@ -24,6 +33,9 @@ Boards.attachSchema(new SimpleSchema({
|
|||
},
|
||||
},
|
||||
archived: {
|
||||
/**
|
||||
* Is the board archived?
|
||||
*/
|
||||
type: Boolean,
|
||||
autoValue() { // eslint-disable-line consistent-return
|
||||
if (this.isInsert && !this.isSet) {
|
||||
|
@ -32,6 +44,9 @@ Boards.attachSchema(new SimpleSchema({
|
|||
},
|
||||
},
|
||||
createdAt: {
|
||||
/**
|
||||
* Creation time of the board
|
||||
*/
|
||||
type: Date,
|
||||
autoValue() { // eslint-disable-line consistent-return
|
||||
if (this.isInsert) {
|
||||
|
@ -43,6 +58,9 @@ Boards.attachSchema(new SimpleSchema({
|
|||
},
|
||||
// XXX Inconsistent field naming
|
||||
modifiedAt: {
|
||||
/**
|
||||
* Last modification time of the board
|
||||
*/
|
||||
type: Date,
|
||||
optional: true,
|
||||
autoValue() { // eslint-disable-line consistent-return
|
||||
|
@ -55,6 +73,9 @@ Boards.attachSchema(new SimpleSchema({
|
|||
},
|
||||
// De-normalized number of users that have starred this board
|
||||
stars: {
|
||||
/**
|
||||
* How many stars the board has
|
||||
*/
|
||||
type: Number,
|
||||
autoValue() { // eslint-disable-line consistent-return
|
||||
if (this.isInsert) {
|
||||
|
@ -64,6 +85,9 @@ Boards.attachSchema(new SimpleSchema({
|
|||
},
|
||||
// De-normalized label system
|
||||
'labels': {
|
||||
/**
|
||||
* List of labels attached to a board
|
||||
*/
|
||||
type: [Object],
|
||||
autoValue() { // eslint-disable-line consistent-return
|
||||
if (this.isInsert && !this.isSet) {
|
||||
|
@ -78,6 +102,9 @@ Boards.attachSchema(new SimpleSchema({
|
|||
},
|
||||
},
|
||||
'labels.$._id': {
|
||||
/**
|
||||
* Unique id of a label
|
||||
*/
|
||||
// We don't specify that this field must be unique in the board because that
|
||||
// will cause performance penalties and is not necessary since this field is
|
||||
// always set on the server.
|
||||
|
@ -86,10 +113,22 @@ Boards.attachSchema(new SimpleSchema({
|
|||
type: String,
|
||||
},
|
||||
'labels.$.name': {
|
||||
/**
|
||||
* Name of a label
|
||||
*/
|
||||
type: String,
|
||||
optional: true,
|
||||
},
|
||||
'labels.$.color': {
|
||||
/**
|
||||
* 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,
|
||||
allowedValues: [
|
||||
'green', 'yellow', 'orange', 'red', 'purple',
|
||||
|
@ -103,6 +142,9 @@ Boards.attachSchema(new SimpleSchema({
|
|||
// documents like de-normalized meta-data (the date the member joined the
|
||||
// board, the number of contributions, etc.).
|
||||
'members': {
|
||||
/**
|
||||
* List of members of a board
|
||||
*/
|
||||
type: [Object],
|
||||
autoValue() { // eslint-disable-line consistent-return
|
||||
if (this.isInsert && !this.isSet) {
|
||||
|
@ -117,27 +159,48 @@ Boards.attachSchema(new SimpleSchema({
|
|||
},
|
||||
},
|
||||
'members.$.userId': {
|
||||
/**
|
||||
* The uniq ID of the member
|
||||
*/
|
||||
type: String,
|
||||
},
|
||||
'members.$.isAdmin': {
|
||||
/**
|
||||
* Is the member an admin of the board?
|
||||
*/
|
||||
type: Boolean,
|
||||
},
|
||||
'members.$.isActive': {
|
||||
/**
|
||||
* Is the member active?
|
||||
*/
|
||||
type: Boolean,
|
||||
},
|
||||
'members.$.isNoComments': {
|
||||
/**
|
||||
* Is the member not allowed to make comments
|
||||
*/
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
},
|
||||
'members.$.isCommentOnly': {
|
||||
/**
|
||||
* Is the member only allowed to comment on the board
|
||||
*/
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
},
|
||||
permission: {
|
||||
/**
|
||||
* visibility of the board
|
||||
*/
|
||||
type: String,
|
||||
allowedValues: ['public', 'private'],
|
||||
},
|
||||
color: {
|
||||
/**
|
||||
* The color of the board.
|
||||
*/
|
||||
type: String,
|
||||
allowedValues: [
|
||||
'belize',
|
||||
|
@ -154,24 +217,45 @@ Boards.attachSchema(new SimpleSchema({
|
|||
},
|
||||
},
|
||||
description: {
|
||||
/**
|
||||
* The description of the board
|
||||
*/
|
||||
type: String,
|
||||
optional: true,
|
||||
},
|
||||
subtasksDefaultBoardId: {
|
||||
/**
|
||||
* The default board ID assigned to subtasks.
|
||||
*/
|
||||
type: String,
|
||||
optional: true,
|
||||
defaultValue: null,
|
||||
},
|
||||
subtasksDefaultListId: {
|
||||
/**
|
||||
* The default List ID assigned to subtasks.
|
||||
*/
|
||||
type: String,
|
||||
optional: true,
|
||||
defaultValue: null,
|
||||
},
|
||||
allowsSubtasks: {
|
||||
/**
|
||||
* Does the board allows subtasks?
|
||||
*/
|
||||
type: Boolean,
|
||||
defaultValue: true,
|
||||
},
|
||||
presentParentTask: {
|
||||
/**
|
||||
* 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,
|
||||
allowedValues: [
|
||||
'prefix-with-full-path',
|
||||
|
@ -184,23 +268,38 @@ Boards.attachSchema(new SimpleSchema({
|
|||
defaultValue: 'no-parent',
|
||||
},
|
||||
startAt: {
|
||||
/**
|
||||
* Starting date of the board.
|
||||
*/
|
||||
type: Date,
|
||||
optional: true,
|
||||
},
|
||||
dueAt: {
|
||||
/**
|
||||
* Due date of the board.
|
||||
*/
|
||||
type: Date,
|
||||
optional: true,
|
||||
},
|
||||
endAt: {
|
||||
/**
|
||||
* End date of the board.
|
||||
*/
|
||||
type: Date,
|
||||
optional: true,
|
||||
},
|
||||
spentTime: {
|
||||
/**
|
||||
* Time spent in the board.
|
||||
*/
|
||||
type: Number,
|
||||
decimal: true,
|
||||
optional: true,
|
||||
},
|
||||
isOvertime: {
|
||||
/**
|
||||
* Is the board overtimed?
|
||||
*/
|
||||
type: Boolean,
|
||||
defaultValue: false,
|
||||
optional: true,
|
||||
|
@ -774,6 +873,14 @@ if (Meteor.isServer) {
|
|||
|
||||
//BOARDS REST API
|
||||
if (Meteor.isServer) {
|
||||
/**
|
||||
* @operation get_boards_from_user
|
||||
* @summary Get all boards attached to a user
|
||||
*
|
||||
* @param {string} userId the ID of the user to retrieve the data
|
||||
* @return_type [{_id: string,
|
||||
title: string}]
|
||||
*/
|
||||
JsonRoutes.add('GET', '/api/users/:userId/boards', function (req, res) {
|
||||
try {
|
||||
Authentication.checkLoggedIn(req.userId);
|
||||
|
@ -804,6 +911,13 @@ if (Meteor.isServer) {
|
|||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @operation get_public_boards
|
||||
* @summary Get all public boards
|
||||
*
|
||||
* @return_type [{_id: string,
|
||||
title: string}]
|
||||
*/
|
||||
JsonRoutes.add('GET', '/api/boards', function (req, res) {
|
||||
try {
|
||||
Authentication.checkUserId(req.userId);
|
||||
|
@ -825,6 +939,13 @@ if (Meteor.isServer) {
|
|||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @operation get_board
|
||||
* @summary Get the board with that particular ID
|
||||
*
|
||||
* @param {string} boardId the ID of the board to retrieve the data
|
||||
* @return_type Boards
|
||||
*/
|
||||
JsonRoutes.add('GET', '/api/boards/:boardId', function (req, res) {
|
||||
try {
|
||||
const id = req.params.boardId;
|
||||
|
@ -843,6 +964,31 @@ if (Meteor.isServer) {
|
|||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @operation 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`, `midnight`:
|
||||
*
|
||||
* <img src="https://wekan.github.io/board-colors.png" width="40%" alt="Wekan logo" />
|
||||
*
|
||||
* @param {string} title the new title of the board
|
||||
* @param {string} owner "ABCDE12345" <= User ID in Wekan.
|
||||
* (Not username or email)
|
||||
* @param {boolean} [isAdmin] is the owner an admin of the board (default true)
|
||||
* @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 {string} [permission] "private" board <== Set to "public" if you
|
||||
* want public Wekan board
|
||||
* @param {string} [color] the color of the board
|
||||
*
|
||||
* @return_type {_id: string,
|
||||
defaultSwimlaneId: string}
|
||||
*/
|
||||
JsonRoutes.add('POST', '/api/boards', function (req, res) {
|
||||
try {
|
||||
Authentication.checkUserId(req.userId);
|
||||
|
@ -880,6 +1026,12 @@ if (Meteor.isServer) {
|
|||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @operation delete_board
|
||||
* @summary Delete a board
|
||||
*
|
||||
* @param {string} boardId the ID of the board
|
||||
*/
|
||||
JsonRoutes.add('DELETE', '/api/boards/:boardId', function (req, res) {
|
||||
try {
|
||||
Authentication.checkUserId(req.userId);
|
||||
|
@ -900,6 +1052,19 @@ if (Meteor.isServer) {
|
|||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @operation 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.
|
||||
*
|
||||
* @param {string} boardId the board
|
||||
* @param {string} color the color of the new label
|
||||
* @param {string} name the name of the new label
|
||||
*
|
||||
* @return_type string
|
||||
*/
|
||||
JsonRoutes.add('PUT', '/api/boards/:boardId/labels', function (req, res) {
|
||||
Authentication.checkUserId(req.userId);
|
||||
const id = req.params.boardId;
|
||||
|
@ -929,6 +1094,17 @@ if (Meteor.isServer) {
|
|||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @operation set_board_member_permission
|
||||
* @tag Users
|
||||
* @summary Change the permission of a member of a board
|
||||
*
|
||||
* @param {string} boardId the ID of the board that we are changing
|
||||
* @param {string} memberId the ID of the user to change permissions
|
||||
* @param {boolean} isAdmin admin capability
|
||||
* @param {boolean} isNoComments NoComments capability
|
||||
* @param {boolean} isCommentOnly CommentsOnly capability
|
||||
*/
|
||||
JsonRoutes.add('POST', '/api/boards/:boardId/members/:memberId', function (req, res) {
|
||||
try {
|
||||
const boardId = req.params.boardId;
|
||||
|
|
|
@ -1,19 +1,34 @@
|
|||
CardComments = new Mongo.Collection('card_comments');
|
||||
|
||||
/**
|
||||
* A comment on a card
|
||||
*/
|
||||
CardComments.attachSchema(new SimpleSchema({
|
||||
boardId: {
|
||||
/**
|
||||
* the board ID
|
||||
*/
|
||||
type: String,
|
||||
},
|
||||
cardId: {
|
||||
/**
|
||||
* the card ID
|
||||
*/
|
||||
type: String,
|
||||
},
|
||||
// XXX Rename in `content`? `text` is a bit vague...
|
||||
text: {
|
||||
/**
|
||||
* the text of the comment
|
||||
*/
|
||||
type: String,
|
||||
},
|
||||
// XXX We probably don't need this information here, since we already have it
|
||||
// in the associated comment creation activity
|
||||
createdAt: {
|
||||
/**
|
||||
* when was the comment created
|
||||
*/
|
||||
type: Date,
|
||||
denyUpdate: false,
|
||||
autoValue() { // eslint-disable-line consistent-return
|
||||
|
@ -26,6 +41,9 @@ CardComments.attachSchema(new SimpleSchema({
|
|||
},
|
||||
// XXX Should probably be called `authorId`
|
||||
userId: {
|
||||
/**
|
||||
* the author ID of the comment
|
||||
*/
|
||||
type: String,
|
||||
autoValue() { // eslint-disable-line consistent-return
|
||||
if (this.isInsert && !this.isSet) {
|
||||
|
@ -87,6 +105,16 @@ if (Meteor.isServer) {
|
|||
|
||||
//CARD COMMENT REST API
|
||||
if (Meteor.isServer) {
|
||||
/**
|
||||
* @operation get_all_comments
|
||||
* @summary Get all comments attached to a card
|
||||
*
|
||||
* @param {string} boardId the board ID of the card
|
||||
* @param {string} cardId the ID of the card
|
||||
* @return_type [{_id: string,
|
||||
* comment: string,
|
||||
* authorId: string}]
|
||||
*/
|
||||
JsonRoutes.add('GET', '/api/boards/:boardId/cards/:cardId/comments', function (req, res) {
|
||||
try {
|
||||
Authentication.checkUserId( req.userId);
|
||||
|
@ -111,6 +139,15 @@ if (Meteor.isServer) {
|
|||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @operation get_comment
|
||||
* @summary Get a comment on a card
|
||||
*
|
||||
* @param {string} boardId the board ID of the card
|
||||
* @param {string} cardId the ID of the card
|
||||
* @param {string} commentId the ID of the comment to retrieve
|
||||
* @return_type CardComments
|
||||
*/
|
||||
JsonRoutes.add('GET', '/api/boards/:boardId/cards/:cardId/comments/:commentId', function (req, res) {
|
||||
try {
|
||||
Authentication.checkUserId( req.userId);
|
||||
|
@ -130,6 +167,16 @@ if (Meteor.isServer) {
|
|||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @operation new_comment
|
||||
* @summary Add a comment on a card
|
||||
*
|
||||
* @param {string} boardId the board ID of the card
|
||||
* @param {string} cardId the ID of the card
|
||||
* @param {string} authorId the user who 'posted' the comment
|
||||
* @param {string} text the content of the comment
|
||||
* @return_type {_id: string}
|
||||
*/
|
||||
JsonRoutes.add('POST', '/api/boards/:boardId/cards/:cardId/comments', function (req, res) {
|
||||
try {
|
||||
Authentication.checkUserId( req.userId);
|
||||
|
@ -160,6 +207,15 @@ if (Meteor.isServer) {
|
|||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @operation delete_comment
|
||||
* @summary Delete a comment on a card
|
||||
*
|
||||
* @param {string} boardId the board ID of the card
|
||||
* @param {string} cardId the ID of the card
|
||||
* @param {string} commentId the ID of the comment to delete
|
||||
* @return_type {_id: string}
|
||||
*/
|
||||
JsonRoutes.add('DELETE', '/api/boards/:boardId/cards/:cardId/comments/:commentId', function (req, res) {
|
||||
try {
|
||||
Authentication.checkUserId( req.userId);
|
||||
|
|
169
models/cards.js
169
models/cards.js
|
@ -5,11 +5,17 @@ Cards = new Mongo.Collection('cards');
|
|||
// of comments just to display the number of them in the board view.
|
||||
Cards.attachSchema(new SimpleSchema({
|
||||
title: {
|
||||
/**
|
||||
* the title of the card
|
||||
*/
|
||||
type: String,
|
||||
optional: true,
|
||||
defaultValue: '',
|
||||
},
|
||||
archived: {
|
||||
/**
|
||||
* is the card archived
|
||||
*/
|
||||
type: Boolean,
|
||||
autoValue() { // eslint-disable-line consistent-return
|
||||
if (this.isInsert && !this.isSet) {
|
||||
|
@ -18,33 +24,51 @@ Cards.attachSchema(new SimpleSchema({
|
|||
},
|
||||
},
|
||||
parentId: {
|
||||
/**
|
||||
* ID of the parent card
|
||||
*/
|
||||
type: String,
|
||||
optional: true,
|
||||
defaultValue: '',
|
||||
},
|
||||
listId: {
|
||||
/**
|
||||
* List ID where the card is
|
||||
*/
|
||||
type: String,
|
||||
optional: true,
|
||||
defaultValue: '',
|
||||
},
|
||||
swimlaneId: {
|
||||
/**
|
||||
* Swimlane ID where the card is
|
||||
*/
|
||||
type: String,
|
||||
},
|
||||
// The system could work without this `boardId` information (we could deduce
|
||||
// the board identifier from the card), but it would make the system more
|
||||
// difficult to manage and less efficient.
|
||||
boardId: {
|
||||
/**
|
||||
* Board ID of the card
|
||||
*/
|
||||
type: String,
|
||||
optional: true,
|
||||
defaultValue: '',
|
||||
},
|
||||
coverId: {
|
||||
/**
|
||||
* Cover ID of the card
|
||||
*/
|
||||
type: String,
|
||||
optional: true,
|
||||
defaultValue: '',
|
||||
|
||||
},
|
||||
createdAt: {
|
||||
/**
|
||||
* creation date
|
||||
*/
|
||||
type: Date,
|
||||
autoValue() { // eslint-disable-line consistent-return
|
||||
if (this.isInsert) {
|
||||
|
@ -55,6 +79,9 @@ Cards.attachSchema(new SimpleSchema({
|
|||
},
|
||||
},
|
||||
customFields: {
|
||||
/**
|
||||
* list of custom fields
|
||||
*/
|
||||
type: [Object],
|
||||
optional: true,
|
||||
defaultValue: [],
|
||||
|
@ -62,11 +89,17 @@ Cards.attachSchema(new SimpleSchema({
|
|||
'customFields.$': {
|
||||
type: new SimpleSchema({
|
||||
_id: {
|
||||
/**
|
||||
* the ID of the related custom field
|
||||
*/
|
||||
type: String,
|
||||
optional: true,
|
||||
defaultValue: '',
|
||||
},
|
||||
value: {
|
||||
/**
|
||||
* value attached to the custom field
|
||||
*/
|
||||
type: Match.OneOf(String, Number, Boolean, Date),
|
||||
optional: true,
|
||||
defaultValue: '',
|
||||
|
@ -74,59 +107,95 @@ Cards.attachSchema(new SimpleSchema({
|
|||
}),
|
||||
},
|
||||
dateLastActivity: {
|
||||
/**
|
||||
* Date of last activity
|
||||
*/
|
||||
type: Date,
|
||||
autoValue() {
|
||||
return new Date();
|
||||
},
|
||||
},
|
||||
description: {
|
||||
/**
|
||||
* description of the card
|
||||
*/
|
||||
type: String,
|
||||
optional: true,
|
||||
defaultValue: '',
|
||||
},
|
||||
requestedBy: {
|
||||
/**
|
||||
* who requested the card (ID of the user)
|
||||
*/
|
||||
type: String,
|
||||
optional: true,
|
||||
defaultValue: '',
|
||||
},
|
||||
assignedBy: {
|
||||
/**
|
||||
* who assigned the card (ID of the user)
|
||||
*/
|
||||
type: String,
|
||||
optional: true,
|
||||
defaultValue: '',
|
||||
},
|
||||
labelIds: {
|
||||
/**
|
||||
* list of labels ID the card has
|
||||
*/
|
||||
type: [String],
|
||||
optional: true,
|
||||
defaultValue: [],
|
||||
},
|
||||
members: {
|
||||
/**
|
||||
* list of members (user IDs)
|
||||
*/
|
||||
type: [String],
|
||||
optional: true,
|
||||
defaultValue: [],
|
||||
},
|
||||
receivedAt: {
|
||||
/**
|
||||
* Date the card was received
|
||||
*/
|
||||
type: Date,
|
||||
optional: true,
|
||||
},
|
||||
startAt: {
|
||||
/**
|
||||
* Date the card was started to be worked on
|
||||
*/
|
||||
type: Date,
|
||||
optional: true,
|
||||
},
|
||||
dueAt: {
|
||||
/**
|
||||
* Date the card is due
|
||||
*/
|
||||
type: Date,
|
||||
optional: true,
|
||||
},
|
||||
endAt: {
|
||||
/**
|
||||
* Date the card ended
|
||||
*/
|
||||
type: Date,
|
||||
optional: true,
|
||||
},
|
||||
spentTime: {
|
||||
/**
|
||||
* How much time has been spent on this
|
||||
*/
|
||||
type: Number,
|
||||
decimal: true,
|
||||
optional: true,
|
||||
defaultValue: 0,
|
||||
},
|
||||
isOvertime: {
|
||||
/**
|
||||
* is the card over time?
|
||||
*/
|
||||
type: Boolean,
|
||||
defaultValue: false,
|
||||
optional: true,
|
||||
|
@ -134,6 +203,9 @@ Cards.attachSchema(new SimpleSchema({
|
|||
// XXX Should probably be called `authorId`. Is it even needed since we have
|
||||
// the `members` field?
|
||||
userId: {
|
||||
/**
|
||||
* user ID of the author of the card
|
||||
*/
|
||||
type: String,
|
||||
autoValue() { // eslint-disable-line consistent-return
|
||||
if (this.isInsert && !this.isSet) {
|
||||
|
@ -142,21 +214,33 @@ Cards.attachSchema(new SimpleSchema({
|
|||
},
|
||||
},
|
||||
sort: {
|
||||
/**
|
||||
* Sort value
|
||||
*/
|
||||
type: Number,
|
||||
decimal: true,
|
||||
defaultValue: '',
|
||||
},
|
||||
subtaskSort: {
|
||||
/**
|
||||
* subtask sort value
|
||||
*/
|
||||
type: Number,
|
||||
decimal: true,
|
||||
defaultValue: -1,
|
||||
optional: true,
|
||||
},
|
||||
type: {
|
||||
/**
|
||||
* type of the card
|
||||
*/
|
||||
type: String,
|
||||
defaultValue: '',
|
||||
},
|
||||
linkedId: {
|
||||
/**
|
||||
* ID of the linked card
|
||||
*/
|
||||
type: String,
|
||||
optional: true,
|
||||
defaultValue: '',
|
||||
|
@ -1309,6 +1393,17 @@ if (Meteor.isServer) {
|
|||
}
|
||||
//SWIMLANES REST API
|
||||
if (Meteor.isServer) {
|
||||
/**
|
||||
* @operation get_swimlane_cards
|
||||
* @summary get all cards attached to a swimlane
|
||||
*
|
||||
* @param {string} boardId the board ID
|
||||
* @param {string} swimlaneId the swimlane ID
|
||||
* @return_type [{_id: string,
|
||||
* title: string,
|
||||
* description: string,
|
||||
* listId: string}]
|
||||
*/
|
||||
JsonRoutes.add('GET', '/api/boards/:boardId/swimlanes/:swimlaneId/cards', function(req, res) {
|
||||
const paramBoardId = req.params.boardId;
|
||||
const paramSwimlaneId = req.params.swimlaneId;
|
||||
|
@ -1332,6 +1427,16 @@ if (Meteor.isServer) {
|
|||
}
|
||||
//LISTS REST API
|
||||
if (Meteor.isServer) {
|
||||
/**
|
||||
* @operation get_all_cards
|
||||
* @summary get all cards attached to a list
|
||||
*
|
||||
* @param {string} boardId the board ID
|
||||
* @param {string} listId the list ID
|
||||
* @return_type [{_id: string,
|
||||
* title: string,
|
||||
* description: string}]
|
||||
*/
|
||||
JsonRoutes.add('GET', '/api/boards/:boardId/lists/:listId/cards', function(req, res) {
|
||||
const paramBoardId = req.params.boardId;
|
||||
const paramListId = req.params.listId;
|
||||
|
@ -1352,6 +1457,15 @@ if (Meteor.isServer) {
|
|||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* @operation get_card
|
||||
* @summary get a card
|
||||
*
|
||||
* @param {string} boardId the board ID
|
||||
* @param {string} listId the list ID of the card
|
||||
* @param {string} cardId the card ID
|
||||
* @return_type Cards
|
||||
*/
|
||||
JsonRoutes.add('GET', '/api/boards/:boardId/lists/:listId/cards/:cardId', function(req, res) {
|
||||
const paramBoardId = req.params.boardId;
|
||||
const paramListId = req.params.listId;
|
||||
|
@ -1368,6 +1482,19 @@ if (Meteor.isServer) {
|
|||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* @operation new_card
|
||||
* @summary creates a new card
|
||||
*
|
||||
* @param {string} boardId the board ID of the new card
|
||||
* @param {string} listId the list ID of the new card
|
||||
* @param {string} authorID the user ID of the person owning the card
|
||||
* @param {string} title the title of the new card
|
||||
* @param {string} description the description of the new card
|
||||
* @param {string} swimlaneId the swimlane ID of the new card
|
||||
* @param {string} [members] the member IDs list of the new card
|
||||
* @return_type {_id: string}
|
||||
*/
|
||||
JsonRoutes.add('POST', '/api/boards/:boardId/lists/:listId/cards', function(req, res) {
|
||||
Authentication.checkUserId(req.userId);
|
||||
const paramBoardId = req.params.boardId;
|
||||
|
@ -1406,6 +1533,36 @@ if (Meteor.isServer) {
|
|||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* Note for the JSDoc:
|
||||
* 'list' will be interpreted as the path parameter
|
||||
* 'listID' will be interpreted as the body parameter
|
||||
*/
|
||||
/**
|
||||
* @operation edit_card
|
||||
* @summary edit fields in a card
|
||||
*
|
||||
* @param {string} boardId the board ID of the card
|
||||
* @param {string} list the list ID of the card
|
||||
* @param {string} cardId the ID of the card
|
||||
* @param {string} [title] the new title of the card
|
||||
* @param {string} [listId] the new list ID of the card (move operation)
|
||||
* @param {string} [description] the new description of the card
|
||||
* @param {string} [authorId] change the owner of the card
|
||||
* @param {string} [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} [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
|
||||
* @param {string} [assignBy] the new assignBy field of the card
|
||||
* @param {string} [startAt] the new startAt field of the card
|
||||
* @param {string} [dueAt] the new dueAt field of the card
|
||||
* @param {string} [endAt] the new endAt field of the card
|
||||
* @param {string} [spentTime] the new spentTime field of the card
|
||||
* @param {boolean} [isOverTime] the new isOverTime field of the card
|
||||
* @param {string} [customFields] the new customFields value of the card
|
||||
*/
|
||||
JsonRoutes.add('PUT', '/api/boards/:boardId/lists/:listId/cards/:cardId', function(req, res) {
|
||||
Authentication.checkUserId(req.userId);
|
||||
const paramBoardId = req.params.boardId;
|
||||
|
@ -1551,6 +1708,18 @@ if (Meteor.isServer) {
|
|||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* @operation delete_card
|
||||
* @summary Delete a card from a board
|
||||
*
|
||||
* @description This operation **deletes** a card, and therefore the card
|
||||
* is not put in the recycle bin.
|
||||
*
|
||||
* @param {string} boardId the board ID of the card
|
||||
* @param {string} list the list ID of the card
|
||||
* @param {string} cardId the ID of the card
|
||||
* @return_type {_id: string}
|
||||
*/
|
||||
JsonRoutes.add('DELETE', '/api/boards/:boardId/lists/:listId/cards/:cardId', function(req, res) {
|
||||
Authentication.checkUserId(req.userId);
|
||||
const paramBoardId = req.params.boardId;
|
||||
|
|
|
@ -1,21 +1,39 @@
|
|||
ChecklistItems = new Mongo.Collection('checklistItems');
|
||||
|
||||
/**
|
||||
* An item in a checklist
|
||||
*/
|
||||
ChecklistItems.attachSchema(new SimpleSchema({
|
||||
title: {
|
||||
/**
|
||||
* the text of the item
|
||||
*/
|
||||
type: String,
|
||||
},
|
||||
sort: {
|
||||
/**
|
||||
* the sorting field of the item
|
||||
*/
|
||||
type: Number,
|
||||
decimal: true,
|
||||
},
|
||||
isFinished: {
|
||||
/**
|
||||
* Is the item checked?
|
||||
*/
|
||||
type: Boolean,
|
||||
defaultValue: false,
|
||||
},
|
||||
checklistId: {
|
||||
/**
|
||||
* the checklist ID the item is attached to
|
||||
*/
|
||||
type: String,
|
||||
},
|
||||
cardId: {
|
||||
/**
|
||||
* the card ID the item is attached to
|
||||
*/
|
||||
type: String,
|
||||
},
|
||||
}));
|
||||
|
@ -193,6 +211,17 @@ if (Meteor.isServer) {
|
|||
}
|
||||
|
||||
if (Meteor.isServer) {
|
||||
/**
|
||||
* @operation get_checklist_item
|
||||
* @tag Checklists
|
||||
* @summary Get a checklist item
|
||||
*
|
||||
* @param {string} boardId the board ID
|
||||
* @param {string} cardId the card ID
|
||||
* @param {string} checklistId the checklist ID
|
||||
* @param {string} itemId the ID of the item
|
||||
* @return_type ChecklistItems
|
||||
*/
|
||||
JsonRoutes.add('GET', '/api/boards/:boardId/cards/:cardId/checklists/:checklistId/items/:itemId', function (req, res) {
|
||||
Authentication.checkUserId( req.userId);
|
||||
const paramItemId = req.params.itemId;
|
||||
|
@ -209,6 +238,19 @@ if (Meteor.isServer) {
|
|||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @operation edit_checklist_item
|
||||
* @tag Checklists
|
||||
* @summary Edit a checklist item
|
||||
*
|
||||
* @param {string} boardId the board ID
|
||||
* @param {string} cardId the card ID
|
||||
* @param {string} checklistId the checklist ID
|
||||
* @param {string} itemId the ID of the item
|
||||
* @param {string} [isFinished] is the item checked?
|
||||
* @param {string} [title] the new text of the item
|
||||
* @return_type {_id: string}
|
||||
*/
|
||||
JsonRoutes.add('PUT', '/api/boards/:boardId/cards/:cardId/checklists/:checklistId/items/:itemId', function (req, res) {
|
||||
Authentication.checkUserId( req.userId);
|
||||
|
||||
|
@ -229,6 +271,19 @@ if (Meteor.isServer) {
|
|||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* @operation delete_checklist_item
|
||||
* @tag Checklists
|
||||
* @summary Delete a checklist item
|
||||
*
|
||||
* @description Note: this operation can't be reverted.
|
||||
*
|
||||
* @param {string} boardId the board ID
|
||||
* @param {string} cardId the card ID
|
||||
* @param {string} checklistId the checklist ID
|
||||
* @param {string} itemId the ID of the item to be removed
|
||||
* @return_type {_id: string}
|
||||
*/
|
||||
JsonRoutes.add('DELETE', '/api/boards/:boardId/cards/:cardId/checklists/:checklistId/items/:itemId', function (req, res) {
|
||||
Authentication.checkUserId( req.userId);
|
||||
const paramItemId = req.params.itemId;
|
||||
|
|
|
@ -1,18 +1,33 @@
|
|||
Checklists = new Mongo.Collection('checklists');
|
||||
|
||||
/**
|
||||
* A Checklist
|
||||
*/
|
||||
Checklists.attachSchema(new SimpleSchema({
|
||||
cardId: {
|
||||
/**
|
||||
* The ID of the card the checklist is in
|
||||
*/
|
||||
type: String,
|
||||
},
|
||||
title: {
|
||||
/**
|
||||
* the title of the checklist
|
||||
*/
|
||||
type: String,
|
||||
defaultValue: 'Checklist',
|
||||
},
|
||||
finishedAt: {
|
||||
/**
|
||||
* When was the checklist finished
|
||||
*/
|
||||
type: Date,
|
||||
optional: true,
|
||||
},
|
||||
createdAt: {
|
||||
/**
|
||||
* Creation date of the checklist
|
||||
*/
|
||||
type: Date,
|
||||
denyUpdate: false,
|
||||
autoValue() { // eslint-disable-line consistent-return
|
||||
|
@ -24,6 +39,9 @@ Checklists.attachSchema(new SimpleSchema({
|
|||
},
|
||||
},
|
||||
sort: {
|
||||
/**
|
||||
* sorting value of the checklist
|
||||
*/
|
||||
type: Number,
|
||||
decimal: true,
|
||||
},
|
||||
|
@ -128,6 +146,15 @@ if (Meteor.isServer) {
|
|||
}
|
||||
|
||||
if (Meteor.isServer) {
|
||||
/**
|
||||
* @operation get_all_checklists
|
||||
* @summary Get the list of checklists attached to a card
|
||||
*
|
||||
* @param {string} boardId the board ID
|
||||
* @param {string} cardId the card ID
|
||||
* @return_type [{_id: string,
|
||||
* title: string}]
|
||||
*/
|
||||
JsonRoutes.add('GET', '/api/boards/:boardId/cards/:cardId/checklists', function (req, res) {
|
||||
Authentication.checkUserId( req.userId);
|
||||
const paramCardId = req.params.cardId;
|
||||
|
@ -149,6 +176,22 @@ if (Meteor.isServer) {
|
|||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @operation get_checklist
|
||||
* @summary Get a checklist
|
||||
*
|
||||
* @param {string} boardId the board ID
|
||||
* @param {string} cardId the card ID
|
||||
* @param {string} checklistId the ID of the checklist
|
||||
* @return_type {cardId: string,
|
||||
* title: string,
|
||||
* finishedAt: string,
|
||||
* createdAt: string,
|
||||
* sort: number,
|
||||
* items: [{_id: string,
|
||||
* title: string,
|
||||
* isFinished: boolean}]}
|
||||
*/
|
||||
JsonRoutes.add('GET', '/api/boards/:boardId/cards/:cardId/checklists/:checklistId', function (req, res) {
|
||||
Authentication.checkUserId( req.userId);
|
||||
const paramChecklistId = req.params.checklistId;
|
||||
|
@ -173,6 +216,15 @@ if (Meteor.isServer) {
|
|||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @operation new_checklist
|
||||
* @summary create a new checklist
|
||||
*
|
||||
* @param {string} boardId the board ID
|
||||
* @param {string} cardId the card ID
|
||||
* @param {string} title the title of the new checklist
|
||||
* @return_type {_id: string}
|
||||
*/
|
||||
JsonRoutes.add('POST', '/api/boards/:boardId/cards/:cardId/checklists', function (req, res) {
|
||||
Authentication.checkUserId( req.userId);
|
||||
|
||||
|
@ -204,6 +256,17 @@ if (Meteor.isServer) {
|
|||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @operation delete_checklist
|
||||
* @summary Delete a checklist
|
||||
*
|
||||
* @description The checklist will be removed, not put in the recycle bin.
|
||||
*
|
||||
* @param {string} boardId the board ID
|
||||
* @param {string} cardId the card ID
|
||||
* @param {string} checklistId the ID of the checklist to remove
|
||||
* @return_type {_id: string}
|
||||
*/
|
||||
JsonRoutes.add('DELETE', '/api/boards/:boardId/cards/:cardId/checklists/:checklistId', function (req, res) {
|
||||
Authentication.checkUserId( req.userId);
|
||||
const paramChecklistId = req.params.checklistId;
|
||||
|
|
|
@ -1,40 +1,73 @@
|
|||
CustomFields = new Mongo.Collection('customFields');
|
||||
|
||||
/**
|
||||
* A custom field on a card in the board
|
||||
*/
|
||||
CustomFields.attachSchema(new SimpleSchema({
|
||||
boardId: {
|
||||
/**
|
||||
* the ID of the board
|
||||
*/
|
||||
type: String,
|
||||
},
|
||||
name: {
|
||||
/**
|
||||
* name of the custom field
|
||||
*/
|
||||
type: String,
|
||||
},
|
||||
type: {
|
||||
/**
|
||||
* type of the custom field
|
||||
*/
|
||||
type: String,
|
||||
allowedValues: ['text', 'number', 'date', 'dropdown'],
|
||||
},
|
||||
settings: {
|
||||
/**
|
||||
* settings of the custom field
|
||||
*/
|
||||
type: Object,
|
||||
},
|
||||
'settings.dropdownItems': {
|
||||
/**
|
||||
* list of drop down items objects
|
||||
*/
|
||||
type: [Object],
|
||||
optional: true,
|
||||
},
|
||||
'settings.dropdownItems.$': {
|
||||
type: new SimpleSchema({
|
||||
_id: {
|
||||
/**
|
||||
* ID of the drop down item
|
||||
*/
|
||||
type: String,
|
||||
},
|
||||
name: {
|
||||
/**
|
||||
* name of the drop down item
|
||||
*/
|
||||
type: String,
|
||||
},
|
||||
}),
|
||||
},
|
||||
showOnCard: {
|
||||
/**
|
||||
* should we show on the cards this custom field
|
||||
*/
|
||||
type: Boolean,
|
||||
},
|
||||
automaticallyOnCard: {
|
||||
/**
|
||||
* should the custom fields automatically be added on cards?
|
||||
*/
|
||||
type: Boolean,
|
||||
},
|
||||
showLabelOnMiniCard: {
|
||||
/**
|
||||
* should the label of the custom field be shown on minicards?
|
||||
*/
|
||||
type: Boolean,
|
||||
},
|
||||
}));
|
||||
|
@ -88,6 +121,15 @@ if (Meteor.isServer) {
|
|||
|
||||
//CUSTOM FIELD REST API
|
||||
if (Meteor.isServer) {
|
||||
/**
|
||||
* @operation get_all_custom_fields
|
||||
* @summary Get the list of Custom Fields attached to a board
|
||||
*
|
||||
* @param {string} boardID the ID of the board
|
||||
* @return_type [{_id: string,
|
||||
* name: string,
|
||||
* type: string}]
|
||||
*/
|
||||
JsonRoutes.add('GET', '/api/boards/:boardId/custom-fields', function (req, res) {
|
||||
Authentication.checkUserId( req.userId);
|
||||
const paramBoardId = req.params.boardId;
|
||||
|
@ -103,6 +145,14 @@ if (Meteor.isServer) {
|
|||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* @operation get_custom_field
|
||||
* @summary Get a Custom Fields attached to a board
|
||||
*
|
||||
* @param {string} boardID the ID of the board
|
||||
* @param {string} customFieldId the ID of the custom field
|
||||
* @return_type CustomFields
|
||||
*/
|
||||
JsonRoutes.add('GET', '/api/boards/:boardId/custom-fields/:customFieldId', function (req, res) {
|
||||
Authentication.checkUserId( req.userId);
|
||||
const paramBoardId = req.params.boardId;
|
||||
|
@ -113,6 +163,19 @@ if (Meteor.isServer) {
|
|||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* @operation new_custom_field
|
||||
* @summary Create a Custom Field
|
||||
*
|
||||
* @param {string} boardID the ID of the board
|
||||
* @param {string} name the name of the custom field
|
||||
* @param {string} type the type of the custom field
|
||||
* @param {string} settings the settings object of the custom field
|
||||
* @param {boolean} showOnCard should we show the custom field on cards?
|
||||
* @param {boolean} automaticallyOnCard should the custom fields automatically be added on cards?
|
||||
* @param {boolean} showLabelOnMiniCard should the label of the custom field be shown on minicards?
|
||||
* @return_type {_id: string}
|
||||
*/
|
||||
JsonRoutes.add('POST', '/api/boards/:boardId/custom-fields', function (req, res) {
|
||||
Authentication.checkUserId( req.userId);
|
||||
const paramBoardId = req.params.boardId;
|
||||
|
@ -137,6 +200,16 @@ if (Meteor.isServer) {
|
|||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* @operation delete_custom_field
|
||||
* @summary Delete a Custom Fields attached to a board
|
||||
*
|
||||
* @description The Custom Field can't be retrieved after this operation
|
||||
*
|
||||
* @param {string} boardID the ID of the board
|
||||
* @param {string} customFieldId the ID of the custom field
|
||||
* @return_type {_id: string}
|
||||
*/
|
||||
JsonRoutes.add('DELETE', '/api/boards/:boardId/custom-fields/:customFieldId', function (req, res) {
|
||||
Authentication.checkUserId( req.userId);
|
||||
const paramBoardId = req.params.boardId;
|
||||
|
|
|
@ -6,13 +6,20 @@ if (Meteor.isServer) {
|
|||
// `ApiRoutes.path('boards/export', boardId)``
|
||||
// on the client instead of copy/pasting the route path manually between the
|
||||
// client and the server.
|
||||
/*
|
||||
* This route is used to export the board FROM THE APPLICATION.
|
||||
* If user is already logged-in, pass loginToken as param "authToken":
|
||||
* '/api/boards/:boardId/export?authToken=:token'
|
||||
/**
|
||||
* @operation export
|
||||
* @tag Boards
|
||||
*
|
||||
* @summary This route is used to export the board **FROM THE APPLICATION**.
|
||||
*
|
||||
* @description If user is already logged-in, pass loginToken as param
|
||||
* "authToken": '/api/boards/:boardId/export?authToken=:token'
|
||||
*
|
||||
* See https://blog.kayla.com.au/server-side-route-authentication-in-meteor/
|
||||
* for detailed explanations
|
||||
*
|
||||
* @param {string} boardId the ID of the board we are exporting
|
||||
* @param {string} authToken the loginToken
|
||||
*/
|
||||
JsonRoutes.add('get', '/api/boards/:boardId/export', function(req, res) {
|
||||
const boardId = req.params.boardId;
|
||||
|
|
|
@ -1,33 +1,60 @@
|
|||
Integrations = new Mongo.Collection('integrations');
|
||||
|
||||
/**
|
||||
* Integration with third-party applications
|
||||
*/
|
||||
Integrations.attachSchema(new SimpleSchema({
|
||||
enabled: {
|
||||
/**
|
||||
* is the integration enabled?
|
||||
*/
|
||||
type: Boolean,
|
||||
defaultValue: true,
|
||||
},
|
||||
title: {
|
||||
/**
|
||||
* name of the integration
|
||||
*/
|
||||
type: String,
|
||||
optional: true,
|
||||
},
|
||||
type: {
|
||||
/**
|
||||
* type of the integratation (Default to 'outgoing-webhooks')
|
||||
*/
|
||||
type: String,
|
||||
defaultValue: 'outgoing-webhooks',
|
||||
},
|
||||
activities: {
|
||||
/**
|
||||
* activities the integration gets triggered (list)
|
||||
*/
|
||||
type: [String],
|
||||
defaultValue: ['all'],
|
||||
},
|
||||
url: { // URL validation regex (https://mathiasbynens.be/demo/url-regex)
|
||||
/**
|
||||
* URL validation regex (https://mathiasbynens.be/demo/url-regex)
|
||||
*/
|
||||
type: String,
|
||||
},
|
||||
token: {
|
||||
/**
|
||||
* token of the integration
|
||||
*/
|
||||
type: String,
|
||||
optional: true,
|
||||
},
|
||||
boardId: {
|
||||
/**
|
||||
* Board ID of the integration
|
||||
*/
|
||||
type: String,
|
||||
},
|
||||
createdAt: {
|
||||
/**
|
||||
* Creation date of the integration
|
||||
*/
|
||||
type: Date,
|
||||
denyUpdate: false,
|
||||
autoValue() { // eslint-disable-line consistent-return
|
||||
|
@ -39,6 +66,9 @@ Integrations.attachSchema(new SimpleSchema({
|
|||
},
|
||||
},
|
||||
userId: {
|
||||
/**
|
||||
* user ID who created the interation
|
||||
*/
|
||||
type: String,
|
||||
},
|
||||
}));
|
||||
|
@ -58,7 +88,13 @@ Integrations.allow({
|
|||
|
||||
//INTEGRATIONS REST API
|
||||
if (Meteor.isServer) {
|
||||
// Get all integrations in board
|
||||
/**
|
||||
* @operation get_all_integrations
|
||||
* @summary Get all integrations in board
|
||||
*
|
||||
* @param {string} boardId the board ID
|
||||
* @return_type [Integrations]
|
||||
*/
|
||||
JsonRoutes.add('GET', '/api/boards/:boardId/integrations', function(req, res) {
|
||||
try {
|
||||
const paramBoardId = req.params.boardId;
|
||||
|
@ -78,7 +114,14 @@ if (Meteor.isServer) {
|
|||
}
|
||||
});
|
||||
|
||||
// Get a single integration in board
|
||||
/**
|
||||
* @operation get_integration
|
||||
* @summary Get a single integration in board
|
||||
*
|
||||
* @param {string} boardId the board ID
|
||||
* @param {string} intId the integration ID
|
||||
* @return_type Integrations
|
||||
*/
|
||||
JsonRoutes.add('GET', '/api/boards/:boardId/integrations/:intId', function(req, res) {
|
||||
try {
|
||||
const paramBoardId = req.params.boardId;
|
||||
|
@ -98,7 +141,14 @@ if (Meteor.isServer) {
|
|||
}
|
||||
});
|
||||
|
||||
// Create a new integration
|
||||
/**
|
||||
* @operation new_integration
|
||||
* @summary Create a new integration
|
||||
*
|
||||
* @param {string} boardId the board ID
|
||||
* @param {string} url the URL of the integration
|
||||
* @return_type {_id: string}
|
||||
*/
|
||||
JsonRoutes.add('POST', '/api/boards/:boardId/integrations', function(req, res) {
|
||||
try {
|
||||
const paramBoardId = req.params.boardId;
|
||||
|
@ -125,7 +175,19 @@ if (Meteor.isServer) {
|
|||
}
|
||||
});
|
||||
|
||||
// Edit integration data
|
||||
/**
|
||||
* @operation edit_integration
|
||||
* @summary Edit integration data
|
||||
*
|
||||
* @param {string} boardId the board ID
|
||||
* @param {string} intId the integration ID
|
||||
* @param {string} [enabled] is the integration enabled?
|
||||
* @param {string} [title] new name of the integration
|
||||
* @param {string} [url] new URL of the integration
|
||||
* @param {string} [token] new token of the integration
|
||||
* @param {string} [activities] new list of activities of the integration
|
||||
* @return_type {_id: string}
|
||||
*/
|
||||
JsonRoutes.add('PUT', '/api/boards/:boardId/integrations/:intId', function (req, res) {
|
||||
try {
|
||||
const paramBoardId = req.params.boardId;
|
||||
|
@ -173,7 +235,15 @@ if (Meteor.isServer) {
|
|||
}
|
||||
});
|
||||
|
||||
// Delete subscribed activities
|
||||
/**
|
||||
* @operation delete_integration_activities
|
||||
* @summary Delete subscribed activities
|
||||
*
|
||||
* @param {string} boardId the board ID
|
||||
* @param {string} intId the integration ID
|
||||
* @param {string} newActivities the activities to remove from the integration
|
||||
* @return_type Integrations
|
||||
*/
|
||||
JsonRoutes.add('DELETE', '/api/boards/:boardId/integrations/:intId/activities', function (req, res) {
|
||||
try {
|
||||
const paramBoardId = req.params.boardId;
|
||||
|
@ -197,7 +267,15 @@ if (Meteor.isServer) {
|
|||
}
|
||||
});
|
||||
|
||||
// Add subscribed activities
|
||||
/**
|
||||
* @operation new_integration_activities
|
||||
* @summary Add subscribed activities
|
||||
*
|
||||
* @param {string} boardId the board ID
|
||||
* @param {string} intId the integration ID
|
||||
* @param {string} newActivities the activities to add to the integration
|
||||
* @return_type Integrations
|
||||
*/
|
||||
JsonRoutes.add('POST', '/api/boards/:boardId/integrations/:intId/activities', function (req, res) {
|
||||
try {
|
||||
const paramBoardId = req.params.boardId;
|
||||
|
@ -221,7 +299,14 @@ if (Meteor.isServer) {
|
|||
}
|
||||
});
|
||||
|
||||
// Delete integration
|
||||
/**
|
||||
* @operation delete_integration
|
||||
* @summary Delete integration
|
||||
*
|
||||
* @param {string} boardId the board ID
|
||||
* @param {string} intId the integration ID
|
||||
* @return_type {_id: string}
|
||||
*/
|
||||
JsonRoutes.add('DELETE', '/api/boards/:boardId/integrations/:intId', function (req, res) {
|
||||
try {
|
||||
const paramBoardId = req.params.boardId;
|
||||
|
|
|
@ -1,10 +1,19 @@
|
|||
Lists = new Mongo.Collection('lists');
|
||||
|
||||
/**
|
||||
* A list (column) in the Wekan board.
|
||||
*/
|
||||
Lists.attachSchema(new SimpleSchema({
|
||||
title: {
|
||||
/**
|
||||
* the title of the list
|
||||
*/
|
||||
type: String,
|
||||
},
|
||||
archived: {
|
||||
/**
|
||||
* is the list archived
|
||||
*/
|
||||
type: Boolean,
|
||||
autoValue() { // eslint-disable-line consistent-return
|
||||
if (this.isInsert && !this.isSet) {
|
||||
|
@ -13,9 +22,15 @@ Lists.attachSchema(new SimpleSchema({
|
|||
},
|
||||
},
|
||||
boardId: {
|
||||
/**
|
||||
* the board associated to this list
|
||||
*/
|
||||
type: String,
|
||||
},
|
||||
createdAt: {
|
||||
/**
|
||||
* creation date
|
||||
*/
|
||||
type: Date,
|
||||
autoValue() { // eslint-disable-line consistent-return
|
||||
if (this.isInsert) {
|
||||
|
@ -26,12 +41,18 @@ Lists.attachSchema(new SimpleSchema({
|
|||
},
|
||||
},
|
||||
sort: {
|
||||
/**
|
||||
* is the list sorted
|
||||
*/
|
||||
type: Number,
|
||||
decimal: true,
|
||||
// XXX We should probably provide a default
|
||||
optional: true,
|
||||
},
|
||||
updatedAt: {
|
||||
/**
|
||||
* last update of the list
|
||||
*/
|
||||
type: Date,
|
||||
optional: true,
|
||||
autoValue() { // eslint-disable-line consistent-return
|
||||
|
@ -43,19 +64,31 @@ Lists.attachSchema(new SimpleSchema({
|
|||
},
|
||||
},
|
||||
wipLimit: {
|
||||
/**
|
||||
* WIP object, see below
|
||||
*/
|
||||
type: Object,
|
||||
optional: true,
|
||||
},
|
||||
'wipLimit.value': {
|
||||
/**
|
||||
* value of the WIP
|
||||
*/
|
||||
type: Number,
|
||||
decimal: false,
|
||||
defaultValue: 1,
|
||||
},
|
||||
'wipLimit.enabled': {
|
||||
/**
|
||||
* is the WIP enabled
|
||||
*/
|
||||
type: Boolean,
|
||||
defaultValue: false,
|
||||
},
|
||||
'wipLimit.soft': {
|
||||
/**
|
||||
* is the WIP a soft or hard requirement
|
||||
*/
|
||||
type: Boolean,
|
||||
defaultValue: false,
|
||||
},
|
||||
|
@ -212,6 +245,14 @@ if (Meteor.isServer) {
|
|||
|
||||
//LISTS REST API
|
||||
if (Meteor.isServer) {
|
||||
/**
|
||||
* @operation get_all_lists
|
||||
* @summary Get the list of Lists attached to a board
|
||||
*
|
||||
* @param {string} boardId the board ID
|
||||
* @return_type [{_id: string,
|
||||
* title: string}]
|
||||
*/
|
||||
JsonRoutes.add('GET', '/api/boards/:boardId/lists', function (req, res) {
|
||||
try {
|
||||
const paramBoardId = req.params.boardId;
|
||||
|
@ -235,6 +276,14 @@ if (Meteor.isServer) {
|
|||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @operation get_list
|
||||
* @summary Get a List attached to a board
|
||||
*
|
||||
* @param {string} boardId the board ID
|
||||
* @param {string} listId the List ID
|
||||
* @return_type Lists
|
||||
*/
|
||||
JsonRoutes.add('GET', '/api/boards/:boardId/lists/:listId', function (req, res) {
|
||||
try {
|
||||
const paramBoardId = req.params.boardId;
|
||||
|
@ -253,6 +302,14 @@ if (Meteor.isServer) {
|
|||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @operation new_list
|
||||
* @summary Add a List to a board
|
||||
*
|
||||
* @param {string} boardId the board ID
|
||||
* @param {string} title the title of the List
|
||||
* @return_type {_id: string}
|
||||
*/
|
||||
JsonRoutes.add('POST', '/api/boards/:boardId/lists', function (req, res) {
|
||||
try {
|
||||
Authentication.checkUserId( req.userId);
|
||||
|
@ -276,6 +333,17 @@ if (Meteor.isServer) {
|
|||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @operation delete_list
|
||||
* @summary Delete a List
|
||||
*
|
||||
* @description This **deletes** a list from a board.
|
||||
* The list is not put in the recycle bin.
|
||||
*
|
||||
* @param {string} boardId the board ID
|
||||
* @param {string} listId the ID of the list to remove
|
||||
* @return_type {_id: string}
|
||||
*/
|
||||
JsonRoutes.add('DELETE', '/api/boards/:boardId/lists/:listId', function (req, res) {
|
||||
try {
|
||||
Authentication.checkUserId( req.userId);
|
||||
|
|
|
@ -1,10 +1,19 @@
|
|||
Swimlanes = new Mongo.Collection('swimlanes');
|
||||
|
||||
/**
|
||||
* A swimlane is an line in the kaban board.
|
||||
*/
|
||||
Swimlanes.attachSchema(new SimpleSchema({
|
||||
title: {
|
||||
/**
|
||||
* the title of the swimlane
|
||||
*/
|
||||
type: String,
|
||||
},
|
||||
archived: {
|
||||
/**
|
||||
* is the swimlane archived?
|
||||
*/
|
||||
type: Boolean,
|
||||
autoValue() { // eslint-disable-line consistent-return
|
||||
if (this.isInsert && !this.isSet) {
|
||||
|
@ -13,9 +22,15 @@ Swimlanes.attachSchema(new SimpleSchema({
|
|||
},
|
||||
},
|
||||
boardId: {
|
||||
/**
|
||||
* the ID of the board the swimlane is attached to
|
||||
*/
|
||||
type: String,
|
||||
},
|
||||
createdAt: {
|
||||
/**
|
||||
* creation date of the swimlane
|
||||
*/
|
||||
type: Date,
|
||||
autoValue() { // eslint-disable-line consistent-return
|
||||
if (this.isInsert) {
|
||||
|
@ -26,12 +41,18 @@ Swimlanes.attachSchema(new SimpleSchema({
|
|||
},
|
||||
},
|
||||
sort: {
|
||||
/**
|
||||
* the sort value of the swimlane
|
||||
*/
|
||||
type: Number,
|
||||
decimal: true,
|
||||
// XXX We should probably provide a default
|
||||
optional: true,
|
||||
},
|
||||
updatedAt: {
|
||||
/**
|
||||
* when was the swimlane last edited
|
||||
*/
|
||||
type: Date,
|
||||
optional: true,
|
||||
autoValue() { // eslint-disable-line consistent-return
|
||||
|
@ -131,6 +152,15 @@ if (Meteor.isServer) {
|
|||
|
||||
//SWIMLANE REST API
|
||||
if (Meteor.isServer) {
|
||||
/**
|
||||
* @operation get_all_swimlanes
|
||||
*
|
||||
* @summary Get the list of swimlanes attached to a board
|
||||
*
|
||||
* @param {string} boardId the ID of the board
|
||||
* @return_type [{_id: string,
|
||||
* title: string}]
|
||||
*/
|
||||
JsonRoutes.add('GET', '/api/boards/:boardId/swimlanes', function (req, res) {
|
||||
try {
|
||||
const paramBoardId = req.params.boardId;
|
||||
|
@ -154,6 +184,15 @@ if (Meteor.isServer) {
|
|||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @operation get_swimlane
|
||||
*
|
||||
* @summary Get a swimlane
|
||||
*
|
||||
* @param {string} boardId the ID of the board
|
||||
* @param {string} swimlaneId the ID of the swimlane
|
||||
* @return_type Swimlanes
|
||||
*/
|
||||
JsonRoutes.add('GET', '/api/boards/:boardId/swimlanes/:swimlaneId', function (req, res) {
|
||||
try {
|
||||
const paramBoardId = req.params.boardId;
|
||||
|
@ -172,6 +211,15 @@ if (Meteor.isServer) {
|
|||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @operation new_swimlane
|
||||
*
|
||||
* @summary Add a swimlane to a board
|
||||
*
|
||||
* @param {string} boardId the ID of the board
|
||||
* @param {string} title the new title of the swimlane
|
||||
* @return_type {_id: string}
|
||||
*/
|
||||
JsonRoutes.add('POST', '/api/boards/:boardId/swimlanes', function (req, res) {
|
||||
try {
|
||||
Authentication.checkUserId( req.userId);
|
||||
|
@ -195,6 +243,17 @@ if (Meteor.isServer) {
|
|||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @operation delete_swimlane
|
||||
*
|
||||
* @summary Delete a swimlane
|
||||
*
|
||||
* @description The swimlane will be deleted, not moved to the recycle bin
|
||||
*
|
||||
* @param {string} boardId the ID of the board
|
||||
* @param {string} swimlaneId the ID of the swimlane
|
||||
* @return_type {_id: string}
|
||||
*/
|
||||
JsonRoutes.add('DELETE', '/api/boards/:boardId/swimlanes/:swimlaneId', function (req, res) {
|
||||
try {
|
||||
Authentication.checkUserId( req.userId);
|
||||
|
|
172
models/users.js
172
models/users.js
|
@ -4,8 +4,14 @@ const isSandstorm = Meteor.settings && Meteor.settings.public &&
|
|||
Meteor.settings.public.sandstorm;
|
||||
Users = Meteor.users;
|
||||
|
||||
/**
|
||||
* A User in wekan
|
||||
*/
|
||||
Users.attachSchema(new SimpleSchema({
|
||||
username: {
|
||||
/**
|
||||
* the username of the user
|
||||
*/
|
||||
type: String,
|
||||
optional: true,
|
||||
autoValue() { // eslint-disable-line consistent-return
|
||||
|
@ -18,17 +24,29 @@ Users.attachSchema(new SimpleSchema({
|
|||
},
|
||||
},
|
||||
emails: {
|
||||
/**
|
||||
* the list of emails attached to a user
|
||||
*/
|
||||
type: [Object],
|
||||
optional: true,
|
||||
},
|
||||
'emails.$.address': {
|
||||
/**
|
||||
* The email address
|
||||
*/
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Email,
|
||||
},
|
||||
'emails.$.verified': {
|
||||
/**
|
||||
* Has the email been verified
|
||||
*/
|
||||
type: Boolean,
|
||||
},
|
||||
createdAt: {
|
||||
/**
|
||||
* creation date of the user
|
||||
*/
|
||||
type: Date,
|
||||
autoValue() { // eslint-disable-line consistent-return
|
||||
if (this.isInsert) {
|
||||
|
@ -39,6 +57,9 @@ Users.attachSchema(new SimpleSchema({
|
|||
},
|
||||
},
|
||||
profile: {
|
||||
/**
|
||||
* profile settings
|
||||
*/
|
||||
type: Object,
|
||||
optional: true,
|
||||
autoValue() { // eslint-disable-line consistent-return
|
||||
|
@ -50,50 +71,86 @@ Users.attachSchema(new SimpleSchema({
|
|||
},
|
||||
},
|
||||
'profile.avatarUrl': {
|
||||
/**
|
||||
* URL of the avatar of the user
|
||||
*/
|
||||
type: String,
|
||||
optional: true,
|
||||
},
|
||||
'profile.emailBuffer': {
|
||||
/**
|
||||
* list of email buffers of the user
|
||||
*/
|
||||
type: [String],
|
||||
optional: true,
|
||||
},
|
||||
'profile.fullname': {
|
||||
/**
|
||||
* full name of the user
|
||||
*/
|
||||
type: String,
|
||||
optional: true,
|
||||
},
|
||||
'profile.hiddenSystemMessages': {
|
||||
/**
|
||||
* does the user wants to hide system messages?
|
||||
*/
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
},
|
||||
'profile.initials': {
|
||||
/**
|
||||
* initials of the user
|
||||
*/
|
||||
type: String,
|
||||
optional: true,
|
||||
},
|
||||
'profile.invitedBoards': {
|
||||
/**
|
||||
* board IDs the user has been invited to
|
||||
*/
|
||||
type: [String],
|
||||
optional: true,
|
||||
},
|
||||
'profile.language': {
|
||||
/**
|
||||
* language of the user
|
||||
*/
|
||||
type: String,
|
||||
optional: true,
|
||||
},
|
||||
'profile.notifications': {
|
||||
/**
|
||||
* enabled notifications for the user
|
||||
*/
|
||||
type: [String],
|
||||
optional: true,
|
||||
},
|
||||
'profile.showCardsCountAt': {
|
||||
/**
|
||||
* showCardCountAt field of the user
|
||||
*/
|
||||
type: Number,
|
||||
optional: true,
|
||||
},
|
||||
'profile.starredBoards': {
|
||||
/**
|
||||
* list of starred board IDs
|
||||
*/
|
||||
type: [String],
|
||||
optional: true,
|
||||
},
|
||||
'profile.icode': {
|
||||
/**
|
||||
* icode
|
||||
*/
|
||||
type: String,
|
||||
optional: true,
|
||||
},
|
||||
'profile.boardView': {
|
||||
/**
|
||||
* boardView field of the user
|
||||
*/
|
||||
type: String,
|
||||
optional: true,
|
||||
allowedValues: [
|
||||
|
@ -103,27 +160,45 @@ Users.attachSchema(new SimpleSchema({
|
|||
],
|
||||
},
|
||||
services: {
|
||||
/**
|
||||
* services field of the user
|
||||
*/
|
||||
type: Object,
|
||||
optional: true,
|
||||
blackbox: true,
|
||||
},
|
||||
heartbeat: {
|
||||
/**
|
||||
* last time the user has been seen
|
||||
*/
|
||||
type: Date,
|
||||
optional: true,
|
||||
},
|
||||
isAdmin: {
|
||||
/**
|
||||
* is the user an admin of the board?
|
||||
*/
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
},
|
||||
createdThroughApi: {
|
||||
/**
|
||||
* was the user created through the API?
|
||||
*/
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
},
|
||||
loginDisabled: {
|
||||
/**
|
||||
* loginDisabled field of the user
|
||||
*/
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
},
|
||||
'authenticationMethod': {
|
||||
/**
|
||||
* authentication method of the user
|
||||
*/
|
||||
type: String,
|
||||
optional: false,
|
||||
defaultValue: 'password',
|
||||
|
@ -681,6 +756,12 @@ if (Meteor.isServer) {
|
|||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @operation get_current_user
|
||||
*
|
||||
* @summary returns the current user
|
||||
* @return_type Users
|
||||
*/
|
||||
JsonRoutes.add('GET', '/api/user', function(req, res) {
|
||||
try {
|
||||
Authentication.checkLoggedIn(req.userId);
|
||||
|
@ -699,6 +780,15 @@ if (Meteor.isServer) {
|
|||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @operation get_all_users
|
||||
*
|
||||
* @summary return all the users
|
||||
*
|
||||
* @description Only the admin user (the first user) can call the REST API.
|
||||
* @return_type [{ _id: string,
|
||||
* username: string}]
|
||||
*/
|
||||
JsonRoutes.add('GET', '/api/users', function (req, res) {
|
||||
try {
|
||||
Authentication.checkUserId(req.userId);
|
||||
|
@ -717,6 +807,16 @@ if (Meteor.isServer) {
|
|||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @operation get_user
|
||||
*
|
||||
* @summary get a given user
|
||||
*
|
||||
* @description Only the admin user (the first user) can call the REST API.
|
||||
*
|
||||
* @param {string} userId the user ID
|
||||
* @return_type Users
|
||||
*/
|
||||
JsonRoutes.add('GET', '/api/users/:userId', function (req, res) {
|
||||
try {
|
||||
Authentication.checkUserId(req.userId);
|
||||
|
@ -734,6 +834,23 @@ if (Meteor.isServer) {
|
|||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @operation edit_user
|
||||
*
|
||||
* @summary edit a given user
|
||||
*
|
||||
* @description Only the admin user (the first user) can call the REST API.
|
||||
*
|
||||
* Possible values for *action*:
|
||||
* - `takeOwnership`: The admin takes the ownership of ALL boards of the user (archived and not archived) where the user is admin on.
|
||||
* - `disableLogin`: Disable a user (the user is not allowed to login and his login tokens are purged)
|
||||
* - `enableLogin`: Enable a user
|
||||
*
|
||||
* @param {string} userId the user ID
|
||||
* @param {string} action the action
|
||||
* @return_type {_id: string,
|
||||
* title: string}
|
||||
*/
|
||||
JsonRoutes.add('PUT', '/api/users/:userId', function (req, res) {
|
||||
try {
|
||||
Authentication.checkUserId(req.userId);
|
||||
|
@ -777,6 +894,25 @@ if (Meteor.isServer) {
|
|||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @operation add_board_member
|
||||
* @tag Boards
|
||||
*
|
||||
* @summary Add New Board Member with Role
|
||||
*
|
||||
* @description Only the admin user (the first user) can call the REST API.
|
||||
*
|
||||
* **Note**: see [Boards.set_board_member_permission](#set_board_member_permission)
|
||||
* to later change the permissions.
|
||||
*
|
||||
* @param {string} boardId the board ID
|
||||
* @param {string} userId the user ID
|
||||
* @param {boolean} isAdmin is the user an admin of the board
|
||||
* @param {boolean} isNoComments disable comments
|
||||
* @param {boolean} isCommentOnly only enable comments
|
||||
* @return_type {_id: string,
|
||||
* title: string}
|
||||
*/
|
||||
JsonRoutes.add('POST', '/api/boards/:boardId/members/:userId/add', function (req, res) {
|
||||
try {
|
||||
Authentication.checkUserId(req.userId);
|
||||
|
@ -817,6 +953,20 @@ if (Meteor.isServer) {
|
|||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @operation remove_board_member
|
||||
* @tag Boards
|
||||
*
|
||||
* @summary Remove Member from Board
|
||||
*
|
||||
* @description Only the admin user (the first user) can call the REST API.
|
||||
*
|
||||
* @param {string} boardId the board ID
|
||||
* @param {string} userId the user ID
|
||||
* @param {string} action the action (needs to be `remove`)
|
||||
* @return_type {_id: string,
|
||||
* title: string}
|
||||
*/
|
||||
JsonRoutes.add('POST', '/api/boards/:boardId/members/:userId/remove', function (req, res) {
|
||||
try {
|
||||
Authentication.checkUserId(req.userId);
|
||||
|
@ -852,6 +1002,18 @@ if (Meteor.isServer) {
|
|||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @operation new_user
|
||||
*
|
||||
* @summary Create a new user
|
||||
*
|
||||
* @description Only the admin user (the first user) can call the REST API.
|
||||
*
|
||||
* @param {string} username the new username
|
||||
* @param {string} email the email of the new user
|
||||
* @param {string} password the password of the new user
|
||||
* @return_type {_id: string}
|
||||
*/
|
||||
JsonRoutes.add('POST', '/api/users/', function (req, res) {
|
||||
try {
|
||||
Authentication.checkUserId(req.userId);
|
||||
|
@ -876,6 +1038,16 @@ if (Meteor.isServer) {
|
|||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @operation delete_user
|
||||
*
|
||||
* @summary Delete a user
|
||||
*
|
||||
* @description Only the admin user (the first user) can call the REST API.
|
||||
*
|
||||
* @param {string} userId the ID of the user to delete
|
||||
* @return_type {_id: string}
|
||||
*/
|
||||
JsonRoutes.add('DELETE', '/api/users/:userId', function (req, res) {
|
||||
try {
|
||||
Authentication.checkUserId(req.userId);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue