mirror of
https://github.com/wekan/wekan.git
synced 2026-11-05 09:40:20 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9e60a23845 | ||
|
|
6cca39af1b | ||
|
|
7ffbe2ab5e | ||
|
|
28850e5510 | ||
|
|
d62bed1536 | ||
|
|
b19cf01a3a | ||
|
|
39dece1e25 | ||
|
|
61ae62a83a | ||
|
|
775f0d9fe6 | ||
|
|
53a925cf7f | ||
|
|
6bf33a5578 | ||
|
|
7f3c4acf62 | ||
|
|
8481c791d7 | ||
|
|
9dd0fb88d6 | ||
|
|
9b004d75c7 | ||
|
|
86c7fbd717 | ||
|
|
6bd7f40511 | ||
|
|
a82257f0b1 | ||
|
|
ee26f32a20 | ||
|
|
7df3d52635 | ||
|
|
f9ba17177e | ||
|
|
ab4941390b | ||
|
|
11d044ede9 | ||
|
|
3c406d955e | ||
|
|
ea37dd5e1d | ||
|
|
fd7225d861 | ||
|
|
e0bd22e674 | ||
|
|
89332cefc5 | ||
|
|
5172f64b72 | ||
|
|
6cb4b9fe4a | ||
|
|
c978f55c56 | ||
|
|
4a205fcfcb | ||
|
|
2e1e703e35 | ||
|
|
a75c162483 | ||
|
|
f6c0700633 | ||
|
|
dece7ddf13 | ||
|
|
d06bcd9dcc | ||
|
|
ee7d82c006 | ||
|
|
b777f7f2af | ||
|
|
fe87b9928c | ||
|
|
fb36709047 | ||
|
|
73aaccb6dd | ||
|
|
1fe0059402 | ||
|
|
0c12c45080 | ||
|
|
a6c48329ef | ||
|
|
a3cd1b89ff | ||
|
|
7a08f42edb | ||
|
|
e8722b56e3 | ||
|
|
052948f6eb | ||
|
|
cd03395e05 | ||
|
|
61caf18fd4 | ||
|
|
015f4d671d | ||
|
|
c13e828c79 | ||
|
|
7a6abaac44 | ||
|
|
58dffd0a33 | ||
|
|
fe0232a4e8 | ||
|
|
8dff6c2e2a | ||
|
|
3a6e2813a6 | ||
|
|
8005640b77 | ||
|
|
bc929fb7e0 | ||
|
|
019874b6af | ||
|
|
a7977a8fc7 | ||
|
|
62f6cc7198 | ||
|
|
ad331ee122 | ||
|
|
387f0600ce | ||
|
|
0801e33f97 | ||
|
|
f576d2f356 | ||
|
|
051f7b2769 | ||
|
|
1f207c493d | ||
|
|
03f565bf95 | ||
|
|
36e29a405e | ||
|
|
2ec53b27d1 | ||
|
|
152a0b50f2 | ||
|
|
c09758fb91 | ||
|
|
2b2884d996 | ||
|
|
4537971300 | ||
|
|
0b43e8b42a | ||
|
|
bf94161f30 |
No files matched your search
@@ -1,12 +1,16 @@
|
||||
FROM ubuntu:rolling
|
||||
FROM quay.io/wekan/ubuntu:groovy-20201125.2
|
||||
LABEL maintainer="sgr"
|
||||
|
||||
# 2020-12-03:
|
||||
# - Above Ubuntu base image copied from Docker Hub ubuntu:groovy-20201125.2
|
||||
# to Quay to avoid Docker Hub rate limits.
|
||||
|
||||
ENV BUILD_DEPS="gnupg gosu bsdtar wget curl bzip2 g++ build-essential python git ca-certificates iproute2"
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
ENV \
|
||||
DEBUG=false \
|
||||
NODE_VERSION=v12.19.1 \
|
||||
NODE_VERSION=v12.20.0 \
|
||||
METEOR_RELEASE=1.10.2 \
|
||||
USE_EDGE=false \
|
||||
METEOR_EDGE=1.5-beta.17 \
|
||||
|
||||
@@ -81,7 +81,7 @@ parts:
|
||||
wekan:
|
||||
source: .
|
||||
plugin: nodejs
|
||||
node-engine: 12.19.1
|
||||
node-engine: 12.20.0
|
||||
node-packages:
|
||||
- node-gyp
|
||||
- node-pre-gyp
|
||||
|
||||
@@ -83,7 +83,7 @@ parts:
|
||||
wekan:
|
||||
source: .
|
||||
plugin: nodejs
|
||||
node-engine: 12.19.1
|
||||
node-engine: 12.20.0
|
||||
node-packages:
|
||||
- node-gyp
|
||||
- node-pre-gyp
|
||||
|
||||
+5
-5
@@ -6,8 +6,8 @@
|
||||
meteor-base@1.4.0
|
||||
|
||||
# Build system
|
||||
ecmascript@0.15.0-beta200.4
|
||||
standard-minifier-css@1.7.0-beta200.4
|
||||
ecmascript@0.14.4
|
||||
standard-minifier-css@1.7.1
|
||||
standard-minifier-js@2.6.0
|
||||
mquandalle:jade
|
||||
coffeescript@2.4.1!
|
||||
@@ -23,7 +23,7 @@ dburles:collection-helpers
|
||||
idmontie:migrations
|
||||
matb33:collection-hooks
|
||||
matteodem:easy-search
|
||||
mongo@1.10.0
|
||||
mongo@1.10.1
|
||||
mquandalle:collection-mutations
|
||||
|
||||
# Account system
|
||||
@@ -72,9 +72,9 @@ simple:rest-accounts-password
|
||||
useraccounts:core
|
||||
email@2.0.0
|
||||
horka:swipebox
|
||||
dynamic-import@0.6.0-beta200.4
|
||||
dynamic-import@0.5.4
|
||||
|
||||
accounts-password@1.6.2
|
||||
accounts-password@1.6.3
|
||||
cfs:gridfs
|
||||
rzymek:fullcalendar
|
||||
momentjs:moment@2.22.2
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
METEOR@2.0-beta.4
|
||||
METEOR@1.12
|
||||
+15
-15
@@ -1,7 +1,7 @@
|
||||
3stack:presence@1.1.2
|
||||
accounts-base@1.7.0
|
||||
accounts-base@1.7.1
|
||||
accounts-oauth@1.2.0
|
||||
accounts-password@1.6.2
|
||||
accounts-password@1.6.3
|
||||
aldeed:collection2@2.10.0
|
||||
aldeed:collection2-core@1.2.0
|
||||
aldeed:schema-deny@1.1.0
|
||||
@@ -10,8 +10,8 @@ aldeed:simple-schema@1.5.4
|
||||
allow-deny@1.1.0
|
||||
arillo:flow-router-helpers@0.5.2
|
||||
audit-argument-checks@1.0.7
|
||||
autoupdate@1.7.0-beta200.4
|
||||
babel-compiler@7.6.0-beta200.4
|
||||
autoupdate@1.6.0
|
||||
babel-compiler@7.5.4
|
||||
babel-runtime@1.5.0
|
||||
base64@1.0.12
|
||||
binary-heap@1.0.11
|
||||
@@ -49,15 +49,15 @@ coffeescript-compiler@2.4.1
|
||||
cottz:publish-relations@2.0.8
|
||||
dburles:collection-helpers@1.1.0
|
||||
ddp@1.4.0
|
||||
ddp-client@2.4.0-beta200.4
|
||||
ddp-client@2.3.3
|
||||
ddp-common@1.4.0
|
||||
ddp-rate-limiter@1.0.9
|
||||
ddp-server@2.3.2
|
||||
deps@1.0.12
|
||||
diff-sequence@1.1.1
|
||||
dynamic-import@0.6.0-beta200.4
|
||||
dynamic-import@0.5.4
|
||||
easylogic:summernote@0.8.8
|
||||
ecmascript@0.15.0-beta200.4
|
||||
ecmascript@0.14.4
|
||||
ecmascript-runtime@0.7.0
|
||||
ecmascript-runtime-client@0.11.0
|
||||
ecmascript-runtime-server@0.10.0
|
||||
@@ -103,14 +103,14 @@ meteorspark:util@0.2.0
|
||||
minifier-css@1.5.3
|
||||
minifier-js@2.6.0
|
||||
minifiers@1.1.8-faster-rebuild.0
|
||||
minimongo@1.6.0
|
||||
minimongo@1.6.1
|
||||
mobile-status-bar@1.1.0
|
||||
modern-browsers@0.1.5
|
||||
modules@0.16.0-beta200.4
|
||||
modules@0.15.0
|
||||
modules-runtime@0.12.0
|
||||
momentjs:moment@2.29.1
|
||||
mongo@1.10.0
|
||||
mongo-decimal@0.1.1
|
||||
mongo@1.10.1
|
||||
mongo-decimal@0.1.2
|
||||
mongo-dev-server@1.1.0
|
||||
mongo-id@1.0.7
|
||||
mongo-livedata@1.0.12
|
||||
@@ -193,7 +193,7 @@ random@1.2.0
|
||||
rate-limit@1.0.9
|
||||
reactive-dict@1.3.0
|
||||
reactive-var@1.0.11
|
||||
reload@1.3.0
|
||||
reload@1.3.1
|
||||
retry@1.1.0
|
||||
routepolicy@1.1.0
|
||||
rzymek:fullcalendar@3.8.0
|
||||
@@ -212,7 +212,7 @@ softwarerero:accounts-t9n@1.3.11
|
||||
spacebars@1.0.15
|
||||
spacebars-compiler@1.1.3
|
||||
srp@1.1.0
|
||||
standard-minifier-css@1.7.0-beta200.4
|
||||
standard-minifier-css@1.7.1
|
||||
standard-minifier-js@2.6.0
|
||||
staringatlights:fast-render@3.3.0
|
||||
staringatlights:inject-data@2.3.0
|
||||
@@ -233,8 +233,8 @@ useraccounts:core@1.14.2
|
||||
useraccounts:flow-routing@1.14.2
|
||||
useraccounts:unstyled@1.14.2
|
||||
verron:autosize@3.0.8
|
||||
webapp@1.10.0-beta200.4
|
||||
webapp-hashing@1.1.0-beta200.4
|
||||
webapp@1.9.1
|
||||
webapp-hashing@1.0.9
|
||||
wekan-accounts-cas@0.1.0
|
||||
wekan-accounts-oidc@1.0.10
|
||||
wekan-ldap@0.0.2
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ sudo: required
|
||||
|
||||
env:
|
||||
TRAVIS_DOCKER_COMPOSE_VERSION: 1.24.0
|
||||
TRAVIS_NODE_VERSION: 12.19.1
|
||||
TRAVIS_NODE_VERSION: 12.20.0
|
||||
TRAVIS_NPM_VERSION: latest
|
||||
|
||||
before_install:
|
||||
|
||||
+122
@@ -1,3 +1,125 @@
|
||||
# v4.63 2020-12-21 Wekan release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Fixed Remove Cover button gives JS error](https://github.com/wekan/wekan/commit/28850e5510f2aaefcae404efac1973c12f1cca65).
|
||||
Thanks to tsukasa1989 and xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v4.62 2020-12-18 Wekan release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Treat unknown attachment types as binary on board
|
||||
import/clone](https://github.com/wekan/wekan/pull/3395).
|
||||
Thanks to daniel-eder.
|
||||
- [Fix Move card from a board to another does not work anymore](https://github.com/wekan/wekan/commit/9dd0fb88d6cb3378a8fc96aaf60214020efeaed1).
|
||||
Thanks to lezioul and xet7.
|
||||
- [Add some permission code, to see does it fix something](https://github.com/wekan/wekan/commit/7f3c4acf62deefa2f7b36b986e06336fd3b2754f).
|
||||
Thanks to xet7.
|
||||
- [Fix delete board button not visible](https://github.com/wekan/wekan/commit/53a925cf7ff95167cbf2f65f7c7e169e18b14b44).
|
||||
Thanks to airtraxx and xet7.
|
||||
- [Board: When removing member from board, remove also from assignees.
|
||||
Admin Panel/People: 1) Allow edit user that does not have email address.
|
||||
2) When creating new user, require username and email address, and save also fullname.
|
||||
3) Some in progress code for deleting user, that does not work correctly yet, so deleting user is not enabled
|
||||
yet](https://github.com/wekan/wekan/commit/61ae62a83aaddb2c6f679ce9d05b675c845ba8bf).
|
||||
Thanks to airtraxx and xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v4.61 2020-12-16 Wekan release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Removed cookie code that is not in use](https://github.com/wekan/wekan/commit/3c406d955ec602d4b86c164acb9e94e715086f8e).
|
||||
Thanks to xet7.
|
||||
- [Allow normal user to delete checklist item](https://github.com/wekan/wekan/commit/f9ba17177e8f1146be1e571f47d26c13a9337034).
|
||||
Thanks to Samunosuke and xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v4.60 2020-12-15 Wekan release
|
||||
|
||||
This release adds the following updates:
|
||||
|
||||
- Update dependencies.
|
||||
[Part 1](https://github.com/wekan/wekan/commit/2e1e703e3591258462b3167f72e2b2319bf57bec),
|
||||
[Part 2](https://github.com/wekan/wekan/commit/a75c162483795775db1631686f8e7017b42c87ca).
|
||||
Thanks to developers of dependencies.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- Prevent normal user deleting or modifying too much. Allow normal user to export board.
|
||||
[Part1](https://github.com/wekan/wekan/commit/4a205fcfcb40438faead3bf8973b10b8e42974f0),
|
||||
[Part2](https://github.com/wekan/wekan/commit/6cb4b9fe4a086202d642de54464088e0a1122ec0).
|
||||
Thanks to Samunosuke, pgh2357 and xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v4.59 2020-12-10 Wekan release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Fix not all checklist items being imported/cloned](https://github.com/wekan/wekan/pull/3389).
|
||||
Thanks to daniel-eder.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v4.58 2020-12-09 Wekan release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Fix issues when duplicating board](https://github.com/wekan/wekan/pull/3387).
|
||||
Thanks to daniel-eder.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v4.57 2020-12-08 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Helm: Introduce secretEnv for secret value provisioning](https://github.com/wekan/wekan/pull/3382).
|
||||
Thanks to ThoreKr.
|
||||
- REST API: List attachments of a board, with download URLs of attachments. In Progress.
|
||||
[Part 1](https://github.com/wekan/wekan/commit/bf94161f30adf9dec6aa41af6946ba54c1573a44),
|
||||
[Part 2](https://github.com/wekan/wekan/commit/2ec53b27d14049bc9622861492cac301512a1e33),
|
||||
[Part 3](https://github.com/wekan/wekan/commit/36e29a405ee943d15e6e1bd9ac02ecefb7a7a06f).
|
||||
For using this, Python code example:
|
||||
https://github.com/wekan/wekan/wiki/New-card-with-Python3-and-REST-API .
|
||||
Thanks to xet7.
|
||||
- REST API: Added Wekan REST API Python CLI, for adding card, etc. In Progress,
|
||||
downloading attachments does not work yet.
|
||||
[Part1](https://github.com/wekan/wekan/commit/051f7b2769c51404063e7f0ddf85fbd0f9508a88),
|
||||
[Part2](https://github.com/wekan/wekan/commit/387f0600ce1389aab955cc125d331dcd5eeeafdd).
|
||||
Thanks to xet7.
|
||||
- [Drag handles at checklist items on mobile view](https://github.com/wekan/wekan/pull/3342).
|
||||
Thanks to mfilser.
|
||||
|
||||
and adds the following updates:
|
||||
|
||||
- [Upgrade to Meteor 1.12](https://github.com/wekan/wekan/commit/7a6abaac44b1235021dc7cc25e3224515c64a068).
|
||||
Thanks to Meteor developers.
|
||||
- [Upgrade to Node 12.20.0](https://github.com/wekan/wekan/commit/015f4d671d136a4a344fe82e2a6bcbe0c2be6cfd).
|
||||
Thanks to Node developers.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Fixed Quay Docker builds that failed](https://github.com/wekan/wekan/issues/3380)
|
||||
because of Docker Hub rate limits by copying base images from Docker Hub to Quay.
|
||||
[Part1](https://github.com/wekan/wekan/commit/4537971300c6ffcc85b7dd930867eb942bd22f86),
|
||||
[Part2](https://github.com/wekan/wekan/commit/2b2884d996b8fc6101eff50db058639631eb5945),
|
||||
[Part3](https://github.com/wekan/wekan/commit/c09758fb913d73e9229f43d17663b3c4715a62b9).
|
||||
Thanks to xet7.
|
||||
- [Hide duplicate create board button, because it did not show board templates
|
||||
correctly](https://github.com/wekan/wekan/commit/a7977a8fc7f171d046a228f81fb0cd481b0ccc41).
|
||||
Thanks to xet7.
|
||||
- [Minicard, reduce space after assignees label](https://github.com/wekan/wekan/pull/3385).
|
||||
Thanks to mfilser.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v4.56 2020-11-30 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
+6
-2
@@ -1,6 +1,10 @@
|
||||
FROM ubuntu:rolling
|
||||
FROM quay.io/wekan/ubuntu:groovy-20201125.2
|
||||
LABEL maintainer="wekan"
|
||||
|
||||
# 2020-12-03:
|
||||
# - Above Ubuntu base image copied from Docker Hub ubuntu:groovy-20201125.2
|
||||
# to Quay to avoid Docker Hub rate limits.
|
||||
|
||||
# Set the environment variables (defaults where required)
|
||||
# DOES NOT WORK: paxctl fix for alpine linux: https://github.com/wekan/wekan/issues/1303
|
||||
# ENV BUILD_DEPS="paxctl"
|
||||
@@ -8,7 +12,7 @@ ARG DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
ENV BUILD_DEPS="apt-utils libarchive-tools gnupg gosu wget curl bzip2 g++ build-essential git ca-certificates python3" \
|
||||
DEBUG=false \
|
||||
NODE_VERSION=v12.19.1 \
|
||||
NODE_VERSION=v12.20.0 \
|
||||
METEOR_RELEASE=1.10.2 \
|
||||
USE_EDGE=false \
|
||||
METEOR_EDGE=1.5-beta.17 \
|
||||
|
||||
+2
-2
@@ -4,7 +4,7 @@ FROM amd64/alpine:3.7 AS builder
|
||||
ENV QEMU_VERSION=v4.2.0-6 \
|
||||
QEMU_ARCHITECTURE=aarch64 \
|
||||
NODE_ARCHITECTURE=linux-arm64 \
|
||||
NODE_VERSION=v12.19.1 \
|
||||
NODE_VERSION=v12.20.0 \
|
||||
WEKAN_VERSION=3.96 \
|
||||
WEKAN_ARCHITECTURE=arm64
|
||||
|
||||
@@ -40,7 +40,7 @@ LABEL maintainer="wekan"
|
||||
# Set the environment variables (defaults where required)
|
||||
ENV QEMU_ARCHITECTURE=aarch64 \
|
||||
NODE_ARCHITECTURE=linux-arm64 \
|
||||
NODE_VERSION=v12.19.1 \
|
||||
NODE_VERSION=v12.20.0 \
|
||||
NODE_ENV=production \
|
||||
NPM_VERSION=latest \
|
||||
WITH_API=true \
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
appId: wekan-public/apps/77b94f60-dec9-0136-304e-16ff53095928
|
||||
appVersion: "v4.56.0"
|
||||
appVersion: "v4.63.0"
|
||||
files:
|
||||
userUploads:
|
||||
- README.md
|
||||
|
||||
@@ -0,0 +1,251 @@
|
||||
#! /usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# vi:ts=4:et
|
||||
|
||||
# Wekan API Python CLI, originally from here, where is more details:
|
||||
# https://github.com/wekan/wekan/wiki/New-card-with-Python3-and-REST-API
|
||||
|
||||
try:
|
||||
# python 3
|
||||
from urllib.parse import urlencode
|
||||
except ImportError:
|
||||
# python 2
|
||||
from urllib import urlencode
|
||||
|
||||
import json
|
||||
import requests
|
||||
import sys
|
||||
|
||||
arguments = len(sys.argv) - 1
|
||||
|
||||
if arguments == 0:
|
||||
print("=== Wekan API Python CLI: Shows IDs for addcard ===")
|
||||
print("AUTHORID is USERID that writes card.")
|
||||
print("If *nix: chmod +x api.py => ./api.py users")
|
||||
print("Syntax:")
|
||||
print(" python3 api.py users # All users")
|
||||
print(" python3 api.py boards USERID # Boards of USERID")
|
||||
print(" python3 api.py board BOARDID # Info of BOARDID")
|
||||
print(" python3 api.py swimlanes BOARDID # Swimlanes of BOARDID")
|
||||
print(" python3 api.py lists BOARDID # Lists of BOARDID")
|
||||
print(" python3 api.py createlist BOARDID LISTTITLE # Create list")
|
||||
print(" python3 api.py addcard AUTHORID BOARDID SWIMLANEID LISTID CARDTITLE CARDDESCRIPTION")
|
||||
print(" python3 api.py listattachments BOARDID # List attachments")
|
||||
# TODO:
|
||||
# print(" python3 api.py attachmentdownload BOARDID ATTACHMENTID # One attachment as file")
|
||||
# print(" python3 api.py attachmentsdownload BOARDID # All attachments as files")
|
||||
exit
|
||||
|
||||
# ------- SETTINGS START -------------
|
||||
|
||||
# Username is your Wekan username or email address.
|
||||
# OIDC/OAuth2 etc uses email address as username.
|
||||
|
||||
username = 'testtest'
|
||||
|
||||
password = 'testtest'
|
||||
|
||||
wekanurl = 'http://localhost:4000/'
|
||||
|
||||
# ------- SETTINGS END -------------
|
||||
|
||||
"""
|
||||
EXAMPLE:
|
||||
|
||||
python3 api.py
|
||||
|
||||
OR:
|
||||
chmod +x api.py
|
||||
./api.py
|
||||
|
||||
=== Wekan API Python CLI: Shows IDs for addcard ===
|
||||
AUTHORID is USERID that writes card.
|
||||
Syntax:
|
||||
python3 api.py users # All users
|
||||
python3 api.py boards USERID # Boards of USERID
|
||||
python3 api.py board BOARDID # Info of BOARDID
|
||||
python3 api.py swimlanes BOARDID # Swimlanes of BOARDID
|
||||
python3 api.py lists BOARDID # Lists of BOARDID
|
||||
python3 api.py createlist BOARDID LISTTITLE # Create list
|
||||
python3 api.py addcard AUTHORID BOARDID SWIMLANEID LISTID CARDTITLE CARDDESCRIPTION
|
||||
python3 api.py listattachments BOARDID # List attachments
|
||||
python3 api.py attachmentjson BOARDID ATTACHMENTID # One attachment as JSON base64
|
||||
python3 api.py attachmentbinary BOARDID ATTACHMENTID # One attachment as binary file
|
||||
|
||||
=== USERS ===
|
||||
|
||||
python3 api.py users
|
||||
|
||||
=> abcd1234
|
||||
|
||||
=== BOARDS ===
|
||||
|
||||
python3 api.py boards abcd1234
|
||||
|
||||
|
||||
=== SWIMLANES ===
|
||||
|
||||
python3 api.py swimlanes dYZ
|
||||
|
||||
[{"_id":"Jiv","title":"Default"}
|
||||
]
|
||||
|
||||
=== LISTS ===
|
||||
|
||||
python3 api.py lists dYZ
|
||||
|
||||
[]
|
||||
|
||||
There is no lists, so create a list:
|
||||
|
||||
=== CREATE LIST ===
|
||||
|
||||
python3 api.py createlist dYZ 'Test'
|
||||
|
||||
{"_id":"7Kp"}
|
||||
|
||||
# python3 api.py addcard AUTHORID BOARDID SWIMLANEID LISTID CARDTITLE CARDDESCRIPTION
|
||||
|
||||
python3 api.py addcard ppg dYZ Jiv 7Kp 'Test card' 'Test description'
|
||||
|
||||
=== LIST ATTACHMENTS WITH DOWNLOAD URLs ====
|
||||
|
||||
python3 api.py listattachments BOARDID
|
||||
|
||||
"""
|
||||
|
||||
# ------- API URL GENERATION START -----------
|
||||
|
||||
loginurl = 'users/login'
|
||||
wekanloginurl = wekanurl + loginurl
|
||||
apiboards = 'api/boards/'
|
||||
apiattachments = 'api/attachments/'
|
||||
apiusers = 'api/users'
|
||||
e = 'export'
|
||||
s = '/'
|
||||
l = 'lists'
|
||||
sw = 'swimlane'
|
||||
sws = 'swimlanes'
|
||||
cs = 'cards'
|
||||
bs = 'boards'
|
||||
atl = 'attachmentslist'
|
||||
at = 'attachment'
|
||||
ats = 'attachments'
|
||||
users = wekanurl + apiusers
|
||||
|
||||
# ------- API URL GENERATION END -----------
|
||||
|
||||
# ------- LOGIN TOKEN START -----------
|
||||
|
||||
data = {"username": username, "password": password}
|
||||
body = requests.post(wekanloginurl, data=data)
|
||||
d = body.json()
|
||||
apikey = d['token']
|
||||
|
||||
# ------- LOGIN TOKEN END -----------
|
||||
|
||||
if arguments == 7:
|
||||
|
||||
if sys.argv[1] == 'addcard':
|
||||
# ------- WRITE TO CARD START -----------
|
||||
authorid = sys.argv[2]
|
||||
boardid = sys.argv[3]
|
||||
swimlaneid = sys.argv[4]
|
||||
listid = sys.argv[5]
|
||||
cardtitle = sys.argv[6]
|
||||
carddescription = sys.argv[7]
|
||||
cardtolist = wekanurl + apiboards + boardid + s + l + s + listid + s + cs
|
||||
# Write to card
|
||||
headers = {'Accept': 'application/json', 'Authorization': 'Bearer {}'.format(apikey)}
|
||||
post_data = {'authorId': '{}'.format(authorid), 'title': '{}'.format(cardtitle), 'description': '{}'.format(carddescription), 'swimlaneId': '{}'.format(swimlaneid)}
|
||||
body = requests.post(cardtolist, data=post_data, headers=headers)
|
||||
print(body.text)
|
||||
# ------- WRITE TO CARD END -----------
|
||||
|
||||
if arguments == 3:
|
||||
|
||||
if sys.argv[1] == 'createlist':
|
||||
|
||||
# ------- CREATE LIST START -----------
|
||||
boardid = sys.argv[2]
|
||||
listtitle = sys.argv[3]
|
||||
list = wekanurl + apiboards + boardid + s + l
|
||||
headers = {'Accept': 'application/json', 'Authorization': 'Bearer {}'.format(apikey)}
|
||||
post_data = {'title': '{}'.format(listtitle)}
|
||||
body = requests.post(list, data=post_data, headers=headers)
|
||||
print("=== CREATE LIST ===\n")
|
||||
print(body.text)
|
||||
# ------- CREATE LIST END -----------
|
||||
|
||||
if arguments == 2:
|
||||
|
||||
# ------- BOARDS LIST START -----------
|
||||
userid = sys.argv[2]
|
||||
boards = users + s + userid + s + bs
|
||||
if sys.argv[1] == 'boards':
|
||||
headers = {'Accept': 'application/json', 'Authorization': 'Bearer {}'.format(apikey)}
|
||||
#post_data = {'userId': '{}'.format(userid)}
|
||||
body = requests.get(boards, headers=headers)
|
||||
print("=== BOARDS ===\n")
|
||||
data2 = body.text.replace('}',"}\n")
|
||||
print(data2)
|
||||
# ------- BOARDS LIST END -----------
|
||||
if sys.argv[1] == 'board':
|
||||
|
||||
# ------- BOARD INFO START -----------
|
||||
boardid = sys.argv[2]
|
||||
board = wekanurl + apiboards + boardid
|
||||
headers = {'Accept': 'application/json', 'Authorization': 'Bearer {}'.format(apikey)}
|
||||
body = requests.get(board, headers=headers)
|
||||
print("=== BOARD ===\n")
|
||||
data2 = body.text.replace('}',"}\n")
|
||||
print(data2)
|
||||
# ------- BOARD INFO END -----------
|
||||
|
||||
if sys.argv[1] == 'swimlanes':
|
||||
boardid = sys.argv[2]
|
||||
swimlanes = wekanurl + apiboards + boardid + s + sws
|
||||
# ------- SWIMLANES OF BOARD START -----------
|
||||
headers = {'Accept': 'application/json', 'Authorization': 'Bearer {}'.format(apikey)}
|
||||
print("=== SWIMLANES ===\n")
|
||||
body = requests.get(swimlanes, headers=headers)
|
||||
data2 = body.text.replace('}',"}\n")
|
||||
print(data2)
|
||||
# ------- SWIMLANES OF BOARD END -----------
|
||||
|
||||
if sys.argv[1] == 'lists':
|
||||
|
||||
# ------- LISTS OF BOARD START -----------
|
||||
boardid = sys.argv[2]
|
||||
attachments = wekanurl + apiboards + boardid
|
||||
headers = {'Accept': 'application/json', 'Authorization': 'Bearer {}'.format(apikey)}
|
||||
print("=== LISTS ===\n")
|
||||
body = requests.get(lists, headers=headers)
|
||||
data2 = body.text.replace('}',"}\n")
|
||||
print(data2)
|
||||
# ------- LISTS OF BOARD END -----------
|
||||
|
||||
if sys.argv[1] == 'listattachments':
|
||||
|
||||
# ------- LISTS OF ATTACHMENTS START -----------
|
||||
boardid = sys.argv[2]
|
||||
listattachments = wekanurl + apiboards + boardid + s + ats
|
||||
headers = {'Accept': 'application/json', 'Authorization': 'Bearer {}'.format(apikey)}
|
||||
print("=== LIST OF ATTACHMENTS ===\n")
|
||||
body = requests.get(listattachments, headers=headers)
|
||||
data2 = body.text.replace('}',"}\n")
|
||||
print(data2)
|
||||
# ------- LISTS OF ATTACHMENTS END -----------
|
||||
|
||||
if arguments == 1:
|
||||
|
||||
if sys.argv[1] == 'users':
|
||||
|
||||
# ------- LIST OF USERS START -----------
|
||||
headers = {'Accept': 'application/json', 'Authorization': 'Bearer {}'.format(apikey)}
|
||||
print(users)
|
||||
print("=== USERS ===\n")
|
||||
body = requests.get(users, headers=headers)
|
||||
data2 = body.text.replace('}',"}\n")
|
||||
print(data2)
|
||||
# ------- LIST OF USERS END -----------
|
||||
@@ -3,6 +3,10 @@ BlazeComponent.extendComponent({
|
||||
this.subscribe('archivedBoards');
|
||||
},
|
||||
|
||||
isBoardAdmin() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
},
|
||||
|
||||
archivedBoards() {
|
||||
return Boards.find(
|
||||
{ archived: true },
|
||||
|
||||
@@ -211,7 +211,12 @@ BlazeComponent.extendComponent({
|
||||
}
|
||||
|
||||
// Disable drag-dropping if the current user is not a board member
|
||||
$swimlanesDom.sortable('option', 'disabled', !userIsMember());
|
||||
//$swimlanesDom.sortable('option', 'disabled', !userIsMember());
|
||||
$swimlanesDom.sortable(
|
||||
'option',
|
||||
'disabled',
|
||||
!Meteor.user().isBoardAdmin(),
|
||||
);
|
||||
});
|
||||
|
||||
function userIsMember() {
|
||||
|
||||
@@ -46,9 +46,10 @@ template(name="attachmentsGalery")
|
||||
| {{_ 'remove-cover'}}
|
||||
else
|
||||
| {{_ 'add-cover'}}
|
||||
a.js-confirm-delete
|
||||
i.fa.fa-close
|
||||
| {{_ 'delete'}}
|
||||
if currentUser.isBoardAdmin
|
||||
a.js-confirm-delete
|
||||
i.fa.fa-close
|
||||
| {{_ 'delete'}}
|
||||
|
||||
if currentUser.isBoardMember
|
||||
unless currentUser.isCommentOnly
|
||||
|
||||
@@ -45,6 +45,12 @@ Template.attachmentsGalery.events({
|
||||
},
|
||||
});
|
||||
|
||||
Template.attachmentsGalery.helpers({
|
||||
isBoardAdmin() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
},
|
||||
});
|
||||
|
||||
Template.previewAttachedImagePopup.events({
|
||||
'click .js-large-image-clicked'() {
|
||||
Popup.close();
|
||||
|
||||
@@ -354,10 +354,11 @@ template(name="cardDetailsActionsPopup")
|
||||
a.js-start-voting
|
||||
i.fa.fa-thumbs-up
|
||||
| {{_ 'card-edit-voting'}}
|
||||
li
|
||||
a.js-custom-fields
|
||||
i.fa.fa-list-alt
|
||||
| {{_ 'card-edit-custom-fields'}}
|
||||
if currentUser.isBoardAdmin
|
||||
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'}}
|
||||
@@ -382,10 +383,11 @@ template(name="cardDetailsActionsPopup")
|
||||
| {{_ 'moveCardToBottom-title'}}
|
||||
hr
|
||||
ul.pop-over-list
|
||||
li
|
||||
a.js-move-card
|
||||
i.fa.fa-arrow-right
|
||||
| {{_ 'moveCardPopup-title'}}
|
||||
if currentUser.isBoardAdmin
|
||||
li
|
||||
a.js-move-card
|
||||
i.fa.fa-arrow-right
|
||||
| {{_ 'moveCardPopup-title'}}
|
||||
unless currentUser.isWorker
|
||||
li
|
||||
a.js-copy-card
|
||||
@@ -562,7 +564,8 @@ template(name="cardMorePopup")
|
||||
br
|
||||
| {{_ 'added'}}
|
||||
span.date(title=card.createdAt) {{ moment createdAt 'LLL' }}
|
||||
a.js-delete(title="{{_ 'card-delete-notice'}}") {{_ 'delete'}}
|
||||
if currentUser.isBoardAdmin
|
||||
a.js-delete(title="{{_ 'card-delete-notice'}}") {{_ 'delete'}}
|
||||
|
||||
template(name="setCardColorPopup")
|
||||
form.edit-label
|
||||
@@ -609,7 +612,8 @@ template(name="cardStartVotingPopup")
|
||||
|
||||
button.primary.js-submit {{_ 'save'}}
|
||||
if getVoteQuestion
|
||||
button.js-remove-vote.negate.wide.right {{_ 'delete'}}
|
||||
if currentUser.isBoardAdmin
|
||||
button.js-remove-vote.negate.wide.right {{_ 'delete'}}
|
||||
|
||||
template(name="positiveVoteMembersPopup")
|
||||
ul.pop-over-list.js-card-member-list
|
||||
|
||||
@@ -567,6 +567,10 @@ Template.cardDetailsActionsPopup.helpers({
|
||||
return this.findWatcher(Meteor.userId());
|
||||
},
|
||||
|
||||
isBoardAdmin() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
},
|
||||
|
||||
canModifyCard() {
|
||||
return (
|
||||
Meteor.user() &&
|
||||
|
||||
@@ -103,6 +103,8 @@ template(name='checklistItemDetail')
|
||||
.check-box-container
|
||||
.check-box.materialCheckBox(class="{{#if item.isFinished }}is-checked{{/if}}")
|
||||
.item-title.js-open-inlined-form.is-editable(class="{{#if item.isFinished }}is-checked{{/if}}")
|
||||
if isMiniScreenOrShowDesktopDragHandles
|
||||
span.fa.checklistitem-handle(class="fa-arrows" title="{{_ 'dragChecklistItem'}}")
|
||||
+viewer
|
||||
= item.title
|
||||
else
|
||||
|
||||
@@ -55,11 +55,13 @@ BlazeComponent.extendComponent({
|
||||
self.autorun(() => {
|
||||
const $itemsDom = $(self.itemsDom);
|
||||
if ($itemsDom.data('uiSortable') || $itemsDom.data('sortable')) {
|
||||
$(self.itemsDom).sortable(
|
||||
'option',
|
||||
'disabled',
|
||||
!userIsMember() || Utils.isMiniScreen(),
|
||||
);
|
||||
$(self.itemsDom).sortable('option', 'disabled', !userIsMember());
|
||||
if (Utils.isMiniScreenOrShowDesktopDragHandles()) {
|
||||
$(self.itemsDom).sortable({
|
||||
handle: 'span.fa.checklistitem-handle',
|
||||
appendTo: 'parent',
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
@@ -156,6 +156,9 @@ textarea.js-add-checklist-item, textarea.js-edit-checklist-item
|
||||
word-wrap: break-word
|
||||
max-width: 420px
|
||||
|
||||
span.fa.checklistitem-handle
|
||||
float: right
|
||||
|
||||
.js-delete-checklist-item
|
||||
margin: 0 0 0.5em 1.33em
|
||||
@extends .delete-text
|
||||
|
||||
@@ -85,7 +85,6 @@ template(name="minicard")
|
||||
.minicard-assignees.js-minicard-assignees
|
||||
each getAssignees
|
||||
+userAvatar(userId=this)
|
||||
hr
|
||||
|
||||
if getMembers
|
||||
.minicard-members.js-minicard-members
|
||||
|
||||
@@ -165,7 +165,7 @@
|
||||
.minicard-members,
|
||||
.minicard-assignees
|
||||
float: right
|
||||
margin: 2px -8px 12px 0
|
||||
margin: 2px -8px 2px 0
|
||||
|
||||
.member
|
||||
float: right
|
||||
|
||||
@@ -2,10 +2,10 @@ template(name="subtasks")
|
||||
h3.card-details-item-title
|
||||
i.fa.fa-sitemap
|
||||
| {{_ 'subtasks'}}
|
||||
if toggleDeleteDialog.get
|
||||
.board-overlay#card-details-overlay
|
||||
+subtaskDeleteDialog(subtask = subtaskToDelete)
|
||||
|
||||
if currentUser.isBoardAdmin
|
||||
if toggleDeleteDialog.get
|
||||
.board-overlay#card-details-overlay
|
||||
+subtaskDeleteDialog(subtask = subtaskToDelete)
|
||||
|
||||
.card-subtasks-items
|
||||
each subtask in currentCard.subtasks
|
||||
@@ -28,7 +28,8 @@ template(name="subtaskDetail")
|
||||
span
|
||||
a.js-view-subtask(title="{{ subtask.title }}") {{_ "view-it"}}
|
||||
if canModifyCard
|
||||
a.js-delete-subtask.toggle-delete-subtask-dialog {{_ "delete"}}...
|
||||
if currentUser.isBoardAdmin
|
||||
a.js-delete-subtask.toggle-delete-subtask-dialog {{_ "delete"}}...
|
||||
|
||||
if canModifyCard
|
||||
h2.title.js-open-inlined-form.is-editable
|
||||
@@ -68,7 +69,8 @@ template(name="editSubtaskItemForm")
|
||||
a.fa.fa-times-thin.js-close-inlined-form
|
||||
span(title=createdAt) {{ moment createdAt }}
|
||||
if canModifyCard
|
||||
a.js-delete-subtask-item {{_ "delete"}}...
|
||||
if currentUser.isBoardAdmin
|
||||
a.js-delete-subtask-item {{_ "delete"}}...
|
||||
|
||||
template(name="subtasksItems")
|
||||
.subtasks-items.js-subtasks-items
|
||||
|
||||
@@ -43,8 +43,9 @@ template(name="listHeader")
|
||||
if canSeeAddCard
|
||||
a.js-add-card.fa.fa-plus.list-header-plus-icon
|
||||
a.fa.fa-navicon.js-open-list-menu
|
||||
if showDesktopDragHandles
|
||||
a.list-header-handle.handle.fa.fa-arrows.js-list-handle
|
||||
if currentUser.isBoardAdmin
|
||||
if showDesktopDragHandles
|
||||
a.list-header-handle.handle.fa.fa-arrows.js-list-handle
|
||||
|
||||
template(name="editListTitleForm")
|
||||
.list-composer
|
||||
@@ -115,8 +116,9 @@ template(name="listMorePopup")
|
||||
input.inline-input(type="text" readonly value="{{ rootUrl }}")
|
||||
| {{_ 'added'}}
|
||||
span.date(title=list.createdAt) {{ moment createdAt 'LLL' }}
|
||||
unless currentUser.isWorker
|
||||
a.js-delete {{_ 'delete'}}
|
||||
//unless currentUser.isWorker
|
||||
// if currentUser.isBoardAdmin
|
||||
// a.js-delete {{_ 'delete'}}
|
||||
|
||||
template(name="listDeletePopup")
|
||||
p {{_ "list-delete-pop"}}
|
||||
|
||||
@@ -104,6 +104,10 @@ BlazeComponent.extendComponent({
|
||||
}).register('listHeader');
|
||||
|
||||
Template.listHeader.helpers({
|
||||
isBoardAdmin() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
},
|
||||
|
||||
showDesktopDragHandles() {
|
||||
currentUser = Meteor.user();
|
||||
if (currentUser) {
|
||||
@@ -117,6 +121,10 @@ Template.listHeader.helpers({
|
||||
});
|
||||
|
||||
Template.listActionPopup.helpers({
|
||||
isBoardAdmin() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
},
|
||||
|
||||
isWipLimitEnabled() {
|
||||
return Template.currentData().getWipLimit('enabled');
|
||||
},
|
||||
@@ -254,6 +262,12 @@ Template.listMorePopup.events({
|
||||
}),
|
||||
});
|
||||
|
||||
Template.listHeader.helpers({
|
||||
isBoardAdmin() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
},
|
||||
});
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {
|
||||
this.currentList = this.currentData();
|
||||
|
||||
@@ -50,8 +50,13 @@ template(name="header")
|
||||
else
|
||||
li.current {{_ 'quick-access-description'}}
|
||||
|
||||
a#header-new-board-icon.js-create-board
|
||||
i.fa.fa-plus(title="Create a new board")
|
||||
// Next line is used only for spacing at header,
|
||||
// there is no visible clickable icon.
|
||||
#header-new-board-icon
|
||||
// Hide duplicate create board button,
|
||||
// because it did not show board templates correctly.
|
||||
//a#header-new-board-icon.js-create-board
|
||||
// i.fa.fa-plus(title="Create a new board")
|
||||
|
||||
+notifications
|
||||
|
||||
|
||||
@@ -112,7 +112,7 @@ template(name="editUserPopup")
|
||||
label.hide.userId(type="text" value=user._id)
|
||||
label
|
||||
| {{_ 'fullname'}}
|
||||
input.js-profile-fullname(type="text" value=user.profile.fullname)
|
||||
input.js-profile-fullname(type="text" value=user.profile.fullname required)
|
||||
label
|
||||
| {{_ 'username'}}
|
||||
span.error.hide.username-taken
|
||||
@@ -120,7 +120,7 @@ template(name="editUserPopup")
|
||||
if isLdap
|
||||
input.js-profile-username(type="text" value=user.username readonly)
|
||||
else
|
||||
input.js-profile-username(type="text" value=user.username)
|
||||
input.js-profile-username(type="text" value=user.username required)
|
||||
label
|
||||
| {{_ 'email'}}
|
||||
span.error.hide.email-taken
|
||||
@@ -128,7 +128,7 @@ template(name="editUserPopup")
|
||||
if isLdap
|
||||
input.js-profile-email(type="email" value="{{user.emails.[0].address}}" readonly)
|
||||
else
|
||||
input.js-profile-email(type="email" value="{{user.emails.[0].address}}")
|
||||
input.js-profile-email(type="email" value="{{user.emails.[0].address}}" required)
|
||||
label
|
||||
| {{_ 'admin'}}
|
||||
select.select-role.js-profile-isadmin
|
||||
@@ -153,15 +153,13 @@ template(name="editUserPopup")
|
||||
input.js-profile-password(type="password")
|
||||
div.buttonsContainer
|
||||
input.primary.wide(type="submit" value="{{_ 'save'}}")
|
||||
// div
|
||||
// input#deleteButton.primary.wide(type="button" value="{{_ 'delete'}}")
|
||||
|
||||
template(name="newUserPopup")
|
||||
form
|
||||
//label.hide.userId(type="text" value=user._id)
|
||||
label
|
||||
| {{_ 'fullname'}}
|
||||
input.js-profile-fullname(type="text" value="")
|
||||
input.js-profile-fullname(type="text" value="" required)
|
||||
label
|
||||
| {{_ 'username'}}
|
||||
span.error.hide.username-taken
|
||||
@@ -169,7 +167,7 @@ template(name="newUserPopup")
|
||||
//if isLdap
|
||||
// input.js-profile-username(type="text" value=user.username readonly)
|
||||
//else
|
||||
input.js-profile-username(type="text" value="")
|
||||
input.js-profile-username(type="text" value="" required)
|
||||
label
|
||||
| {{_ 'email'}}
|
||||
span.error.hide.email-taken
|
||||
@@ -177,7 +175,7 @@ template(name="newUserPopup")
|
||||
//if isLdap
|
||||
// input.js-profile-email(type="email" value="{{user.emails.[0].address}}" readonly)
|
||||
//else
|
||||
input.js-profile-email(type="email" value="")
|
||||
input.js-profile-email(type="email" value="" required)
|
||||
label
|
||||
| {{_ 'admin'}}
|
||||
select.select-role.js-profile-isadmin
|
||||
@@ -199,7 +197,7 @@ template(name="newUserPopup")
|
||||
hr
|
||||
label
|
||||
| {{_ 'password'}}
|
||||
input.js-profile-password(type="password")
|
||||
input.js-profile-password(type="password" required)
|
||||
div.buttonsContainer
|
||||
input.primary.wide(type="submit" value="{{_ 'save'}}")
|
||||
|
||||
@@ -209,3 +207,21 @@ template(name="settingsUserPopup")
|
||||
a.impersonate-user
|
||||
i.fa.fa-user
|
||||
| {{_ 'impersonate-user'}}
|
||||
// Delete is not enabled yet, because it does leave empty user avatars
|
||||
// to boards: boards members, card members and assignees have
|
||||
// empty users. See:
|
||||
// - wekan/client/components/settings/peopleBody.jade deleteButton
|
||||
// - wekan/client/components/settings/peopleBody.js deleteButton
|
||||
// - wekan/client/components/sidebar/sidebar.js Popup.afterConfirm('removeMember'
|
||||
// that does now remove member from board, card members and assignees correctly,
|
||||
// but that should be used to remove user from all boards similarly
|
||||
// - wekan/models/users.js Delete is not enabled
|
||||
//li
|
||||
// br
|
||||
// br
|
||||
// hr
|
||||
//li
|
||||
// form
|
||||
// label.hide.userId(type="text" value=user._id)
|
||||
// div.buttonsContainer
|
||||
// input#deleteButton.card-details-red.right.wide(type="button" value="{{_ 'delete'}}")
|
||||
@@ -226,8 +226,14 @@ Template.editUserPopup.events({
|
||||
|
||||
const isChangePassword = password.length > 0;
|
||||
const isChangeUserName = username !== user.username;
|
||||
|
||||
// If previously email address has not been set, it is undefined,
|
||||
// check for undefined, and allow adding email address.
|
||||
const isChangeEmail =
|
||||
email.toLowerCase() !== user.emails[0].address.toLowerCase();
|
||||
email.toLowerCase() !==
|
||||
(typeof user.emails !== 'undefined'
|
||||
? user.emails[0].address.toLowerCase()
|
||||
: false);
|
||||
|
||||
Users.update(this.userId, {
|
||||
$set: {
|
||||
@@ -297,11 +303,6 @@ Template.editUserPopup.events({
|
||||
});
|
||||
} else Popup.close();
|
||||
},
|
||||
|
||||
'click #deleteButton': Popup.afterConfirm('userDelete', function() {
|
||||
Users.remove(this.userId);
|
||||
Popup.close();
|
||||
}),
|
||||
});
|
||||
|
||||
Template.newUserPopup.events({
|
||||
@@ -356,4 +357,58 @@ Template.settingsUserPopup.events({
|
||||
}
|
||||
});
|
||||
},
|
||||
'click #deleteButton'(event) {
|
||||
event.preventDefault();
|
||||
/*
|
||||
// Delete is not enabled yet, because it does leave empty user avatars
|
||||
// to boards: boards members, card members and assignees have
|
||||
// empty users. See:
|
||||
// - wekan/client/components/settings/peopleBody.jade deleteButton
|
||||
// - wekan/client/components/settings/peopleBody.js deleteButton
|
||||
// - wekan/client/components/sidebar/sidebar.js Popup.afterConfirm('removeMember'
|
||||
// that does now remove member from board, card members and assignees correctly,
|
||||
// but that should be used to remove user from all boards similarly
|
||||
// - wekan/models/users.js Delete is not enabled
|
||||
//
|
||||
//console.log('user id: ' + this.userId);
|
||||
//Popup.afterConfirm('userDelete', function(event) {
|
||||
//Boards.find({ members: this.userId }).forEach(board => {
|
||||
// console.log('board id: ' + board._id);
|
||||
//Cards.find({ boardId: board._id, members: this.userId }).forEach(card => {
|
||||
// card.unassignMember(this.userId);
|
||||
//});
|
||||
//Cards.find({ boardId: board._id, members: this.userId }).forEach(card => {
|
||||
// card.unassignMember(this.userId);
|
||||
//});
|
||||
//Cards.find({ boardId: board._id, assignees: this.userId }).forEach(card => {
|
||||
// card.unassignAssignee(this.userId);
|
||||
//});
|
||||
//Boards.findOne({ boardId: board._id }).removeMember(this.userId);
|
||||
//});
|
||||
//Users.remove(this.userId);
|
||||
*/
|
||||
Popup.close();
|
||||
},
|
||||
});
|
||||
|
||||
Template.settingsUserPopup.helpers({
|
||||
user() {
|
||||
return Users.findOne(this.userId);
|
||||
},
|
||||
authentications() {
|
||||
return Template.instance().authenticationMethods.get();
|
||||
},
|
||||
isSelected(match) {
|
||||
const userId = Template.instance().data.userId;
|
||||
const selected = Users.findOne(userId).authenticationMethod;
|
||||
return selected === match;
|
||||
},
|
||||
isLdap() {
|
||||
const userId = Template.instance().data.userId;
|
||||
const selected = Users.findOne(userId).authenticationMethod;
|
||||
return selected === 'ldap';
|
||||
},
|
||||
errorMessage() {
|
||||
return Template.instance().errorMessage.get();
|
||||
},
|
||||
});
|
||||
@@ -269,14 +269,16 @@ template(name="outgoingWebhooksPopup")
|
||||
|
||||
template(name="boardMenuPopup")
|
||||
ul.pop-over-list
|
||||
li
|
||||
a.js-open-rules-view(title="{{_ 'rules'}}")
|
||||
i.fa.fa-magic
|
||||
| {{_ 'rules'}}
|
||||
li
|
||||
a.js-custom-fields
|
||||
i.fa.fa-list-alt
|
||||
| {{_ 'custom-fields'}}
|
||||
if currentUser.isBoardAdmin
|
||||
li
|
||||
a.js-open-rules-view(title="{{_ 'rules'}}")
|
||||
i.fa.fa-magic
|
||||
| {{_ 'rules'}}
|
||||
if currentUser.isBoardAdmin
|
||||
li
|
||||
a.js-custom-fields
|
||||
i.fa.fa-list-alt
|
||||
| {{_ 'custom-fields'}}
|
||||
li
|
||||
a.js-open-archives
|
||||
i.fa.fa-archive
|
||||
@@ -297,14 +299,14 @@ template(name="boardMenuPopup")
|
||||
i.fa.fa-flag
|
||||
| {{_ 'language'}}
|
||||
unless isSandstorm
|
||||
if currentUser.isBoardAdmin
|
||||
hr
|
||||
ul.pop-over-list
|
||||
if withApi
|
||||
li
|
||||
a.js-export-board
|
||||
i.fa.fa-share-alt
|
||||
| {{_ 'export-board'}}
|
||||
hr
|
||||
ul.pop-over-list
|
||||
if withApi
|
||||
li
|
||||
a.js-export-board
|
||||
i.fa.fa-share-alt
|
||||
| {{_ 'export-board'}}
|
||||
if currentUser.isBoardAdmin
|
||||
li
|
||||
a.js-outgoing-webhooks
|
||||
i.fa.fa-globe
|
||||
@@ -317,7 +319,8 @@ template(name="boardMenuPopup")
|
||||
a.js-subtask-settings
|
||||
i.fa.fa-sitemap
|
||||
| {{_ 'subtask-settings'}}
|
||||
unless currentBoard.isTemplatesBoard
|
||||
unless currentBoard.isTemplatesBoard
|
||||
if currentUser.isBoardAdmin
|
||||
hr
|
||||
ul.pop-over-list
|
||||
li
|
||||
@@ -329,20 +332,22 @@ template(name="boardMenuPopup")
|
||||
if isSandstorm
|
||||
hr
|
||||
ul.pop-over-list
|
||||
li
|
||||
a.js-export-board
|
||||
i.fa.fa-share-alt
|
||||
| {{_ 'export-board'}}
|
||||
li
|
||||
a.js-import-board
|
||||
i.fa.fa-share-alt
|
||||
i.fa.fa-sign-in
|
||||
| {{_ 'import-board-c'}}
|
||||
li
|
||||
a.js-archive-board
|
||||
i.fa.fa-arrow-right
|
||||
i.fa.fa-archive
|
||||
| {{_ 'archive-board'}}
|
||||
if currentUser.isMember
|
||||
li
|
||||
a.js-export-board
|
||||
i.fa.fa-share-alt
|
||||
| {{_ 'export-board'}}
|
||||
li
|
||||
a.js-import-board
|
||||
i.fa.fa-share-alt
|
||||
i.fa.fa-sign-in
|
||||
| {{_ 'import-board-c'}}
|
||||
if currentUser.isBoardAdmin
|
||||
li
|
||||
a.js-archive-board
|
||||
i.fa.fa-arrow-right
|
||||
i.fa.fa-archive
|
||||
| {{_ 'archive-board'}}
|
||||
li
|
||||
a.js-outgoing-webhooks
|
||||
i.fa.fa-globe
|
||||
|
||||
@@ -155,6 +155,9 @@ Template.memberPopup.helpers({
|
||||
user() {
|
||||
return Users.findOne(this.userId);
|
||||
},
|
||||
isBoardAdmin() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
},
|
||||
memberType() {
|
||||
const type = Users.findOne(this.userId).isBoardAdmin() ? 'admin' : 'normal';
|
||||
if (type === 'normal') {
|
||||
@@ -224,6 +227,9 @@ Template.boardMenuPopup.onCreated(function() {
|
||||
});
|
||||
|
||||
Template.boardMenuPopup.helpers({
|
||||
isBoardAdmin() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
},
|
||||
withApi() {
|
||||
return Template.instance().apiEnabled.get();
|
||||
},
|
||||
@@ -249,11 +255,15 @@ Template.memberPopup.events({
|
||||
},
|
||||
'click .js-change-role': Popup.open('changePermissions'),
|
||||
'click .js-remove-member': Popup.afterConfirm('removeMember', function() {
|
||||
// This works from removing member from board, card members and assignees.
|
||||
const boardId = Session.get('currentBoard');
|
||||
const memberId = this.userId;
|
||||
Cards.find({ boardId, members: memberId }).forEach(card => {
|
||||
card.unassignMember(memberId);
|
||||
});
|
||||
Cards.find({ boardId, assignees: memberId }).forEach(card => {
|
||||
card.unassignAssignee(memberId);
|
||||
});
|
||||
Boards.findOne(boardId).removeMember(memberId);
|
||||
Popup.close();
|
||||
}),
|
||||
@@ -294,6 +304,9 @@ Template.membersWidget.helpers({
|
||||
return false;
|
||||
}
|
||||
},
|
||||
isBoardAdmin() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
},
|
||||
});
|
||||
|
||||
Template.membersWidget.events({
|
||||
@@ -475,6 +488,12 @@ Template.labelsWidget.events({
|
||||
'click .js-add-label': Popup.open('createLabel'),
|
||||
});
|
||||
|
||||
Template.labelsWidget.helpers({
|
||||
isBoardAdmin() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
},
|
||||
});
|
||||
|
||||
// Board members can assign people or labels by drag-dropping elements from the
|
||||
// sidebar to the cards on the board. In order to re-initialize the jquery-ui
|
||||
// plugin any time a draggable member or label is modified or removed we use a
|
||||
|
||||
@@ -5,8 +5,9 @@ template(name="archivesSidebar")
|
||||
unless isWorker
|
||||
p.quiet
|
||||
a.js-restore-all-cards {{_ 'restore-all'}}
|
||||
| -
|
||||
a.js-delete-all-cards {{_ 'delete-all'}}
|
||||
if currentUser.isBoardAdmin
|
||||
| -
|
||||
a.js-delete-all-cards {{_ 'delete-all'}}
|
||||
each archivedCards
|
||||
.minicard-wrapper.js-minicard
|
||||
+minicard(this)
|
||||
@@ -14,8 +15,9 @@ template(name="archivesSidebar")
|
||||
unless isWorker
|
||||
p.quiet
|
||||
a.js-restore-card {{_ 'restore'}}
|
||||
| -
|
||||
a.js-delete-card {{_ 'delete'}}
|
||||
if currentUser.isBoardAdmin
|
||||
| -
|
||||
a.js-delete-card {{_ 'delete'}}
|
||||
if cardIsInArchivedList
|
||||
p.quiet.small ({{_ 'warn-list-archived'}})
|
||||
else
|
||||
@@ -25,8 +27,9 @@ template(name="archivesSidebar")
|
||||
unless isWorker
|
||||
p.quiet
|
||||
a.js-restore-all-lists {{_ 'restore-all'}}
|
||||
| -
|
||||
a.js-delete-all-lists {{_ 'delete-all'}}
|
||||
if currentUser.isBoardAdmin
|
||||
| -
|
||||
a.js-delete-all-lists {{_ 'delete-all'}}
|
||||
ul.archived-lists
|
||||
each archivedLists
|
||||
li.archived-lists-item
|
||||
@@ -35,8 +38,9 @@ template(name="archivesSidebar")
|
||||
unless isWorker
|
||||
p.quiet
|
||||
a.js-restore-list {{_ 'restore'}}
|
||||
| -
|
||||
a.js-delete-list {{_ 'delete'}}
|
||||
if currentUser.isBoardAdmin
|
||||
| -
|
||||
a.js-delete-list {{_ 'delete'}}
|
||||
else
|
||||
li.no-items-message {{_ 'no-archived-lists'}}
|
||||
|
||||
@@ -44,8 +48,9 @@ template(name="archivesSidebar")
|
||||
unless isWorker
|
||||
p.quiet
|
||||
a.js-restore-all-swimlanes {{_ 'restore-all'}}
|
||||
| -
|
||||
a.js-delete-all-swimlanes {{_ 'delete-all'}}
|
||||
if currentUser.isBoardAdmin
|
||||
| -
|
||||
a.js-delete-all-swimlanes {{_ 'delete-all'}}
|
||||
ul.archived-lists
|
||||
each archivedSwimlanes
|
||||
li.archived-lists-item
|
||||
@@ -54,8 +59,9 @@ template(name="archivesSidebar")
|
||||
unless isWorker
|
||||
p.quiet
|
||||
a.js-restore-swimlane {{_ 'restore'}}
|
||||
| -
|
||||
a.js-delete-swimlane {{_ 'delete'}}
|
||||
if currentUser.isBoardAdmin
|
||||
| -
|
||||
a.js-delete-swimlane {{_ 'delete'}}
|
||||
else
|
||||
li.no-items-message {{_ 'no-archived-swimlanes'}}
|
||||
else
|
||||
|
||||
@@ -141,6 +141,9 @@ BlazeComponent.extendComponent({
|
||||
}).register('archivesSidebar');
|
||||
|
||||
Template.archivesSidebar.helpers({
|
||||
isBoardAdmin() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
},
|
||||
isWorker() {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
return (
|
||||
|
||||
@@ -155,7 +155,7 @@ template(name="multiselectionSidebar")
|
||||
i.fa.fa-check
|
||||
else if someSelectedElementHave 'member' _id
|
||||
i.fa.fa-ellipsis-h
|
||||
unless currentUser.isWorker
|
||||
if currentUser.isBoardAdmin
|
||||
hr
|
||||
a.sidebar-btn.js-move-selection
|
||||
i.fa.fa-share
|
||||
|
||||
@@ -134,6 +134,15 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
}).register('multiselectionSidebar');
|
||||
|
||||
Template.multiselectionSidebar.helpers({
|
||||
isBoardAdmin() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
},
|
||||
isCommentOnly() {
|
||||
return Meteor.user().isCommentOnly();
|
||||
},
|
||||
});
|
||||
|
||||
Template.disambiguateMultiLabelPopup.events({
|
||||
'click .js-remove-label'() {
|
||||
mutateSelectedCards('removeLabel', this._id);
|
||||
|
||||
@@ -15,8 +15,9 @@ template(name="swimlaneFixedHeader")
|
||||
= title
|
||||
.swimlane-header-menu
|
||||
unless currentUser.isCommentOnly
|
||||
a.fa.fa-plus.js-open-add-swimlane-menu.swimlane-header-plus-icon
|
||||
a.fa.fa-navicon.js-open-swimlane-menu
|
||||
if currentUser.isBoardAdmin
|
||||
a.fa.fa-plus.js-open-add-swimlane-menu.swimlane-header-plus-icon
|
||||
a.fa.fa-navicon.js-open-swimlane-menu
|
||||
unless isMiniScreen
|
||||
if showDesktopDragHandles
|
||||
a.swimlane-header-handle.handle.fa.fa-arrows.js-swimlane-header-handle
|
||||
|
||||
@@ -41,6 +41,12 @@ Template.swimlaneHeader.helpers({
|
||||
},
|
||||
});
|
||||
|
||||
Template.swimlaneFixedHeader.helpers({
|
||||
isBoardAdmin() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
},
|
||||
});
|
||||
|
||||
Template.swimlaneActionPopup.events({
|
||||
'click .js-set-swimlane-color': Popup.open('setSwimlaneColor'),
|
||||
'click .js-close-swimlane'(event) {
|
||||
@@ -50,6 +56,12 @@ Template.swimlaneActionPopup.events({
|
||||
},
|
||||
});
|
||||
|
||||
Template.swimlaneActionPopup.helpers({
|
||||
isCommentOnly() {
|
||||
return Meteor.user().isCommentOnly();
|
||||
},
|
||||
});
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {
|
||||
this.currentSwimlane = this.currentData();
|
||||
|
||||
@@ -45,18 +45,19 @@ template(name="listsGroup")
|
||||
template(name="addListForm")
|
||||
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'}}
|
||||
if currentUser.isBoardAdmin
|
||||
.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'}}
|
||||
@@ -122,7 +122,8 @@ function initSortable(boardComponent, $listsDom) {
|
||||
'option',
|
||||
'disabled',
|
||||
// Disable drag-dropping when user is not member/is worker
|
||||
!userIsMember() || Meteor.user().isWorker(),
|
||||
//!userIsMember() || Meteor.user().isWorker(),
|
||||
!Meteor.user().isBoardAdmin(),
|
||||
// Not disable drag-dropping while in multi-selection mode
|
||||
// MultiSelection.isActive() || !userIsMember(),
|
||||
);
|
||||
@@ -274,12 +275,13 @@ Template.swimlane.helpers({
|
||||
}
|
||||
},
|
||||
canSeeAddList() {
|
||||
return (
|
||||
return Meteor.user().isBoardAdmin();
|
||||
/*
|
||||
Meteor.user() &&
|
||||
Meteor.user().isBoardMember() &&
|
||||
!Meteor.user().isCommentOnly() &&
|
||||
!Meteor.user().isWorker()
|
||||
);
|
||||
*/
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -195,8 +195,6 @@ Utils = {
|
||||
const currentUser = Meteor.user();
|
||||
if (currentUser) {
|
||||
return (currentUser.profile || {}).showDesktopDragHandles;
|
||||
} else if (cookies.has('showDesktopDragHandles')) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
+4
-1
@@ -92,7 +92,10 @@ services:
|
||||
#-------------------------------------------------------------------------------------
|
||||
# ==== MONGODB AND METEOR VERSION ====
|
||||
# a) mongodb latest, like 3.2 - 4.4 or newer https://hub.docker.com/_/mongo?tab=description
|
||||
image: mongo:latest
|
||||
# 2020-12-03:
|
||||
# - Mongo image copied from Docker Hub mongo:4.4.2-bionic to Quay
|
||||
# to avoid Docker Hub rate limits.
|
||||
image: quay.io/wekan/mongo:4.4.2-bionic
|
||||
#-------------------------------------------------------------------------------------
|
||||
container_name: wekan-db
|
||||
restart: always
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: wekan
|
||||
version: 1.0.1
|
||||
version: 1.0.2
|
||||
apiVersion: v1
|
||||
description: Open Source kanban
|
||||
home: https://wekan.github.io/
|
||||
|
||||
@@ -43,6 +43,12 @@ spec:
|
||||
value: {{ .value | quote }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- range $key := .Values.secretEnv }}
|
||||
{{- if .value }}
|
||||
- name: {{ .name }}
|
||||
value: {{ .value | quote }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
|
||||
@@ -28,6 +28,14 @@ env:
|
||||
- name: ""
|
||||
value: ""
|
||||
|
||||
## Specify additional secret environmental variables for the
|
||||
## Deployment. These can e.g. be provided by a Secret and allow
|
||||
## to store passwords separately
|
||||
##
|
||||
secretEnv:
|
||||
- name: ""
|
||||
value: ""
|
||||
|
||||
service:
|
||||
type: NodePort
|
||||
port: 8080
|
||||
|
||||
+839
-839
File diff suppressed because it is too large.
Load diff
+839
-839
File diff suppressed because it is too large.
Load diff
+839
-839
File diff suppressed because it is too large.
Load diff
+839
-839
File diff suppressed because it is too large.
Load diff
+839
-839
File diff suppressed because it is too large.
Load diff
+839
-839
File diff suppressed because it is too large.
Load diff
+839
-839
File diff suppressed because it is too large.
Load diff
@@ -1753,6 +1753,41 @@ if (Meteor.isServer) {
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
//ATTACHMENTS REST API
|
||||
/**
|
||||
* @operation get_board_attachments
|
||||
* @summary Get the list of attachments of a board
|
||||
*
|
||||
* @param {string} boardId the board ID
|
||||
* @return_type [{attachmentId: string,
|
||||
* attachmentName: string,
|
||||
* attachmentType: string,
|
||||
* cardId: string,
|
||||
* listId: string,
|
||||
* swimlaneId: string}]
|
||||
*/
|
||||
JsonRoutes.add('GET', '/api/boards/:boardId/attachments', function(req, res) {
|
||||
const paramBoardId = req.params.boardId;
|
||||
Authentication.checkBoardAccess(req.userId, paramBoardId);
|
||||
JsonRoutes.sendResult(res, {
|
||||
code: 200,
|
||||
data: Attachments.files
|
||||
.find({ boardId: paramBoardId }, { fields: { boardId: 0 } })
|
||||
.map(function(doc) {
|
||||
return {
|
||||
attachmentId: doc._id,
|
||||
attachmentName: doc.original.name,
|
||||
attachmentType: doc.original.type,
|
||||
url: FlowRouter.url(doc.url()),
|
||||
urlDownload: `${FlowRouter.url(doc.url())}?download=true&token=`,
|
||||
cardId: doc.cardId,
|
||||
listId: doc.listId,
|
||||
swimlaneId: doc.swimlaneId,
|
||||
};
|
||||
}),
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export default Boards;
|
||||
+17
-3
@@ -42,9 +42,23 @@ Meteor.methods({
|
||||
check(currentBoardId, Match.Maybe(String));
|
||||
const exporter = new Exporter(sourceBoardId);
|
||||
const data = exporter.build();
|
||||
const addData = {};
|
||||
addData.membersMapping = getMembersToMap(data);
|
||||
const creator = new WekanCreator(addData);
|
||||
const additionalData = {};
|
||||
|
||||
//get the members to map
|
||||
const membersMapping = getMembersToMap(data);
|
||||
|
||||
//now mirror the mapping done in finishImport in client/components/import/import.js:
|
||||
if (membersMapping) {
|
||||
const mappingById = {};
|
||||
membersMapping.forEach(member => {
|
||||
if (member.wekanId) {
|
||||
mappingById[member.id] = member.wekanId;
|
||||
}
|
||||
});
|
||||
additionalData.membersMapping = mappingById;
|
||||
}
|
||||
|
||||
const creator = new WekanCreator(additionalData);
|
||||
//data.title = `${data.title } - ${ TAPi18n.__('copy-tag')}`;
|
||||
data.title = `${data.title}`;
|
||||
return creator.create(data, currentBoardId);
|
||||
|
||||
+25
-2
@@ -616,6 +616,15 @@ Users.mutations({
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
setName(value) {
|
||||
return {
|
||||
$set: {
|
||||
'profile.fullname': value,
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
toggleDesktopHandles(value = false) {
|
||||
return {
|
||||
$set: {
|
||||
@@ -752,7 +761,6 @@ if (Meteor.isServer) {
|
||||
throw new Meteor.Error('email-already-taken');
|
||||
} else {
|
||||
Accounts.createUser({
|
||||
fullname,
|
||||
username,
|
||||
password,
|
||||
isAdmin,
|
||||
@@ -760,6 +768,12 @@ if (Meteor.isServer) {
|
||||
email: email.toLowerCase(),
|
||||
from: 'admin',
|
||||
});
|
||||
user = Users.findOne(username) || Users.findOne({ username });
|
||||
if (user) {
|
||||
Users.update(user._id, {
|
||||
$set: { 'profile.fullname': fullname },
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1631,7 +1645,16 @@ if (Meteor.isServer) {
|
||||
try {
|
||||
Authentication.checkUserId(req.userId);
|
||||
const id = req.params.userId;
|
||||
Meteor.users.remove({ _id: id });
|
||||
// Delete is not enabled yet, because it does leave empty user avatars
|
||||
// to boards: boards members, card members and assignees have
|
||||
// empty users. See:
|
||||
// - wekan/client/components/settings/peopleBody.jade deleteButton
|
||||
// - wekan/client/components/settings/peopleBody.js deleteButton
|
||||
// - wekan/client/components/sidebar/sidebar.js Popup.afterConfirm('removeMember'
|
||||
// that does now remove member from board, card members and assignees correctly,
|
||||
// but that should be used to remove user from all boards similarly
|
||||
// - wekan/models/users.js Delete is not enabled
|
||||
// Meteor.users.remove({ _id: id });
|
||||
JsonRoutes.sendResult(res, {
|
||||
code: 200,
|
||||
data: {
|
||||
|
||||
+127
-12
@@ -15,6 +15,7 @@ export class WekanCreator {
|
||||
cards: {},
|
||||
lists: {},
|
||||
swimlanes: {},
|
||||
customFields: {},
|
||||
};
|
||||
// The object creator Wekan Id, indexed by the object Wekan id
|
||||
// (so we only parse actions once!)
|
||||
@@ -30,6 +31,8 @@ export class WekanCreator {
|
||||
this.lists = {};
|
||||
// Map of cards Wekan ID => Wekan ID
|
||||
this.cards = {};
|
||||
// Map of custom fields Wekan ID => Wekan ID
|
||||
this.customFields = {};
|
||||
// Map of comments Wekan ID => Wekan ID
|
||||
this.commentIds = {};
|
||||
// Map of attachments Wekan ID => Wekan ID
|
||||
@@ -244,6 +247,7 @@ export class WekanCreator {
|
||||
swimlaneId: false,
|
||||
},
|
||||
],
|
||||
presentParentTask: boardToImport.presentParentTask,
|
||||
// Standalone Export has modifiedAt missing, adding modifiedAt to fix it
|
||||
modifiedAt: this._now(boardToImport.modifiedAt),
|
||||
permission: boardToImport.permission,
|
||||
@@ -352,10 +356,40 @@ export class WekanCreator {
|
||||
cardToCreate.members = wekanMembers;
|
||||
}
|
||||
}
|
||||
// add assignees
|
||||
if (card.assignees) {
|
||||
const wekanAssignees = [];
|
||||
// we can't just map, as some members may not have been mapped
|
||||
card.assignees.forEach(sourceMemberId => {
|
||||
if (this.members[sourceMemberId]) {
|
||||
const wekanId = this.members[sourceMemberId];
|
||||
// we may map multiple Wekan members to the same wekan user
|
||||
// in which case we risk adding the same user multiple times
|
||||
if (!wekanAssignees.find(wId => wId === wekanId)) {
|
||||
wekanAssignees.push(wekanId);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
if (wekanAssignees.length > 0) {
|
||||
cardToCreate.assignees = wekanAssignees;
|
||||
}
|
||||
}
|
||||
// set color
|
||||
if (card.color) {
|
||||
cardToCreate.color = card.color;
|
||||
}
|
||||
|
||||
// add custom fields
|
||||
if (card.customFields) {
|
||||
cardToCreate.customFields = card.customFields.map(field => {
|
||||
return {
|
||||
_id: this.customFields[field._id],
|
||||
value: field.value,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
// insert card
|
||||
const cardId = Cards.direct.insert(cardToCreate);
|
||||
// keep track of Wekan id => Wekan id
|
||||
@@ -440,6 +474,12 @@ export class WekanCreator {
|
||||
}
|
||||
});
|
||||
} else if (att.file) {
|
||||
//If attribute type is null or empty string is set, assume binary stream
|
||||
att.type =
|
||||
!att.type || att.type.trim().length === 0
|
||||
? 'application/octet-stream'
|
||||
: att.type;
|
||||
|
||||
file.attachData(
|
||||
Buffer.from(att.file, 'base64'),
|
||||
{
|
||||
@@ -481,6 +521,39 @@ export class WekanCreator {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the Wekan custom fields corresponding to the supplied Wekan
|
||||
* custom fields.
|
||||
* @param wekanCustomFields
|
||||
* @param boardId
|
||||
*/
|
||||
createCustomFields(wekanCustomFields, boardId) {
|
||||
wekanCustomFields.forEach((field, fieldIndex) => {
|
||||
const fieldToCreate = {
|
||||
boardIds: [boardId],
|
||||
name: field.name,
|
||||
type: field.type,
|
||||
settings: field.settings,
|
||||
showOnCard: field.showOnCard,
|
||||
showLabelOnMiniCard: field.showLabelOnMiniCard,
|
||||
automaticallyOnCard: field.automaticallyOnCard,
|
||||
//use date "now" if now created at date is provided (e.g. for very old boards)
|
||||
createdAt: this._now(this.createdAt.customFields[field._id]),
|
||||
modifiedAt: field.modifiedAt,
|
||||
};
|
||||
//insert copy of custom field
|
||||
const fieldId = CustomFields.direct.insert(fieldToCreate);
|
||||
//set modified date to now
|
||||
CustomFields.direct.update(fieldId, {
|
||||
$set: {
|
||||
modifiedAt: this._now(),
|
||||
},
|
||||
});
|
||||
//store mapping of old id to new id
|
||||
this.customFields[field._id] = fieldId;
|
||||
});
|
||||
}
|
||||
|
||||
// Create labels if they do not exist and load this.labels.
|
||||
createLabels(wekanLabels, board) {
|
||||
wekanLabels.forEach(label => {
|
||||
@@ -560,6 +633,35 @@ export class WekanCreator {
|
||||
});
|
||||
}
|
||||
|
||||
createSubtasks(wekanCards) {
|
||||
wekanCards.forEach(card => {
|
||||
// get new id of card (in created / new board)
|
||||
const cardIdInNewBoard = this.cards[card._id];
|
||||
|
||||
//If there is a mapped parent card, use the mapped card
|
||||
// this means, the card and parent were in the same source board
|
||||
//If there is no mapped parent card, use the original parent id,
|
||||
// this should handle cases where source and parent are in different boards
|
||||
// Note: This can only handle board cloning (within the same wekan instance).
|
||||
// When importing boards between instances the IDs are definitely
|
||||
// lost if source and parent are two different boards
|
||||
// This is not the place to fix it, the entire subtask system needs to be rethought there.
|
||||
const parentIdInNewBoard = this.cards[card.parentId]
|
||||
? this.cards[card.parentId]
|
||||
: card.parentId;
|
||||
|
||||
//if the parent card exists, proceed
|
||||
if (Cards.findOne(parentIdInNewBoard)) {
|
||||
//set parent id of the card in the new board to the new id of the parent
|
||||
Cards.direct.update(cardIdInNewBoard, {
|
||||
$set: {
|
||||
parentId: parentIdInNewBoard,
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
createChecklists(wekanChecklists) {
|
||||
const result = [];
|
||||
wekanChecklists.forEach((checklist, checklistIndex) => {
|
||||
@@ -620,18 +722,24 @@ export class WekanCreator {
|
||||
|
||||
createChecklistItems(wekanChecklistItems) {
|
||||
wekanChecklistItems.forEach((checklistitem, checklistitemIndex) => {
|
||||
// Create the checklistItem
|
||||
const checklistItemTocreate = {
|
||||
title: checklistitem.title,
|
||||
checklistId: this.checklists[checklistitem.checklistId],
|
||||
cardId: this.cards[checklistitem.cardId],
|
||||
sort: checklistitem.sort ? checklistitem.sort : checklistitemIndex,
|
||||
isFinished: checklistitem.isFinished,
|
||||
};
|
||||
const checklistItemId = ChecklistItems.direct.insert(
|
||||
checklistItemTocreate,
|
||||
);
|
||||
this.checklistItems[checklistitem._id] = checklistItemId;
|
||||
//Check if the checklist for this item (still) exists
|
||||
//If a checklist was deleted, but items remain, the import would error out here
|
||||
//Leading to no further checklist items being imported
|
||||
if (this.checklists[checklistitem.checklistId]) {
|
||||
// Create the checklistItem
|
||||
const checklistItemTocreate = {
|
||||
title: checklistitem.title,
|
||||
checklistId: this.checklists[checklistitem.checklistId],
|
||||
cardId: this.cards[checklistitem.cardId],
|
||||
sort: checklistitem.sort ? checklistitem.sort : checklistitemIndex,
|
||||
isFinished: checklistitem.isFinished,
|
||||
};
|
||||
|
||||
const checklistItemId = ChecklistItems.direct.insert(
|
||||
checklistItemTocreate,
|
||||
);
|
||||
this.checklistItems[checklistitem._id] = checklistItemId;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -690,6 +798,11 @@ export class WekanCreator {
|
||||
this.createdAt.swimlanes[swimlaneId] = activity.createdAt;
|
||||
break;
|
||||
}
|
||||
case 'createCustomField': {
|
||||
const customFieldId = activity.customFieldId;
|
||||
this.createdAt.customFields[customFieldId] = activity.createdAt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -840,7 +953,9 @@ export class WekanCreator {
|
||||
const boardId = this.createBoardAndLabels(board);
|
||||
this.createLists(board.lists, boardId);
|
||||
this.createSwimlanes(board.swimlanes, boardId);
|
||||
this.createCustomFields(board.customFields, boardId);
|
||||
this.createCards(board.cards, boardId);
|
||||
this.createSubtasks(board.cards);
|
||||
this.createChecklists(board.checklists);
|
||||
this.createChecklistItems(board.checklistItems);
|
||||
this.importActivities(board.activities, boardId);
|
||||
|
||||
Generated
+4
-4
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "wekan",
|
||||
"version": "v4.56.0",
|
||||
"version": "v4.63.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@@ -2460,9 +2460,9 @@
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||
},
|
||||
"ini": {
|
||||
"version": "1.3.5",
|
||||
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
|
||||
"integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw=="
|
||||
"version": "1.3.7",
|
||||
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.7.tgz",
|
||||
"integrity": "sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ=="
|
||||
},
|
||||
"inquirer": {
|
||||
"version": "6.5.2",
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "wekan",
|
||||
"version": "v4.56.0",
|
||||
"version": "v4.63.0",
|
||||
"description": "Open-Source kanban",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
|
||||
+251
-2
@@ -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 v4.56">Wekan REST API v4.56</a>
|
||||
<a href="#wekan-rest-api" class="toc-h1 toc-link" data-title="Wekan REST API v4.63">Wekan REST API v4.63</a>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -1582,6 +1582,11 @@ var n=this.pipeline.run(e.tokenizer(t)),r=new e.Vector,i=[],o=this._fields.reduc
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#get_board_attachments" class="toc-h2 toc-link" data-title="get_board_attachments">get_board_attachments</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#exportjson" class="toc-h2 toc-link" data-title="exportJson">exportJson</a>
|
||||
|
||||
@@ -2027,7 +2032,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 v4.56</h1>
|
||||
<h1 id="wekan-rest-api">Wekan REST API v4.63</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>
|
||||
@@ -3510,6 +3515,250 @@ System.out.println(response.toString());
|
||||
To perform this operation, you must be authenticated by means of one of the following methods:
|
||||
UserSecurity
|
||||
</aside>
|
||||
<h2 id="get_board_attachments">get_board_attachments</h2>
|
||||
<p><a id="opIdget_board_attachments"></a></p>
|
||||
<blockquote>
|
||||
<p>Code samples</p>
|
||||
</blockquote>
|
||||
<pre class="highlight tab tab-shell"><code><span class="hljs-comment"># You can also use wget</span>
|
||||
curl -X GET /api/boards/{board}/attachments \
|
||||
-H <span class="hljs-string">'Accept: application/json'</span> \
|
||||
-H <span class="hljs-string">'Authorization: API_KEY'</span>
|
||||
|
||||
</code></pre>
|
||||
<pre class="highlight tab tab-http"><code><span class="hljs-keyword">GET</span> <span class="hljs-string">/api/boards/{board}/attachments</span> HTTP/1.1
|
||||
|
||||
<span class="http"><span class="hljs-attribute">Accept</span>: application/json
|
||||
|
||||
<span class="undefined"></span></span></code></pre>
|
||||
<pre class="highlight tab tab-javascript"><code><span class="hljs-keyword">var</span> headers = {
|
||||
<span class="hljs-string">'Accept'</span>:<span class="hljs-string">'application/json'</span>,
|
||||
<span class="hljs-string">'Authorization'</span>:<span class="hljs-string">'API_KEY'</span>
|
||||
|
||||
};
|
||||
|
||||
$.ajax({
|
||||
<span class="hljs-attr">url</span>: <span class="hljs-string">'/api/boards/{board}/attachments'</span>,
|
||||
<span class="hljs-attr">method</span>: <span class="hljs-string">'get'</span>,
|
||||
|
||||
<span class="hljs-attr">headers</span>: headers,
|
||||
<span class="hljs-attr">success</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">data</span>) </span>{
|
||||
<span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">JSON</span>.stringify(data));
|
||||
}
|
||||
})
|
||||
|
||||
</code></pre>
|
||||
<pre class="highlight tab tab-javascript--nodejs"><code><span class="hljs-keyword">const</span> fetch = <span class="hljs-built_in">require</span>(<span class="hljs-string">'node-fetch'</span>);
|
||||
|
||||
<span class="hljs-keyword">const</span> headers = {
|
||||
<span class="hljs-string">'Accept'</span>:<span class="hljs-string">'application/json'</span>,
|
||||
<span class="hljs-string">'Authorization'</span>:<span class="hljs-string">'API_KEY'</span>
|
||||
|
||||
};
|
||||
|
||||
fetch(<span class="hljs-string">'/api/boards/{board}/attachments'</span>,
|
||||
{
|
||||
<span class="hljs-attr">method</span>: <span class="hljs-string">'GET'</span>,
|
||||
|
||||
<span class="hljs-attr">headers</span>: headers
|
||||
})
|
||||
.then(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">res</span>) </span>{
|
||||
<span class="hljs-keyword">return</span> res.json();
|
||||
}).then(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">body</span>) </span>{
|
||||
<span class="hljs-built_in">console</span>.log(body);
|
||||
});
|
||||
|
||||
</code></pre>
|
||||
<pre class="highlight tab tab-ruby"><code><span class="hljs-keyword">require</span> <span class="hljs-string">'rest-client'</span>
|
||||
<span class="hljs-keyword">require</span> <span class="hljs-string">'json'</span>
|
||||
|
||||
headers = {
|
||||
<span class="hljs-string">'Accept'</span> => <span class="hljs-string">'application/json'</span>,
|
||||
<span class="hljs-string">'Authorization'</span> => <span class="hljs-string">'API_KEY'</span>
|
||||
}
|
||||
|
||||
result = RestClient.get <span class="hljs-string">'/api/boards/{board}/attachments'</span>,
|
||||
<span class="hljs-symbol">params:</span> {
|
||||
}, <span class="hljs-symbol">headers:</span> headers
|
||||
|
||||
p JSON.parse(result)
|
||||
|
||||
</code></pre>
|
||||
<pre class="highlight tab tab-python"><code><span class="hljs-keyword">import</span> requests
|
||||
headers = {
|
||||
<span class="hljs-string">'Accept'</span>: <span class="hljs-string">'application/json'</span>,
|
||||
<span class="hljs-string">'Authorization'</span>: <span class="hljs-string">'API_KEY'</span>
|
||||
}
|
||||
|
||||
r = requests.get(<span class="hljs-string">'/api/boards/{board}/attachments'</span>, params={
|
||||
|
||||
}, headers = headers)
|
||||
|
||||
<span class="hljs-keyword">print</span> r.json()
|
||||
|
||||
</code></pre>
|
||||
<pre class="highlight tab tab-java"><code>URL obj = <span class="hljs-keyword">new</span> URL(<span class="hljs-string">"/api/boards/{board}/attachments"</span>);
|
||||
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
|
||||
con.setRequestMethod(<span class="hljs-string">"GET"</span>);
|
||||
<span class="hljs-keyword">int</span> responseCode = con.getResponseCode();
|
||||
BufferedReader in = <span class="hljs-keyword">new</span> BufferedReader(
|
||||
<span class="hljs-keyword">new</span> InputStreamReader(con.getInputStream()));
|
||||
String inputLine;
|
||||
StringBuffer response = <span class="hljs-keyword">new</span> StringBuffer();
|
||||
<span class="hljs-keyword">while</span> ((inputLine = in.readLine()) != <span class="hljs-keyword">null</span>) {
|
||||
response.append(inputLine);
|
||||
}
|
||||
in.close();
|
||||
System.out.println(response.toString());
|
||||
|
||||
</code></pre>
|
||||
<pre class="highlight tab tab-go"><code><span class="hljs-keyword">package</span> main
|
||||
|
||||
<span class="hljs-keyword">import</span> (
|
||||
<span class="hljs-string">"bytes"</span>
|
||||
<span class="hljs-string">"net/http"</span>
|
||||
)
|
||||
|
||||
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
|
||||
|
||||
headers := <span class="hljs-keyword">map</span>[<span class="hljs-keyword">string</span>][]<span class="hljs-keyword">string</span>{
|
||||
<span class="hljs-string">"Accept"</span>: []<span class="hljs-keyword">string</span>{<span class="hljs-string">"application/json"</span>},
|
||||
<span class="hljs-string">"Authorization"</span>: []<span class="hljs-keyword">string</span>{<span class="hljs-string">"API_KEY"</span>},
|
||||
|
||||
}
|
||||
|
||||
data := bytes.NewBuffer([]<span class="hljs-keyword">byte</span>{jsonReq})
|
||||
req, err := http.NewRequest(<span class="hljs-string">"GET"</span>, <span class="hljs-string">"/api/boards/{board}/attachments"</span>, data)
|
||||
req.Header = headers
|
||||
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(req)
|
||||
<span class="hljs-comment">// ...</span>
|
||||
}
|
||||
|
||||
</code></pre>
|
||||
<p><code>GET /api/boards/{board}/attachments</code></p>
|
||||
<p><em>Get the list of attachments of a board</em></p>
|
||||
<h3 id="get_board_attachments-parameters">Parameters</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>In</th>
|
||||
<th>Type</th>
|
||||
<th>Required</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>board</td>
|
||||
<td>path</td>
|
||||
<td>string</td>
|
||||
<td>true</td>
|
||||
<td>the board ID</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h4 id="detailed-descriptions">Detailed descriptions</h4>
|
||||
<p><strong>board</strong>: the board ID</p>
|
||||
<blockquote>
|
||||
<p>Example responses</p>
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<p>200 Response</p>
|
||||
</blockquote>
|
||||
<pre class="highlight tab tab-json"><code>[
|
||||
{
|
||||
<span class="hljs-attr">"attachmentId"</span>: <span class="hljs-string">"string"</span>,
|
||||
<span class="hljs-attr">"attachmentName"</span>: <span class="hljs-string">"string"</span>,
|
||||
<span class="hljs-attr">"attachmentType"</span>: <span class="hljs-string">"string"</span>,
|
||||
<span class="hljs-attr">"cardId"</span>: <span class="hljs-string">"string"</span>,
|
||||
<span class="hljs-attr">"listId"</span>: <span class="hljs-string">"string"</span>,
|
||||
<span class="hljs-attr">"swimlaneId"</span>: <span class="hljs-string">"string"</span>
|
||||
}
|
||||
]
|
||||
</code></pre>
|
||||
<h3 id="get_board_attachments-responses">Responses</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Status</th>
|
||||
<th>Meaning</th>
|
||||
<th>Description</th>
|
||||
<th>Schema</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>200</td>
|
||||
<td><a href="https://tools.ietf.org/html/rfc7231#section-6.3.1">OK</a></td>
|
||||
<td>200 response</td>
|
||||
<td>Inline</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3 id="get_board_attachments-responseschema">Response Schema</h3>
|
||||
<p>Status Code <strong>200</strong></p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Type</th>
|
||||
<th>Required</th>
|
||||
<th>Restrictions</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>» attachmentId</td>
|
||||
<td>string</td>
|
||||
<td>false</td>
|
||||
<td>none</td>
|
||||
<td>none</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>» attachmentName</td>
|
||||
<td>string</td>
|
||||
<td>false</td>
|
||||
<td>none</td>
|
||||
<td>none</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>» attachmentType</td>
|
||||
<td>string</td>
|
||||
<td>false</td>
|
||||
<td>none</td>
|
||||
<td>none</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>» cardId</td>
|
||||
<td>string</td>
|
||||
<td>false</td>
|
||||
<td>none</td>
|
||||
<td>none</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>» listId</td>
|
||||
<td>string</td>
|
||||
<td>false</td>
|
||||
<td>none</td>
|
||||
<td>none</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>» swimlaneId</td>
|
||||
<td>string</td>
|
||||
<td>false</td>
|
||||
<td>none</td>
|
||||
<td>none</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<aside class="warning">
|
||||
To perform this operation, you must be authenticated by means of one of the following methods:
|
||||
UserSecurity
|
||||
</aside>
|
||||
<h2 id="exportjson">exportJson</h2>
|
||||
<p><a id="opIdexportJson"></a></p>
|
||||
<blockquote>
|
||||
|
||||
+39
-1
@@ -1,7 +1,7 @@
|
||||
swagger: '2.0'
|
||||
info:
|
||||
title: Wekan REST API
|
||||
version: v4.56
|
||||
version: v4.63
|
||||
description: |
|
||||
The REST API allows you to control and extend Wekan with ease.
|
||||
|
||||
@@ -288,6 +288,44 @@ paths:
|
||||
'200':
|
||||
description: |-
|
||||
200 response
|
||||
/api/boards/{board}/attachments:
|
||||
get:
|
||||
operationId: get_board_attachments
|
||||
summary: Get the list of attachments of a board
|
||||
tags:
|
||||
- Boards
|
||||
parameters:
|
||||
- name: board
|
||||
in: path
|
||||
description: |
|
||||
the board ID
|
||||
type: string
|
||||
required: true
|
||||
produces:
|
||||
- application/json
|
||||
security:
|
||||
- UserSecurity: []
|
||||
responses:
|
||||
'200':
|
||||
description: |-
|
||||
200 response
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
attachmentId:
|
||||
type: string
|
||||
attachmentName:
|
||||
type: string
|
||||
attachmentType:
|
||||
type: string
|
||||
cardId:
|
||||
type: string
|
||||
listId:
|
||||
type: string
|
||||
swimlaneId:
|
||||
type: string
|
||||
/api/boards/{board}/cards/{card}/checklists:
|
||||
get:
|
||||
operationId: get_all_checklists
|
||||
|
||||
+2
-2
@@ -18,8 +18,8 @@ REM Install chocolatey
|
||||
|
||||
choco install -y git curl python2 dotnet4.5.2 nano mongodb-3 mongoclient meteor
|
||||
|
||||
curl -O https://nodejs.org/dist/v12.19.0/node-v12.19.0-x64.msi
|
||||
call node-v12.19.0-x64.msi
|
||||
curl -O https://nodejs.org/dist/v12.20.0/node-v12.20.0-x64.msi
|
||||
call node-v12.20.0-x64.msi
|
||||
|
||||
call npm config -g set msvs_version 2015
|
||||
call meteor npm config -g set msvs_version 2015
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ do
|
||||
#curl -0 -L https://npmjs.org/install.sh | sudo sh
|
||||
#sudo chown -R $(id -u):$(id -g) $HOME/.npm
|
||||
sudo npm -g install n
|
||||
sudo n 12.19.0
|
||||
sudo n 12.20.0
|
||||
#curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
|
||||
#sudo apt-get install -y nodejs
|
||||
elif [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
|
||||
@@ -18,7 +18,7 @@ cd $REPODIR
|
||||
rm -rf $WEKANDIR
|
||||
git clone git@github.com:wekan/wekan.git
|
||||
cd $WEKANDIR
|
||||
sudo n 12.19.1
|
||||
sudo n 12.20.0
|
||||
sudo mkdir -p /usr/local/lib/node_modules/fibers/.node-gyp
|
||||
# Build Wekan
|
||||
./releases/rebuild-release.sh
|
||||
|
||||
@@ -22,10 +22,10 @@ const pkgdef :Spk.PackageDefinition = (
|
||||
appTitle = (defaultText = "Wekan"),
|
||||
# The name of the app as it is displayed to the user.
|
||||
|
||||
appVersion = 456,
|
||||
appVersion = 463,
|
||||
# Increment this for every release.
|
||||
|
||||
appMarketingVersion = (defaultText = "4.56.0~2020-11-30"),
|
||||
appMarketingVersion = (defaultText = "4.63.0~2020-12-21"),
|
||||
# Human-readable presentation of the app version.
|
||||
|
||||
minUpgradableAppVersion = 0,
|
||||
|
||||
+1
-1
@@ -81,7 +81,7 @@ parts:
|
||||
wekan:
|
||||
source: .
|
||||
plugin: nodejs
|
||||
node-engine: 12.19.1
|
||||
node-engine: 12.20.0
|
||||
node-packages:
|
||||
- node-gyp
|
||||
- node-pre-gyp
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
set -euxo pipefail
|
||||
|
||||
BUILD_DEPS="bsdtar gnupg wget curl bzip2 python git ca-certificates perl-Digest-SHA"
|
||||
NODE_VERSION=v12.19.1
|
||||
NODE_VERSION=v12.20.0
|
||||
#METEOR_RELEASE=1.6.0.1 - for Stacksmith, meteor-1.8 branch that could have METEOR@1.8.1-beta.8 or newer
|
||||
USE_EDGE=false
|
||||
METEOR_EDGE=1.5-beta.17
|
||||
|
||||
@@ -85,10 +85,14 @@ version: '2'
|
||||
# # 11) Start wekan
|
||||
# docker start wekan-app
|
||||
#-------------------------------------------------------------------------
|
||||
# 2020-12-03:
|
||||
# - base images copied from Docker Hub to Quay to avoid Docker Hub rate limits,
|
||||
# from: torodb/stampede:1.0.0, postgres:9.6, mongo:3.2
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
services:
|
||||
torodb-stampede:
|
||||
image: torodb/stampede:latest
|
||||
image: quay.io/wekan/torodb-stampede:1.0.0
|
||||
networks:
|
||||
- wekan-tier
|
||||
links:
|
||||
@@ -105,7 +109,7 @@ services:
|
||||
- TORODB_BACKEND_PASSWORD=wekan
|
||||
- DEBUG
|
||||
postgres:
|
||||
image: postgres:9.6
|
||||
image: quay.io/wekan/postgres:9.6
|
||||
networks:
|
||||
- wekan-tier
|
||||
environment:
|
||||
|
||||
Reference in new issue
Block a user