forked from vikunja/vikunja
Compare commits
27 Commits
837360f122
...
f18cde269b
Author | SHA1 | Date |
---|---|---|
kolaente | f18cde269b | |
kolaente | 09d446765d | |
renovate | a99e7f9aa3 | |
renovate | e93e48c4c2 | |
renovate | 06688fa8d4 | |
renovate | 1a15c865e2 | |
renovate | 7b9a72ebe1 | |
renovate | a0f4bdbdad | |
renovate | eea356e570 | |
kolaente | 5b70609ba7 | |
kolaente | 6b1e67485b | |
kolaente | 5d127c2897 | |
kolaente | 1275dfc260 | |
kolaente | 997fb6bc54 | |
kolaente | b2e5de88ff | |
kolaente | baa5d14ca6 | |
kolaente | 2d5c496397 | |
kolaente | b8533d2bfc | |
kolaente | 8a82093233 | |
kolaente | 3d39fc3960 | |
kolaente | 43e13d9cdd | |
kolaente | a0e812395f | |
kolaente | 2e5c19352e | |
kolaente | 1ffb93b63c | |
renovate | 1bf8659423 | |
renovate | 7629c8426e | |
renovate | a83acc0300 |
|
@ -1,6 +1,7 @@
|
|||
files/
|
||||
dist/
|
||||
logs/
|
||||
docs/
|
||||
|
||||
Dockerfile
|
||||
docker-manifest.tmpl
|
||||
|
|
107
.drone.yml
107
.drone.yml
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: build-and-test-api
|
||||
name: build-and-test
|
||||
|
||||
workspace:
|
||||
base: /go
|
||||
|
@ -122,7 +122,7 @@ steps:
|
|||
when:
|
||||
event: [ push, tag, pull_request ]
|
||||
|
||||
- name: build
|
||||
- name: api-build
|
||||
image: vikunja/golang-build:latest
|
||||
pull: always
|
||||
environment:
|
||||
|
@ -133,7 +133,7 @@ steps:
|
|||
when:
|
||||
event: [ push, tag, pull_request ]
|
||||
|
||||
- name: lint
|
||||
- name: api-lint
|
||||
image: golangci/golangci-lint:v1.55.2
|
||||
pull: always
|
||||
environment:
|
||||
|
@ -156,7 +156,9 @@ steps:
|
|||
- name: test-migration-sqlite
|
||||
image: vikunja/golang-build:latest
|
||||
pull: always
|
||||
depends_on: [ test-migration-prepare, build ]
|
||||
depends_on:
|
||||
- test-migration-prepare
|
||||
- api-build
|
||||
environment:
|
||||
VIKUNJA_DATABASE_TYPE: sqlite
|
||||
VIKUNJA_DATABASE_PATH: /db/vikunja-migration-test.db
|
||||
|
@ -175,7 +177,9 @@ steps:
|
|||
- name: test-migration-mysql
|
||||
image: vikunja/golang-build:latest
|
||||
pull: always
|
||||
depends_on: [ test-migration-prepare, build ]
|
||||
depends_on:
|
||||
- test-migration-prepare
|
||||
- api-build
|
||||
environment:
|
||||
VIKUNJA_DATABASE_TYPE: mysql
|
||||
VIKUNJA_DATABASE_HOST: test-mysql-migration
|
||||
|
@ -194,7 +198,9 @@ steps:
|
|||
- name: test-migration-psql
|
||||
image: vikunja/golang-build:latest
|
||||
pull: always
|
||||
depends_on: [ test-migration-prepare, build ]
|
||||
depends_on:
|
||||
- test-migration-prepare
|
||||
- api-build
|
||||
environment:
|
||||
VIKUNJA_DATABASE_TYPE: postgres
|
||||
VIKUNJA_DATABASE_HOST: test-postgres-migration
|
||||
|
@ -211,7 +217,7 @@ steps:
|
|||
when:
|
||||
event: [ push, tag, pull_request ]
|
||||
|
||||
- name: test
|
||||
- name: api-test-unit
|
||||
image: vikunja/golang-build:latest
|
||||
pull: always
|
||||
environment:
|
||||
|
@ -222,7 +228,7 @@ steps:
|
|||
when:
|
||||
event: [ push, tag, pull_request ]
|
||||
|
||||
- name: test-sqlite
|
||||
- name: api-test-unit-sqlite
|
||||
image: vikunja/golang-build:latest
|
||||
pull: always
|
||||
environment:
|
||||
|
@ -239,7 +245,7 @@ steps:
|
|||
when:
|
||||
event: [ push, tag, pull_request ]
|
||||
|
||||
- name: test-mysql
|
||||
- name: api-test-unit-mysql
|
||||
image: vikunja/golang-build:latest
|
||||
pull: always
|
||||
environment:
|
||||
|
@ -256,7 +262,7 @@ steps:
|
|||
when:
|
||||
event: [ push, tag, pull_request ]
|
||||
|
||||
- name: test-postgres
|
||||
- name: api-test-unit-postgres
|
||||
image: vikunja/golang-build:latest
|
||||
pull: always
|
||||
environment:
|
||||
|
@ -337,31 +343,22 @@ steps:
|
|||
when:
|
||||
event: [ push, tag, pull_request ]
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: build-and-test-frontend
|
||||
|
||||
trigger:
|
||||
branch:
|
||||
include:
|
||||
- main
|
||||
event:
|
||||
include:
|
||||
- push
|
||||
- pull_request
|
||||
|
||||
services:
|
||||
- name: api
|
||||
image: vikunja/vikunja:unstable
|
||||
- name: test-api-run
|
||||
image: vikunja/golang-build:latest
|
||||
pull: always
|
||||
environment:
|
||||
VIKUNJA_SERVICE_TESTINGTOKEN: averyLongSecretToSe33dtheDB
|
||||
VIKUNJA_LOG_LEVEL: DEBUG
|
||||
VIKUNJA_CORS_ENABLE: 1
|
||||
VIKUNJA_DATABASE_PATH: memory
|
||||
VIKUNJA_DATABASE_TYPE: sqlite
|
||||
commands:
|
||||
- ./vikunja
|
||||
detach: true
|
||||
depends_on:
|
||||
- api-build
|
||||
|
||||
steps:
|
||||
- name: dependencies
|
||||
- name: frontend-dependencies
|
||||
image: node:20.11.0-alpine
|
||||
pull: always
|
||||
environment:
|
||||
|
@ -375,7 +372,7 @@ steps:
|
|||
# depends_on:
|
||||
# - restore-cache
|
||||
|
||||
- name: lint
|
||||
- name: frontend-lint
|
||||
image: node:20.11.0-alpine
|
||||
pull: always
|
||||
environment:
|
||||
|
@ -385,9 +382,9 @@ steps:
|
|||
- corepack enable && pnpm config set store-dir .cache/pnpm
|
||||
- pnpm run lint
|
||||
depends_on:
|
||||
- dependencies
|
||||
- frontend-dependencies
|
||||
|
||||
- name: build-prod
|
||||
- name: frontend-build-prod
|
||||
image: node:20.11.0-alpine
|
||||
pull: always
|
||||
environment:
|
||||
|
@ -395,11 +392,11 @@ steps:
|
|||
commands:
|
||||
- cd frontend
|
||||
- corepack enable && pnpm config set store-dir .cache/pnpm
|
||||
- pnpm run build
|
||||
- pnpm run build:test
|
||||
depends_on:
|
||||
- dependencies
|
||||
- frontend-dependencies
|
||||
|
||||
- name: test-unit
|
||||
- name: frontend-test-unit
|
||||
image: node:20.11.0-alpine
|
||||
pull: always
|
||||
commands:
|
||||
|
@ -407,9 +404,9 @@ steps:
|
|||
- corepack enable && pnpm config set store-dir .cache/pnpm
|
||||
- pnpm run test:unit
|
||||
depends_on:
|
||||
- dependencies
|
||||
- frontend-dependencies
|
||||
|
||||
- name: typecheck
|
||||
- name: frontend-typecheck
|
||||
failure: ignore
|
||||
image: node:20.11.0-alpine
|
||||
pull: always
|
||||
|
@ -420,13 +417,13 @@ steps:
|
|||
- corepack enable && pnpm config set store-dir .cache/pnpm
|
||||
- pnpm run typecheck
|
||||
depends_on:
|
||||
- dependencies
|
||||
- frontend-dependencies
|
||||
|
||||
- name: test-frontend
|
||||
- name: frontend-test
|
||||
image: cypress/browsers:node18.12.0-chrome107
|
||||
pull: always
|
||||
environment:
|
||||
CYPRESS_API_URL: http://api:3456/api/v1
|
||||
CYPRESS_API_URL: http://test-api-run:3456/api/v1
|
||||
CYPRESS_TEST_SECRET: averyLongSecretToSe33dtheDB
|
||||
PNPM_CACHE_FOLDER: .cache/pnpm
|
||||
CYPRESS_CACHE_FOLDER: .cache/cypress
|
||||
|
@ -435,14 +432,15 @@ steps:
|
|||
from_secret: cypress_project_key
|
||||
commands:
|
||||
- cd frontend
|
||||
- sed -i 's/localhost/api/g' dist/index.html
|
||||
- sed -i 's/localhost/test-api-run/g' dist-test/index.html
|
||||
- corepack enable && pnpm config set store-dir .cache/pnpm
|
||||
- pnpm cypress install
|
||||
- pnpm run test:e2e-record
|
||||
- pnpm run test:e2e-record-test
|
||||
depends_on:
|
||||
- build-prod
|
||||
- frontend-build-prod
|
||||
- test-api-run
|
||||
|
||||
- name: deploy-preview
|
||||
- name: frontend-deploy-preview
|
||||
image: williamjackson/netlify-cli
|
||||
pull: always
|
||||
user: root # The rest runs as root and thus the permissions wouldn't work
|
||||
|
@ -455,7 +453,7 @@ steps:
|
|||
from_secret: gitea_token
|
||||
commands:
|
||||
- cd frontend
|
||||
- cp -r dist dist-preview
|
||||
- cp -r dist-test dist-preview
|
||||
# Override the default api url used for preview
|
||||
- sed -i 's|http://localhost:3456|https://try.vikunja.io|g' dist-preview/index.html
|
||||
- apk add --no-cache perl-utils
|
||||
|
@ -464,7 +462,7 @@ steps:
|
|||
- shasum -a 384 -c ./scripts/deploy-preview-netlify.mjs.sha384
|
||||
- node ./scripts/deploy-preview-netlify.mjs
|
||||
depends_on:
|
||||
- build-prod
|
||||
- frontend-build-prod
|
||||
when:
|
||||
event:
|
||||
include:
|
||||
|
@ -476,7 +474,7 @@ type: docker
|
|||
name: generate-swagger-docs
|
||||
|
||||
depends_on:
|
||||
- build-and-test-api
|
||||
- build-and-test
|
||||
|
||||
workspace:
|
||||
base: /go
|
||||
|
@ -520,8 +518,7 @@ type: docker
|
|||
name: release
|
||||
|
||||
depends_on:
|
||||
- build-and-test-api
|
||||
- build-and-test-frontend
|
||||
- build-and-test
|
||||
|
||||
workspace:
|
||||
base: /source
|
||||
|
@ -805,8 +802,7 @@ type: docker
|
|||
name: docker-release
|
||||
|
||||
depends_on:
|
||||
- build-and-test-api
|
||||
- build-and-test-frontend
|
||||
- build-and-test
|
||||
|
||||
trigger:
|
||||
ref:
|
||||
|
@ -880,7 +876,7 @@ type: docker
|
|||
name: frontend-release-unstable
|
||||
|
||||
depends_on:
|
||||
- build-and-test-frontend
|
||||
- build-and-test
|
||||
|
||||
trigger:
|
||||
branch:
|
||||
|
@ -943,7 +939,7 @@ type: docker
|
|||
name: frontend-release-version
|
||||
|
||||
depends_on:
|
||||
- build-and-test-frontend
|
||||
- build-and-test
|
||||
|
||||
trigger:
|
||||
event:
|
||||
|
@ -1366,8 +1362,7 @@ trigger:
|
|||
- "refs/tags/**"
|
||||
|
||||
depends_on:
|
||||
- build-and-test-api
|
||||
- build-and-test-frontend
|
||||
- build-and-test
|
||||
- release
|
||||
- deploy-docs
|
||||
- docker-release
|
||||
|
@ -1389,6 +1384,6 @@ steps:
|
|||
- failure
|
||||
---
|
||||
kind: signature
|
||||
hmac: aa9bd51fc7d73686ee169060dcb4d6540214825a0d5134035f477a97f77dd24d
|
||||
hmac: 008b86263a8d03806da907c128a837a380901f1a2190a658c22d4e06cadc1b64
|
||||
|
||||
...
|
||||
|
|
16
Dockerfile
16
Dockerfile
|
@ -33,22 +33,14 @@ RUN export PATH=$PATH:$GOPATH/bin && \
|
|||
# ┘└┘┘─┘┘└┘┘└┘┴─┘┘└┘
|
||||
|
||||
# The actual image
|
||||
# Note: I wanted to use the scratch image here, but unfortunatly the go-sqlite bindings require cgo and
|
||||
# because of this, the container would not start when I compiled the image without cgo.
|
||||
FROM alpine:3.19 AS runner
|
||||
FROM scratch
|
||||
LABEL maintainer="maintainers@vikunja.io"
|
||||
WORKDIR /app/vikunja
|
||||
ENTRYPOINT [ "/sbin/tini", "-g", "--", "/entrypoint.sh" ]
|
||||
ENTRYPOINT [ "/app/vikunja/vikunja" ]
|
||||
EXPOSE 3456
|
||||
USER 1000
|
||||
|
||||
ENV VIKUNJA_SERVICE_ROOTPATH=/app/vikunja/
|
||||
ENV PUID 1000
|
||||
ENV PGID 1000
|
||||
|
||||
RUN apk --update --no-cache add tzdata tini shadow && \
|
||||
addgroup vikunja && \
|
||||
adduser -s /bin/sh -D -G vikunja vikunja -h /app/vikunja -H
|
||||
COPY docker/entrypoint.sh /entrypoint.sh
|
||||
RUN chmod 0755 /entrypoint.sh && mkdir files
|
||||
ENV VIKUNJA_DATABASE_PATH=/db/vikunja.db
|
||||
|
||||
COPY --from=apibuilder /build/vikunja-* vikunja
|
||||
|
|
|
@ -76,7 +76,7 @@ sentry:
|
|||
frontenddsn: "https://85694a2d757547cbbc90cd4b55c5a18d@o1047380.ingest.sentry.io/6024480"
|
||||
|
||||
database:
|
||||
# Database type to use. Supported types are mysql, postgres and sqlite.
|
||||
# Database type to use. Supported values are mysql, postgres and sqlite. Vikunja is able to run with MySQL 8.0+, Mariadb 10.2+, PostgreSQL 12+, and sqlite.
|
||||
type: "sqlite"
|
||||
# Database user which is used to connect to the database.
|
||||
user: "vikunja"
|
||||
|
|
|
@ -51,11 +51,11 @@
|
|||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"electron": "29.0.0",
|
||||
"electron-builder": "24.9.1"
|
||||
"electron": "29.1.0",
|
||||
"electron-builder": "24.12.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"connect-history-api-fallback": "2.0.0",
|
||||
"express": "4.18.2"
|
||||
"express": "4.18.3"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -253,12 +253,11 @@ app-builder-bin@4.0.0:
|
|||
resolved "https://registry.yarnpkg.com/app-builder-bin/-/app-builder-bin-4.0.0.tgz#1df8e654bd1395e4a319d82545c98667d7eed2f0"
|
||||
integrity sha512-xwdG0FJPQMe0M0UA4Tz0zEB8rBJTRA5a476ZawAqiBkMv16GRK5xpXThOjMaEOFnZ6zabejjG4J3da0SXG63KA==
|
||||
|
||||
app-builder-lib@24.9.1:
|
||||
version "24.9.1"
|
||||
resolved "https://registry.yarnpkg.com/app-builder-lib/-/app-builder-lib-24.9.1.tgz#bf3568529298b4de8595ed1acbb351fe27db5ba4"
|
||||
integrity sha512-Q1nYxZcio4r+W72cnIRVYofEAyjBd3mG47o+zms8HlD51zWtA/YxJb01Jei5F+jkWhge/PTQK+uldsPh6d0/4g==
|
||||
app-builder-lib@24.12.0:
|
||||
version "24.12.0"
|
||||
resolved "https://registry.yarnpkg.com/app-builder-lib/-/app-builder-lib-24.12.0.tgz#2e985968c341d28fc887be3ecee658e6a240e147"
|
||||
integrity sha512-t/xinVrMbsEhwljLDoFOtGkiZlaxY1aceZbHERGAS02EkUHJp9lgs/+L8okXLlYCaDSqYdB05Yb8Co+krvguXA==
|
||||
dependencies:
|
||||
"7zip-bin" "~5.2.0"
|
||||
"@develar/schema-utils" "~2.6.5"
|
||||
"@electron/notarize" "2.1.0"
|
||||
"@electron/osx-sign" "1.0.5"
|
||||
|
@ -267,12 +266,12 @@ app-builder-lib@24.9.1:
|
|||
"@types/fs-extra" "9.0.13"
|
||||
async-exit-hook "^2.0.1"
|
||||
bluebird-lst "^1.0.9"
|
||||
builder-util "24.8.1"
|
||||
builder-util "24.9.4"
|
||||
builder-util-runtime "9.2.3"
|
||||
chromium-pickle-js "^0.2.0"
|
||||
debug "^4.3.4"
|
||||
ejs "^3.1.8"
|
||||
electron-publish "24.8.1"
|
||||
electron-publish "24.9.4"
|
||||
form-data "^4.0.0"
|
||||
fs-extra "^10.1.0"
|
||||
hosted-git-info "^4.1.0"
|
||||
|
@ -349,13 +348,13 @@ bluebird@^3.5.5:
|
|||
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
|
||||
integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==
|
||||
|
||||
body-parser@1.20.1:
|
||||
version "1.20.1"
|
||||
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668"
|
||||
integrity sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==
|
||||
body-parser@1.20.2:
|
||||
version "1.20.2"
|
||||
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd"
|
||||
integrity sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==
|
||||
dependencies:
|
||||
bytes "3.1.2"
|
||||
content-type "~1.0.4"
|
||||
content-type "~1.0.5"
|
||||
debug "2.6.9"
|
||||
depd "2.0.0"
|
||||
destroy "1.2.0"
|
||||
|
@ -363,7 +362,7 @@ body-parser@1.20.1:
|
|||
iconv-lite "0.4.24"
|
||||
on-finished "2.4.1"
|
||||
qs "6.11.0"
|
||||
raw-body "2.5.1"
|
||||
raw-body "2.5.2"
|
||||
type-is "~1.6.18"
|
||||
unpipe "1.0.0"
|
||||
|
||||
|
@ -418,10 +417,10 @@ builder-util-runtime@9.2.3:
|
|||
debug "^4.3.4"
|
||||
sax "^1.2.4"
|
||||
|
||||
builder-util@24.8.1:
|
||||
version "24.8.1"
|
||||
resolved "https://registry.yarnpkg.com/builder-util/-/builder-util-24.8.1.tgz#594d45b0c86d1d17f5c7bebbb77405080b2571c2"
|
||||
integrity sha512-ibmQ4BnnqCnJTNrdmdNlnhF48kfqhNzSeqFMXHLIl+o9/yhn6QfOaVrloZ9YUu3m0k3rexvlT5wcki6LWpjTZw==
|
||||
builder-util@24.9.4:
|
||||
version "24.9.4"
|
||||
resolved "https://registry.yarnpkg.com/builder-util/-/builder-util-24.9.4.tgz#8cde880e7c719285e9cb30e6850ddd5bf475ac04"
|
||||
integrity sha512-YNon3rYjPSm4XDDho9wD6jq7vLRJZUy9FR+yFZnHoWvvdVCnZakL4BctTlPABP41MvIH5yk2cTZ2YfkOhGistQ==
|
||||
dependencies:
|
||||
"7zip-bin" "~5.2.0"
|
||||
"@types/debug" "^4.1.6"
|
||||
|
@ -572,7 +571,7 @@ content-disposition@0.5.4:
|
|||
dependencies:
|
||||
safe-buffer "5.2.1"
|
||||
|
||||
content-type@~1.0.4:
|
||||
content-type@~1.0.4, content-type@~1.0.5:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918"
|
||||
integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==
|
||||
|
@ -690,13 +689,13 @@ dir-compare@^3.0.0:
|
|||
buffer-equal "^1.0.0"
|
||||
minimatch "^3.0.4"
|
||||
|
||||
dmg-builder@24.9.1:
|
||||
version "24.9.1"
|
||||
resolved "https://registry.yarnpkg.com/dmg-builder/-/dmg-builder-24.9.1.tgz#04bf6c0dcd235f6214511f2358a78ed2b9379421"
|
||||
integrity sha512-huC+O6hvHd24Ubj3cy2GMiGLe2xGFKN3klqVMLAdcbB6SWMd1yPSdZvV8W1O01ICzCCRlZDHiv4VrNUgnPUfbQ==
|
||||
dmg-builder@24.12.0:
|
||||
version "24.12.0"
|
||||
resolved "https://registry.yarnpkg.com/dmg-builder/-/dmg-builder-24.12.0.tgz#62a08162f2b3160a286d03ebb6db65c36a3711c7"
|
||||
integrity sha512-nS22OyHUIYcK40UnILOtqC5Qffd1SN1Ljqy/6e+QR2H1wM3iNBrKJoEbDRfEmYYaALKNFRkKPqSbZKRsGUBdPw==
|
||||
dependencies:
|
||||
app-builder-lib "24.9.1"
|
||||
builder-util "24.8.1"
|
||||
app-builder-lib "24.12.0"
|
||||
builder-util "24.9.4"
|
||||
builder-util-runtime "9.2.3"
|
||||
fs-extra "^10.1.0"
|
||||
iconv-lite "^0.6.2"
|
||||
|
@ -740,16 +739,16 @@ ejs@^3.1.8:
|
|||
dependencies:
|
||||
jake "^10.8.5"
|
||||
|
||||
electron-builder@24.9.1:
|
||||
version "24.9.1"
|
||||
resolved "https://registry.yarnpkg.com/electron-builder/-/electron-builder-24.9.1.tgz#4aee03947963b829a7f48a850fe02c219311ef63"
|
||||
integrity sha512-v7BuakDuY6sKMUYM8mfQGrwyjBpZ/ObaqnenU0H+igEL10nc6ht049rsCw2HghRBdEwJxGIBuzs3jbEhNaMDmg==
|
||||
electron-builder@24.12.0:
|
||||
version "24.12.0"
|
||||
resolved "https://registry.yarnpkg.com/electron-builder/-/electron-builder-24.12.0.tgz#95c41d14b3b1cc177db62715e42ef9fd27344491"
|
||||
integrity sha512-dH4O9zkxFxFbBVFobIR5FA71yJ1TZSCvjZ2maCskpg7CWjBF+SNRSQAThlDyUfRuB+jBTMwEMzwARywmap0CSw==
|
||||
dependencies:
|
||||
app-builder-lib "24.9.1"
|
||||
builder-util "24.8.1"
|
||||
app-builder-lib "24.12.0"
|
||||
builder-util "24.9.4"
|
||||
builder-util-runtime "9.2.3"
|
||||
chalk "^4.1.2"
|
||||
dmg-builder "24.9.1"
|
||||
dmg-builder "24.12.0"
|
||||
fs-extra "^10.1.0"
|
||||
is-ci "^3.0.0"
|
||||
lazy-val "^1.0.5"
|
||||
|
@ -757,23 +756,23 @@ electron-builder@24.9.1:
|
|||
simple-update-notifier "2.0.0"
|
||||
yargs "^17.6.2"
|
||||
|
||||
electron-publish@24.8.1:
|
||||
version "24.8.1"
|
||||
resolved "https://registry.yarnpkg.com/electron-publish/-/electron-publish-24.8.1.tgz#4216740372bf4297a429543402a1a15ce8c3560b"
|
||||
integrity sha512-IFNXkdxMVzUdweoLJNXSupXkqnvgbrn3J4vognuOY06LaS/m0xvfFYIf+o1CM8if6DuWYWoQFKPcWZt/FUjZPw==
|
||||
electron-publish@24.9.4:
|
||||
version "24.9.4"
|
||||
resolved "https://registry.yarnpkg.com/electron-publish/-/electron-publish-24.9.4.tgz#70db542763a78e4980e4e6409c203aef320d0d05"
|
||||
integrity sha512-FghbeVMfxHneHjsG2xUSC0NMZYWOOWhBxfZKPTbibcJ0CjPH0Ph8yb5CUO62nqywXfA5u1Otq6K8eOdOixxmNg==
|
||||
dependencies:
|
||||
"@types/fs-extra" "^9.0.11"
|
||||
builder-util "24.8.1"
|
||||
builder-util "24.9.4"
|
||||
builder-util-runtime "9.2.3"
|
||||
chalk "^4.1.2"
|
||||
fs-extra "^10.1.0"
|
||||
lazy-val "^1.0.5"
|
||||
mime "^2.5.2"
|
||||
|
||||
electron@29.0.0:
|
||||
version "29.0.0"
|
||||
resolved "https://registry.yarnpkg.com/electron/-/electron-29.0.0.tgz#2c1d34a95fc23a5b3530aa53de6eacca89a410b1"
|
||||
integrity sha512-HhrRC5vWb6fAbWXP3A6ABwKUO9JvYSC4E141RzWFgnDBqNiNtabfmgC8hsVeCR65RQA2MLSDgC8uP52I9zFllQ==
|
||||
electron@29.1.0:
|
||||
version "29.1.0"
|
||||
resolved "https://registry.yarnpkg.com/electron/-/electron-29.1.0.tgz#37f0e4915226db3c87bc54b187795272bf61fc39"
|
||||
integrity sha512-giJVIm0sWVp+8V1GXrKqKTb+h7no0P3ooYqEd34AD9wMJzGnAeL+usj+R0155/0pdvvP1mgydnA7lcaFA2M9lw==
|
||||
dependencies:
|
||||
"@electron/get" "^2.0.0"
|
||||
"@types/node" "^20.9.0"
|
||||
|
@ -831,14 +830,14 @@ etag@~1.8.1:
|
|||
resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
|
||||
integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==
|
||||
|
||||
express@4.18.2:
|
||||
version "4.18.2"
|
||||
resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59"
|
||||
integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==
|
||||
express@4.18.3:
|
||||
version "4.18.3"
|
||||
resolved "https://registry.yarnpkg.com/express/-/express-4.18.3.tgz#6870746f3ff904dee1819b82e4b51509afffb0d4"
|
||||
integrity sha512-6VyCijWQ+9O7WuVMTRBTl+cjNNIzD5cY5mQ1WM8r/LEkI2u8EYpOotESNwzNlyCn3g+dmjKYI6BmNneSr/FSRw==
|
||||
dependencies:
|
||||
accepts "~1.3.8"
|
||||
array-flatten "1.1.1"
|
||||
body-parser "1.20.1"
|
||||
body-parser "1.20.2"
|
||||
content-disposition "0.5.4"
|
||||
content-type "~1.0.4"
|
||||
cookie "0.5.0"
|
||||
|
@ -1570,10 +1569,10 @@ range-parser@~1.2.1:
|
|||
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
|
||||
integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==
|
||||
|
||||
raw-body@2.5.1:
|
||||
version "2.5.1"
|
||||
resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857"
|
||||
integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==
|
||||
raw-body@2.5.2:
|
||||
version "2.5.2"
|
||||
resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a"
|
||||
integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==
|
||||
dependencies:
|
||||
bytes "3.1.2"
|
||||
http-errors "2.0.0"
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
#!/usr/bin/env sh
|
||||
set -e
|
||||
|
||||
if [ -n "$PUID" ] && [ "$PUID" -ne 0 ] && \
|
||||
[ -n "$PGID" ] && [ "$PGID" -ne 0 ] ; then
|
||||
echo "info: creating the new user vikunja with $PUID:$PGID"
|
||||
groupmod -g "$PGID" -o vikunja
|
||||
usermod -u "$PUID" -o vikunja
|
||||
chown -R vikunja:vikunja ./files/
|
||||
chown vikunja:vikunja .
|
||||
exec su vikunja -c /app/vikunja/vikunja "$@"
|
||||
else
|
||||
echo "info: creation of non-root user is skipped"
|
||||
exec /app/vikunja/vikunja "$@"
|
||||
fi
|
|
@ -406,7 +406,7 @@ Environment path: `VIKUNJA_SENTRY_FRONTENDDSN`
|
|||
|
||||
### type
|
||||
|
||||
Database type to use. Supported types are mysql, postgres and sqlite.
|
||||
Database type to use. Supported values are mysql, postgres and sqlite. Vikunja is able to run with MySQL 8.0+, Mariadb 10.2+, PostgreSQL 12+, and sqlite.
|
||||
|
||||
Default: `sqlite`
|
||||
|
||||
|
|
|
@ -27,7 +27,6 @@ Create a directory for the project where all data and the compose file will live
|
|||
|
||||
Create a `docker-compose.yml` file with the following contents in your directory:
|
||||
|
||||
|
||||
```yaml
|
||||
version: '3'
|
||||
|
||||
|
@ -80,6 +79,18 @@ The number before the colon is the host port - This is where you can reach vikun
|
|||
|
||||
You'll need to change the value of the `VIKUNJA_SERVICE_PUBLICURL` environment variable to the public port or hostname where Vikunja is reachable.
|
||||
|
||||
## Ensure adequate file permissions
|
||||
|
||||
Vikunja runs as user `1000` and no group by default.
|
||||
|
||||
To be able to upload task attachments or change the background of project, Vikunja must be able to write into the `files` directory.
|
||||
To do this, create the folder and chown it before starting the stack:
|
||||
|
||||
```
|
||||
mkdir $PWD/files
|
||||
chown 1000 $PWD/files
|
||||
```
|
||||
|
||||
## Run it
|
||||
|
||||
Run `sudo docker-compose up` in your directory and take a look at the output you get.
|
||||
|
|
|
@ -15,8 +15,6 @@ It uses a proxy configuration to make it available under a domain.
|
|||
|
||||
For all available configuration options, see [configuration]({{< ref "config.md">}}).
|
||||
|
||||
Once deployed, you might want to change the [`PUID` and `GUID` settings]({{< ref "install.md">}}#setting-user-and-group-id-of-the-user-running-vikunja) or [set the time zone]({{< ref "config.md">}}#timezone).
|
||||
|
||||
After registering all your users, you might also want to [disable the user registration]({{<ref "config.md">}}#enableregistration).
|
||||
|
||||
<div class="notification is-warning">
|
||||
|
@ -27,6 +25,23 @@ All examples on this page already reflect this and do not require additional wor
|
|||
|
||||
{{< table_of_contents >}}
|
||||
|
||||
## File permissions
|
||||
|
||||
Vikunja runs as user `1000` and no group by default.
|
||||
You can use Docker's [`--user`](https://docs.docker.com/engine/reference/run/#user) flag to change that.
|
||||
|
||||
You must ensure Vikunja is able to write into the `files` directory.
|
||||
To do this, create the folder and chown it before starting the stack:
|
||||
|
||||
```
|
||||
mkdir $PWD/files
|
||||
chown 1000 $PWD/files
|
||||
```
|
||||
|
||||
You'll need to do this before running any of the examples on this page.
|
||||
|
||||
Vikunja will not try to aquire ownership of the files folder, as that would mean it had to run as root.
|
||||
|
||||
## PostgreSQL
|
||||
|
||||
Vikunja supports postgres, mysql and sqlite as a database backend. The examples on this page use mysql with a mariadb container.
|
||||
|
@ -78,6 +93,13 @@ You'll also need to remove or change the `VIKUNJA_DATABASE_TYPE` to `sqlite` on
|
|||
|
||||
You can also remove the db section.
|
||||
|
||||
To run the container, you need to create the directories first and make sure they have all required permissions:
|
||||
|
||||
```
|
||||
mkdir $PWD/files $PWD/db
|
||||
chown 1000 $PWD/files $PWD/db
|
||||
```
|
||||
|
||||
<div class="notification is-warning">
|
||||
<b>NOTE:</b> If you'll use your instance with more than a handful of users, we recommend using mysql or postgres.
|
||||
</div>
|
||||
|
@ -91,6 +113,11 @@ If you want to make Vikunja available on a domain or need tls termination, check
|
|||
Note that you need to change the [`VIKUNJA_SERVICE_PUBLICURL`]({{< ref "config.md" >}}#publicurl) environment variable to the public ip or hostname including the port (the docker host you're running this on) is reachable at, prefixed with `http://`.
|
||||
Because the browser you'll use to access the Vikunja frontend uses that url to make the requests, it has to be able to reach it from the outside.
|
||||
|
||||
<div class="notification is-warning">
|
||||
<b>NOTE:</b> You must ensure Vikunja has write permissions on the `files` directory before starting the stack.
|
||||
To do this, <a href="#file-permissions">check out the related commands here</a>.
|
||||
</div>
|
||||
|
||||
```yaml
|
||||
version: '3'
|
||||
|
||||
|
@ -140,6 +167,11 @@ We also make a few assumptions here which you'll most likely need to adjust for
|
|||
* The entrypoint you want to make vikunja available from is called `https`
|
||||
* The tls cert resolver is called `acme`
|
||||
|
||||
<div class="notification is-warning">
|
||||
<b>NOTE:</b> You must ensure Vikunja has write permissions on the `files` directory before starting the stack.
|
||||
To do this, <a href="#file-permissions">check out the related commands here</a>.
|
||||
</div>
|
||||
|
||||
```yaml
|
||||
version: '3'
|
||||
|
||||
|
@ -203,6 +235,11 @@ vikunja.example.com {
|
|||
Note that you need to change the [`VIKUNJA_SERVICE_PUBLICURL`]({{< ref "config.md" >}}#publicurl) environment variable to the ip (the docker host you're running this on) is reachable at.
|
||||
Because the browser you'll use to access the Vikunja frontend uses that url to make the requests, it has to be able to reach that ip + port from the outside.
|
||||
|
||||
<div class="notification is-warning">
|
||||
<b>NOTE:</b> You must ensure Vikunja has write permissions on the `files` directory before starting the stack.
|
||||
To do this, <a href="#file-permissions">check out the related commands here</a>.
|
||||
</div>
|
||||
|
||||
Docker Compose config:
|
||||
|
||||
```yaml
|
||||
|
@ -286,10 +323,13 @@ The docker-compose file we're going to use is exactly the same from the [example
|
|||
|
||||
You may want to change the volumes to match the rest of your setup.
|
||||
|
||||
Once deployed, you might want to change the [`PUID` and `GUID` settings]({{< ref "install.md">}}#setting-user-and-group-id-of-the-user-running-vikunja) or [set the time zone]({{< ref "config.md">}}#timezone).
|
||||
|
||||
After registering all your users, you might also want to [disable the user registration]({{<ref "config.md">}}#enableregistration).
|
||||
|
||||
<div class="notification is-warning">
|
||||
<b>NOTE:</b> You must ensure Vikunja has write permissions on the `files` directory before starting the stack.
|
||||
To do this, <a href="#file-permissions">check out the related commands here</a>.
|
||||
</div>
|
||||
|
||||
## Redis
|
||||
|
||||
While Vikunja has support to use redis as a caching backend, you'll probably not need it unless you're using Vikunja with more than a handful of users.
|
||||
|
|
|
@ -140,17 +140,23 @@ It will automatically run all necessary database migrations.
|
|||
To get up and running quickly, use this command:
|
||||
|
||||
```
|
||||
touch vikunja.db
|
||||
docker run -p 3456:3456 -v $PWD/files:/app/vikunja/files -v $PWD/vikunja.db:/app/vikunja/vikunja.db vikunja/vikunja
|
||||
mkdir $PWD/files $PWD/db
|
||||
chown 1000 $PWD/files $PWD/db
|
||||
docker run -p 3456:3456 -v $PWD/files:/app/vikunja/files -v $PWD/db:/db vikunja/vikunja
|
||||
```
|
||||
|
||||
This will expose vikunja on port `3456` on the host running the container and use sqlite as database backend.
|
||||
|
||||
**Note**: The container runs as the user `1000` and no group by default.
|
||||
You can use Docker's [`--user`](https://docs.docker.com/engine/reference/run/#user) flag to change that.
|
||||
Make sure the new user has required permissions on the `db` and `files` folder.
|
||||
|
||||
You can mount a local configuration like so:
|
||||
|
||||
```
|
||||
touch vikunja.db
|
||||
docker run -p 3456:3456 -v /path/to/config/on/host.yml:/app/vikunja/config.yml:ro -v $PWD/files:/app/vikunja/files -v $PWD/vikunja.db:/app/vikunja/vikunja.db vikunja/vikunja
|
||||
mkdir $PWD/files $PWD/db
|
||||
chown 1000 $PWD/files $PWD/db
|
||||
docker run -p 3456:3456 -v /path/to/config/on/host.yml:/app/vikunja/config.yml:ro -v $PWD/files:/app/vikunja/files -v $PWD/db:/db vikunja/vikunja
|
||||
```
|
||||
|
||||
Though it is recommended to use environment variables or `.env` files to configure Vikunja in docker.
|
||||
|
@ -163,13 +169,6 @@ Check out the [docker examples]({{<ref "full-docker-example.md">}}) for more adv
|
|||
By default, the container stores all files uploaded and used through vikunja inside of `/app/vikunja/files` which is created as a docker volume.
|
||||
You should mount the volume somewhere to the host to permanently store the files and don't lose them if the container restarts.
|
||||
|
||||
### Setting user and group id of the user running vikunja
|
||||
|
||||
You can set the user and group id of the user running vikunja with the `PUID` and `PGID` environment variables.
|
||||
This follows the pattern used by [the linuxserver.io](https://docs.linuxserver.io/general/understanding-puid-and-pgid) docker images.
|
||||
|
||||
This is useful to solve general permission problems when host-mounting volumes such as the volume used for task attachments.
|
||||
|
||||
### Docker compose
|
||||
|
||||
Check out the [docker examples]({{<ref "full-docker-example.md">}}) for more advanced configuration using docker compose.
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
},
|
||||
"homepage": "https://vikunja.io/",
|
||||
"funding": "https://opencollective.com/vikunja",
|
||||
"packageManager": "pnpm@8.15.3",
|
||||
"packageManager": "pnpm@8.15.4",
|
||||
"keywords": [
|
||||
"todo",
|
||||
"productivity",
|
||||
|
@ -28,13 +28,15 @@
|
|||
"serve": "pnpm run dev",
|
||||
"preview": "vite preview --port 4173",
|
||||
"preview:dev": "vite preview --outDir dist-dev --mode development --port 4173",
|
||||
"preview:test": "vite preview --port 4173 --outDir dist-test",
|
||||
"build": "vite build && workbox copyLibraries dist/",
|
||||
"build:test": "vite build --outDir dist-test && workbox copyLibraries dist-dev/",
|
||||
"build:modern-only": "BUILD_MODERN_ONLY=true vite build && workbox copyLibraries dist/",
|
||||
"build:dev": "vite build --mode development --outDir dist-dev/",
|
||||
"lint": "eslint 'src/**/*.{js,ts,vue}'",
|
||||
"lint:fix": "pnpm run lint --fix",
|
||||
"test:e2e": "start-server-and-test preview http://127.0.0.1:4173 'cypress run --e2e --browser chrome'",
|
||||
"test:e2e-record": "start-server-and-test preview http://127.0.0.1:4173 'cypress run --e2e --browser chrome --record'",
|
||||
"test:e2e-record-test": "start-server-and-test preview:test http://127.0.0.1:4173 'cypress run --e2e --browser chrome --record'",
|
||||
"test:e2e-dev-dev": "start-server-and-test preview:dev http://127.0.0.1:4173 'cypress open --e2e'",
|
||||
"test:e2e-dev": "start-server-and-test preview http://127.0.0.1:4173 'cypress open --e2e'",
|
||||
"test:unit": "vitest --dir ./src",
|
||||
|
@ -56,45 +58,45 @@
|
|||
"@infectoone/vue-ganttastic": "2.2.0",
|
||||
"@intlify/unplugin-vue-i18n": "2.0.0",
|
||||
"@kyvg/vue3-notification": "3.2.0",
|
||||
"@sentry/tracing": "7.102.0",
|
||||
"@sentry/vue": "7.102.0",
|
||||
"@tiptap/core": "2.2.3",
|
||||
"@tiptap/extension-blockquote": "2.2.3",
|
||||
"@tiptap/extension-bold": "2.2.3",
|
||||
"@tiptap/extension-bullet-list": "2.2.3",
|
||||
"@tiptap/extension-code": "2.2.3",
|
||||
"@tiptap/extension-code-block-lowlight": "2.2.3",
|
||||
"@tiptap/extension-document": "2.2.3",
|
||||
"@tiptap/extension-dropcursor": "2.2.3",
|
||||
"@tiptap/extension-gapcursor": "2.2.3",
|
||||
"@tiptap/extension-hard-break": "2.2.3",
|
||||
"@tiptap/extension-heading": "2.2.3",
|
||||
"@tiptap/extension-history": "2.2.3",
|
||||
"@tiptap/extension-horizontal-rule": "2.2.3",
|
||||
"@tiptap/extension-image": "2.2.3",
|
||||
"@tiptap/extension-italic": "2.2.3",
|
||||
"@tiptap/extension-link": "2.2.3",
|
||||
"@tiptap/extension-list-item": "2.2.3",
|
||||
"@tiptap/extension-ordered-list": "2.2.3",
|
||||
"@tiptap/extension-paragraph": "2.2.3",
|
||||
"@tiptap/extension-placeholder": "2.2.3",
|
||||
"@tiptap/extension-strike": "2.2.3",
|
||||
"@tiptap/extension-table": "2.2.3",
|
||||
"@tiptap/extension-table-cell": "2.2.3",
|
||||
"@tiptap/extension-table-header": "2.2.3",
|
||||
"@tiptap/extension-table-row": "2.2.3",
|
||||
"@tiptap/extension-task-item": "2.2.3",
|
||||
"@tiptap/extension-task-list": "2.2.3",
|
||||
"@tiptap/extension-text": "2.2.3",
|
||||
"@tiptap/extension-typography": "2.2.3",
|
||||
"@tiptap/extension-underline": "2.2.3",
|
||||
"@tiptap/pm": "2.2.3",
|
||||
"@tiptap/suggestion": "2.2.3",
|
||||
"@tiptap/vue-3": "2.2.3",
|
||||
"@sentry/tracing": "7.103.0",
|
||||
"@sentry/vue": "7.103.0",
|
||||
"@tiptap/core": "2.2.4",
|
||||
"@tiptap/extension-blockquote": "2.2.4",
|
||||
"@tiptap/extension-bold": "2.2.4",
|
||||
"@tiptap/extension-bullet-list": "2.2.4",
|
||||
"@tiptap/extension-code": "2.2.4",
|
||||
"@tiptap/extension-code-block-lowlight": "2.2.4",
|
||||
"@tiptap/extension-document": "2.2.4",
|
||||
"@tiptap/extension-dropcursor": "2.2.4",
|
||||
"@tiptap/extension-gapcursor": "2.2.4",
|
||||
"@tiptap/extension-hard-break": "2.2.4",
|
||||
"@tiptap/extension-heading": "2.2.4",
|
||||
"@tiptap/extension-history": "2.2.4",
|
||||
"@tiptap/extension-horizontal-rule": "2.2.4",
|
||||
"@tiptap/extension-image": "2.2.4",
|
||||
"@tiptap/extension-italic": "2.2.4",
|
||||
"@tiptap/extension-link": "2.2.4",
|
||||
"@tiptap/extension-list-item": "2.2.4",
|
||||
"@tiptap/extension-ordered-list": "2.2.4",
|
||||
"@tiptap/extension-paragraph": "2.2.4",
|
||||
"@tiptap/extension-placeholder": "2.2.4",
|
||||
"@tiptap/extension-strike": "2.2.4",
|
||||
"@tiptap/extension-table": "2.2.4",
|
||||
"@tiptap/extension-table-cell": "2.2.4",
|
||||
"@tiptap/extension-table-header": "2.2.4",
|
||||
"@tiptap/extension-table-row": "2.2.4",
|
||||
"@tiptap/extension-task-item": "2.2.4",
|
||||
"@tiptap/extension-task-list": "2.2.4",
|
||||
"@tiptap/extension-text": "2.2.4",
|
||||
"@tiptap/extension-typography": "2.2.4",
|
||||
"@tiptap/extension-underline": "2.2.4",
|
||||
"@tiptap/pm": "2.2.4",
|
||||
"@tiptap/suggestion": "2.2.4",
|
||||
"@tiptap/vue-3": "2.2.4",
|
||||
"@types/is-touch-device": "1.0.2",
|
||||
"@types/lodash.clonedeep": "4.5.9",
|
||||
"@vueuse/core": "10.8.0",
|
||||
"@vueuse/router": "10.8.0",
|
||||
"@vueuse/core": "10.9.0",
|
||||
"@vueuse/router": "10.9.0",
|
||||
"axios": "1.6.7",
|
||||
"blurhash": "2.0.5",
|
||||
"bulma-css-variables": "0.9.33",
|
||||
|
@ -116,7 +118,7 @@
|
|||
"sortablejs": "1.15.2",
|
||||
"tippy.js": "6.3.7",
|
||||
"ufo": "1.4.0",
|
||||
"vue": "3.4.19",
|
||||
"vue": "3.4.21",
|
||||
"vue-advanced-cropper": "2.8.8",
|
||||
"vue-flatpickr-component": "11.0.4",
|
||||
"vue-i18n": "9.9.1",
|
||||
|
@ -128,9 +130,9 @@
|
|||
"@4tw/cypress-drag-drop": "2.2.5",
|
||||
"@cypress/vite-dev-server": "5.0.7",
|
||||
"@cypress/vue": "6.0.0",
|
||||
"@faker-js/faker": "8.4.0",
|
||||
"@faker-js/faker": "8.4.1",
|
||||
"@histoire/plugin-screenshot": "0.17.8",
|
||||
"@histoire/plugin-vue": "0.17.9",
|
||||
"@histoire/plugin-vue": "0.17.12",
|
||||
"@rushstack/eslint-patch": "1.7.2",
|
||||
"@tsconfig/node18": "18.2.2",
|
||||
"@types/codemirror": "5.60.15",
|
||||
|
@ -139,43 +141,43 @@
|
|||
"@types/is-touch-device": "1.0.2",
|
||||
"@types/lodash.debounce": "4.0.9",
|
||||
"@types/marked": "5.0.2",
|
||||
"@types/node": "20.11.10",
|
||||
"@types/node": "20.11.22",
|
||||
"@types/postcss-preset-env": "7.7.0",
|
||||
"@types/sortablejs": "1.15.7",
|
||||
"@typescript-eslint/eslint-plugin": "7.0.1",
|
||||
"@typescript-eslint/parser": "7.0.1",
|
||||
"@vitejs/plugin-legacy": "5.3.0",
|
||||
"@vitejs/plugin-vue": "5.0.3",
|
||||
"@types/sortablejs": "1.15.8",
|
||||
"@typescript-eslint/eslint-plugin": "7.1.0",
|
||||
"@typescript-eslint/parser": "7.1.0",
|
||||
"@vitejs/plugin-legacy": "5.3.1",
|
||||
"@vitejs/plugin-vue": "5.0.4",
|
||||
"@vue/eslint-config-typescript": "12.0.0",
|
||||
"@vue/test-utils": "2.4.4",
|
||||
"@vue/tsconfig": "0.5.1",
|
||||
"autoprefixer": "10.4.17",
|
||||
"browserslist": "4.22.3",
|
||||
"caniuse-lite": "1.0.30001581",
|
||||
"css-has-pseudo": "6.0.1",
|
||||
"browserslist": "4.23.0",
|
||||
"caniuse-lite": "1.0.30001591",
|
||||
"css-has-pseudo": "6.0.2",
|
||||
"csstype": "3.1.3",
|
||||
"cypress": "13.6.3",
|
||||
"esbuild": "0.20.0",
|
||||
"eslint": "8.56.0",
|
||||
"eslint-plugin-vue": "9.20.1",
|
||||
"happy-dom": "13.3.5",
|
||||
"cypress": "13.6.6",
|
||||
"esbuild": "0.20.1",
|
||||
"eslint": "8.57.0",
|
||||
"eslint-plugin-vue": "9.22.0",
|
||||
"happy-dom": "13.6.2",
|
||||
"histoire": "0.17.9",
|
||||
"postcss": "8.4.33",
|
||||
"postcss": "8.4.35",
|
||||
"postcss-easing-gradients": "3.0.1",
|
||||
"postcss-easings": "4.0.0",
|
||||
"postcss-focus-within": "8.0.1",
|
||||
"postcss-preset-env": "9.3.0",
|
||||
"rollup": "4.9.6",
|
||||
"postcss-preset-env": "9.4.0",
|
||||
"rollup": "4.12.0",
|
||||
"rollup-plugin-visualizer": "5.12.0",
|
||||
"sass": "1.70.0",
|
||||
"sass": "1.71.1",
|
||||
"start-server-and-test": "2.0.3",
|
||||
"typescript": "5.3.3",
|
||||
"vite": "5.0.12",
|
||||
"vite": "5.1.4",
|
||||
"vite-plugin-inject-preload": "1.3.3",
|
||||
"vite-plugin-pwa": "0.17.5",
|
||||
"vite-plugin-sentry": "1.3.0",
|
||||
"vite-plugin-pwa": "0.19.1",
|
||||
"vite-plugin-sentry": "1.4.0",
|
||||
"vite-svg-loader": "5.1.0",
|
||||
"vitest": "1.2.2",
|
||||
"vitest": "1.3.1",
|
||||
"vue-tsc": "1.8.27",
|
||||
"wait-on": "7.2.0",
|
||||
"workbox-cli": "7.0.0"
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -51,10 +51,12 @@ Hi ${process.env.DRONE_COMMIT_AUTHOR}!
|
|||
|
||||
Thank you for creating a PR!
|
||||
|
||||
I've deployed the changes of this PR on a preview environment under this URL: ${fullPreviewUrl}
|
||||
I've deployed the frontend changes of this PR on a preview environment under this URL: ${fullPreviewUrl}
|
||||
|
||||
You can use this url to view the changes live and test them out.
|
||||
You will need to manually connect this to an api running somehwere. The easiest to use is https://try.vikunja.io/.
|
||||
You will need to manually connect this to an api running somewhere. The easiest to use is https://try.vikunja.io/.
|
||||
|
||||
This preview does not contain any changes made to the api, only the frontend.
|
||||
|
||||
Have a nice day!
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
d58cd9ebc135407aa29d093b046d84b72ec7073b3f08cedfdbb936318a0ad3e272fab921d3ff91a82c1a7059fcdecd7b ./scripts/deploy-preview-netlify.mjs
|
||||
2ba5ae4c831fd749296d92f92c5f89339030e22b80be62b1253dc26982e8fd0082e354f884a3ba15293e0b96317ec758 ./scripts/deploy-preview-netlify.mjs
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
<template>
|
||||
<BaseButton class="dropdown-item">
|
||||
<BaseButton
|
||||
class="dropdown-item"
|
||||
:class="{'is-disabled': disabled}"
|
||||
>
|
||||
<span
|
||||
v-if="icon"
|
||||
class="icon is-small"
|
||||
|
@ -21,6 +24,7 @@ import type {IconProp} from '@fortawesome/fontawesome-svg-core'
|
|||
export interface DropDownItemProps extends /* @vue-ignore */ BaseButtonProps {
|
||||
icon?: IconProp,
|
||||
iconClass?: object | string,
|
||||
disabled?: boolean,
|
||||
}
|
||||
|
||||
defineProps<DropDownItemProps>()
|
||||
|
|
|
@ -67,8 +67,10 @@
|
|||
{{ $t('menu.duplicate') }}
|
||||
</DropdownItem>
|
||||
<DropdownItem
|
||||
v-tooltip="isDefaultProject ? $t('menu.cantArchiveIsDefault') : ''"
|
||||
:to="{ name: 'project.settings.archive', params: { projectId: project.id } }"
|
||||
icon="archive"
|
||||
:disabled="isDefaultProject"
|
||||
>
|
||||
{{ $t('menu.archive') }}
|
||||
</DropdownItem>
|
||||
|
@ -95,9 +97,11 @@
|
|||
{{ $t('menu.createProject') }}
|
||||
</DropdownItem>
|
||||
<DropdownItem
|
||||
v-tooltip="isDefaultProject ? $t('menu.cantDeleteIsDefault') : ''"
|
||||
:to="{ name: 'project.settings.delete', params: { projectId: project.id } }"
|
||||
icon="trash-alt"
|
||||
class="has-text-danger"
|
||||
:disabled="isDefaultProject"
|
||||
>
|
||||
{{ $t('menu.delete') }}
|
||||
</DropdownItem>
|
||||
|
@ -106,7 +110,7 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {ref, computed, watchEffect, type PropType} from 'vue'
|
||||
import {computed, type PropType, ref, watchEffect} from 'vue'
|
||||
|
||||
import BaseButton from '@/components/base/BaseButton.vue'
|
||||
import Dropdown from '@/components/misc/dropdown.vue'
|
||||
|
@ -118,6 +122,7 @@ import type {ISubscription} from '@/modelTypes/ISubscription'
|
|||
import {isSavedFilter} from '@/services/savedFilter'
|
||||
import {useConfigStore} from '@/stores/config'
|
||||
import {useProjectStore} from '@/stores/projects'
|
||||
import {useAuthStore} from '@/stores/auth'
|
||||
|
||||
const props = defineProps({
|
||||
project: {
|
||||
|
@ -146,4 +151,7 @@ function setSubscriptionInStore(sub: ISubscription) {
|
|||
}
|
||||
projectStore.setProject(updatedProject)
|
||||
}
|
||||
|
||||
const authStore = useAuthStore()
|
||||
const isDefaultProject = computed(() => props.project?.id === authStore.settings.defaultProjectId)
|
||||
</script>
|
|
@ -17,6 +17,7 @@
|
|||
bar-end="endDate"
|
||||
:grid="true"
|
||||
:width="ganttChartWidth"
|
||||
:color-scheme="GANTT_COLOR_SCHEME"
|
||||
@dragendBar="updateGanttTask"
|
||||
@dblclickBar="openTask"
|
||||
>
|
||||
|
@ -59,7 +60,7 @@ import {
|
|||
extendDayjs,
|
||||
GGanttChart,
|
||||
GGanttRow,
|
||||
type GanttBarObject,
|
||||
type GanttBarObject, type ColorScheme,
|
||||
} from '@infectoone/vue-ganttastic'
|
||||
|
||||
import Loading from '@/components/misc/loading.vue'
|
||||
|
@ -113,6 +114,16 @@ const ganttChartWidth = computed(() => {
|
|||
|
||||
const ganttBars = ref<GanttBarObject[][]>([])
|
||||
|
||||
const GANTT_COLOR_SCHEME: ColorScheme = {
|
||||
primary: 'var(--grey-100)',
|
||||
secondary: 'var(--grey-300)',
|
||||
ternary: 'var(--grey-500)',
|
||||
quartenary: 'var(--grey-600)',
|
||||
hoverHighlight: 'var(--grey-700)',
|
||||
text: 'var(--grey-800)',
|
||||
background: 'var(--white)',
|
||||
}
|
||||
|
||||
/**
|
||||
* Update ganttBars when tasks change
|
||||
*/
|
||||
|
|
|
@ -59,7 +59,7 @@ const hasDelete = computed(() => typeof remove !== 'undefined' && !disabled)
|
|||
}
|
||||
|
||||
&:hover .assignee:not(:first-child) {
|
||||
margin-left: -1rem;
|
||||
margin-left: -0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -68,7 +68,7 @@ const hasDelete = computed(() => typeof remove !== 'undefined' && !disabled)
|
|||
transition: all $transition;
|
||||
|
||||
&:not(:first-child) {
|
||||
margin-left: -1.5rem;
|
||||
margin-left: -1rem;
|
||||
}
|
||||
|
||||
:deep(.user img) {
|
||||
|
|
|
@ -27,7 +27,8 @@ defineProps({
|
|||
display: inline;
|
||||
|
||||
:deep(.tag) {
|
||||
margin-bottom: .25rem;
|
||||
margin-top: .125rem;
|
||||
margin-bottom: .125rem;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -103,7 +103,7 @@ import {getHexColor} from '@/models/task'
|
|||
import type {ITask} from '@/modelTypes/ITask'
|
||||
|
||||
import PriorityLabel from '@/components/tasks/partials/priorityLabel.vue'
|
||||
import Labels from '@/components/tasks/partials//labels.vue'
|
||||
import Labels from '@/components/tasks/partials/labels.vue'
|
||||
import ChecklistSummary from '@/components/tasks/partials/checklist-summary.vue'
|
||||
|
||||
import ColorBubble from '@/components/misc/colorBubble.vue'
|
||||
|
@ -197,6 +197,7 @@ const project = computed(() => projectStore.projects[task.projectId])
|
|||
span.parent-tasks {
|
||||
color: var(--grey-500);
|
||||
width: auto;
|
||||
margin-left: .25rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -978,7 +978,9 @@
|
|||
"setBackground": "Set background",
|
||||
"share": "Share",
|
||||
"newProject": "New project",
|
||||
"createProject": "Create project"
|
||||
"createProject": "Create project",
|
||||
"cantArchiveIsDefault": "You cannot archive this because it is your default project.",
|
||||
"cantDeleteIsDefault": "You cannot delete this because it is your default project."
|
||||
},
|
||||
"apiConfig": {
|
||||
"url": "Vikunja URL",
|
||||
|
|
|
@ -246,8 +246,9 @@ export const useKanbanStore = defineStore('kanban', () => {
|
|||
}
|
||||
|
||||
async function loadNextTasksForBucket(
|
||||
{projectId, ps = {}, bucketId} :
|
||||
{projectId: IProject['id'], ps, bucketId: IBucket['id']},
|
||||
projectId: IProject['id'],
|
||||
ps,
|
||||
bucketId: IBucket['id'],
|
||||
) {
|
||||
const isLoading = bucketLoading.value[bucketId] ?? false
|
||||
if (isLoading) {
|
||||
|
|
|
@ -53,7 +53,7 @@
|
|||
<p>{{ $t('migrate.inProgress') }}</p>
|
||||
</div>
|
||||
</template>
|
||||
<div v-else-if="lastMigrationStartedAt && lastMigrationFinishedAt === null">
|
||||
<div v-else-if="!migrationJustStarted && lastMigrationStartedAt && lastMigrationFinishedAt === null">
|
||||
<Message class="mb-4">
|
||||
{{ $t('migrate.migrationInProgress') }}
|
||||
</Message>
|
||||
|
@ -145,6 +145,7 @@ const lastMigrationFinishedAt = ref<Date | null>(null)
|
|||
const lastMigrationStartedAt = ref<Date | null>(null)
|
||||
const message = ref('')
|
||||
const migratorAuthCode = ref('')
|
||||
const migrationJustStarted = ref(false)
|
||||
|
||||
const migrator = computed<Migrator>(() => MIGRATORS[props.service])
|
||||
|
||||
|
@ -207,12 +208,15 @@ async function migrate() {
|
|||
}
|
||||
|
||||
try {
|
||||
const result = migrator.value.isFileMigrator
|
||||
? await migrationFileService.migrate(migrationConfig as File)
|
||||
: await migrationService.migrate(migrationConfig as MigrationConfig)
|
||||
message.value = result.message
|
||||
const projectStore = useProjectStore()
|
||||
return projectStore.loadProjects()
|
||||
if (migrator.value.isFileMigrator) {
|
||||
const result = await migrationFileService.migrate(migrationConfig as File)
|
||||
message.value = result.message
|
||||
const projectStore = useProjectStore()
|
||||
return projectStore.loadProjects()
|
||||
}
|
||||
|
||||
await migrationService.migrate(migrationConfig as MigrationConfig)
|
||||
migrationJustStarted.value = true
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
} finally {
|
||||
|
|
|
@ -416,11 +416,11 @@ function handleTaskContainerScroll(id: IBucket['id'], projectId: IProject['id'],
|
|||
return
|
||||
}
|
||||
|
||||
kanbanStore.loadNextTasksForBucket({
|
||||
projectId: projectId,
|
||||
params: params.value,
|
||||
bucketId: id,
|
||||
})
|
||||
kanbanStore.loadNextTasksForBucket(
|
||||
projectId,
|
||||
params.value,
|
||||
id,
|
||||
)
|
||||
}
|
||||
|
||||
function updateTasks(bucketId: IBucket['id'], tasks: IBucket['tasks']) {
|
||||
|
|
8
go.mod
8
go.mod
|
@ -52,7 +52,7 @@ require (
|
|||
github.com/olekukonko/tablewriter v0.0.5
|
||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
|
||||
github.com/pquerna/otp v1.4.0
|
||||
github.com/prometheus/client_golang v1.18.0
|
||||
github.com/prometheus/client_golang v1.19.0
|
||||
github.com/redis/go-redis/v9 v9.5.1
|
||||
github.com/robfig/cron/v3 v3.0.1
|
||||
github.com/samedi/caldav-go v3.0.0+incompatible
|
||||
|
@ -66,7 +66,7 @@ require (
|
|||
github.com/ulule/limiter/v3 v3.11.2
|
||||
github.com/wneessen/go-mail v0.4.0
|
||||
github.com/yuin/goldmark v1.7.0
|
||||
golang.org/x/crypto v0.19.0
|
||||
golang.org/x/crypto v0.20.0
|
||||
golang.org/x/image v0.15.0
|
||||
golang.org/x/oauth2 v0.17.0
|
||||
golang.org/x/sync v0.6.0
|
||||
|
@ -148,7 +148,7 @@ require (
|
|||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/prometheus/client_model v0.5.0 // indirect
|
||||
github.com/prometheus/common v0.45.0 // indirect
|
||||
github.com/prometheus/common v0.48.0 // indirect
|
||||
github.com/prometheus/procfs v0.12.0 // indirect
|
||||
github.com/rivo/uniseg v0.4.4 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
|
@ -178,7 +178,7 @@ require (
|
|||
golang.org/x/time v0.5.0 // indirect
|
||||
golang.org/x/tools v0.13.0 // indirect
|
||||
google.golang.org/appengine v1.6.8 // indirect
|
||||
google.golang.org/protobuf v1.31.0 // indirect
|
||||
google.golang.org/protobuf v1.32.0 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
sigs.k8s.io/yaml v1.3.0 // indirect
|
||||
|
|
8
go.sum
8
go.sum
|
@ -450,6 +450,8 @@ github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1
|
|||
github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY=
|
||||
github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk=
|
||||
github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA=
|
||||
github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU=
|
||||
github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k=
|
||||
github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 h1:v7DLqVdK4VrYkVD5diGdl4sxJurKJEMnODWRJlxV9oM=
|
||||
github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU=
|
||||
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
|
||||
|
@ -458,6 +460,8 @@ github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdO
|
|||
github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY=
|
||||
github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM=
|
||||
github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY=
|
||||
github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE=
|
||||
github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc=
|
||||
github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI=
|
||||
github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY=
|
||||
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
|
||||
|
@ -628,6 +632,8 @@ golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
|
|||
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
||||
golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.20.0 h1:jmAMJJZXr5KiCw05dfYK9QnqaqKLYXijU23lsEdcQqg=
|
||||
golang.org/x/crypto v0.20.0/go.mod h1:Xwo95rrVNIoSMx9wa1JroENMToLWn3RNVrTBpLHgZPQ=
|
||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
|
||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
|
||||
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
|
@ -778,6 +784,8 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ
|
|||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
|
||||
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
|
||||
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
|
|
@ -158,7 +158,7 @@ func setRootPath() {
|
|||
|
||||
func setGoFiles() {
|
||||
// GOFILES := $(shell find . -name "*.go" -type f ! -path "*/bindata.go")
|
||||
files, err := runCmdWithOutput("find", ".", "-name", "*.go", "-type", "f", "!", "-path", "*/bindata.go")
|
||||
files, err := runCmdWithOutput("find", "./pkg", "-name", "*.go", "-type", "f", "!", "-path", "*/bindata.go")
|
||||
if err != nil {
|
||||
fmt.Printf("Error getting go files: %s\n", err)
|
||||
os.Exit(1)
|
||||
|
|
|
@ -234,6 +234,7 @@
|
|||
title: Test25
|
||||
owner_id: 6
|
||||
parent_project_id: 12
|
||||
position: 25
|
||||
updated: 2018-12-02 15:13:12
|
||||
created: 2018-12-01 15:13:12
|
||||
-
|
||||
|
@ -241,6 +242,7 @@
|
|||
title: Test26
|
||||
owner_id: 6
|
||||
parent_project_id: 25
|
||||
position: 26
|
||||
updated: 2018-12-02 15:13:12
|
||||
created: 2018-12-01 15:13:12
|
||||
-
|
||||
|
|
|
@ -368,7 +368,7 @@ func TestTaskCollection(t *testing.T) {
|
|||
t.Run("by priority", func(t *testing.T) {
|
||||
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"priority"}}, nil)
|
||||
require.NoError(t, err)
|
||||
assert.Contains(t, rec.Body.String(), `{"id":33,"title":"task #33 with percent done","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminders":null,"project_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0.5,"identifier":"test1-17","index":17,"related_tasks":{},"attachments":null,"cover_image_attachment_id":0,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":1,"position":0,"kanban_position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":35,"title":"task #35","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminders":null,"project_id":21,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":[{"id":2,"name":"","username":"user2","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}],"labels":[{"id":4,"title":"Label #4 - visible via other task","description":"","hex_color":"","created_by":{"id":2,"name":"","username":"user2","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"},"created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}],"hex_color":"","percent_done":0,"identifier":"test21-1","index":1,"related_tasks":{"related":[{"id":1,"title":"task #1","description":"Lorem Ipsum","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminders":null,"project_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"","index":1,"related_tasks":null,"attachments":null,"cover_image_attachment_id":0,"is_favorite":true,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":1,"position":2,"kanban_position":0,"created_by":null},{"id":1,"title":"task #1","description":"Lorem Ipsum","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminders":null,"project_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"","index":1,"related_tasks":null,"attachments":null,"cover_image_attachment_id":0,"is_favorite":true,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":1,"position":2,"kanban_position":0,"created_by":null}]},"attachments":null,"cover_image_attachment_id":0,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":19,"position":0,"kanban_position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}}]`)
|
||||
assert.Contains(t, rec.Body.String(), `{"id":33,"title":"task #33 with percent done","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminders":null,"project_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0.5,"identifier":"test1-17","index":17,"related_tasks":{},"attachments":null,"cover_image_attachment_id":0,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":1,"position":0,"kanban_position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":35,"title":"task #35","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminders":null,"project_id":21,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":[{"id":2,"name":"","username":"user2","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}],"labels":[{"id":4,"title":"Label #4 - visible via other task","description":"","hex_color":"","created_by":{"id":2,"name":"","username":"user2","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"},"created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}],"hex_color":"","percent_done":0,"identifier":"test21-1","index":1,"related_tasks":{"related":[{"id":1,"title":"task #1","description":"Lorem Ipsum","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminders":null,"project_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"","index":1,"related_tasks":null,"attachments":null,"cover_image_attachment_id":0,"is_favorite":true,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":1,"position":2,"kanban_position":0,"created_by":null},{"id":1,"title":"task #1","description":"Lorem Ipsum","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminders":null,"project_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"","index":1,"related_tasks":null,"attachments":null,"cover_image_attachment_id":0,"is_favorite":true,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":1,"position":2,"kanban_position":0,"created_by":null}]},"attachments":null,"cover_image_attachment_id":0,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":19,"position":0,"kanban_position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":39,"title":"task #39","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminders":null,"project_id":25,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"#0","index":0,"related_tasks":{},"attachments":null,"cover_image_attachment_id":0,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":0,"position":0,"kanban_position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}}]`)
|
||||
})
|
||||
t.Run("by priority desc", func(t *testing.T) {
|
||||
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"priority"}, "order_by": []string{"desc"}}, nil)
|
||||
|
@ -378,7 +378,7 @@ func TestTaskCollection(t *testing.T) {
|
|||
t.Run("by priority asc", func(t *testing.T) {
|
||||
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"priority"}, "order_by": []string{"asc"}}, nil)
|
||||
require.NoError(t, err)
|
||||
assert.Contains(t, rec.Body.String(), `{"id":33,"title":"task #33 with percent done","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminders":null,"project_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0.5,"identifier":"test1-17","index":17,"related_tasks":{},"attachments":null,"cover_image_attachment_id":0,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":1,"position":0,"kanban_position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":35,"title":"task #35","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminders":null,"project_id":21,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":[{"id":2,"name":"","username":"user2","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}],"labels":[{"id":4,"title":"Label #4 - visible via other task","description":"","hex_color":"","created_by":{"id":2,"name":"","username":"user2","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"},"created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}],"hex_color":"","percent_done":0,"identifier":"test21-1","index":1,"related_tasks":{"related":[{"id":1,"title":"task #1","description":"Lorem Ipsum","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminders":null,"project_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"","index":1,"related_tasks":null,"attachments":null,"cover_image_attachment_id":0,"is_favorite":true,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":1,"position":2,"kanban_position":0,"created_by":null},{"id":1,"title":"task #1","description":"Lorem Ipsum","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminders":null,"project_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"","index":1,"related_tasks":null,"attachments":null,"cover_image_attachment_id":0,"is_favorite":true,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":1,"position":2,"kanban_position":0,"created_by":null}]},"attachments":null,"cover_image_attachment_id":0,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":19,"position":0,"kanban_position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}}]`)
|
||||
assert.Contains(t, rec.Body.String(), `{"id":33,"title":"task #33 with percent done","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminders":null,"project_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0.5,"identifier":"test1-17","index":17,"related_tasks":{},"attachments":null,"cover_image_attachment_id":0,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":1,"position":0,"kanban_position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":35,"title":"task #35","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminders":null,"project_id":21,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":[{"id":2,"name":"","username":"user2","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}],"labels":[{"id":4,"title":"Label #4 - visible via other task","description":"","hex_color":"","created_by":{"id":2,"name":"","username":"user2","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"},"created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}],"hex_color":"","percent_done":0,"identifier":"test21-1","index":1,"related_tasks":{"related":[{"id":1,"title":"task #1","description":"Lorem Ipsum","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminders":null,"project_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"","index":1,"related_tasks":null,"attachments":null,"cover_image_attachment_id":0,"is_favorite":true,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":1,"position":2,"kanban_position":0,"created_by":null},{"id":1,"title":"task #1","description":"Lorem Ipsum","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminders":null,"project_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"","index":1,"related_tasks":null,"attachments":null,"cover_image_attachment_id":0,"is_favorite":true,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":1,"position":2,"kanban_position":0,"created_by":null}]},"attachments":null,"cover_image_attachment_id":0,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":19,"position":0,"kanban_position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":39,"title":"task #39","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminders":null,"project_id":25,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"#0","index":0,"related_tasks":{},"attachments":null,"cover_image_attachment_id":0,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":0,"position":0,"kanban_position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}}]`)
|
||||
})
|
||||
// should equal duedate asc
|
||||
t.Run("by due_date", func(t *testing.T) {
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
@ -418,67 +419,49 @@ func getUserProjectsStatement(parentProjectIDs []int64, userID int64, search str
|
|||
parentCondition,
|
||||
builder.NotIn("l.id", parentProjectIDs),
|
||||
)).
|
||||
OrderBy("position").
|
||||
GroupBy("l.id")
|
||||
}
|
||||
|
||||
func getAllProjectsForUser(s *xorm.Session, userID int64, parentProjectIDs []int64, opts *projectOptions, projects *[]*Project, oldTotalCount int64, archivedProjects map[int64]bool) (resultCount int, totalCount int64, err error) {
|
||||
func getAllProjectsForUser(s *xorm.Session, userID int64, opts *projectOptions) (projects []*Project, totalCount int64, err error) {
|
||||
|
||||
limit, start := getLimitFromPageIndex(opts.page, opts.perPage)
|
||||
query := getUserProjectsStatement(parentProjectIDs, userID, opts.search, opts.getArchived)
|
||||
if limit > 0 {
|
||||
query = query.Limit(limit, start)
|
||||
query := getUserProjectsStatement(nil, userID, opts.search, opts.getArchived)
|
||||
|
||||
querySQLString, args, err := query.ToSQL()
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
var limitSQL string
|
||||
if limit > 0 {
|
||||
limitSQL = fmt.Sprintf("LIMIT %d OFFSET %d", limit, start)
|
||||
}
|
||||
|
||||
baseQuery := querySQLString + `
|
||||
UNION ALL
|
||||
SELECT p.* FROM projects p
|
||||
INNER JOIN all_projects ap ON p.parent_project_id = ap.id`
|
||||
|
||||
currentProjects := []*Project{}
|
||||
err = s.SQL(query).Find(¤tProjects)
|
||||
err = s.SQL(`WITH RECURSIVE all_projects as (`+baseQuery+`)
|
||||
SELECT DISTINCT * FROM all_projects ORDER BY position `+limitSQL, args...).Find(¤tProjects)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
return
|
||||
}
|
||||
|
||||
if len(currentProjects) == 0 {
|
||||
return 0, oldTotalCount, err
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
query = getUserProjectsStatement(parentProjectIDs, userID, opts.search, opts.getArchived)
|
||||
totalCount, err = s.
|
||||
SQL(query.Select("count(*)")).
|
||||
SQL(`WITH RECURSIVE all_projects as (`+baseQuery+`)
|
||||
SELECT count(*) FROM all_projects GROUP BY all_projects.id`, args...).
|
||||
Count(&Project{})
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
parentIDsMap := make(map[int64]bool, len(parentProjectIDs))
|
||||
for _, id := range parentProjectIDs {
|
||||
parentIDsMap[id] = true
|
||||
}
|
||||
|
||||
for _, project := range currentProjects {
|
||||
parentIDsMap[project.ID] = true
|
||||
}
|
||||
|
||||
newParentIDs := []int64{}
|
||||
for _, project := range currentProjects {
|
||||
if project.IsArchived {
|
||||
archivedProjects[project.ID] = true
|
||||
}
|
||||
if archivedProjects[project.ParentProjectID] {
|
||||
project.IsArchived = true
|
||||
}
|
||||
// Filter out parent project ids which we're not looking for to avoid leaking
|
||||
// information about parent projects
|
||||
if !parentIDsMap[project.ParentProjectID] {
|
||||
project.ParentProjectID = 0
|
||||
}
|
||||
newParentIDs = append(newParentIDs, project.ID)
|
||||
}
|
||||
|
||||
*projects = append(*projects, currentProjects...)
|
||||
|
||||
// If we don't reset the limit for subprojects, it will be impossible to fetch all subprojects.
|
||||
opts.page = -1
|
||||
|
||||
return getAllProjectsForUser(s, userID, newParentIDs, opts, projects, oldTotalCount+totalCount, archivedProjects)
|
||||
return currentProjects, totalCount, err
|
||||
}
|
||||
|
||||
// Gets the projects with their children without any tasks
|
||||
|
@ -488,9 +471,7 @@ func getRawProjectsForUser(s *xorm.Session, opts *projectOptions) (projects []*P
|
|||
return nil, 0, 0, err
|
||||
}
|
||||
|
||||
allProjects := []*Project{}
|
||||
archivedProjects := make(map[int64]bool)
|
||||
resultCount, totalItems, err = getAllProjectsForUser(s, fullUser.ID, nil, opts, &allProjects, 0, archivedProjects)
|
||||
allProjects, totalItems, err := getAllProjectsForUser(s, fullUser.ID, opts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -349,11 +349,9 @@ func TestProject_ReadAll(t *testing.T) {
|
|||
t.Run("all", func(t *testing.T) {
|
||||
db.LoadAndAssertFixtures(t)
|
||||
s := db.NewSession()
|
||||
projects := []*Project{}
|
||||
archivedProjects := make(map[int64]bool)
|
||||
_, _, err := getAllProjectsForUser(s, 1, nil, &projectOptions{}, &projects, 0, archivedProjects)
|
||||
projects, _, err := getAllProjectsForUser(s, 6, &projectOptions{})
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, projects, 24)
|
||||
assert.Len(t, projects, 25)
|
||||
_ = s.Close()
|
||||
})
|
||||
t.Run("only child projects for one project", func(t *testing.T) {
|
||||
|
@ -369,12 +367,12 @@ func TestProject_ReadAll(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
assert.Equal(t, reflect.Slice, reflect.TypeOf(projects3).Kind())
|
||||
ls := projects3.([]*Project)
|
||||
assert.Len(t, ls, 26)
|
||||
assert.Len(t, ls, 28)
|
||||
assert.Equal(t, int64(3), ls[0].ID) // Project 3 has a position of 1 and should be sorted first
|
||||
assert.Equal(t, int64(1), ls[1].ID)
|
||||
assert.Equal(t, int64(6), ls[2].ID)
|
||||
assert.Equal(t, int64(-1), ls[24].ID)
|
||||
assert.Equal(t, int64(-2), ls[25].ID)
|
||||
assert.Equal(t, int64(-1), ls[26].ID)
|
||||
assert.Equal(t, int64(-2), ls[27].ID)
|
||||
_ = s.Close()
|
||||
})
|
||||
t.Run("projects for nonexistant user", func(t *testing.T) {
|
||||
|
|
|
@ -656,6 +656,18 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
|||
Created: time.Unix(1543626724, 0).In(loc),
|
||||
Updated: time.Unix(1543626724, 0).In(loc),
|
||||
}
|
||||
task39 := &Task{
|
||||
ID: 39,
|
||||
Title: "task #39",
|
||||
Identifier: "#0",
|
||||
CreatedByID: 1,
|
||||
CreatedBy: user1,
|
||||
ProjectID: 25,
|
||||
RelatedTasks: map[RelationKind][]*Task{},
|
||||
BucketID: 0,
|
||||
Created: time.Unix(1543626724, 0).In(loc),
|
||||
Updated: time.Unix(1543626724, 0).In(loc),
|
||||
}
|
||||
|
||||
type fields struct {
|
||||
ProjectID int64
|
||||
|
@ -728,6 +740,7 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
|||
task32,
|
||||
task33,
|
||||
task35,
|
||||
task39,
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
|
@ -772,6 +785,7 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
|||
task3,
|
||||
task1,
|
||||
task2,
|
||||
task39,
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
|
@ -943,6 +957,7 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
|||
task32, // has nil dates
|
||||
task33, // has nil dates
|
||||
task35, // has nil dates
|
||||
task39, // has nil dates
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
|
@ -1202,6 +1217,7 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
|||
task32,
|
||||
task33,
|
||||
task35,
|
||||
task39,
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -1218,6 +1234,7 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
|||
task6,
|
||||
task5,
|
||||
// The other ones don't have a due date
|
||||
task39,
|
||||
task35,
|
||||
task33,
|
||||
task32,
|
||||
|
|
121
publiccode.yml
121
publiccode.yml
|
@ -1,82 +1,83 @@
|
|||
publiccode-yml-version: '0.2'
|
||||
name: 'Vikunja'
|
||||
url: 'https://vikunja.io'
|
||||
url: 'https://code.vikunja.io/vikunja'
|
||||
landingURL: 'https://vikunja.io'
|
||||
isBasedOn: 'https://go.dev/'
|
||||
softwareVersion: 'v0.23.0'
|
||||
releaseDate: '2024-02-10'
|
||||
logo: 'https://vikunja.io/images/vikunja-logo.svg'
|
||||
platforms:
|
||||
- 'linux'
|
||||
- 'lxc'
|
||||
- 'docker'
|
||||
- 'k8s'
|
||||
- 'web'
|
||||
- 'linux'
|
||||
- 'windows'
|
||||
- 'mac'
|
||||
- 'lxc'
|
||||
- 'docker'
|
||||
- 'k8s'
|
||||
- 'debian'
|
||||
categories:
|
||||
- 'agile-project-management'
|
||||
- 'enterprise-project-management'
|
||||
- 'project-management'
|
||||
- 'task-management'
|
||||
- 'workflow-management'
|
||||
- 'agile-project-management'
|
||||
- 'enterprise-project-management'
|
||||
- 'project-management'
|
||||
- 'task-management'
|
||||
- 'workflow-management'
|
||||
usedBy:
|
||||
- 'City of Treuchtlingen'
|
||||
roadmap:
|
||||
'https://my.vikunja.cloud/projects/16/list#share-auth-token=QFyzYEmEYfSyQfTOmIRSwLUpkFjboaBqQCnaPmWd'
|
||||
- 'City of Treuchtlingen'
|
||||
roadmap: 'https://my.vikunja.cloud/projects/16/list#share-auth-token=QFyzYEmEYfSyQfTOmIRSwLUpkFjboaBqQCnaPmWd'
|
||||
developmentStatus: 'stable'
|
||||
softwareType: 'webservice'
|
||||
softwareType: 'standalone/web'
|
||||
intendedAudience:
|
||||
scope:
|
||||
- 'Providers of standard based workflow management services who
|
||||
wish or are required to use Open Source solutions'
|
||||
scope:
|
||||
- 'Providers of standard based workflow management services who wish or are required to use Open Source solutions'
|
||||
description:
|
||||
en: ' The open-source, self-hostable to-do app. Organize everything,
|
||||
on all platforms.'
|
||||
en: ' The open-source, self-hostable to-do app. Organize everything, on all platforms.'
|
||||
documentation: 'https://vikunja.io/docs/'
|
||||
apiDocumentation: 'https://vikunja.io/docs/api-documentation/'
|
||||
features:
|
||||
- 'workflow management'
|
||||
- 'CalDAV provider'
|
||||
- 'kanban tool'
|
||||
- 'gantt display tool'
|
||||
- 'ticket system'
|
||||
- 'workflow management'
|
||||
- 'CalDAV provider'
|
||||
- 'kanban tool'
|
||||
- 'gantt display tool'
|
||||
- 'ticket system'
|
||||
screenshots:
|
||||
- 'https://vikunja.io/images/vikunja/09-task-detail-dark.webp'
|
||||
- 'https://vikunja.io/images/vikunja/09-task-detail-dark.webp'
|
||||
videos:
|
||||
- 'none'
|
||||
- 'none'
|
||||
legal:
|
||||
license: 'GNU AFFERO GENERAL PUBLIC LICENSE Version 3'
|
||||
mainCopyrightOwner: 'Konrad Langenberg Software'
|
||||
repoOwner: 'Konrad Langenberg Software'
|
||||
authorsFile: 'hello@vikunja.io'
|
||||
license: 'GNU AFFERO GENERAL PUBLIC LICENSE Version 3'
|
||||
mainCopyrightOwner: 'Konrad Langenberg Software'
|
||||
repoOwner: 'Konrad Langenberg Software'
|
||||
authorsFile: 'hello@vikunja.io'
|
||||
maintenance:
|
||||
type: 'https://vikunja.cloud/'
|
||||
contractors:
|
||||
- name: 'Vikunja Cloud '
|
||||
type: 'https://vikunja.cloud/'
|
||||
contractors:
|
||||
- name: 'Vikunja Cloud '
|
||||
localisation:
|
||||
localisationReady: 'true'
|
||||
availableLanguages:
|
||||
- 'en'
|
||||
- 'de-de'
|
||||
- 'ru-ru'
|
||||
- 'fr-fr'
|
||||
- 'vi-vn'
|
||||
- 'it-it'
|
||||
- 'cs-cz'
|
||||
- 'pl-pl'
|
||||
- 'nl-nl'
|
||||
- 'pt-pt'
|
||||
- 'zh-cn'
|
||||
- 'no-no'
|
||||
- 'es-es'
|
||||
- 'da-dk'
|
||||
- 'ja-jp'
|
||||
- 'hu-hu'
|
||||
- 'sl-si'
|
||||
localisationReady: 'true'
|
||||
availableLanguages:
|
||||
- 'en'
|
||||
- 'de-de'
|
||||
- 'ru-ru'
|
||||
- 'fr-fr'
|
||||
- 'vi-vn'
|
||||
- 'it-it'
|
||||
- 'cs-cz'
|
||||
- 'pl-pl'
|
||||
- 'nl-nl'
|
||||
- 'pt-pt'
|
||||
- 'zh-cn'
|
||||
- 'no-no'
|
||||
- 'es-es'
|
||||
- 'da-dk'
|
||||
- 'ja-jp'
|
||||
- 'hu-hu'
|
||||
- 'sl-si'
|
||||
dependsOn:
|
||||
open:
|
||||
- name: 'CalDAV'
|
||||
- name: 'GoLANG'
|
||||
- name: 'Vue.js'
|
||||
- name: 'HTTP-Proxy'
|
||||
- name: 'SSL'
|
||||
- name: 'Unit file (SystemD)'
|
||||
- name: 'Firewall Rules (Web: 443)'
|
||||
open:
|
||||
- name: 'CalDAV'
|
||||
- name: 'GoLANG'
|
||||
- name: 'Vue.js'
|
||||
- name: 'HTTP-Proxy'
|
||||
- name: 'SSL'
|
||||
- name: 'Unit file (SystemD)'
|
||||
- name: 'Firewall Rules (Web: 443)'
|
||||
|
|
Loading…
Reference in New Issue