Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6cd92ab2c6 | ||
|
|
e92ebe5151 | ||
|
|
8cb838c0de | ||
|
|
6cae14d6e9 | ||
|
|
b42d8346cd | ||
|
|
1a065ff351 | ||
|
|
3565ff2700 | ||
|
|
e354715a9d | ||
|
|
e7002f417b | ||
|
|
ef5f38f431 | ||
|
|
b3efa71d13 | ||
|
|
10fcc19b7f | ||
|
|
948f05fecb | ||
|
|
927bb83813 | ||
|
|
9f396e9038 | ||
|
|
2400c91013 | ||
|
|
f583645744 | ||
|
|
42b3cff99f | ||
|
|
960fe5163b | ||
|
|
41665c079d | ||
|
|
8a0defc988 | ||
|
|
d7e0350ecf | ||
|
|
bf15fa988d | ||
|
|
db2d59181c | ||
|
|
dcc9a0d498 | ||
|
|
936dea591a | ||
|
|
cf7e5472ba | ||
|
|
5c61119716 | ||
|
|
3558d711ff | ||
|
|
72c1c49da3 | ||
|
|
93f8ff946f | ||
|
|
61d582ffd9 | ||
|
|
60384be5ff | ||
|
|
8ac305778a | ||
|
|
5be93741ee | ||
|
|
c2f91baaf9 | ||
|
|
9df5c0e2de | ||
|
|
2c792363bf |
No files matched your search
@@ -1,3 +1,29 @@
|
||||
# v3.97 2020-04-19 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Sortable boards](https://github.com/wekan/wekan/pull/3027).
|
||||
Thanks to boeserwolf.
|
||||
- [Added dockerfiles for multi-arch builds and manifest](https://github.com/wekan/wekan/pull/3023).
|
||||
[In Progress](https://github.com/wekan/wekan/issues/2999).
|
||||
Thanks to brokencode64.
|
||||
- [Make linked card clickable](https://github.com/wekan/wekan/pull/3025).
|
||||
Thanks to boeserwolf.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Fix using checklists on mobile and iPad](https://github.com/wekan/wekan/pull/3019).
|
||||
Thanks to devinsm.
|
||||
- [Improve card layout on mobile devices](https://github.com/wekan/wekan/pull/3024).
|
||||
Thanks to marc1006.
|
||||
- [Make OCP OAuth work with Openshift 4.x](https://github.com/wekan/wekan/pull/3020).
|
||||
Thanks to ckavili.
|
||||
- [Remove old warning from Sandstorm import board data loss, because bug has been already
|
||||
fixed](https://github.com/wekan/wekan/commit/960fe5163b6a2f7c3dca03b5e31d69611b49f079).
|
||||
Thanks to aputsiaq and xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v3.96 2020-04-15 Wekan release
|
||||
|
||||
This release adds the following Sandstorm updates:
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
FROM amd64/alpine:3.7 AS builder
|
||||
|
||||
# Set the environment variables for builder
|
||||
ENV QEMU_VERSION=v4.2.0-6 \
|
||||
QEMU_ARCHITECTURE=aarch64 \
|
||||
NODE_ARCHITECTURE=linux-arm64 \
|
||||
NODE_VERSION=v12.16.1 \
|
||||
WEKAN_VERSION=3.96 \
|
||||
WEKAN_ARCHITECTURE=arm64
|
||||
|
||||
# Install dependencies
|
||||
RUN apk update && apk add ca-certificates outils-sha1 && \
|
||||
\
|
||||
# Download qemu static for our architecture
|
||||
wget https://github.com/multiarch/qemu-user-static/releases/download/${QEMU_VERSION}/qemu-${QEMU_ARCHITECTURE}-static.tar.gz -O - | tar -xz && \
|
||||
\
|
||||
# Download wekan and shasum
|
||||
wget https://releases.wekan.team/raspi3/wekan-${WEKAN_VERSION}-${WEKAN_ARCHITECTURE}.zip && \
|
||||
wget https://releases.wekan.team/raspi3/SHA256SUMS.txt && \
|
||||
# Verify wekan
|
||||
grep wekan-${WEKAN_VERSION}-${WEKAN_ARCHITECTURE}.zip SHA256SUMS.txt | sha256sum -c - && \
|
||||
\
|
||||
# Unzip wekan
|
||||
unzip wekan-${WEKAN_VERSION}-${WEKAN_ARCHITECTURE}.zip && \
|
||||
\
|
||||
# Download node and shasums
|
||||
wget https://nodejs.org/dist/${NODE_VERSION}/node-${NODE_VERSION}-${NODE_ARCHITECTURE}.tar.gz && \
|
||||
wget https://nodejs.org/dist/${NODE_VERSION}/SHASUMS256.txt.asc && \
|
||||
\
|
||||
# Verify nodejs authenticity
|
||||
grep node-${NODE_VERSION}-${NODE_ARCHITECTURE}.tar.gz SHASUMS256.txt.asc | sha256sum -c - && \
|
||||
\
|
||||
# Extract node and remove tar.gz
|
||||
tar xvzf node-${NODE_VERSION}-${NODE_ARCHITECTURE}.tar.gz
|
||||
|
||||
# Build wekan dockerfile
|
||||
FROM arm64v8/ubuntu:19.10
|
||||
LABEL maintainer="wekan"
|
||||
|
||||
# Set the environment variables (defaults where required)
|
||||
ENV QEMU_ARCHITECTURE=aarch64 \
|
||||
NODE_ARCHITECTURE=linux-arm64 \
|
||||
NODE_VERSION=v12.16.1 \
|
||||
NODE_ENV=production \
|
||||
NPM_VERSION=latest \
|
||||
WITH_API=true \
|
||||
PORT=8080 \
|
||||
ROOT_URL=http://localhost \
|
||||
MONGO_URL=mongodb://127.0.0.1:27017/wekan
|
||||
|
||||
# Copy qemu-static to image
|
||||
COPY --from=builder qemu-${QEMU_ARCHITECTURE}-static /usr/bin
|
||||
|
||||
# Copy the app to the image
|
||||
COPY --from=builder bundle /home/wekan/bundle
|
||||
|
||||
# Copy
|
||||
COPY --from=builder node-${NODE_VERSION}-${NODE_ARCHITECTURE} /opt/nodejs
|
||||
|
||||
RUN \
|
||||
set -o xtrace && \
|
||||
# Add non-root user wekan
|
||||
useradd --user-group --system --home-dir /home/wekan wekan && \
|
||||
\
|
||||
# Install Node
|
||||
ln -s /opt/nodejs/bin/node /usr/bin/node && \
|
||||
ln -s /opt/nodejs/bin/npm /usr/bin/npm && \
|
||||
mkdir -p /opt/nodejs/lib/node_modules/fibers/.node-gyp /root/.node-gyp/8.16.1 /home/wekan/.config && \
|
||||
chown wekan --recursive /home/wekan/.config && \
|
||||
\
|
||||
# Install Node dependencies
|
||||
npm install -g npm@${NPM_VERSION}
|
||||
|
||||
EXPOSE $PORT
|
||||
USER wekan
|
||||
|
||||
CMD ["node", "/home/wekan/bundle/main.js"]
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
appId: wekan-public/apps/77b94f60-dec9-0136-304e-16ff53095928
|
||||
appVersion: "v3.96.0"
|
||||
appVersion: "v3.97.0"
|
||||
files:
|
||||
userUploads:
|
||||
- README.md
|
||||
|
||||
@@ -7,7 +7,7 @@ BlazeComponent.extendComponent({
|
||||
return Boards.find(
|
||||
{ archived: true },
|
||||
{
|
||||
sort: ['title'],
|
||||
sort: { sort: 1 /* boards default sorting */ }
|
||||
},
|
||||
);
|
||||
},
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
template(name="boardList")
|
||||
.wrapper
|
||||
ul.board-list.clearfix
|
||||
ul.board-list.clearfix.js-boards
|
||||
li.js-add-board
|
||||
a.board-list-item.label {{_ 'add-board'}}
|
||||
each boards
|
||||
li(class="{{#if isStarred}}starred{{/if}}" class=colorClass)
|
||||
li(class="{{#if isStarred}}starred{{/if}}" class=colorClass).js-board
|
||||
if isInvited
|
||||
.board-list-item
|
||||
span.details
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
const subManager = new SubsManager();
|
||||
const { calculateIndex, enableClickOnTouch } = Utils;
|
||||
|
||||
Template.boardListHeaderBar.events({
|
||||
'click .js-open-archived-board'() {
|
||||
@@ -7,8 +8,8 @@ Template.boardListHeaderBar.events({
|
||||
});
|
||||
|
||||
Template.boardListHeaderBar.helpers({
|
||||
title(){
|
||||
return FlowRouter.getRouteName() == 'home' ? 'my-boards' :'public';
|
||||
title() {
|
||||
return FlowRouter.getRouteName() == 'home' ? 'my-boards' : 'public';
|
||||
},
|
||||
templatesBoardId() {
|
||||
return Meteor.user() && Meteor.user().getTemplatesBoardId();
|
||||
@@ -23,20 +24,69 @@ BlazeComponent.extendComponent({
|
||||
Meteor.subscribe('setting');
|
||||
},
|
||||
|
||||
onRendered() {
|
||||
const self = this;
|
||||
function userIsAllowedToMove() {
|
||||
return Meteor.user();
|
||||
}
|
||||
|
||||
const itemsSelector = '.js-board:not(.placeholder)';
|
||||
|
||||
const $boards = this.$('.js-boards');
|
||||
$boards.sortable({
|
||||
connectWith: '.js-boards',
|
||||
tolerance: 'pointer',
|
||||
appendTo: '.board-list',
|
||||
helper: 'clone',
|
||||
distance: 7,
|
||||
items: itemsSelector,
|
||||
placeholder: 'board-wrapper placeholder',
|
||||
start(evt, ui) {
|
||||
ui.helper.css('z-index', 1000);
|
||||
ui.placeholder.height(ui.helper.height());
|
||||
EscapeActions.executeUpTo('popup-close');
|
||||
},
|
||||
stop(evt, ui) {
|
||||
// To attribute the new index number, we need to get the DOM element
|
||||
// of the previous and the following card -- if any.
|
||||
const prevBoardDom = ui.item.prev('.js-board').get(0);
|
||||
const nextBoardBom = ui.item.next('.js-board').get(0);
|
||||
const sortIndex = calculateIndex(prevBoardDom, nextBoardBom, 1);
|
||||
|
||||
const boardDomElement = ui.item.get(0);
|
||||
const board = Blaze.getData(boardDomElement);
|
||||
// Normally the jquery-ui sortable library moves the dragged DOM element
|
||||
// to its new position, which disrupts Blaze reactive updates mechanism
|
||||
// (especially when we move the last card of a list, or when multiple
|
||||
// users move some cards at the same time). To prevent these UX glitches
|
||||
// we ask sortable to gracefully cancel the move, and to put back the
|
||||
// DOM in its initial state. The card move is then handled reactively by
|
||||
// Blaze with the below query.
|
||||
$boards.sortable('cancel');
|
||||
|
||||
board.move(sortIndex.base);
|
||||
},
|
||||
});
|
||||
|
||||
// ugly touch event hotfix
|
||||
enableClickOnTouch(itemsSelector);
|
||||
|
||||
// Disable drag-dropping if the current user is not a board member or is comment only
|
||||
this.autorun(() => {
|
||||
$boards.sortable('option', 'disabled', !userIsAllowedToMove());
|
||||
});
|
||||
},
|
||||
|
||||
boards() {
|
||||
let query = {
|
||||
archived: false,
|
||||
type: 'board',
|
||||
}
|
||||
};
|
||||
if (FlowRouter.getRouteName() == 'home')
|
||||
query['members.userId'] = Meteor.userId()
|
||||
else
|
||||
query.permission = 'public'
|
||||
query['members.userId'] = Meteor.userId();
|
||||
else query.permission = 'public';
|
||||
|
||||
return Boards.find(
|
||||
query,
|
||||
{ sort: ['title'] },
|
||||
);
|
||||
return Boards.find(query, { sort: { sort: 1 /* boards default sorting */ } });
|
||||
},
|
||||
isStarred() {
|
||||
const user = Meteor.user();
|
||||
|
||||
@@ -11,6 +11,19 @@ $spaceBetweenTiles = 16px
|
||||
box-sizing: border-box
|
||||
position: relative
|
||||
|
||||
&.placeholder:after
|
||||
content: '';
|
||||
display: block;
|
||||
background: darken(white, 20%)
|
||||
border-radius: 3px;
|
||||
height: 106px;
|
||||
margin: 8px;
|
||||
|
||||
&.ui-sortable-helper
|
||||
cursor: grabbing
|
||||
transform: rotate(4deg)
|
||||
display: block !important
|
||||
|
||||
&.starred
|
||||
.fa-star,
|
||||
.fa-star-o
|
||||
@@ -183,7 +196,7 @@ $spaceBetweenTiles = 16px
|
||||
overflow: scroll
|
||||
|
||||
li
|
||||
width: 50%
|
||||
width: 50%
|
||||
|
||||
.board-list-item
|
||||
overflow: hidden
|
||||
|
||||
@@ -32,7 +32,7 @@ template(name="cardDetails")
|
||||
// else
|
||||
{{_ 'top-level-card'}}
|
||||
if isLinkedCard
|
||||
h3.linked-card-location
|
||||
a.linked-card-location.js-go-to-linked-card
|
||||
+viewer
|
||||
| {{getBoardTitle}} > {{getTitle}}
|
||||
|
||||
|
||||
@@ -379,6 +379,9 @@ BlazeComponent.extendComponent({
|
||||
this.data().setRequestedBy('');
|
||||
}
|
||||
},
|
||||
'click .js-go-to-linked-card'() {
|
||||
Utils.goCardId(this.data().linkedId)
|
||||
},
|
||||
'click .js-member': Popup.open('cardMember'),
|
||||
'click .js-add-members': Popup.open('cardMembers'),
|
||||
'click .js-assignee': Popup.open('cardAssignee'),
|
||||
@@ -724,7 +727,7 @@ BlazeComponent.extendComponent({
|
||||
_id: { $ne: Meteor.user().getTemplatesBoardId() },
|
||||
},
|
||||
{
|
||||
sort: ['title'],
|
||||
sort: { sort: 1 /* boards default sorting */ },
|
||||
},
|
||||
);
|
||||
return boards;
|
||||
@@ -900,7 +903,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
},
|
||||
{
|
||||
sort: ['title'],
|
||||
sort: { sort: 1 /* boards default sorting */ },
|
||||
},
|
||||
);
|
||||
return boards;
|
||||
@@ -971,7 +974,7 @@ BlazeComponent.extendComponent({
|
||||
}
|
||||
}
|
||||
},
|
||||
'click .js-delete': Popup.afterConfirm('cardDelete', function () {
|
||||
'click .js-delete': Popup.afterConfirm('cardDelete', function() {
|
||||
Popup.close();
|
||||
Cards.remove(this._id);
|
||||
Utils.goBoardId(this.boardId);
|
||||
|
||||
@@ -94,6 +94,7 @@ avatar-radius = 50%
|
||||
animation: flexGrowIn 0.1s
|
||||
box-shadow: 0 0 7px 0 darken(white, 30%)
|
||||
transition: flex-basis 0.1s
|
||||
box-sizing: border-box
|
||||
|
||||
.mCustomScrollBox
|
||||
padding-left: 0
|
||||
|
||||
@@ -88,7 +88,8 @@ template(name="checklistItems")
|
||||
template(name='checklistItemDetail')
|
||||
.js-checklist-item.checklist-item
|
||||
if canModifyCard
|
||||
.check-box.materialCheckBox(class="{{#if item.isFinished }}is-checked{{/if}}")
|
||||
.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}}")
|
||||
+viewer
|
||||
= item.title
|
||||
|
||||
@@ -250,7 +250,7 @@ BlazeComponent.extendComponent({
|
||||
events() {
|
||||
return [
|
||||
{
|
||||
'click .js-checklist-item .check-box': this.toggleItem,
|
||||
'click .js-checklist-item .check-box-container': this.toggleItem,
|
||||
},
|
||||
];
|
||||
},
|
||||
|
||||
@@ -113,6 +113,9 @@ textarea.js-add-checklist-item, textarea.js-edit-checklist-item
|
||||
&:hover
|
||||
background-color: darken(white, 8%)
|
||||
|
||||
.check-box-container
|
||||
padding-right: 1px;
|
||||
|
||||
.check-box
|
||||
margin: 0.1em 0 0 0;
|
||||
&.is-checked
|
||||
@@ -121,7 +124,7 @@ textarea.js-add-checklist-item, textarea.js-edit-checklist-item
|
||||
|
||||
.item-title
|
||||
flex: 1
|
||||
padding-left: 10px;
|
||||
margin-left: 10px;
|
||||
&.is-checked
|
||||
color: #8c8c8c
|
||||
font-style: italic
|
||||
|
||||
@@ -15,9 +15,6 @@ template(name="importTextarea")
|
||||
p: label(for='import-textarea') {{_ instruction}} {{_ 'import-board-instruction-about-errors'}}
|
||||
textarea.js-import-json(placeholder="{{_ 'import-json-placeholder'}}" autofocus)
|
||||
| {{jsonText}}
|
||||
if isSandstorm
|
||||
h1.warning {{_ 'import-sandstorm-backup-warning'}}
|
||||
p.warning {{_ 'import-sandstorm-warning'}}
|
||||
input.primary.wide(type="submit" value="{{_ 'import'}}")
|
||||
|
||||
template(name="importMapMembers")
|
||||
|
||||
@@ -411,7 +411,7 @@ BlazeComponent.extendComponent({
|
||||
type: 'board',
|
||||
},
|
||||
{
|
||||
sort: ['title'],
|
||||
sort: { sort: 1 /* boards default sorting */ },
|
||||
},
|
||||
);
|
||||
return boards;
|
||||
@@ -597,7 +597,7 @@ BlazeComponent.extendComponent({
|
||||
type: 'board',
|
||||
},
|
||||
{
|
||||
sort: ['title'],
|
||||
sort: { sort: 1 /* boards default sorting */ },
|
||||
},
|
||||
);
|
||||
return boards;
|
||||
|
||||
@@ -11,7 +11,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
},
|
||||
{
|
||||
sort: ['title'],
|
||||
sort: { sort: 1 /* boards default sorting */ },
|
||||
},
|
||||
);
|
||||
return boards;
|
||||
|
||||
@@ -48,7 +48,7 @@ BlazeComponent.extendComponent({
|
||||
'members.isAdmin': true,
|
||||
},
|
||||
{
|
||||
sort: ['title'],
|
||||
sort: { sort: 1 /* boards default sorting */ },
|
||||
},
|
||||
);
|
||||
},
|
||||
|
||||
@@ -510,7 +510,7 @@ BlazeComponent.extendComponent({
|
||||
'members.userId': Meteor.userId(),
|
||||
},
|
||||
{
|
||||
sort: ['title'],
|
||||
sort: { sort: 1 /* boards default sorting */ },
|
||||
},
|
||||
);
|
||||
},
|
||||
@@ -589,7 +589,7 @@ BlazeComponent.extendComponent({
|
||||
'subtext-with-parent',
|
||||
'no-parent',
|
||||
];
|
||||
options.forEach(function (element) {
|
||||
options.forEach(function(element) {
|
||||
if (element !== value) {
|
||||
$(`#${element} ${MCB}`).toggleClass(CKCLS, false);
|
||||
$(`#${element}`).toggleClass(CKCLS, false);
|
||||
@@ -688,7 +688,7 @@ BlazeComponent.extendComponent({
|
||||
'members.userId': Meteor.userId(),
|
||||
},
|
||||
{
|
||||
sort: ['title'],
|
||||
sort: { sort: 1 /* boards default sorting */ },
|
||||
},
|
||||
);
|
||||
},
|
||||
|
||||
@@ -37,6 +37,12 @@ spec:
|
||||
value: {{ .Values.root_url | default "https://wekan.local" | quote }}
|
||||
- name: MONGO_URL
|
||||
value: "{{ template "mongodb-replicaset.url" . }}"
|
||||
{{- range $key := .Values.env }}
|
||||
{{- if .value }}
|
||||
- name: {{ .name }}
|
||||
value: {{ .value | quote }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
{{- if .Values.serviceAccounts.annotations }}
|
||||
annotations:
|
||||
{{ .Values.serviceAccounts.annotations | indent 4}}
|
||||
{{- end }}
|
||||
labels:
|
||||
app: {{ template "wekan.name" . }}
|
||||
chart: {{ template "wekan.chart" . }}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
serviceAccounts:
|
||||
create: true
|
||||
name: ""
|
||||
annotations: ""
|
||||
|
||||
## Wekan image configuration
|
||||
##
|
||||
@@ -29,7 +30,9 @@ credentials:
|
||||
|
||||
## Specify additional environmental variables for the Deployment
|
||||
##
|
||||
env: {}
|
||||
env:
|
||||
- name: ""
|
||||
value: ""
|
||||
|
||||
service:
|
||||
type: NodePort
|
||||
@@ -59,10 +62,10 @@ ingress:
|
||||
# hosts:
|
||||
# - wekan-example.local
|
||||
|
||||
route:
|
||||
enabled: false
|
||||
route:
|
||||
enabled: false
|
||||
|
||||
resources:
|
||||
resources:
|
||||
requests:
|
||||
memory: 128Mi
|
||||
cpu: 300m
|
||||
|
||||
+777
-779
File diff suppressed because it is too large.
Load diff
+777
-779
File diff suppressed because it is too large.
Load diff
+777
-779
File diff suppressed because it is too large.
Load diff
+777
-779
File diff suppressed because it is too large.
Load diff
+777
-779
File diff suppressed because it is too large.
Load diff
+777
-779
File diff suppressed because it is too large.
Load diff
+777
-779
File diff suppressed because it is too large.
Load diff
+777
-779
File diff suppressed because it is too large.
Load diff
+777
-779
File diff suppressed because it is too large.
Load diff
@@ -348,8 +348,6 @@
|
||||
"import-board-c": "Import board",
|
||||
"import-board-title-trello": "Import board from Trello",
|
||||
"import-board-title-wekan": "Import board from previous export",
|
||||
"import-sandstorm-backup-warning": "Do not delete data you import from original exported board or Trello before checking does this grain close and open again, or do you get Board not found error, that means data loss.",
|
||||
"import-sandstorm-warning": "Imported board will delete all existing data on board and replace it with imported board.",
|
||||
"from-trello": "From Trello",
|
||||
"from-wekan": "From previous export",
|
||||
"import-board-instruction-trello": "In your Trello board, go to 'Menu', then 'More', 'Print and Export', 'Export JSON', and copy the resulting text.",
|
||||
|
||||
+777
-779
File diff suppressed because it is too large.
Load diff
+777
-779
File diff suppressed because it is too large.
Load diff
+777
-779
File diff suppressed because it is too large.
Load diff
+777
-779
File diff suppressed because it is too large.
Load diff
+777
-779
File diff suppressed because it is too large.
Load diff
+777
-779
File diff suppressed because it is too large.
Load diff
+777
-779
File diff suppressed because it is too large.
Load diff
+777
-779
File diff suppressed because it is too large.
Load diff
+777
-779
File diff suppressed because it is too large.
Load diff
+777
-779
File diff suppressed because it is too large.
Load diff
+777
-779
File diff suppressed because it is too large.
Load diff
+777
-779
File diff suppressed because it is too large.
Load diff
+777
-779
File diff suppressed because it is too large.
Load diff
+777
-779
File diff suppressed because it is too large.
Load diff
+777
-779
File diff suppressed because it is too large.
Load diff
+777
-779
File diff suppressed because it is too large.
Load diff
+777
-779
File diff suppressed because it is too large.
Load diff
+777
-779
File diff suppressed because it is too large.
Load diff
+777
-779
File diff suppressed because it is too large.
Load diff
+777
-779
File diff suppressed because it is too large.
Load diff
+777
-779
File diff suppressed because it is too large.
Load diff
+777
-779
File diff suppressed because it is too large.
Load diff
+777
-779
File diff suppressed because it is too large.
Load diff
+777
-779
File diff suppressed because it is too large.
Load diff
+777
-779
File diff suppressed because it is too large.
Load diff
+777
-779
File diff suppressed because it is too large.
Load diff
+777
-779
File diff suppressed because it is too large.
Load diff
+777
-779
File diff suppressed because it is too large.
Load diff
+777
-779
File diff suppressed because it is too large.
Load diff
+777
-779
File diff suppressed because it is too large.
Load diff
+777
-779
File diff suppressed because it is too large.
Load diff
+777
-779
File diff suppressed because it is too large.
Load diff
+777
-779
File diff suppressed because it is too large.
Load diff
+777
-779
File diff suppressed because it is too large.
Load diff
+777
-779
File diff suppressed because it is too large.
Load diff
+777
-779
File diff suppressed because it is too large.
Load diff
+777
-779
File diff suppressed because it is too large.
Load diff
+777
-779
File diff suppressed because it is too large.
Load diff
+777
-779
File diff suppressed because it is too large.
Load diff
+777
-779
File diff suppressed because it is too large.
Load diff
+777
-779
File diff suppressed because it is too large.
Load diff
+777
-779
File diff suppressed because it is too large.
Load diff
+27
-2
@@ -493,6 +493,14 @@ Boards.attachSchema(
|
||||
type: String,
|
||||
defaultValue: 'board',
|
||||
},
|
||||
sort: {
|
||||
/**
|
||||
* Sort value
|
||||
*/
|
||||
type: Number,
|
||||
decimal: true,
|
||||
defaultValue: -1,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -1186,6 +1194,10 @@ Boards.mutations({
|
||||
setPresentParentTask(presentParentTask) {
|
||||
return { $set: { presentParentTask } };
|
||||
},
|
||||
|
||||
move(sortIndex) {
|
||||
return { $set: { sort: sortIndex } };
|
||||
},
|
||||
});
|
||||
|
||||
function boardRemover(userId, doc) {
|
||||
@@ -1283,6 +1295,14 @@ if (Meteor.isServer) {
|
||||
});
|
||||
}
|
||||
|
||||
// Insert new board at last position in sort order.
|
||||
Boards.before.insert((userId, doc) => {
|
||||
const lastBoard = Boards.findOne({ sort: { $exists: true } }, { sort: { sort: -1 } });
|
||||
if (lastBoard && typeof lastBoard.sort !== 'undefined') {
|
||||
doc.sort = lastBoard.sort + 1;
|
||||
}
|
||||
});
|
||||
|
||||
if (Meteor.isServer) {
|
||||
// Let MongoDB ensure that a member is not included twice in the same board
|
||||
Meteor.startup(() => {
|
||||
@@ -1466,7 +1486,7 @@ if (Meteor.isServer) {
|
||||
'members.userId': paramUserId,
|
||||
},
|
||||
{
|
||||
sort: ['title'],
|
||||
sort: { sort: 1 /* boards default sorting */ },
|
||||
},
|
||||
).map(function(board) {
|
||||
return {
|
||||
@@ -1496,7 +1516,12 @@ if (Meteor.isServer) {
|
||||
Authentication.checkUserId(req.userId);
|
||||
JsonRoutes.sendResult(res, {
|
||||
code: 200,
|
||||
data: Boards.find({ permission: 'public' }).map(function(doc) {
|
||||
data: Boards.find(
|
||||
{ permission: 'public' },
|
||||
{
|
||||
sort: { sort: 1 /* boards default sorting */ },
|
||||
},
|
||||
).map(function(doc) {
|
||||
return {
|
||||
_id: doc._id,
|
||||
title: doc.title,
|
||||
|
||||
+23
-7
@@ -386,12 +386,20 @@ if (Meteor.isClient) {
|
||||
|
||||
Users.helpers({
|
||||
boards() {
|
||||
return Boards.find({ 'members.userId': this._id });
|
||||
return Boards.find(
|
||||
{ 'members.userId': this._id },
|
||||
{ sort: { sort: 1 /* boards default sorting */ } },
|
||||
);
|
||||
},
|
||||
|
||||
starredBoards() {
|
||||
const { starredBoards = [] } = this.profile || {};
|
||||
return Boards.find({ archived: false, _id: { $in: starredBoards } });
|
||||
return Boards.find(
|
||||
{ archived: false, _id: { $in: starredBoards } },
|
||||
{
|
||||
sort: { sort: 1 /* boards default sorting */ },
|
||||
},
|
||||
);
|
||||
},
|
||||
|
||||
hasStarred(boardId) {
|
||||
@@ -401,7 +409,12 @@ Users.helpers({
|
||||
|
||||
invitedBoards() {
|
||||
const { invitedBoards = [] } = this.profile || {};
|
||||
return Boards.find({ archived: false, _id: { $in: invitedBoards } });
|
||||
return Boards.find(
|
||||
{ archived: false, _id: { $in: invitedBoards } },
|
||||
{
|
||||
sort: { sort: 1 /* boards default sorting */ },
|
||||
},
|
||||
);
|
||||
},
|
||||
|
||||
isInvitedTo(boardId) {
|
||||
@@ -1292,10 +1305,13 @@ if (Meteor.isServer) {
|
||||
let data = Meteor.users.findOne({ _id: id });
|
||||
if (data !== undefined) {
|
||||
if (action === 'takeOwnership') {
|
||||
data = Boards.find({
|
||||
'members.userId': id,
|
||||
'members.isAdmin': true,
|
||||
}).map(function(board) {
|
||||
data = Boards.find(
|
||||
{
|
||||
'members.userId': id,
|
||||
'members.isAdmin': true,
|
||||
},
|
||||
{ sort: { sort: 1 /* boards default sorting */ } },
|
||||
).map(function(board) {
|
||||
if (board.hasMember(req.userId)) {
|
||||
board.removeMember(req.userId);
|
||||
}
|
||||
|
||||
Generated
+2
-2
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "wekan",
|
||||
"version": "v3.96.0",
|
||||
"version": "v3.97.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@@ -3835,7 +3835,7 @@
|
||||
"requires": {
|
||||
"deep-extend": "^0.6.0",
|
||||
"ini": "~1.3.0",
|
||||
"minimist": "^1.2.5",
|
||||
"minimist": "^1.2.0",
|
||||
"strip-json-comments": "~2.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "wekan",
|
||||
"version": "v3.96.0",
|
||||
"version": "v3.97.0",
|
||||
"description": "Open-Source kanban",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
|
||||
@@ -11,6 +11,7 @@ OAuth.registerService('oidc', 2, null, function (query) {
|
||||
|
||||
var userinfo = getUserInfo(accessToken);
|
||||
if (userinfo.ocs) userinfo = userinfo.ocs.data; // Nextcloud hack
|
||||
if (userinfo.metadata) userinfo = userinfo.metadata // Openshift hack
|
||||
if (debug) console.log('XXX: userinfo:', userinfo);
|
||||
|
||||
var serviceData = {};
|
||||
|
||||
+301
-292
File diff suppressed because it is too large.
Load diff
@@ -1,7 +1,7 @@
|
||||
swagger: '2.0'
|
||||
info:
|
||||
title: Wekan REST API
|
||||
version: v3.96
|
||||
version: v3.97
|
||||
description: |
|
||||
The REST API allows you to control and extend Wekan with ease.
|
||||
|
||||
@@ -1895,6 +1895,10 @@ definitions:
|
||||
description: |
|
||||
The type of board
|
||||
type: string
|
||||
sort:
|
||||
description: |
|
||||
Sort value
|
||||
type: number
|
||||
required:
|
||||
- title
|
||||
- slug
|
||||
@@ -1922,6 +1926,7 @@ definitions:
|
||||
- allowsEndDate
|
||||
- allowsDueDate
|
||||
- type
|
||||
- sort
|
||||
BoardsLabels:
|
||||
type: object
|
||||
properties:
|
||||
|
||||
@@ -22,10 +22,10 @@ const pkgdef :Spk.PackageDefinition = (
|
||||
appTitle = (defaultText = "Wekan"),
|
||||
# The name of the app as it is displayed to the user.
|
||||
|
||||
appVersion = 396,
|
||||
appVersion = 397,
|
||||
# Increment this for every release.
|
||||
|
||||
appMarketingVersion = (defaultText = "3.96.0~2020-04-15"),
|
||||
appMarketingVersion = (defaultText = "3.97.0~2020-04-19"),
|
||||
# Human-readable presentation of the app version.
|
||||
|
||||
minUpgradableAppVersion = 0,
|
||||
|
||||
@@ -1033,3 +1033,15 @@ Migrations.add('add-description-text-allowed', () => {
|
||||
noValidateMulti,
|
||||
);
|
||||
});
|
||||
|
||||
Migrations.add('add-sort-field-to-boards', () => {
|
||||
Boards.find().forEach((board, index) => {
|
||||
if (!board.hasOwnProperty('sort')) {
|
||||
Boards.direct.update(
|
||||
board._id,
|
||||
{ $set: { sort: index } },
|
||||
noValidate
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -35,7 +35,9 @@ Meteor.publish('boards', function() {
|
||||
members: 1,
|
||||
permission: 1,
|
||||
type: 1,
|
||||
sort: 1,
|
||||
},
|
||||
sort: { sort: 1 /* boards default sorting */ },
|
||||
},
|
||||
);
|
||||
});
|
||||
@@ -61,6 +63,7 @@ Meteor.publish('archivedBoards', function() {
|
||||
slug: 1,
|
||||
title: 1,
|
||||
},
|
||||
sort: { sort: 1 /* boards default sorting */ },
|
||||
},
|
||||
);
|
||||
});
|
||||
@@ -90,7 +93,7 @@ Meteor.publishRelations('board', function(boardId, isArchived) {
|
||||
$or,
|
||||
// Sort required to ensure oplog usage
|
||||
},
|
||||
{ limit: 1, sort: { _id: 1 } },
|
||||
{ limit: 1, sort: { sort: 1 /* boards default sorting */ } },
|
||||
),
|
||||
function(boardId, board) {
|
||||
this.cursor(Lists.find({ boardId, archived: isArchived }));
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
image: quay.io/wekan/wekan
|
||||
manifests:
|
||||
- image: quay.io/wekan/wekan:amd64
|
||||
platform:
|
||||
architecture: amd64
|
||||
os: linux
|
||||
- image: quay.io/wekan/wekan:arm64v8
|
||||
platform:
|
||||
architecture: arm64
|
||||
os: linux
|
||||
variant: v8
|
||||
Reference in new issue
Block a user