Compare commits
40
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
08821ea8a8 | ||
|
|
e9a466fa31 | ||
|
|
de9f686480 | ||
|
|
d08e9650ba | ||
|
|
0434a96c3a | ||
|
|
2b9b77bef2 | ||
|
|
f5040ad2f4 | ||
|
|
7bc77ae8c0 | ||
|
|
715269a5d0 | ||
|
|
53605c24f0 | ||
|
|
da0b741b69 | ||
|
|
73f923bc47 | ||
|
|
25a8c7ea80 | ||
|
|
950de7c954 | ||
|
|
42ba9240b0 | ||
|
|
3da6299021 | ||
|
|
1ac0f412b9 | ||
|
|
e7fbdc2727 | ||
|
|
7117303d57 | ||
|
|
0ca43dc147 | ||
|
|
c47ea2716c | ||
|
|
cbdcc61414 | ||
|
|
194a7d4cf8 | ||
|
|
9695785a0c | ||
|
|
d9f555554e | ||
|
|
6e38bcf349 | ||
|
|
fc780a90ae | ||
|
|
d586f691b7 | ||
|
|
9e8e43bd12 | ||
|
|
c554a96b4b | ||
|
|
3ecc81094f | ||
|
|
811ccc1baa | ||
|
|
d7c5451729 | ||
|
|
96884372b4 | ||
|
|
dddba4d64a | ||
|
|
a0e3efe2d1 | ||
|
|
d707e1576a | ||
|
|
3aaf363413 | ||
|
|
28fff10fec | ||
|
|
8729c24e1d |
+4
-4
@@ -139,7 +139,7 @@ steps:
|
||||
event: [ push, tag, pull_request ]
|
||||
|
||||
- name: api-lint
|
||||
image: golangci/golangci-lint:v1.61.0
|
||||
image: golangci/golangci-lint:v1.59.1
|
||||
pull: always
|
||||
environment:
|
||||
GOPROXY: 'https://goproxy.kolaente.de'
|
||||
@@ -716,7 +716,7 @@ steps:
|
||||
|
||||
# Build os packages and push it to our bucket
|
||||
- name: build-os-packages-unstable
|
||||
image: goreleaser/nfpm:v2.40.0
|
||||
image: goreleaser/nfpm:v2.38.0
|
||||
pull: always
|
||||
commands:
|
||||
- apk add git go
|
||||
@@ -732,7 +732,7 @@ steps:
|
||||
depends_on: [ after-build-compress ]
|
||||
|
||||
- name: build-os-packages-version
|
||||
image: goreleaser/nfpm:v2.40.0
|
||||
image: goreleaser/nfpm:v2.38.0
|
||||
pull: always
|
||||
commands:
|
||||
- apk add git go
|
||||
@@ -1352,6 +1352,6 @@ steps:
|
||||
- failure
|
||||
---
|
||||
kind: signature
|
||||
hmac: eff6e40dc763fa1395078daaabcbef2aaa74fe0a36818a87e89015dbc4e9dae4
|
||||
hmac: dc96a5f8aaa332b35fc02f1b8566493e494452d62bed52973d804f5347ae47ae
|
||||
|
||||
...
|
||||
|
||||
@@ -28,7 +28,6 @@ vendor/
|
||||
os-packages/
|
||||
mage_output_file.go
|
||||
mage-static
|
||||
.DS_Store
|
||||
|
||||
# Devenv
|
||||
.devenv*
|
||||
|
||||
@@ -109,13 +109,3 @@ issues:
|
||||
text: 'structtag: struct field Position repeats json tag "position" also at'
|
||||
linters:
|
||||
- govet
|
||||
- path: pkg/cmd/user.go
|
||||
text: 'G115: integer overflow conversion uintptr -> int'
|
||||
linters:
|
||||
- gosec
|
||||
- text: 'G115: integer overflow conversion int64 -> uint64'
|
||||
linters:
|
||||
- gosec
|
||||
- text: 'G115: integer overflow conversion int -> uint64'
|
||||
linters:
|
||||
- gosec
|
||||
|
||||
Vendored
+11
-13
@@ -1,15 +1,13 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"codezombiech.gitignore",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"editorconfig.editorconfig",
|
||||
"vue.volar",
|
||||
"lokalise.i18n-ally",
|
||||
"mgmcdermott.vscode-language-babel",
|
||||
"mikestead.dotenv",
|
||||
"Syler.sass-indented",
|
||||
"vitest.explorer",
|
||||
"mkhl.direnv",
|
||||
"golang.Go"
|
||||
]
|
||||
"recommendations": [
|
||||
"codezombiech.gitignore",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"editorconfig.editorconfig",
|
||||
"vue.volar",
|
||||
"lokalise.i18n-ally",
|
||||
"mgmcdermott.vscode-language-babel",
|
||||
"mikestead.dotenv",
|
||||
"Syler.sass-indented",
|
||||
"vitest.explorer"
|
||||
]
|
||||
}
|
||||
+5
-12
@@ -3,9 +3,9 @@ FROM --platform=$BUILDPLATFORM node:20.16.0-alpine AS frontendbuilder
|
||||
|
||||
WORKDIR /build
|
||||
|
||||
ENV PNPM_CACHE_FOLDER=.cache/pnpm/
|
||||
ENV PUPPETEER_SKIP_DOWNLOAD=true
|
||||
ENV CYPRESS_INSTALL_BINARY=0
|
||||
ENV PNPM_CACHE_FOLDER .cache/pnpm/
|
||||
ENV PUPPETEER_SKIP_DOWNLOAD true
|
||||
ENV CYPRESS_INSTALL_BINARY 0
|
||||
|
||||
COPY frontend/ ./
|
||||
|
||||
@@ -24,7 +24,7 @@ COPY --from=frontendbuilder /build/dist ./frontend/dist
|
||||
|
||||
ARG TARGETOS TARGETARCH TARGETVARIANT
|
||||
|
||||
ENV GOPROXY=https://goproxy.kolaente.de
|
||||
ENV GOPROXY https://goproxy.kolaente.de
|
||||
RUN export PATH=$PATH:$GOPATH/bin && \
|
||||
mage build:clean && \
|
||||
mage release:xgo "${TARGETOS}/${TARGETARCH}/${TARGETVARIANT}"
|
||||
@@ -35,14 +35,7 @@ RUN export PATH=$PATH:$GOPATH/bin && \
|
||||
|
||||
# The actual image
|
||||
FROM scratch
|
||||
|
||||
LABEL org.opencontainers.image.authors='maintainers@vikunja.io'
|
||||
LABEL org.opencontainers.image.url='https://vikunja.io'
|
||||
LABEL org.opencontainers.image.documentation='https://vikunja.io/docs'
|
||||
LABEL org.opencontainers.image.source='https://code.vikunja.io/vikunja'
|
||||
LABEL org.opencontainers.image.licenses='AGPLv3'
|
||||
LABEL org.opencontainers.image.title='Vikunja'
|
||||
|
||||
LABEL maintainer="maintainers@vikunja.io"
|
||||
WORKDIR /app/vikunja
|
||||
ENTRYPOINT [ "/app/vikunja/vikunja" ]
|
||||
EXPOSE 3456
|
||||
|
||||
@@ -51,11 +51,11 @@
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"electron": "29.4.6",
|
||||
"electron": "29.4.5",
|
||||
"electron-builder": "24.13.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"connect-history-api-fallback": "2.0.0",
|
||||
"express": "4.21.0"
|
||||
"express": "4.19.2"
|
||||
}
|
||||
}
|
||||
|
||||
Generated
+34
-39
@@ -9,13 +9,13 @@ dependencies:
|
||||
specifier: 2.0.0
|
||||
version: 2.0.0
|
||||
express:
|
||||
specifier: 4.21.0
|
||||
version: 4.21.0
|
||||
specifier: 4.19.2
|
||||
version: 4.19.2
|
||||
|
||||
devDependencies:
|
||||
electron:
|
||||
specifier: 29.4.6
|
||||
version: 29.4.6
|
||||
specifier: 29.4.5
|
||||
version: 29.4.5
|
||||
electron-builder:
|
||||
specifier: 24.13.3
|
||||
version: 24.13.3(electron-builder-squirrel-windows@24.13.3)
|
||||
@@ -445,8 +445,8 @@ packages:
|
||||
resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==}
|
||||
dev: true
|
||||
|
||||
/body-parser@1.20.3:
|
||||
resolution: {integrity: sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==}
|
||||
/body-parser@1.20.2:
|
||||
resolution: {integrity: sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==}
|
||||
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
|
||||
dependencies:
|
||||
bytes: 3.1.2
|
||||
@@ -457,7 +457,7 @@ packages:
|
||||
http-errors: 2.0.0
|
||||
iconv-lite: 0.4.24
|
||||
on-finished: 2.4.1
|
||||
qs: 6.13.0
|
||||
qs: 6.11.0
|
||||
raw-body: 2.5.2
|
||||
type-is: 1.6.18
|
||||
unpipe: 1.0.0
|
||||
@@ -917,8 +917,8 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/electron@29.4.6:
|
||||
resolution: {integrity: sha512-fz8ndj8cmmf441t4Yh2FDP3Rn0JhLkVGvtUf2YVMbJ5SdJPlc0JWll9jYkhh60jDKVVCr/tBAmfxqRnXMWJpzg==}
|
||||
/electron@29.4.5:
|
||||
resolution: {integrity: sha512-DlEuzGbWBYl1Qr0qUYgNZdoixJg4YGHy2HC6fkRjSXSlb01UrQ5ORi8hNLzelzyYx8rNQyyE3zDUuk9EnZwYuA==}
|
||||
engines: {node: '>= 12.20.55'}
|
||||
hasBin: true
|
||||
requiresBuild: true
|
||||
@@ -943,11 +943,6 @@ packages:
|
||||
engines: {node: '>= 0.8'}
|
||||
dev: false
|
||||
|
||||
/encodeurl@2.0.0:
|
||||
resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==}
|
||||
engines: {node: '>= 0.8'}
|
||||
dev: false
|
||||
|
||||
/end-of-stream@1.4.4:
|
||||
resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==}
|
||||
dependencies:
|
||||
@@ -1000,36 +995,36 @@ packages:
|
||||
engines: {node: '>= 0.6'}
|
||||
dev: false
|
||||
|
||||
/express@4.21.0:
|
||||
resolution: {integrity: sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==}
|
||||
/express@4.19.2:
|
||||
resolution: {integrity: sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==}
|
||||
engines: {node: '>= 0.10.0'}
|
||||
dependencies:
|
||||
accepts: 1.3.8
|
||||
array-flatten: 1.1.1
|
||||
body-parser: 1.20.3
|
||||
body-parser: 1.20.2
|
||||
content-disposition: 0.5.4
|
||||
content-type: 1.0.5
|
||||
cookie: 0.6.0
|
||||
cookie-signature: 1.0.6
|
||||
debug: 2.6.9
|
||||
depd: 2.0.0
|
||||
encodeurl: 2.0.0
|
||||
encodeurl: 1.0.2
|
||||
escape-html: 1.0.3
|
||||
etag: 1.8.1
|
||||
finalhandler: 1.3.1
|
||||
finalhandler: 1.2.0
|
||||
fresh: 0.5.2
|
||||
http-errors: 2.0.0
|
||||
merge-descriptors: 1.0.3
|
||||
merge-descriptors: 1.0.1
|
||||
methods: 1.1.2
|
||||
on-finished: 2.4.1
|
||||
parseurl: 1.3.3
|
||||
path-to-regexp: 0.1.10
|
||||
path-to-regexp: 0.1.7
|
||||
proxy-addr: 2.0.7
|
||||
qs: 6.13.0
|
||||
qs: 6.11.0
|
||||
range-parser: 1.2.1
|
||||
safe-buffer: 5.2.1
|
||||
send: 0.19.0
|
||||
serve-static: 1.16.2
|
||||
send: 0.18.0
|
||||
serve-static: 1.15.0
|
||||
setprototypeof: 1.2.0
|
||||
statuses: 2.0.1
|
||||
type-is: 1.6.18
|
||||
@@ -1082,12 +1077,12 @@ packages:
|
||||
minimatch: 5.1.6
|
||||
dev: true
|
||||
|
||||
/finalhandler@1.3.1:
|
||||
resolution: {integrity: sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==}
|
||||
/finalhandler@1.2.0:
|
||||
resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==}
|
||||
engines: {node: '>= 0.8'}
|
||||
dependencies:
|
||||
debug: 2.6.9
|
||||
encodeurl: 2.0.0
|
||||
encodeurl: 1.0.2
|
||||
escape-html: 1.0.3
|
||||
on-finished: 2.4.1
|
||||
parseurl: 1.3.3
|
||||
@@ -1548,8 +1543,8 @@ packages:
|
||||
engines: {node: '>= 0.6'}
|
||||
dev: false
|
||||
|
||||
/merge-descriptors@1.0.3:
|
||||
resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==}
|
||||
/merge-descriptors@1.0.1:
|
||||
resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==}
|
||||
dev: false
|
||||
|
||||
/methods@1.1.2:
|
||||
@@ -1729,8 +1724,8 @@ packages:
|
||||
minipass: 7.0.4
|
||||
dev: true
|
||||
|
||||
/path-to-regexp@0.1.10:
|
||||
resolution: {integrity: sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==}
|
||||
/path-to-regexp@0.1.7:
|
||||
resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==}
|
||||
dev: false
|
||||
|
||||
/pend@1.2.0:
|
||||
@@ -1785,8 +1780,8 @@ packages:
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
|
||||
/qs@6.13.0:
|
||||
resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==}
|
||||
/qs@6.11.0:
|
||||
resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==}
|
||||
engines: {node: '>=0.6'}
|
||||
dependencies:
|
||||
side-channel: 1.0.6
|
||||
@@ -1924,8 +1919,8 @@ packages:
|
||||
lru-cache: 6.0.0
|
||||
dev: true
|
||||
|
||||
/send@0.19.0:
|
||||
resolution: {integrity: sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==}
|
||||
/send@0.18.0:
|
||||
resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==}
|
||||
engines: {node: '>= 0.8.0'}
|
||||
dependencies:
|
||||
debug: 2.6.9
|
||||
@@ -1954,14 +1949,14 @@ packages:
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/serve-static@1.16.2:
|
||||
resolution: {integrity: sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==}
|
||||
/serve-static@1.15.0:
|
||||
resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==}
|
||||
engines: {node: '>= 0.8.0'}
|
||||
dependencies:
|
||||
encodeurl: 2.0.0
|
||||
encodeurl: 1.0.2
|
||||
escape-html: 1.0.3
|
||||
parseurl: 1.3.3
|
||||
send: 0.19.0
|
||||
send: 0.18.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
+12
-12
@@ -3,11 +3,11 @@
|
||||
"devenv": {
|
||||
"locked": {
|
||||
"dir": "src/modules",
|
||||
"lastModified": 1726063457,
|
||||
"lastModified": 1723409744,
|
||||
"owner": "cachix",
|
||||
"repo": "devenv",
|
||||
"rev": "39bf6ce569103c9390d37322daa59468c31b3ce7",
|
||||
"treeHash": "839747a1cb35ba6d5b36cce9a739ab2ba5e4a5d4",
|
||||
"rev": "116159a4bfeaa79662f4c39dbfaf2fce6a5737f7",
|
||||
"treeHash": "ccbae63055f83e669996a88a3cbb4ef69febd002",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -72,11 +72,11 @@
|
||||
},
|
||||
"nixpkgs-stable": {
|
||||
"locked": {
|
||||
"lastModified": 1725930920,
|
||||
"lastModified": 1723282977,
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "44a71ff39c182edaf25a7ace5c9454e7cba2c658",
|
||||
"treeHash": "56e93544112b7bb7aa0c3093d537295683ef9148",
|
||||
"rev": "a781ff33ae258bbcfd4ed6e673860c3e923bf2cc",
|
||||
"treeHash": "75cf71293251c603e56d6076098346b4128b2ec8",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -88,11 +88,11 @@
|
||||
},
|
||||
"nixpkgs-unstable": {
|
||||
"locked": {
|
||||
"lastModified": 1725983898,
|
||||
"lastModified": 1723175592,
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "1355a0cbfeac61d785b7183c0caaec1f97361b43",
|
||||
"treeHash": "d8ce0c1af7690da6161f0991484661331f5bc999",
|
||||
"rev": "5e0ca22929f3342b19569b21b2f3462f053e497b",
|
||||
"treeHash": "a6b38d5232ae0ae0c666c37f5ec9620c14f30369",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -112,11 +112,11 @@
|
||||
"nixpkgs-stable": "nixpkgs-stable"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1725513492,
|
||||
"lastModified": 1723202784,
|
||||
"owner": "cachix",
|
||||
"repo": "pre-commit-hooks.nix",
|
||||
"rev": "7570de7b9b504cfe92025dd1be797bf546f66528",
|
||||
"treeHash": "4b46d77870afecd8f642541cb4f4927326343b59",
|
||||
"rev": "c7012d0c18567c889b948781bc74a501e92275d1",
|
||||
"treeHash": "0016d5d748d61d3bfaa69d3c02abff74740a46b7",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
||||
+3
-9
@@ -5,14 +5,13 @@ let
|
||||
in {
|
||||
packages = with pkgs-unstable; [
|
||||
# General tools
|
||||
git-cliff
|
||||
git-cliff
|
||||
# Frontend tools
|
||||
cypress
|
||||
# API tools
|
||||
golangci-lint mage
|
||||
# Desktop
|
||||
electron
|
||||
] ++ lib.optionals (!pkgs.stdenv.isDarwin) [
|
||||
# Frontend tools (exclude on Darwin)
|
||||
cypress
|
||||
];
|
||||
|
||||
languages = {
|
||||
@@ -29,9 +28,4 @@ in {
|
||||
enable = true;
|
||||
};
|
||||
};
|
||||
|
||||
services.mailpit = {
|
||||
enable = true;
|
||||
package = pkgs-unstable.mailpit;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ node_modules
|
||||
dist
|
||||
coverage
|
||||
*.zip
|
||||
.vite/
|
||||
|
||||
# Test files
|
||||
cypress/screenshots
|
||||
|
||||
@@ -484,7 +484,7 @@ describe('Task', () => {
|
||||
|
||||
addLabelToTaskAndVerify(labels[0].title)
|
||||
|
||||
cy.get('.modal-container > .close')
|
||||
cy.get('.modal-content .close')
|
||||
.click()
|
||||
|
||||
cy.get('.bucket .task')
|
||||
@@ -850,7 +850,7 @@ describe('Task', () => {
|
||||
|
||||
uploadAttachmentAndVerify(tasks[0].id)
|
||||
|
||||
cy.get('.modal-container > .close')
|
||||
cy.get('.modal-content .close')
|
||||
.click()
|
||||
|
||||
cy.get('.bucket .task .footer .icon svg.fa-paperclip')
|
||||
|
||||
+75
-75
@@ -13,7 +13,7 @@
|
||||
},
|
||||
"homepage": "https://vikunja.io/",
|
||||
"funding": "https://opencollective.com/vikunja",
|
||||
"packageManager": "pnpm@9.10.0",
|
||||
"packageManager": "pnpm@9.6.0",
|
||||
"keywords": [
|
||||
"todo",
|
||||
"productivity",
|
||||
@@ -56,131 +56,131 @@
|
||||
"@fortawesome/vue-fontawesome": "3.0.8",
|
||||
"@github/hotkey": "3.1.1",
|
||||
"@infectoone/vue-ganttastic": "2.3.2",
|
||||
"@intlify/unplugin-vue-i18n": "5.0.0",
|
||||
"@kyvg/vue3-notification": "3.3.0",
|
||||
"@intlify/unplugin-vue-i18n": "4.0.0",
|
||||
"@kyvg/vue3-notification": "3.2.1",
|
||||
"@sentry/tracing": "7.114.0",
|
||||
"@sentry/vue": "8.30.0",
|
||||
"@tiptap/core": "2.7.1",
|
||||
"@tiptap/extension-blockquote": "2.7.1",
|
||||
"@tiptap/extension-bold": "2.7.1",
|
||||
"@tiptap/extension-bullet-list": "2.7.1",
|
||||
"@tiptap/extension-code": "2.7.1",
|
||||
"@tiptap/extension-code-block": "2.7.1",
|
||||
"@tiptap/extension-code-block-lowlight": "2.7.1",
|
||||
"@tiptap/extension-document": "2.7.1",
|
||||
"@tiptap/extension-dropcursor": "2.7.1",
|
||||
"@tiptap/extension-gapcursor": "2.7.1",
|
||||
"@tiptap/extension-hard-break": "2.7.1",
|
||||
"@tiptap/extension-heading": "2.7.1",
|
||||
"@tiptap/extension-history": "2.7.1",
|
||||
"@tiptap/extension-horizontal-rule": "2.7.1",
|
||||
"@tiptap/extension-image": "2.7.1",
|
||||
"@tiptap/extension-italic": "2.7.1",
|
||||
"@tiptap/extension-link": "2.7.1",
|
||||
"@tiptap/extension-list-item": "2.7.1",
|
||||
"@tiptap/extension-ordered-list": "2.7.1",
|
||||
"@tiptap/extension-paragraph": "2.7.1",
|
||||
"@tiptap/extension-placeholder": "2.7.1",
|
||||
"@tiptap/extension-strike": "2.7.1",
|
||||
"@tiptap/extension-table": "2.7.1",
|
||||
"@tiptap/extension-table-cell": "2.7.1",
|
||||
"@tiptap/extension-table-header": "2.7.1",
|
||||
"@tiptap/extension-table-row": "2.7.1",
|
||||
"@tiptap/extension-task-item": "2.7.1",
|
||||
"@tiptap/extension-task-list": "2.7.1",
|
||||
"@tiptap/extension-text": "2.7.1",
|
||||
"@tiptap/extension-typography": "2.7.1",
|
||||
"@tiptap/extension-underline": "2.7.1",
|
||||
"@tiptap/pm": "2.7.1",
|
||||
"@tiptap/suggestion": "2.7.1",
|
||||
"@tiptap/vue-3": "2.7.1",
|
||||
"@vueuse/core": "11.1.0",
|
||||
"@vueuse/router": "11.1.0",
|
||||
"axios": "1.7.7",
|
||||
"@sentry/vue": "8.18.0",
|
||||
"@tiptap/core": "2.5.4",
|
||||
"@tiptap/extension-blockquote": "2.5.4",
|
||||
"@tiptap/extension-bold": "2.5.4",
|
||||
"@tiptap/extension-bullet-list": "2.5.4",
|
||||
"@tiptap/extension-code": "2.5.4",
|
||||
"@tiptap/extension-code-block": "2.5.4",
|
||||
"@tiptap/extension-code-block-lowlight": "2.5.4",
|
||||
"@tiptap/extension-document": "2.5.4",
|
||||
"@tiptap/extension-dropcursor": "2.5.4",
|
||||
"@tiptap/extension-gapcursor": "2.5.4",
|
||||
"@tiptap/extension-hard-break": "2.5.4",
|
||||
"@tiptap/extension-heading": "2.5.4",
|
||||
"@tiptap/extension-history": "2.5.4",
|
||||
"@tiptap/extension-horizontal-rule": "2.5.4",
|
||||
"@tiptap/extension-image": "2.5.4",
|
||||
"@tiptap/extension-italic": "2.5.4",
|
||||
"@tiptap/extension-link": "2.5.4",
|
||||
"@tiptap/extension-list-item": "2.5.4",
|
||||
"@tiptap/extension-ordered-list": "2.5.4",
|
||||
"@tiptap/extension-paragraph": "2.5.4",
|
||||
"@tiptap/extension-placeholder": "2.5.4",
|
||||
"@tiptap/extension-strike": "2.5.4",
|
||||
"@tiptap/extension-table": "2.5.4",
|
||||
"@tiptap/extension-table-cell": "2.5.4",
|
||||
"@tiptap/extension-table-header": "2.5.4",
|
||||
"@tiptap/extension-table-row": "2.5.4",
|
||||
"@tiptap/extension-task-item": "2.5.4",
|
||||
"@tiptap/extension-task-list": "2.5.4",
|
||||
"@tiptap/extension-text": "2.5.4",
|
||||
"@tiptap/extension-typography": "2.5.4",
|
||||
"@tiptap/extension-underline": "2.5.4",
|
||||
"@tiptap/pm": "2.5.4",
|
||||
"@tiptap/suggestion": "2.5.4",
|
||||
"@tiptap/vue-3": "2.5.4",
|
||||
"@vueuse/core": "10.11.0",
|
||||
"@vueuse/router": "10.11.0",
|
||||
"axios": "1.7.2",
|
||||
"blurhash": "2.0.5",
|
||||
"bulma-css-variables": "0.9.33",
|
||||
"change-case": "5.4.4",
|
||||
"date-fns": "4.1.0",
|
||||
"dayjs": "1.11.13",
|
||||
"date-fns": "3.6.0",
|
||||
"dayjs": "1.11.12",
|
||||
"dompurify": "3.1.6",
|
||||
"fast-deep-equal": "3.1.3",
|
||||
"flatpickr": "4.6.13",
|
||||
"flexsearch": "0.7.43",
|
||||
"flexsearch": "0.7.31",
|
||||
"floating-vue": "5.2.2",
|
||||
"is-touch-device": "1.0.1",
|
||||
"klona": "2.0.6",
|
||||
"lowlight": "2.9.0",
|
||||
"pinia": "2.2.2",
|
||||
"pinia": "2.1.7",
|
||||
"register-service-worker": "1.7.2",
|
||||
"sortablejs": "1.15.3",
|
||||
"tailwindcss": "3.4.12",
|
||||
"sortablejs": "1.15.2",
|
||||
"tailwindcss": "3.4.4",
|
||||
"tippy.js": "6.3.7",
|
||||
"ufo": "1.5.4",
|
||||
"vue": "3.5.6",
|
||||
"vue": "3.4.32",
|
||||
"vue-advanced-cropper": "2.8.9",
|
||||
"vue-flatpickr-component": "11.0.5",
|
||||
"vue-i18n": "10.0.1",
|
||||
"vue-router": "4.4.5",
|
||||
"vue-i18n": "9.13.1",
|
||||
"vue-router": "4.4.0",
|
||||
"vuemoji-picker": "0.2.1",
|
||||
"workbox-precaching": "7.1.0",
|
||||
"zhyswan-vuedraggable": "4.1.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@4tw/cypress-drag-drop": "2.2.5",
|
||||
"@cypress/vite-dev-server": "5.2.0",
|
||||
"@cypress/vite-dev-server": "5.1.1",
|
||||
"@cypress/vue": "6.0.1",
|
||||
"@faker-js/faker": "8.4.1",
|
||||
"@histoire/plugin-screenshot": "0.17.17",
|
||||
"@histoire/plugin-vue": "0.17.17",
|
||||
"@rushstack/eslint-patch": "1.10.4",
|
||||
"@rushstack/eslint-patch": "1.10.3",
|
||||
"@tsconfig/node20": "20.1.4",
|
||||
"@types/codemirror": "5.60.15",
|
||||
"@types/dompurify": "3.0.5",
|
||||
"@types/flexsearch": "0.7.6",
|
||||
"@types/is-touch-device": "1.0.2",
|
||||
"@types/lodash.clonedeep": "4.5.9",
|
||||
"@types/node": "20.16.5",
|
||||
"@types/node": "20.14.11",
|
||||
"@types/sortablejs": "1.15.8",
|
||||
"@typescript-eslint/eslint-plugin": "7.18.0",
|
||||
"@typescript-eslint/parser": "7.18.0",
|
||||
"@vitejs/plugin-legacy": "5.4.2",
|
||||
"@vitejs/plugin-vue": "5.1.4",
|
||||
"@typescript-eslint/eslint-plugin": "7.16.1",
|
||||
"@typescript-eslint/parser": "7.16.1",
|
||||
"@vitejs/plugin-legacy": "5.4.1",
|
||||
"@vitejs/plugin-vue": "5.0.5",
|
||||
"@vue/eslint-config-typescript": "13.0.0",
|
||||
"@vue/test-utils": "2.4.6",
|
||||
"@vue/tsconfig": "0.5.1",
|
||||
"autoprefixer": "10.4.20",
|
||||
"browserslist": "4.23.3",
|
||||
"caniuse-lite": "1.0.30001660",
|
||||
"autoprefixer": "10.4.19",
|
||||
"browserslist": "4.23.2",
|
||||
"caniuse-lite": "1.0.30001642",
|
||||
"csstype": "3.1.3",
|
||||
"cypress": "13.14.2",
|
||||
"esbuild": "0.23.1",
|
||||
"eslint": "8.57.1",
|
||||
"eslint-plugin-vue": "9.28.0",
|
||||
"cypress": "13.13.1",
|
||||
"esbuild": "0.23.0",
|
||||
"eslint": "8.57.0",
|
||||
"eslint-plugin-vue": "9.27.0",
|
||||
"happy-dom": "14.12.3",
|
||||
"histoire": "0.17.17",
|
||||
"postcss": "8.4.47",
|
||||
"postcss": "8.4.39",
|
||||
"postcss-easing-gradients": "3.0.1",
|
||||
"postcss-easings": "4.0.0",
|
||||
"postcss-preset-env": "9.6.0",
|
||||
"rollup": "4.21.3",
|
||||
"rollup": "4.18.1",
|
||||
"rollup-plugin-visualizer": "5.12.0",
|
||||
"sass": "1.79.1",
|
||||
"start-server-and-test": "2.0.8",
|
||||
"typescript": "5.6.2",
|
||||
"unplugin-inject-preload": "2.0.5",
|
||||
"vite": "5.4.6",
|
||||
"vite-plugin-pwa": "0.20.5",
|
||||
"sass": "1.77.8",
|
||||
"start-server-and-test": "2.0.4",
|
||||
"typescript": "5.5.3",
|
||||
"unplugin-inject-preload": "2.0.4",
|
||||
"vite": "5.3.4",
|
||||
"vite-plugin-pwa": "0.20.0",
|
||||
"vite-plugin-sentry": "1.4.0",
|
||||
"vite-svg-loader": "5.1.0",
|
||||
"vitest": "1.6.0",
|
||||
"vue-tsc": "2.1.6",
|
||||
"vue-tsc": "2.0.26",
|
||||
"wait-on": "7.2.0",
|
||||
"workbox-cli": "7.1.0"
|
||||
},
|
||||
"pnpm": {
|
||||
"patchedDependencies": {
|
||||
"@github/hotkey@3.1.1": "patches/@github__hotkey@3.1.1.patch",
|
||||
"flexsearch@0.7.43": "patches/flexsearch@0.7.43.patch"
|
||||
"flexsearch@0.7.31": "patches/flexsearch@0.7.31.patch",
|
||||
"@github/hotkey@3.1.1": "patches/@github__hotkey@3.1.1.patch"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
diff --git a/index.d.ts b/index.d.ts
|
||||
deleted file mode 100644
|
||||
index 9f39f41073864b83968bdaa242ac4e3c3149685a..0000000000000000000000000000000000000000
|
||||
diff --git a/package.json b/package.json
|
||||
index 8968f5bf8010ff194240591c8b83299f7328e79d..6d84b6f590a841b129ed8b3860cb786df5a185c0 100644
|
||||
--- a/package.json
|
||||
+++ b/package.json
|
||||
@@ -22,8 +22,6 @@
|
||||
},
|
||||
"main": "dist/flexsearch.bundle.js",
|
||||
"browser": "dist/flexsearch.bundle.js",
|
||||
- "module": "dist/module/index.js",
|
||||
- "types": "./index.d.ts",
|
||||
"preferGlobal": false,
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -1,18 +0,0 @@
|
||||
diff --git a/package.json b/package.json
|
||||
index c154e54029c94be444916fb2249941e7182d80ed..54a65c42a42c4627506e016132becc43b47a517c 100644
|
||||
--- a/package.json
|
||||
+++ b/package.json
|
||||
@@ -28,13 +28,11 @@
|
||||
"email": "info@nextapps.de"
|
||||
},
|
||||
"main": "dist/flexsearch.bundle.min.js",
|
||||
- "module": "dist/flexsearch.bundle.module.min.js",
|
||||
"browser": {
|
||||
"dist/flexsearch.bundle.min.js": "./dist/flexsearch.bundle.min.js",
|
||||
"dist/flexsearch.bundle.module.min.js": "./dist/flexsearch.bundle.module.min.js",
|
||||
"worker_threads": false
|
||||
},
|
||||
- "types": "./index.d.ts",
|
||||
"scripts": {
|
||||
"build": "npm run copy && npm run build:bundle",
|
||||
"build:bundle": "node task/build RELEASE=bundle DEBUG=false SUPPORT_WORKER=true SUPPORT_ENCODER=true SUPPORT_CACHE=true SUPPORT_ASYNC=true SUPPORT_STORE=true SUPPORT_TAGS=true SUPPORT_SUGGESTION=true SUPPORT_SERIALIZE=true SUPPORT_DOCUMENT=true POLYFILL=false",
|
||||
Generated
+2374
-2543
File diff suppressed because it is too large
Load Diff
@@ -69,10 +69,6 @@ const shouldShowMessage = computed(() => {
|
||||
@media screen and (min-width: $tablet) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media print {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&.has-update-available {
|
||||
bottom: 5rem;
|
||||
|
||||
@@ -48,10 +48,7 @@
|
||||
class="task-detail-view-modal"
|
||||
@close="closeModal()"
|
||||
>
|
||||
<component
|
||||
:is="currentModal"
|
||||
@close="closeModal()"
|
||||
/>
|
||||
<component :is="currentModal" />
|
||||
</Modal>
|
||||
|
||||
<BaseButton
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
class="list-menu loader-container is-loading-small"
|
||||
:class="{'is-loading': isLoading}"
|
||||
>
|
||||
<div class="navigation-item">
|
||||
<div>
|
||||
<BaseButton
|
||||
v-if="canCollapse && childProjects?.length > 0"
|
||||
class="collapse-project-button"
|
||||
@@ -193,18 +193,4 @@ const childProjects = computed(() => {
|
||||
.is-touch .handle.has-color-bubble {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.navigation-item:has(*:focus-visible) {
|
||||
box-shadow: 0 0 0 2px hsla(var(--primary-hsl), 0.5);
|
||||
background-color: var(--white);
|
||||
|
||||
.favorite, .menu-list-dropdown {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.navigation-item a:focus-visible {
|
||||
// The focus ring is already added to the navigation-item, so we don't need to add it again.
|
||||
box-shadow: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -2,9 +2,8 @@
|
||||
<div
|
||||
ref="multiselectRoot"
|
||||
class="multiselect"
|
||||
:class="{'has-search-results': searchResultsVisible, 'is-disabled': disabled}"
|
||||
:class="{'has-search-results': searchResultsVisible}"
|
||||
tabindex="-1"
|
||||
:aria-disabled="disabled"
|
||||
@focus="focus"
|
||||
>
|
||||
<div
|
||||
@@ -13,7 +12,7 @@
|
||||
>
|
||||
<div
|
||||
class="input-wrapper input"
|
||||
:class="{'has-multiple': hasMultiple, 'has-removal-button': removalAvailable && !disabled}"
|
||||
:class="{'has-multiple': hasMultiple, 'has-removal-button': removalAvailable}"
|
||||
>
|
||||
<slot
|
||||
v-if="Array.isArray(internalValue)"
|
||||
@@ -32,7 +31,6 @@
|
||||
>
|
||||
{{ label !== '' ? item[label] : item }}
|
||||
<BaseButton
|
||||
v-if="!disabled"
|
||||
class="delete is-small"
|
||||
@click="() => remove(item)"
|
||||
/>
|
||||
@@ -42,7 +40,6 @@
|
||||
</slot>
|
||||
|
||||
<input
|
||||
v-if="!disabled"
|
||||
:id="id"
|
||||
ref="searchInput"
|
||||
v-model="query"
|
||||
@@ -58,7 +55,7 @@
|
||||
@focus="handleFocus"
|
||||
>
|
||||
<BaseButton
|
||||
v-if="removalAvailable && !disabled"
|
||||
v-if="removalAvailable"
|
||||
class="removal-button"
|
||||
@click="resetSelectedValue"
|
||||
>
|
||||
@@ -154,7 +151,7 @@ const props = withDefaults(defineProps<{
|
||||
/** The text shown next to the new value option. */
|
||||
createPlaceholder?: string
|
||||
/** The text shown next to an option. */
|
||||
selectPlaceholder?: string
|
||||
selectPlaceholder: string
|
||||
/** If true, allows for selecting multiple items. v-model will be an array with all selected values in that case. */
|
||||
multiple?: boolean
|
||||
/** If true, displays the search results inline instead of using a dropdown. */
|
||||
@@ -167,8 +164,6 @@ const props = withDefaults(defineProps<{
|
||||
closeAfterSelect?: boolean
|
||||
/** If false, the search input will get the autocomplete="off" attributes attached to it. */
|
||||
autocompleteEnabled?: boolean
|
||||
/** If true, disables the multiselect input */
|
||||
disabled?: boolean
|
||||
}>(), {
|
||||
modelValue: null,
|
||||
loading: false,
|
||||
@@ -184,7 +179,6 @@ const props = withDefaults(defineProps<{
|
||||
searchDelay: 200,
|
||||
closeAfterSelect: true,
|
||||
autocompleteEnabled: true,
|
||||
disabled: false,
|
||||
})
|
||||
|
||||
const emit = defineEmits<{
|
||||
@@ -454,18 +448,6 @@ function focus() {
|
||||
.control.is-loading::after {
|
||||
top: .75rem;
|
||||
}
|
||||
|
||||
&.is-disabled {
|
||||
.input-wrapper, .input, & {
|
||||
cursor: default !important;
|
||||
|
||||
&:focus-within,&:focus-visible, &:hover, &:focus {
|
||||
border-color: transparent !important;
|
||||
background: transparent !important;
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.input-wrapper {
|
||||
|
||||
@@ -36,7 +36,6 @@ import {ref, watchEffect} from 'vue'
|
||||
import {useDebounceFn} from '@vueuse/core'
|
||||
import {useI18n} from 'vue-i18n'
|
||||
import BaseButton from '@/components/base/BaseButton.vue'
|
||||
import {validatePassword} from '@/helpers/validatePasswort'
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
modelValue: string,
|
||||
@@ -61,8 +60,22 @@ const validateAfterFirst = ref(false)
|
||||
watchEffect(() => props.validateInitially && validate())
|
||||
|
||||
const validate = useDebounceFn(() => {
|
||||
const valid = validatePassword(password.value, props.validateMinLength)
|
||||
isValid.value = valid === true ? true : t(valid)
|
||||
if (password.value === '') {
|
||||
isValid.value = t('user.auth.passwordRequired')
|
||||
return
|
||||
}
|
||||
|
||||
if (props.validateMinLength && password.value.length < 8) {
|
||||
isValid.value = t('user.auth.passwordNotMin')
|
||||
return
|
||||
}
|
||||
|
||||
if (props.validateMinLength && password.value.length > 250) {
|
||||
isValid.value = t('user.auth.passwordNotMax')
|
||||
return
|
||||
}
|
||||
|
||||
isValid.value = true
|
||||
}, 100)
|
||||
|
||||
function togglePasswordFieldType() {
|
||||
|
||||
@@ -314,17 +314,7 @@ const internalMode = ref<Mode>('preview')
|
||||
const isEditing = computed(() => internalMode.value === 'edit' && isEditEnabled)
|
||||
const contentHasChanged = ref<boolean>(false)
|
||||
|
||||
let lastSavedState = ''
|
||||
|
||||
watch(
|
||||
() => modelValue,
|
||||
(newValue) => {
|
||||
if (!contentHasChanged.value) {
|
||||
lastSavedState = newValue
|
||||
}
|
||||
},
|
||||
{ immediate: true },
|
||||
)
|
||||
let lastSavedState = modelValue
|
||||
|
||||
watch(
|
||||
() => internalMode.value,
|
||||
|
||||
@@ -20,12 +20,6 @@
|
||||
class="modal-container"
|
||||
@mousedown.self.prevent.stop="$emit('close')"
|
||||
>
|
||||
<BaseButton
|
||||
class="close"
|
||||
@click="$emit('close')"
|
||||
>
|
||||
<Icon icon="times" />
|
||||
</BaseButton>
|
||||
<div
|
||||
class="modal-content"
|
||||
:class="{
|
||||
@@ -33,6 +27,13 @@
|
||||
'is-wide': wide
|
||||
}"
|
||||
>
|
||||
<BaseButton
|
||||
class="close"
|
||||
@click="$emit('close')"
|
||||
>
|
||||
<Icon icon="times" />
|
||||
</BaseButton>
|
||||
|
||||
<slot>
|
||||
<div class="header">
|
||||
<slot name="header" />
|
||||
@@ -136,8 +137,8 @@ $modal-width: 1024px;
|
||||
|
||||
@media screen and (max-width: $tablet) {
|
||||
margin: 0;
|
||||
position: static;
|
||||
transform: none;
|
||||
top: 25%;
|
||||
transform: translate(-50%, -25%);
|
||||
}
|
||||
|
||||
.header {
|
||||
@@ -153,15 +154,12 @@ $modal-width: 1024px;
|
||||
// scrolling-content
|
||||
// used e.g. for <TaskDetailViewModal>
|
||||
.scrolling .modal-content {
|
||||
max-width: $modal-width;
|
||||
width: 100%;
|
||||
margin: $modal-margin auto;
|
||||
|
||||
max-height: none; // reset bulma
|
||||
overflow: visible; // reset bulma
|
||||
|
||||
@media not print {
|
||||
max-width: $modal-width;
|
||||
}
|
||||
|
||||
@media screen and (min-width: $tablet) {
|
||||
max-height: none; // reset bulma
|
||||
@@ -169,7 +167,7 @@ $modal-width: 1024px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@media screen and (max-width: $desktop), print {
|
||||
@media screen and (max-width: $desktop) {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
@@ -196,7 +194,7 @@ $modal-width: 1024px;
|
||||
position: fixed;
|
||||
top: .5rem;
|
||||
right: $close-button-padding;
|
||||
color: var(--white);
|
||||
color: var(--grey-900);
|
||||
font-size: 2rem;
|
||||
|
||||
@media screen and (min-width: $desktop) and (max-width: calc(#{$desktop } + #{$close-button-min-space})) {
|
||||
@@ -205,42 +203,15 @@ $modal-width: 1024px;
|
||||
// we align the close button to the modal until there is enough space outside for it
|
||||
transform: translateX(calc((#{$modal-width} / 2) - #{$close-button-padding}));
|
||||
}
|
||||
// we can only use light color when there is enough space for the close button next to the modal
|
||||
@media screen and (min-width: calc(#{$desktop } + #{$close-button-min-space})) {
|
||||
color: var(--white);
|
||||
}
|
||||
|
||||
@media screen and (min-width: $tablet) and (max-width: #{$desktop + $close-button-min-space}) {
|
||||
top: .75rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media print, screen and (max-width: $tablet) {
|
||||
.modal-mask {
|
||||
position: static;
|
||||
overflow: visible !important;
|
||||
}
|
||||
|
||||
.modal-container {
|
||||
height: auto;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
position: static;
|
||||
max-height: none;
|
||||
}
|
||||
|
||||
.close {
|
||||
display: none;
|
||||
}
|
||||
|
||||
:deep(.card) {
|
||||
border: none !important;
|
||||
border-radius: 0 !important;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss">
|
||||
@@ -248,10 +219,4 @@ $modal-width: 1024px;
|
||||
.dark .close {
|
||||
color: var(--grey-900);
|
||||
}
|
||||
|
||||
@media print, screen and (max-width: $tablet) {
|
||||
body:has(.modal-mask) #app {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
@@ -218,35 +218,33 @@ function handleFieldInput() {
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const [matched, prefix, operator, space, keyword] = match
|
||||
if(!keyword) {
|
||||
return
|
||||
}
|
||||
|
||||
let search = keyword
|
||||
if (operator === 'in' || operator === '?=') {
|
||||
const keywords = keyword.split(',')
|
||||
search = keywords[keywords.length - 1].trim()
|
||||
}
|
||||
if (matched.startsWith('label')) {
|
||||
autocompleteResultType.value = 'labels'
|
||||
autocompleteResults.value = labelStore.filterLabelsByQuery([], search)
|
||||
}
|
||||
if (matched.startsWith('assignee')) {
|
||||
autocompleteResultType.value = 'assignees'
|
||||
if (props.projectId) {
|
||||
projectUserService.getAll({projectId: props.projectId}, {s: search})
|
||||
.then(users => autocompleteResults.value = users.length > 1 ? users : [])
|
||||
} else {
|
||||
userService.getAll({}, {s: search})
|
||||
.then(users => autocompleteResults.value = users.length > 1 ? users : [])
|
||||
if (keyword) {
|
||||
let search = keyword
|
||||
if (operator === 'in' || operator === '?=') {
|
||||
const keywords = keyword.split(',')
|
||||
search = keywords[keywords.length - 1].trim()
|
||||
}
|
||||
if (matched.startsWith('label')) {
|
||||
autocompleteResultType.value = 'labels'
|
||||
autocompleteResults.value = labelStore.filterLabelsByQuery([], search)
|
||||
}
|
||||
if (matched.startsWith('assignee')) {
|
||||
autocompleteResultType.value = 'assignees'
|
||||
if (props.projectId) {
|
||||
projectUserService.getAll({projectId: props.projectId}, {s: search})
|
||||
.then(users => autocompleteResults.value = users.length > 1 ? users : [])
|
||||
} else {
|
||||
userService.getAll({}, {s: search})
|
||||
.then(users => autocompleteResults.value = users.length > 1 ? users : [])
|
||||
}
|
||||
}
|
||||
if (!props.projectId && matched.startsWith('project')) {
|
||||
autocompleteResultType.value = 'projects'
|
||||
autocompleteResults.value = projectStore.searchProject(search)
|
||||
}
|
||||
autocompleteMatchText.value = keyword
|
||||
autocompleteMatchPosition.value = match.index + prefix.length - 1 + keyword.replace(search, '').length
|
||||
}
|
||||
if (!props.projectId && matched.startsWith('project')) {
|
||||
autocompleteResultType.value = 'projects'
|
||||
autocompleteResults.value = projectStore.searchProject(search)
|
||||
}
|
||||
autocompleteMatchText.value = keyword
|
||||
autocompleteMatchPosition.value = match.index + prefix.length - 1 + keyword.replace(search, '').length
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -112,7 +112,7 @@ watch(
|
||||
const val = {...value}
|
||||
val.filter = transformFilterStringFromApi(
|
||||
val?.filter || '',
|
||||
labelId => labelStore.getLabelById(labelId)?.title || null,
|
||||
labelId => labelStore.getLabelById(labelId)?.title,
|
||||
projectId => projectStore.projects[projectId]?.title || null,
|
||||
)
|
||||
params.value = val
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
<BaseButton
|
||||
class="project-button"
|
||||
:aria-label="project.title"
|
||||
:title="textOnlyDescription"
|
||||
:title="project.description"
|
||||
:to="{
|
||||
name: 'project.index',
|
||||
params: { projectId: project.id}
|
||||
@@ -53,7 +53,6 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {computed} from 'vue'
|
||||
import type {IProject} from '@/modelTypes/IProject'
|
||||
|
||||
import BaseButton from '@/components/base/BaseButton.vue'
|
||||
@@ -69,10 +68,6 @@ const props = defineProps<{
|
||||
const {background, blurHashUrl} = useProjectBackground(() => props.project)
|
||||
|
||||
const projectStore = useProjectStore()
|
||||
|
||||
const textOnlyDescription = computed(() => {
|
||||
return props.project.description ? props.project.description.replace(/<[^>]*>/g, '') : ''
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
<template>
|
||||
<ul
|
||||
class="project-grid"
|
||||
:class="{ 'show-even-number-of-projects': showEvenNumberOfProjects }"
|
||||
>
|
||||
<ul class="project-grid">
|
||||
<li
|
||||
v-for="(item, index) in filteredProjects"
|
||||
:key="`project_${item.id}_${index}`"
|
||||
@@ -22,13 +19,11 @@ import ProjectCard from './ProjectCard.vue'
|
||||
const props = withDefaults(defineProps<{
|
||||
projects: IProject[],
|
||||
showArchived?: boolean,
|
||||
itemLimit?: boolean,
|
||||
showEvenNumberOfProjects?: boolean,
|
||||
itemLimit?: boolean
|
||||
}>(), {
|
||||
projects: () => [],
|
||||
showArchived: false,
|
||||
itemLimit: false,
|
||||
showEvenNumberOfProjects: false,
|
||||
})
|
||||
|
||||
const filteredProjects = computed(() => {
|
||||
@@ -63,13 +58,9 @@ const filteredProjects = computed(() => {
|
||||
|
||||
@media screen and (min-width: $widescreen) {
|
||||
--project-grid-columns: 5;
|
||||
}
|
||||
|
||||
&.show-even-number-of-projects {
|
||||
@media screen and (min-width: $widescreen) {
|
||||
.project-grid-item:nth-child(5) {
|
||||
display: none;
|
||||
}
|
||||
.project-grid-item:nth-child(6) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
@click="() => unCollapseBucket(bucket)"
|
||||
>
|
||||
<span
|
||||
v-if="bucket.id !== 0 && view?.doneBucketId === bucket.id"
|
||||
v-if="view?.doneBucketId === bucket.id"
|
||||
v-tooltip="$t('project.kanban.doneBucketHint')"
|
||||
class="icon is-small has-text-success mr-2"
|
||||
>
|
||||
@@ -512,7 +512,6 @@ async function updateTaskPosition(e) {
|
||||
taskId: newTask.id,
|
||||
})
|
||||
await taskPositionService.value.update(newPosition)
|
||||
newTask.position = position
|
||||
|
||||
if(bucketHasChanged) {
|
||||
const updatedTaskBucket = await taskBucketService.value.update(new TaskBucketModel({
|
||||
@@ -525,8 +524,8 @@ async function updateTaskPosition(e) {
|
||||
if (updatedTaskBucket.bucketId !== newTask.bucketId) {
|
||||
kanbanStore.moveTaskToBucket(newTask, updatedTaskBucket.bucketId)
|
||||
}
|
||||
kanbanStore.setTaskInBucket(newTask)
|
||||
}
|
||||
kanbanStore.setTaskInBucket(newTask)
|
||||
|
||||
// Make sure the first and second task don't both get position 0 assigned
|
||||
if (newTaskIndex === 0 && taskAfter !== null && taskAfter.position === 0) {
|
||||
@@ -547,9 +546,6 @@ async function updateTaskPosition(e) {
|
||||
}
|
||||
|
||||
function toggleShowNewTaskInput(bucketId: IBucket['id']) {
|
||||
if (loading.value || taskLoading.value) {
|
||||
return
|
||||
}
|
||||
showNewTaskInput.value[bucketId] = !showNewTaskInput.value[bucketId]
|
||||
newTaskInputFocused.value = false
|
||||
}
|
||||
@@ -566,18 +562,17 @@ async function addTaskToBucket(bucketId: IBucket['id']) {
|
||||
bucketId,
|
||||
projectId: project.value.id,
|
||||
})
|
||||
toggleShowNewTaskInput(bucketId)
|
||||
newTaskText.value = ''
|
||||
kanbanStore.addTaskToBucket(task)
|
||||
scrollTaskContainerToTop(bucketId)
|
||||
scrollTaskContainerToBottom(bucketId)
|
||||
}
|
||||
|
||||
function scrollTaskContainerToTop(bucketId: IBucket['id']) {
|
||||
function scrollTaskContainerToBottom(bucketId: IBucket['id']) {
|
||||
const bucketEl = taskContainerRefs.value[bucketId]
|
||||
if (!bucketEl) {
|
||||
return
|
||||
}
|
||||
bucketEl.scrollTop = 0
|
||||
bucketEl.scrollTop = bucketEl.scrollHeight
|
||||
}
|
||||
|
||||
async function createNewBucket() {
|
||||
@@ -771,18 +766,6 @@ function unCollapseBucket(bucket: IBucket) {
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.control.is-loading {
|
||||
&::after {
|
||||
top: 30%;
|
||||
right: 50%;
|
||||
transform: translate(-50%, 0);
|
||||
--loader-border-color: var(--grey-500);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
<style lang="scss">
|
||||
$ease-out: all .3s cubic-bezier(0.23, 1, 0.32, 1);
|
||||
$bucket-width: 300px;
|
||||
@@ -805,9 +788,8 @@ $filter-container-height: '1rem - #{$switch-view-height}';
|
||||
}
|
||||
|
||||
@media screen and (max-width: $tablet) {
|
||||
height: calc(#{$crazy-height-calculation} - #{$filter-container-height} + 9px);
|
||||
height: calc(#{$crazy-height-calculation} - #{$filter-container-height});
|
||||
scroll-snap-type: x mandatory;
|
||||
margin: 0 -0.5rem;
|
||||
}
|
||||
|
||||
&-bucket-container {
|
||||
@@ -885,6 +867,7 @@ $filter-container-height: '1rem - #{$switch-view-height}';
|
||||
// to hide the fact we just made the button smaller.
|
||||
min-width: calc(#{$bucket-width} + 1rem);
|
||||
background: transparent;
|
||||
padding-right: 1rem;
|
||||
|
||||
.button {
|
||||
background: var(--grey-100);
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
|
||||
<draggable
|
||||
v-if="tasks && tasks.length > 0"
|
||||
v-bind="DRAG_OPTIONS"
|
||||
v-model="tasks"
|
||||
group="tasks"
|
||||
handle=".handle"
|
||||
@@ -58,8 +59,6 @@
|
||||
},
|
||||
type: 'transition-group'
|
||||
}"
|
||||
:animation="100"
|
||||
ghost-class="task-ghost"
|
||||
@start="() => drag = true"
|
||||
@end="saveTaskPosition"
|
||||
>
|
||||
@@ -129,6 +128,10 @@ const props = defineProps<{
|
||||
const ctaVisible = ref(false)
|
||||
|
||||
const drag = ref(false)
|
||||
const DRAG_OPTIONS = {
|
||||
animation: 100,
|
||||
ghostClass: 'task-ghost',
|
||||
} as const
|
||||
|
||||
const {
|
||||
tasks: allTasks,
|
||||
|
||||
@@ -289,7 +289,6 @@ import type {ITask} from '@/modelTypes/ITask'
|
||||
import type {IProject} from '@/modelTypes/IProject'
|
||||
import AssigneeList from '@/components/tasks/partials/AssigneeList.vue'
|
||||
import type {IProjectView} from '@/modelTypes/IProjectView'
|
||||
import { camelCase } from 'change-case'
|
||||
|
||||
const props = defineProps<{
|
||||
projectId: IProject['id'],
|
||||
@@ -356,7 +355,7 @@ function sort(property: keyof SortBy) {
|
||||
|
||||
function setActiveColumnsSortParam() {
|
||||
sortByParam.value = Object.keys(sortBy.value)
|
||||
.filter(prop => activeColumns.value[camelCase(prop)])
|
||||
.filter(prop => activeColumns.value[prop])
|
||||
.reduce((obj, key) => {
|
||||
obj[key] = sortBy.value[key]
|
||||
return obj
|
||||
|
||||
@@ -30,7 +30,7 @@ const projectStore = useProjectStore()
|
||||
onBeforeMount(() => {
|
||||
const transform = (filterString: string) => transformFilterStringFromApi(
|
||||
filterString,
|
||||
labelId => labelStore.getLabelById(labelId)?.title || null,
|
||||
labelId => labelStore.getLabelById(labelId)?.title,
|
||||
projectId => projectStore.projects[projectId]?.title || null,
|
||||
)
|
||||
|
||||
@@ -51,7 +51,7 @@ onBeforeMount(() => {
|
||||
function save() {
|
||||
const transformFilter = (filterQuery: string) => transformFilterStringForApi(
|
||||
filterQuery,
|
||||
labelTitle => labelStore.getLabelByExactTitle(labelTitle)?.id || null,
|
||||
labelTitle => labelStore.filterLabelsByQuery([], labelTitle)[0]?.id || null,
|
||||
projectTitle => {
|
||||
const found = projectStore.findProjectByExactname(projectTitle)
|
||||
return found?.id || null
|
||||
|
||||
@@ -51,7 +51,6 @@
|
||||
import {computed, ref} from 'vue'
|
||||
import {useI18n} from 'vue-i18n'
|
||||
import {useElementHover} from '@vueuse/core'
|
||||
import {useRouter} from 'vue-router'
|
||||
|
||||
import {RELATION_KIND} from '@/types/IRelationKind'
|
||||
import type {ITask} from '@/modelTypes/ITask'
|
||||
@@ -67,8 +66,6 @@ import {useAuthStore} from '@/stores/auth'
|
||||
import {useTaskStore} from '@/stores/tasks'
|
||||
|
||||
import {useAutoHeightTextarea} from '@/composables/useAutoHeightTextarea'
|
||||
import TaskService from '@/services/task'
|
||||
import TaskModel from '@/models/task'
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
defaultPosition?: number,
|
||||
@@ -84,7 +81,6 @@ const {textarea: newTaskInput} = useAutoHeightTextarea(newTaskTitle)
|
||||
const {t} = useI18n({useScope: 'global'})
|
||||
const authStore = useAuthStore()
|
||||
const taskStore = useTaskStore()
|
||||
const router = useRouter()
|
||||
|
||||
// enable only if we don't have a modal
|
||||
// onStartTyping(() => {
|
||||
@@ -133,55 +129,21 @@ async function addTask() {
|
||||
const allLabels = tasksToCreate.map(({title}) => getLabelsFromPrefix(title, authStore.settings.frontendSettings.quickAddMagicMode) ?? [])
|
||||
await taskStore.ensureLabelsExist(allLabels.flat())
|
||||
|
||||
const taskCollectionService = new TaskService()
|
||||
const projectIndices = new Map<number, number>()
|
||||
|
||||
let currentProjectId = authStore.settings.defaultProjectId
|
||||
if (typeof router.currentRoute.value.params.projectId !== 'undefined') {
|
||||
currentProjectId = Number(router.currentRoute.value.params.projectId)
|
||||
}
|
||||
|
||||
// Create a map of project indices before creating tasks
|
||||
if (tasksToCreate.length > 1) {
|
||||
for (const {project} of tasksToCreate) {
|
||||
const projectId = project !== null
|
||||
? await taskStore.findProjectId({project, projectId: 0})
|
||||
: currentProjectId
|
||||
|
||||
if (!projectIndices.has(projectId)) {
|
||||
const newestTask = await taskCollectionService.getAll(new TaskModel({}), {
|
||||
sort_by: ['id'],
|
||||
order_by: ['desc'],
|
||||
per_page: 1,
|
||||
filter: `project_id = ${projectId}`,
|
||||
})
|
||||
projectIndices.set(projectId, newestTask[0]?.index || 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const newTasks = tasksToCreate.map(async ({title, project}, index) => {
|
||||
const newTasks = tasksToCreate.map(async ({title, project}) => {
|
||||
if (title === '') {
|
||||
return
|
||||
}
|
||||
|
||||
// If the task has a project specified, make sure to use it
|
||||
const projectId = project !== null
|
||||
? await taskStore.findProjectId({project, projectId: 0})
|
||||
: currentProjectId
|
||||
|
||||
// Calculate new index for this task per project
|
||||
let taskIndex: number | undefined
|
||||
if (tasksToCreate.length > 1) {
|
||||
const lastIndex = projectIndices.get(projectId)
|
||||
taskIndex = lastIndex + index + 1
|
||||
let projectId = null
|
||||
if (project !== null) {
|
||||
projectId = await taskStore.findProjectId({project, projectId: 0})
|
||||
}
|
||||
|
||||
const task = await taskStore.createNewTask({
|
||||
title,
|
||||
projectId: projectId || authStore.settings.defaultProjectId,
|
||||
position: props.defaultPosition,
|
||||
index: taskIndex,
|
||||
})
|
||||
createdTasks[title] = task
|
||||
return task
|
||||
|
||||
@@ -180,7 +180,7 @@ import ProgressBar from '@/components/misc/ProgressBar.vue'
|
||||
import BaseButton from '@/components/base/BaseButton.vue'
|
||||
|
||||
import AttachmentService from '@/services/attachment'
|
||||
import {canPreview} from '@/models/attachment'
|
||||
import {SUPPORTED_IMAGE_SUFFIX} from '@/models/attachment'
|
||||
import type {IAttachment} from '@/modelTypes/IAttachment'
|
||||
import type {ITask} from '@/modelTypes/ITask'
|
||||
|
||||
@@ -274,6 +274,10 @@ async function viewOrDownload(attachment: IAttachment) {
|
||||
}
|
||||
}
|
||||
|
||||
function canPreview(attachment: IAttachment): boolean {
|
||||
return SUPPORTED_IMAGE_SUFFIX.some((suffix) => attachment.file.name.toLowerCase().endsWith(suffix))
|
||||
}
|
||||
|
||||
const copy = useCopyToClipboard()
|
||||
|
||||
function copyUrl(attachment: IAttachment) {
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
</span>
|
||||
<div
|
||||
v-for="c in comments"
|
||||
:id="`comment-${c.id}`"
|
||||
:key="c.id"
|
||||
class="media comment"
|
||||
>
|
||||
@@ -57,13 +56,6 @@
|
||||
>
|
||||
· {{ $t('task.comment.edited', {date: formatDateSince(c.updated)}) }}
|
||||
</span>
|
||||
<a
|
||||
v-tooltip="$t('task.comment.permalink')"
|
||||
:href="`#comment-${c.id}`"
|
||||
class="comment-permalink"
|
||||
:title="$t('task.comment.permalink')"
|
||||
@click.prevent.stop="copy(getCommentUrl(`${c.id}`))"
|
||||
><Icon icon="link" /></a>
|
||||
<CustomTransition name="fade">
|
||||
<span
|
||||
v-if="
|
||||
@@ -207,7 +199,6 @@ import {getAvatarUrl, getDisplayName} from '@/models/user'
|
||||
import {useConfigStore} from '@/stores/config'
|
||||
import {useAuthStore} from '@/stores/auth'
|
||||
import Reactions from '@/components/input/Reactions.vue'
|
||||
import { useCopyToClipboard } from '@/composables/useCopyToClipboard'
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
taskId: number,
|
||||
@@ -216,8 +207,6 @@ const props = withDefaults(defineProps<{
|
||||
canWrite: true,
|
||||
})
|
||||
|
||||
const copy = useCopyToClipboard()
|
||||
|
||||
const {t} = useI18n({useScope: 'global'})
|
||||
const configStore = useConfigStore()
|
||||
const authStore = useAuthStore()
|
||||
@@ -253,8 +242,6 @@ const actions = computed(() => {
|
||||
])))
|
||||
})
|
||||
|
||||
const frontendUrl = computed(() => configStore.frontendUrl)
|
||||
|
||||
async function attachmentUpload(files: File[] | FileList): (Promise<string[]>) {
|
||||
|
||||
const uploadPromises: Promise<string>[] = []
|
||||
@@ -377,10 +364,6 @@ async function deleteComment(commentToDelete: ITaskComment) {
|
||||
showDeleteModal.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function getCommentUrl(commentId: string) {
|
||||
return `${frontendUrl.value}${location.pathname}${location.search}#comment-${commentId}`
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@@ -408,23 +391,10 @@ function getCommentUrl(commentId: string) {
|
||||
}
|
||||
|
||||
|
||||
span,
|
||||
.comment-permalink {
|
||||
span {
|
||||
font-size: .75rem;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.comment-permalink {
|
||||
font-size: 1rem;
|
||||
border: 1px solid transparent;
|
||||
padding: 0.25rem;
|
||||
border-radius: 1rem;
|
||||
color: var(--grey, hsl(0, 0%, 48%));
|
||||
}
|
||||
.comment-permalink:hover {
|
||||
color: var(--grey-dark, hsl(0, 0%, 29%));
|
||||
border-color: var(--grey-dark, hsl(0, 0%, 29%));
|
||||
}
|
||||
}
|
||||
|
||||
.image.is-avatar {
|
||||
|
||||
@@ -135,8 +135,18 @@ async function updateDueDate() {
|
||||
$defer-task-max-width: 350px + 100px;
|
||||
|
||||
.defer-task {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
max-width: $defer-task-max-width;
|
||||
border-radius: $radius;
|
||||
border: 1px solid var(--grey-200);
|
||||
padding: 1rem;
|
||||
margin: 1rem;
|
||||
background: var(--white);
|
||||
color: var(--text);
|
||||
cursor: default;
|
||||
z-index: 10;
|
||||
box-shadow: var(--shadow-lg);
|
||||
|
||||
@media screen and (max-width: ($defer-task-max-width)) {
|
||||
left: .5rem;
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
:create-placeholder="$t('task.label.createPlaceholder')"
|
||||
:search-delay="10"
|
||||
:close-after-select="false"
|
||||
:disabled="disabled"
|
||||
@search="findLabel"
|
||||
@select="addLabel"
|
||||
@create="createAndAddLabel"
|
||||
@@ -22,7 +21,6 @@
|
||||
>
|
||||
<span>{{ label.title }}</span>
|
||||
<BaseButton
|
||||
v-if="!disabled"
|
||||
v-cy="'taskDetail.removeLabel'"
|
||||
class="delete is-small"
|
||||
@click="removeLabel(label)"
|
||||
|
||||
@@ -20,9 +20,9 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import {ref, shallowReactive, watchEffect} from 'vue'
|
||||
import AttachmentService, {PREVIEW_SIZE} from '@/services/attachment'
|
||||
import AttachmentService from '@/services/attachment'
|
||||
import type {IAttachment} from '@/modelTypes/IAttachment'
|
||||
import {canPreview} from '@/models/attachment'
|
||||
import {SUPPORTED_IMAGE_SUFFIX} from '@/models/attachment'
|
||||
|
||||
const props = defineProps<{
|
||||
modelValue?: IAttachment
|
||||
@@ -33,9 +33,13 @@ const blobUrl = ref<string | undefined>(undefined)
|
||||
|
||||
watchEffect(async () => {
|
||||
if (props.modelValue && canPreview(props.modelValue)) {
|
||||
blobUrl.value = await attachmentService.getBlobUrl(props.modelValue, PREVIEW_SIZE.MD)
|
||||
blobUrl.value = await attachmentService.getBlobUrl(props.modelValue)
|
||||
}
|
||||
})
|
||||
|
||||
function canPreview(attachment: IAttachment): boolean {
|
||||
return SUPPORTED_IMAGE_SUFFIX.some((suffix) => attachment.file.name.toLowerCase().endsWith(suffix))
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
@@ -1,26 +1,20 @@
|
||||
<template>
|
||||
<div class="heading">
|
||||
<div class="tw-flex tw-items-center md:tw-items-stretch tw-flex-col tw-gap-1 task-properties">
|
||||
<div class="tw-flex tw-items-center tw-gap-2">
|
||||
<ColorBubble
|
||||
v-if="task.hexColor !== ''"
|
||||
:color="getHexColor(task.hexColor)"
|
||||
/>
|
||||
<BaseButton @click="copyUrl">
|
||||
<h1 class="title task-id">
|
||||
{{ textIdentifier }}
|
||||
</h1>
|
||||
</BaseButton>
|
||||
</div>
|
||||
<div class="flex is-align-items-center">
|
||||
<BaseButton @click="copyUrl">
|
||||
<h1 class="title task-id">
|
||||
{{ textIdentifier }}
|
||||
</h1>
|
||||
</BaseButton>
|
||||
<Done
|
||||
class="heading__done"
|
||||
:is-done="task.done"
|
||||
/>
|
||||
<BaseButton
|
||||
class="close"
|
||||
@click="$emit('close')"
|
||||
>
|
||||
<Icon icon="times" />
|
||||
</BaseButton>
|
||||
<ColorBubble
|
||||
v-if="task.hexColor !== ''"
|
||||
:color="getHexColor(task.hexColor)"
|
||||
class="ml-2"
|
||||
/>
|
||||
</div>
|
||||
<h1
|
||||
class="title input"
|
||||
@@ -32,12 +26,6 @@
|
||||
>
|
||||
{{ task.title.trim() }}
|
||||
</h1>
|
||||
<BaseButton
|
||||
class="close"
|
||||
@click="$emit('close')"
|
||||
>
|
||||
<Icon icon="times" />
|
||||
</BaseButton>
|
||||
<CustomTransition name="fade">
|
||||
<span
|
||||
v-if="loading && saving"
|
||||
@@ -83,8 +71,7 @@ const props = withDefaults(defineProps<{
|
||||
})
|
||||
|
||||
const emit = defineEmits<{
|
||||
'update:task': [task: ITask],
|
||||
'close': [],
|
||||
'update:task': [task: ITask]
|
||||
}>()
|
||||
|
||||
const router = useRouter()
|
||||
@@ -151,11 +138,14 @@ async function save(title: string) {
|
||||
.title.input {
|
||||
// 1.8rem is the font-size, 1.125 is the line-height, .3rem padding everywhere, 1px border around the whole thing.
|
||||
min-height: calc(1.8rem * 1.125 + .6rem + 2px);
|
||||
margin-right: 0;
|
||||
|
||||
@media screen and (max-width: $tablet) {
|
||||
margin: 0 -.3rem .5rem -.3rem; // the title has 0.3rem padding - this make the text inside of it align with the rest
|
||||
}
|
||||
|
||||
@media screen and (min-width: $tablet) and (max-width: #{$desktop + $close-button-min-space}) {
|
||||
width: calc(100% - 6.5rem);
|
||||
}
|
||||
}
|
||||
|
||||
.title.task-id {
|
||||
@@ -163,39 +153,12 @@ async function save(title: string) {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.heading__done {
|
||||
margin-left: .5rem;
|
||||
}
|
||||
|
||||
.color-bubble {
|
||||
height: .75rem;
|
||||
width: .75rem;
|
||||
}
|
||||
|
||||
.close {
|
||||
font-size: 2rem;
|
||||
margin-left: 0.5rem;
|
||||
line-height: 1;
|
||||
|
||||
@media screen and (max-width: $tablet) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media screen and (min-width: #{$desktop + 1px}) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.task-properties .close {
|
||||
display: none;
|
||||
position: absolute;
|
||||
right: 1.25rem;
|
||||
top: 1.1rem;
|
||||
|
||||
@media screen and (max-width: $tablet) {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.task-properties {
|
||||
@media screen and (max-width: $tablet) {
|
||||
flex-direction: row;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -93,7 +93,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {computed, ref, watch} from 'vue'
|
||||
import {ref, computed, watch} from 'vue'
|
||||
import {useRouter} from 'vue-router'
|
||||
|
||||
import PriorityLabel from '@/components/tasks/partials/PriorityLabel.vue'
|
||||
@@ -105,9 +105,9 @@ import ChecklistSummary from './ChecklistSummary.vue'
|
||||
import {getHexColor} from '@/models/task'
|
||||
import type {ITask} from '@/modelTypes/ITask'
|
||||
import {SUPPORTED_IMAGE_SUFFIX} from '@/models/attachment'
|
||||
import AttachmentService, {PREVIEW_SIZE} from '@/services/attachment'
|
||||
import AttachmentService from '@/services/attachment'
|
||||
|
||||
import {formatDateLong, formatDateSince, formatISO} from '@/helpers/time/formatDate'
|
||||
import {formatDateLong, formatISO, formatDateSince} from '@/helpers/time/formatDate'
|
||||
import {colorIsDark} from '@/helpers/color/colorIsDark'
|
||||
import {useTaskStore} from '@/stores/tasks'
|
||||
import AssigneeList from '@/components/tasks/partials/AssigneeList.vue'
|
||||
@@ -165,7 +165,7 @@ async function maybeDownloadCoverImage() {
|
||||
}
|
||||
|
||||
const attachmentService = new AttachmentService()
|
||||
coverImageBlobUrl.value = await attachmentService.getBlobUrl(attachment, PREVIEW_SIZE.LG)
|
||||
coverImageBlobUrl.value = await attachmentService.getBlobUrl(attachment)
|
||||
}
|
||||
|
||||
watch(
|
||||
|
||||
@@ -123,7 +123,7 @@
|
||||
<FancyCheckbox
|
||||
v-model="task.done"
|
||||
class="task-done-checkbox"
|
||||
@update:modelValue="toggleTaskDone(task)"
|
||||
@update:modelValue="toggleTaskDone(t)"
|
||||
/>
|
||||
<RouterLink
|
||||
:to="{ name: route.name as string, params: { id: task.id } }"
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
<template>
|
||||
<div>
|
||||
<div
|
||||
ref="taskContainerRef"
|
||||
:class="{'is-loading': taskService.loading}"
|
||||
class="task loader-container single-task"
|
||||
tabindex="-1"
|
||||
@click="openTaskDetail"
|
||||
@keyup.enter="openTaskDetail"
|
||||
@mouseup.stop.self="openTaskDetail"
|
||||
@mousedown.stop.self="focusTaskLink"
|
||||
>
|
||||
<FancyCheckbox
|
||||
v-model="task.done"
|
||||
:disabled="(isArchived || disabled) && !canMarkAsDone"
|
||||
@update:modelValue="markAsDone"
|
||||
@click.stop
|
||||
/>
|
||||
|
||||
<ColorBubble
|
||||
@@ -23,6 +23,8 @@
|
||||
<div
|
||||
:class="{ 'done': task.done, 'show-project': showProject && project}"
|
||||
class="tasktext"
|
||||
@mouseup.stop.self="openTaskDetail"
|
||||
@mousedown.stop.self="focusTaskLink"
|
||||
>
|
||||
<span>
|
||||
<RouterLink
|
||||
@@ -31,7 +33,6 @@
|
||||
:to="{ name: 'project.index', params: { projectId: task.projectId } }"
|
||||
class="task-project mr-1"
|
||||
:class="{'mr-2': task.hexColor !== ''}"
|
||||
@click.stop
|
||||
>
|
||||
{{ project.title }}
|
||||
</RouterLink>
|
||||
@@ -41,15 +42,15 @@
|
||||
:color="getHexColor(task.hexColor)"
|
||||
class="mr-1"
|
||||
/>
|
||||
|
||||
|
||||
<PriorityLabel
|
||||
:priority="task.priority"
|
||||
:done="task.done"
|
||||
class="pr-2"
|
||||
/>
|
||||
|
||||
|
||||
<RouterLink
|
||||
ref="taskLinkRef"
|
||||
ref="taskLink"
|
||||
:to="taskDetailRoute"
|
||||
class="task-link"
|
||||
tabindex="-1"
|
||||
@@ -72,32 +73,29 @@
|
||||
:inline="true"
|
||||
/>
|
||||
|
||||
<Popup
|
||||
<!-- FIXME: use popup -->
|
||||
<BaseButton
|
||||
v-if="+new Date(task.dueDate) > 0"
|
||||
v-tooltip="formatDateLong(task.dueDate)"
|
||||
class="dueDate"
|
||||
@click.prevent.stop="showDefer = !showDefer"
|
||||
>
|
||||
<template #trigger="{toggle, isOpen}">
|
||||
<BaseButton
|
||||
v-tooltip="formatDateLong(task.dueDate)"
|
||||
class="dueDate"
|
||||
@click.prevent.stop="toggle()"
|
||||
>
|
||||
<time
|
||||
:datetime="formatISO(task.dueDate)"
|
||||
:class="{'overdue': task.dueDate <= new Date() && !task.done}"
|
||||
class="is-italic"
|
||||
:aria-expanded="isOpen ? 'true' : 'false'"
|
||||
>
|
||||
– {{ $t('task.detail.due', {at: dueDateFormatted}) }}
|
||||
</time>
|
||||
</BaseButton>
|
||||
</template>
|
||||
<template #content>
|
||||
<DeferTask
|
||||
v-model="task"
|
||||
/>
|
||||
</template>
|
||||
</Popup>
|
||||
|
||||
<time
|
||||
:datetime="formatISO(task.dueDate)"
|
||||
:class="{'overdue': task.dueDate <= new Date() && !task.done}"
|
||||
class="is-italic"
|
||||
:aria-expanded="showDefer ? 'true' : 'false'"
|
||||
>
|
||||
– {{ $t('task.detail.due', {at: dueDateFormatted}) }}
|
||||
</time>
|
||||
</BaseButton>
|
||||
<CustomTransition name="fade">
|
||||
<DeferTask
|
||||
v-if="+new Date(task.dueDate) > 0 && showDefer"
|
||||
ref="deferDueDate"
|
||||
v-model="task"
|
||||
/>
|
||||
</CustomTransition>
|
||||
|
||||
<span>
|
||||
<span
|
||||
@@ -140,7 +138,6 @@
|
||||
v-tooltip="$t('task.detail.belongsToProject', {project: project.title})"
|
||||
:to="{ name: 'project.index', params: { projectId: task.projectId } }"
|
||||
class="task-project"
|
||||
@click.stop
|
||||
>
|
||||
{{ project.title }}
|
||||
</RouterLink>
|
||||
@@ -148,7 +145,7 @@
|
||||
<BaseButton
|
||||
:class="{'is-favorite': task.isFavorite}"
|
||||
class="favorite"
|
||||
@click.stop="toggleFavorite"
|
||||
@click="toggleFavorite"
|
||||
>
|
||||
<Icon
|
||||
v-if="task.isFavorite"
|
||||
@@ -179,7 +176,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {ref, watch, shallowReactive, onMounted, computed} from 'vue'
|
||||
import {ref, watch, shallowReactive, onMounted, onBeforeUnmount, computed} from 'vue'
|
||||
import {useI18n} from 'vue-i18n'
|
||||
|
||||
import TaskModel, {getHexColor} from '@/models/task'
|
||||
@@ -194,10 +191,11 @@ import ProgressBar from '@/components/misc/ProgressBar.vue'
|
||||
import BaseButton from '@/components/base/BaseButton.vue'
|
||||
import FancyCheckbox from '@/components/input/FancyCheckbox.vue'
|
||||
import ColorBubble from '@/components/misc/ColorBubble.vue'
|
||||
import Popup from '@/components/misc/Popup.vue'
|
||||
import CustomTransition from '@/components/misc/CustomTransition.vue'
|
||||
|
||||
import TaskService from '@/services/task'
|
||||
|
||||
import {closeWhenClickedOutside} from '@/helpers/closeWhenClickedOutside'
|
||||
import {formatDateSince, formatISO, formatDateLong} from '@/helpers/time/formatDate'
|
||||
import {success} from '@/message'
|
||||
|
||||
@@ -241,6 +239,7 @@ const {t} = useI18n({useScope: 'global'})
|
||||
|
||||
const taskService = shallowReactive(new TaskService())
|
||||
const task = ref<ITask>(new TaskModel())
|
||||
const showDefer = ref(false)
|
||||
|
||||
const isRepeating = computed(() => task.value.repeatAfter.amount > 0 || (task.value.repeatAfter.amount === 0 && task.value.repeatMode === TASK_REPEAT_MODES.REPEAT_MODE_MONTH))
|
||||
|
||||
@@ -255,6 +254,14 @@ watch(
|
||||
},
|
||||
)
|
||||
|
||||
onMounted(() => {
|
||||
document.addEventListener('click', hideDeferDueDatePopup)
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
document.removeEventListener('click', hideDeferDueDatePopup)
|
||||
})
|
||||
|
||||
const baseStore = useBaseStore()
|
||||
const projectStore = useProjectStore()
|
||||
const taskStore = useTaskStore()
|
||||
@@ -343,22 +350,35 @@ async function toggleFavorite() {
|
||||
emit('taskUpdated', task.value)
|
||||
}
|
||||
|
||||
const taskLinkRef = ref<HTMLElement | null>(null)
|
||||
const deferDueDate = ref<typeof DeferTask | null>(null)
|
||||
|
||||
function hideDeferDueDatePopup(e) {
|
||||
if (!showDefer.value) {
|
||||
return
|
||||
}
|
||||
closeWhenClickedOutside(e, deferDueDate.value.$el, () => {
|
||||
showDefer.value = false
|
||||
})
|
||||
}
|
||||
|
||||
const taskLink = ref<HTMLElement | null>(null)
|
||||
const taskContainerRef = ref<HTMLElement | null>(null)
|
||||
|
||||
function hasTextSelected() {
|
||||
const isTextSelected = window.getSelection().toString()
|
||||
return !(typeof isTextSelected === 'undefined' || isTextSelected === '' || isTextSelected === '\n')
|
||||
}
|
||||
|
||||
function openTaskDetail(event: MouseEvent | KeyboardEvent) {
|
||||
if (event.target instanceof HTMLElement) {
|
||||
const isInteractiveElement = event.target.closest('a, button, input, .favorite, [role="button"]')
|
||||
if (isInteractiveElement || hasTextSelected()) {
|
||||
return
|
||||
}
|
||||
function openTaskDetail() {
|
||||
if (!hasTextSelected()) {
|
||||
taskLink.value.$el.click()
|
||||
}
|
||||
}
|
||||
|
||||
taskLinkRef.value?.$el.click()
|
||||
function focusTaskLink() {
|
||||
if (!hasTextSelected()) {
|
||||
taskContainerRef.value.focus()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -377,7 +397,7 @@ function openTaskDetail(event: MouseEvent | KeyboardEvent) {
|
||||
background-color: var(--grey-100);
|
||||
}
|
||||
|
||||
&:focus-within {
|
||||
&:focus-within, &:focus {
|
||||
box-shadow: 0 0 0 2px hsla(var(--primary-hsl), 0.5);
|
||||
|
||||
a.task-link {
|
||||
@@ -385,16 +405,6 @@ function openTaskDetail(event: MouseEvent | KeyboardEvent) {
|
||||
}
|
||||
}
|
||||
|
||||
@supports not selector(:focus-within) {
|
||||
:focus {
|
||||
box-shadow: 0 0 0 2px hsla(var(--primary-hsl), 0.5);
|
||||
|
||||
a.task-link {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tasktext,
|
||||
&.tasktext {
|
||||
text-overflow: ellipsis;
|
||||
@@ -532,17 +542,4 @@ function openTaskDetail(event: MouseEvent | KeyboardEvent) {
|
||||
.subtask-nested {
|
||||
margin-left: 1.75rem;
|
||||
}
|
||||
|
||||
:deep(.popup) {
|
||||
border-radius: $radius;
|
||||
background-color: var(--white);
|
||||
box-shadow: var(--shadow-lg);
|
||||
color: var(--text);
|
||||
top: unset;
|
||||
|
||||
&.is-open {
|
||||
padding: 1rem;
|
||||
border: 1px solid var(--grey-200);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -147,26 +147,6 @@ describe('Filter Transformation', () => {
|
||||
|
||||
expect(transformed).toBe('start_date > now')
|
||||
})
|
||||
|
||||
it('should correctly resolve label when the label is called label', () => {
|
||||
const transformed = transformFilterStringForApi(
|
||||
'labels = label',
|
||||
(title: string) => 1,
|
||||
nullTitleToIdResolver,
|
||||
)
|
||||
|
||||
expect(transformed).toBe('labels = 1')
|
||||
})
|
||||
|
||||
it('should correctly resolve project when the project is called project', () => {
|
||||
const transformed = transformFilterStringForApi(
|
||||
'project = project',
|
||||
nullTitleToIdResolver,
|
||||
(title: string) => 1,
|
||||
)
|
||||
|
||||
expect(transformed).toBe('project = 1')
|
||||
})
|
||||
})
|
||||
|
||||
describe('To API', () => {
|
||||
@@ -219,26 +199,6 @@ describe('Filter Transformation', () => {
|
||||
expect(transformed).toBe('labels in lorem, ipsum')
|
||||
})
|
||||
|
||||
it('should not touch the label value when it is undefined', () => {
|
||||
const transformed = transformFilterStringFromApi(
|
||||
'labels = one',
|
||||
(id: number) => undefined,
|
||||
nullIdToTitleResolver,
|
||||
)
|
||||
|
||||
expect(transformed).toBe('labels = one')
|
||||
})
|
||||
|
||||
it('should not touch the label value when it is null', () => {
|
||||
const transformed = transformFilterStringFromApi(
|
||||
'labels = one',
|
||||
(id: number) => null,
|
||||
nullIdToTitleResolver,
|
||||
)
|
||||
|
||||
expect(transformed).toBe('labels = one')
|
||||
})
|
||||
|
||||
it('should correctly resolve projects', () => {
|
||||
const transformed = transformFilterStringFromApi(
|
||||
'project = 1',
|
||||
@@ -268,26 +228,6 @@ describe('Filter Transformation', () => {
|
||||
|
||||
expect(transformed).toBe('project in lorem, ipsum')
|
||||
})
|
||||
|
||||
it('should not touch the project value when it is undefined', () => {
|
||||
const transformed = transformFilterStringFromApi(
|
||||
'project = one',
|
||||
nullIdToTitleResolver,
|
||||
(id: number) => undefined,
|
||||
)
|
||||
|
||||
expect(transformed).toBe('project = one')
|
||||
})
|
||||
|
||||
it('should not touch the project value when it is null', () => {
|
||||
const transformed = transformFilterStringFromApi(
|
||||
'project = one',
|
||||
nullIdToTitleResolver,
|
||||
(id: number) => null,
|
||||
)
|
||||
|
||||
expect(transformed).toBe('project = one')
|
||||
})
|
||||
|
||||
it('should transform the same attribute multiple times', () => {
|
||||
const transformed = transformFilterStringFromApi(
|
||||
|
||||
@@ -77,34 +77,49 @@ export function transformFilterStringForApi(
|
||||
filter = filter.replace(new RegExp(f, 'ig'), f)
|
||||
})
|
||||
|
||||
// Transform labels and projects to ids
|
||||
function transformFieldToIds(
|
||||
fields: string[],
|
||||
resolver: (title: string) => number | null,
|
||||
filter: string,
|
||||
): string {
|
||||
fields.forEach(field => {
|
||||
const pattern = getFilterFieldRegexPattern(field)
|
||||
|
||||
let match: RegExpExecArray | null
|
||||
while ((match = pattern.exec(filter)) !== null) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const [matched, prefix, operator, space, keyword] = match
|
||||
if (!keyword) {
|
||||
continue
|
||||
}
|
||||
// Transform labels to ids
|
||||
LABEL_FIELDS.forEach(field => {
|
||||
const pattern = getFilterFieldRegexPattern(field)
|
||||
|
||||
let match: RegExpExecArray | null
|
||||
while ((match = pattern.exec(filter)) !== null) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const [matched, prefix, operator, space, keyword] = match
|
||||
if (keyword) {
|
||||
let keywords = [keyword.trim()]
|
||||
if (operator === 'in' || operator === '?=') {
|
||||
keywords = keyword.trim().split(',').map(k => k.trim())
|
||||
}
|
||||
|
||||
|
||||
keywords.forEach(k => {
|
||||
const labelId = labelResolver(k)
|
||||
if (labelId !== null) {
|
||||
filter = filter.replace(k, String(labelId))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
// Transform projects to ids
|
||||
PROJECT_FIELDS.forEach(field => {
|
||||
const pattern = getFilterFieldRegexPattern(field)
|
||||
|
||||
let match: RegExpExecArray | null
|
||||
while ((match = pattern.exec(filter)) !== null) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const [matched, prefix, operator, space, keyword] = match
|
||||
if (keyword) {
|
||||
let keywords = [keyword.trim()]
|
||||
if (operator === 'in' || operator === '?=') {
|
||||
keywords = keyword.trim().split(',').map(k => k.trim())
|
||||
}
|
||||
|
||||
let replaced = keyword
|
||||
|
||||
keywords.forEach(k => {
|
||||
const id = resolver(k)
|
||||
if (id !== null) {
|
||||
replaced = replaced.replace(k, String(id))
|
||||
const projectId = projectResolver(k)
|
||||
if (projectId !== null) {
|
||||
replaced = replaced.replace(k, String(projectId))
|
||||
}
|
||||
})
|
||||
|
||||
@@ -113,15 +128,8 @@ export function transformFilterStringForApi(
|
||||
replaced +
|
||||
filter.substring(actualKeywordStart + keyword.length)
|
||||
}
|
||||
})
|
||||
return filter
|
||||
}
|
||||
|
||||
// Transform labels to ids
|
||||
filter = transformFieldToIds(LABEL_FIELDS, labelResolver, filter)
|
||||
|
||||
// Transform projects to ids
|
||||
filter = transformFieldToIds(PROJECT_FIELDS, projectResolver, filter)
|
||||
}
|
||||
})
|
||||
|
||||
// Transform all attributes to snake case
|
||||
AVAILABLE_FILTER_FIELDS.forEach(f => {
|
||||
@@ -133,8 +141,8 @@ export function transformFilterStringForApi(
|
||||
|
||||
export function transformFilterStringFromApi(
|
||||
filter: string,
|
||||
labelResolver: (id: number) => string | null | undefined,
|
||||
projectResolver: (id: number) => string | null | undefined,
|
||||
labelResolver: (id: number) => string | null,
|
||||
projectResolver: (id: number) => string | null,
|
||||
): string {
|
||||
|
||||
if (filter.trim() === '') {
|
||||
@@ -146,40 +154,53 @@ export function transformFilterStringFromApi(
|
||||
filter = filter.replaceAll(snakeCase(f), f)
|
||||
})
|
||||
|
||||
// Function to transform fields to their titles
|
||||
function transformFieldsToTitles(
|
||||
fields: string[],
|
||||
resolver: (id: number) => string | null | undefined,
|
||||
) {
|
||||
fields.forEach(field => {
|
||||
const pattern = getFilterFieldRegexPattern(field)
|
||||
|
||||
let match: RegExpExecArray | null
|
||||
while ((match = pattern.exec(filter)) !== null) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const [matched, prefix, operator, space, keyword] = match
|
||||
if (keyword) {
|
||||
let keywords = [keyword.trim()]
|
||||
if (operator === 'in' || operator === '?=') {
|
||||
keywords = keyword.trim().split(',').map(k => k.trim())
|
||||
}
|
||||
|
||||
keywords.forEach(k => {
|
||||
const title = resolver(parseInt(k))
|
||||
if (title) {
|
||||
filter = filter.replace(k, title)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Transform labels to their titles
|
||||
transformFieldsToTitles(LABEL_FIELDS, labelResolver)
|
||||
LABEL_FIELDS.forEach(field => {
|
||||
const pattern = getFilterFieldRegexPattern(field)
|
||||
|
||||
// Transform projects to their titles
|
||||
transformFieldsToTitles(PROJECT_FIELDS, projectResolver)
|
||||
let match: RegExpExecArray | null
|
||||
while ((match = pattern.exec(filter)) !== null) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const [matched, prefix, operator, space, keyword] = match
|
||||
if (keyword) {
|
||||
let keywords = [keyword.trim()]
|
||||
if (operator === 'in' || operator === '?=') {
|
||||
keywords = keyword.trim().split(',').map(k => k.trim())
|
||||
}
|
||||
|
||||
keywords.forEach(k => {
|
||||
const labelTitle = labelResolver(parseInt(k))
|
||||
if (labelTitle !== null) {
|
||||
filter = filter.replace(k, labelTitle)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// Transform projects to ids
|
||||
PROJECT_FIELDS.forEach(field => {
|
||||
const pattern = getFilterFieldRegexPattern(field)
|
||||
|
||||
let match: RegExpExecArray | null
|
||||
while ((match = pattern.exec(filter)) !== null) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const [matched, prefix, operator, space, keyword] = match
|
||||
if (keyword) {
|
||||
let keywords = [keyword.trim()]
|
||||
if (operator === 'in' || operator === '?=') {
|
||||
keywords = keyword.trim().split(',').map(k => k.trim())
|
||||
}
|
||||
|
||||
keywords.forEach(k => {
|
||||
const project = projectResolver(parseInt(k))
|
||||
if (project !== null) {
|
||||
filter = filter.replace(k, project)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return filter
|
||||
}
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
export function validatePassword(password: string, validateMinLength: boolean = true): string | true {
|
||||
if (password === '') {
|
||||
return 'user.auth.passwordRequired'
|
||||
}
|
||||
|
||||
if (validateMinLength && password.length < 8) {
|
||||
return 'user.auth.passwordNotMin'
|
||||
}
|
||||
|
||||
if (validateMinLength && password.length > 72) {
|
||||
return 'user.auth.passwordNotMax'
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
@@ -25,7 +25,6 @@ export const SUPPORTED_LOCALES = {
|
||||
'pt-BR': 'Português Brasileiro',
|
||||
'hr-HR': 'Hrvatski',
|
||||
'uk-UA': 'Українська',
|
||||
'lt-LT': 'Lietuvių Kalba',
|
||||
// IMPORTANT: Also add new languages to useDayjsLanguageSync
|
||||
} as const
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
"usernameMustNotLookLikeUrl": "The username must not look like a URL.",
|
||||
"passwordRequired": "الرجاء إدخال كلمة المرور.",
|
||||
"passwordNotMin": "Password must have at least 8 characters.",
|
||||
"passwordNotMax": "Password must have at most 72 characters.",
|
||||
"passwordNotMax": "Password must have at most 250 characters.",
|
||||
"showPassword": "إظهار كلمة المرور",
|
||||
"hidePassword": "إخفاء كلمة المرور",
|
||||
"noAccountYet": "ليس لديك حساب بعد؟",
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
"usernameMustNotLookLikeUrl": "The username must not look like a URL.",
|
||||
"passwordRequired": "Please provide a password.",
|
||||
"passwordNotMin": "Password must have at least 8 characters.",
|
||||
"passwordNotMax": "Password must have at most 72 characters.",
|
||||
"passwordNotMax": "Password must have at most 250 characters.",
|
||||
"showPassword": "Show the password",
|
||||
"hidePassword": "Hide the password",
|
||||
"noAccountYet": "Don't have an account yet?",
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
"usernameMustNotLookLikeUrl": "Uživatelské jméno nesmí vypadat jako adresa URL.",
|
||||
"passwordRequired": "Zadejte prosím heslo.",
|
||||
"passwordNotMin": "Heslo musí mít nejméně 8 znaků.",
|
||||
"passwordNotMax": "Password must have at most 72 characters.",
|
||||
"passwordNotMax": "Heslo může mít maximálně 250 znaků.",
|
||||
"showPassword": "Ukázat heslo",
|
||||
"hidePassword": "Skrýt heslo",
|
||||
"noAccountYet": "Ještě nemáte účet?",
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
"usernameMustNotLookLikeUrl": "The username must not look like a URL.",
|
||||
"passwordRequired": "Angiv venligst en adgangskode.",
|
||||
"passwordNotMin": "Password must have at least 8 characters.",
|
||||
"passwordNotMax": "Password must have at most 72 characters.",
|
||||
"passwordNotMax": "Password must have at most 250 characters.",
|
||||
"showPassword": "Vis adgangskoden",
|
||||
"hidePassword": "Skjul adgangskoden",
|
||||
"noAccountYet": "Har du ikke en konto endnu?",
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
"usernameMustNotLookLikeUrl": "Der Anmeldename darf nicht wie eine URL aussehen.",
|
||||
"passwordRequired": "Bitte gib ein Passwort ein.",
|
||||
"passwordNotMin": "Das Passwort muss aus mindestens 8 Zeichen bestehen.",
|
||||
"passwordNotMax": "Das Passwort darf höchstens 72 Zeichen lang sein.",
|
||||
"passwordNotMax": "Das Passwort darf höchstens 250 Zeichen lang sein.",
|
||||
"showPassword": "Passwort anzeigen",
|
||||
"hidePassword": "Passwort verbergen",
|
||||
"noAccountYet": "Noch kein Account?",
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
"usernameMustNotLookLikeUrl": "Der Anmeldename darf nicht wie eine URL aussehen.",
|
||||
"passwordRequired": "Bitte gib ein Passwort ein.",
|
||||
"passwordNotMin": "Das Passwort muss aus mindestens 8 Zeichen bestehen.",
|
||||
"passwordNotMax": "Das Passwort darf höchstens 72 Zeichen lang sein.",
|
||||
"passwordNotMax": "Das Passwort darf höchstens 250 Zeichen lang sein.",
|
||||
"showPassword": "Passwort anzeigen",
|
||||
"hidePassword": "Passwort verbergen",
|
||||
"noAccountYet": "Noch kein Account?",
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
"usernameMustNotLookLikeUrl": "The username must not look like a URL.",
|
||||
"passwordRequired": "Please provide a password.",
|
||||
"passwordNotMin": "Password must have at least 8 characters.",
|
||||
"passwordNotMax": "Password must have at most 72 characters.",
|
||||
"passwordNotMax": "Password must have at most 250 characters.",
|
||||
"showPassword": "Show the password",
|
||||
"hidePassword": "Hide the password",
|
||||
"noAccountYet": "Don't have an account yet?",
|
||||
@@ -848,8 +848,7 @@
|
||||
"delete": "Delete this comment",
|
||||
"deleteText1": "Are you sure you want to delete this comment?",
|
||||
"deleteSuccess": "The comment was deleted successfully.",
|
||||
"addedSuccess": "The comment was added successfully.",
|
||||
"permalink": "Copy permalink to this comment"
|
||||
"addedSuccess": "The comment was added successfully."
|
||||
},
|
||||
"deferDueDate": {
|
||||
"title": "Defer due date",
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
"usernameMustNotLookLikeUrl": "The username must not look like a URL.",
|
||||
"passwordRequired": "Please provide a password.",
|
||||
"passwordNotMin": "Password must have at least 8 characters.",
|
||||
"passwordNotMax": "Password must have at most 72 characters.",
|
||||
"passwordNotMax": "Password must have at most 250 characters.",
|
||||
"showPassword": "Show the password",
|
||||
"hidePassword": "Hide the password",
|
||||
"noAccountYet": "Don't have an account yet?",
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
"usernameMustNotLookLikeUrl": "The username must not look like a URL.",
|
||||
"passwordRequired": "Por favor, proporciona una contraseña.",
|
||||
"passwordNotMin": "Password must have at least 8 characters.",
|
||||
"passwordNotMax": "Password must have at most 72 characters.",
|
||||
"passwordNotMax": "Password must have at most 250 characters.",
|
||||
"showPassword": "Mostrar la contraseña",
|
||||
"hidePassword": "Ocultar la contraseña",
|
||||
"noAccountYet": "¿Aún no tienes una cuenta?",
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
"usernameMustNotLookLikeUrl": "The username must not look like a URL.",
|
||||
"passwordRequired": "Veuillez fournir un mot de passe.",
|
||||
"passwordNotMin": "Password must have at least 8 characters.",
|
||||
"passwordNotMax": "Password must have at most 72 characters.",
|
||||
"passwordNotMax": "Password must have at most 250 characters.",
|
||||
"showPassword": "Afficher le mot de passe",
|
||||
"hidePassword": "Masquer le mot de passe",
|
||||
"noAccountYet": "Vous n'avez pas encore de compte ?",
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
"usernameMustNotLookLikeUrl": "Korisničko ime ne smije izgledati kao URL.",
|
||||
"passwordRequired": "Molimo upišite lozinku.",
|
||||
"passwordNotMin": "Lozinka treba imati barem 8 znakova.",
|
||||
"passwordNotMax": "Password must have at most 72 characters.",
|
||||
"passwordNotMax": "Lozinka treba imati barem 250 znakova.",
|
||||
"showPassword": "Prikaži lozinku",
|
||||
"hidePassword": "Sakrij lozinku",
|
||||
"noAccountYet": "Još nemate račun?",
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
"usernameMustNotLookLikeUrl": "A felhasználónév nem nézhet ki URL-nek.",
|
||||
"passwordRequired": "Kérjük, adjon meg új jelszót.",
|
||||
"passwordNotMin": "A jelszónak legalább 8 karakterből kell állnia.",
|
||||
"passwordNotMax": "Password must have at most 72 characters.",
|
||||
"passwordNotMax": "A jelszó legfeljebb 250 karakterből állhat.",
|
||||
"showPassword": "Jelszó megjelenítése",
|
||||
"hidePassword": "A jelszó elrejtése",
|
||||
"noAccountYet": "Még nincs fiókja?",
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
"usernameMustNotLookLikeUrl": "The username must not look like a URL.",
|
||||
"passwordRequired": "Inserisci una password.",
|
||||
"passwordNotMin": "Password must have at least 8 characters.",
|
||||
"passwordNotMax": "Password must have at most 72 characters.",
|
||||
"passwordNotMax": "Password must have at most 250 characters.",
|
||||
"showPassword": "Mostra la password",
|
||||
"hidePassword": "Nascondi la password",
|
||||
"noAccountYet": "Non hai un account?",
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
"usernameMustNotLookLikeUrl": "The username must not look like a URL.",
|
||||
"passwordRequired": "パスワードを入力してください。",
|
||||
"passwordNotMin": "パスワードは8文字以上でなければなりません。",
|
||||
"passwordNotMax": "Password must have at most 72 characters.",
|
||||
"passwordNotMax": "パスワードは250文字以内でなければなりません。",
|
||||
"showPassword": "パスワードの表示",
|
||||
"hidePassword": "パスワードの非表示",
|
||||
"noAccountYet": "まだアカウントをお持ちでないですか?",
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
"usernameMustNotLookLikeUrl": "The username must not look like a URL.",
|
||||
"passwordRequired": "비밀번호를 입력하세요.",
|
||||
"passwordNotMin": "Password must have at least 8 characters.",
|
||||
"passwordNotMax": "Password must have at most 72 characters.",
|
||||
"passwordNotMax": "Password must have at most 250 characters.",
|
||||
"showPassword": "비밀번호 표시",
|
||||
"hidePassword": "비밀번호 숨김",
|
||||
"noAccountYet": "아직 계정이 없으신가요?",
|
||||
|
||||
+233
-233
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"home": {
|
||||
"welcomeNight": "Labanaktis {username}!",
|
||||
"welcomeMorning": "Labas rytas {username}!",
|
||||
"welcomeDay": "Labas {username}!",
|
||||
"welcomeEvening": "Labas vakaras {username}!",
|
||||
"welcomeNight": "Good Night {username}!",
|
||||
"welcomeMorning": "Good Morning {username}!",
|
||||
"welcomeDay": "Hi {username}!",
|
||||
"welcomeEvening": "Good Evening {username}!",
|
||||
"lastViewed": "Last viewed",
|
||||
"addToHomeScreen": "Add this app to your home screen for faster access and improved experience.",
|
||||
"goToOverview": "Go to overview",
|
||||
@@ -33,9 +33,9 @@
|
||||
},
|
||||
"user": {
|
||||
"auth": {
|
||||
"username": "Vartotojo vardas",
|
||||
"usernameEmail": "Vartotojo vardas arba el. pašto adresas",
|
||||
"usernamePlaceholder": "pvz.: frederick",
|
||||
"username": "Username",
|
||||
"usernameEmail": "Username Or Email Address",
|
||||
"usernamePlaceholder": "e.g. frederick",
|
||||
"email": "Email address",
|
||||
"emailPlaceholder": "e.g. frederic{'@'}vikunja.io",
|
||||
"password": "Password",
|
||||
@@ -56,12 +56,12 @@
|
||||
"openIdGeneralError": "An error occurred while authenticating against the third party.",
|
||||
"logout": "Logout",
|
||||
"emailInvalid": "Please enter a valid email address.",
|
||||
"usernameRequired": "Prašau nurodyti vartotojo vardą.",
|
||||
"usernameMustNotContainSpace": "Vartotojo vardas negali turėti tarpų.",
|
||||
"usernameMustNotLookLikeUrl": "Vartotojo vardas negali atrodyti kaip nuoroda.",
|
||||
"usernameRequired": "Please provide a username.",
|
||||
"usernameMustNotContainSpace": "The username must not contain spaces.",
|
||||
"usernameMustNotLookLikeUrl": "The username must not look like a URL.",
|
||||
"passwordRequired": "Please provide a password.",
|
||||
"passwordNotMin": "Password must have at least 8 characters.",
|
||||
"passwordNotMax": "Password must have at most 72 characters.",
|
||||
"passwordNotMax": "Password must have at most 250 characters.",
|
||||
"showPassword": "Show the password",
|
||||
"hidePassword": "Hide the password",
|
||||
"noAccountYet": "Don't have an account yet?",
|
||||
@@ -83,12 +83,12 @@
|
||||
"updateEmailSuccess": "Your email address was successfully updated. We've sent you a link to confirm it.",
|
||||
"general": {
|
||||
"title": "General Settings",
|
||||
"name": "Mano vardas",
|
||||
"newName": "Naujas vardas",
|
||||
"name": "My Name",
|
||||
"newName": "The new name",
|
||||
"savedSuccess": "The settings were successfully updated.",
|
||||
"emailReminders": "Send me reminders for tasks via email",
|
||||
"overdueReminders": "Send me a summary of my undone overdue tasks every day",
|
||||
"discoverableByName": "Leisti kitiems vartotojas mane pridėti prie komandų ar projektų radus mano vardą paieškoje",
|
||||
"discoverableByName": "Allow other users to add me as a member to teams or projects when they search for my name",
|
||||
"discoverableByEmail": "Allow other users to add me as a member to teams or projects when they search for my full email",
|
||||
"playSoundWhenDone": "Play a sound when marking tasks as done",
|
||||
"weekStart": "Week starts on",
|
||||
@@ -99,7 +99,7 @@
|
||||
"defaultView": "Default view",
|
||||
"timezone": "Time zone",
|
||||
"overdueTasksRemindersTime": "Overdue tasks reminder email time",
|
||||
"filterUsedOnOverview": "Išsaugotas filtras naudojamas apžvalgos puslapyje"
|
||||
"filterUsedOnOverview": "Saved filter used on the overview page"
|
||||
},
|
||||
"totp": {
|
||||
"title": "Two Factor Authentication",
|
||||
@@ -121,11 +121,11 @@
|
||||
"more": "More information about CalDAV in Vikunja",
|
||||
"tokens": "CalDAV Tokens",
|
||||
"tokensHowTo": "You can use a CalDAV token to use instead of a password to log in the above endpoint.",
|
||||
"createToken": "Sukurti prieigos raktą",
|
||||
"createToken": "Create a token",
|
||||
"tokenCreated": "Here is your token: {token}",
|
||||
"wontSeeItAgain": "Write it down, you won't be able to see it again.",
|
||||
"mustUseToken": "You need to create a CalDAV token if you want to use CalDAV with a third party client. Use the token as the password.",
|
||||
"usernameIs": "Tavo vartotojo vardas yra: {0}"
|
||||
"usernameIs": "Your username is: {0}"
|
||||
},
|
||||
"avatar": {
|
||||
"title": "Avatar",
|
||||
@@ -167,14 +167,14 @@
|
||||
"expired": "This token has expired {ago}.",
|
||||
"tokenCreatedSuccess": "Here is your new api token: {token}",
|
||||
"tokenCreatedNotSeeAgain": "Store it in a secure location, you won't see it again!",
|
||||
"selectAll": "Pažymėti viską",
|
||||
"selectAll": "Select all",
|
||||
"delete": {
|
||||
"header": "Delete this token",
|
||||
"text1": "Are you sure you want to delete the token \"{token}\"?",
|
||||
"text2": "This will revoke access to all applications or integrations using it. You cannot undo this."
|
||||
},
|
||||
"attributes": {
|
||||
"title": "Pavadinimas",
|
||||
"title": "Title",
|
||||
"titlePlaceholder": "Enter a title you will recognize later",
|
||||
"expiresAt": "Expires at",
|
||||
"permissions": "Permissions"
|
||||
@@ -184,22 +184,22 @@
|
||||
"deletion": {
|
||||
"title": "Delete your Vikunja Account",
|
||||
"text1": "The deletion of your account is permanent and cannot be undone. We will delete all your projects, tasks and everything associated with it.",
|
||||
"text2": "Norėdama -s tęsti, įvesk savo slaptažodį. Gausi email'ą su tolimesnėmis instrukcijomis.",
|
||||
"text2": "To proceed, please enter your password. You will receive an email with further instructions.",
|
||||
"text3": "To proceed, please press the button below. You will receive an email with further instructions.",
|
||||
"confirm": "Delete my account",
|
||||
"requestSuccess": "Tavo užklausa sėkminga. Gausi email'ą su tolimesnėmis instrukcijomis.",
|
||||
"passwordRequired": "Prašome įvesti savo slaptažodį.",
|
||||
"requestSuccess": "The request was successful. You'll receive an email with further instructions.",
|
||||
"passwordRequired": "Please enter your password.",
|
||||
"confirmSuccess": "You've successfully confirmed the deletion of your account. We will delete your account in three days.",
|
||||
"scheduled": "We will delete your Vikunja account at {date} ({dateSince}).",
|
||||
"scheduledCancel": "Norėdama -s nutraukti paskyros ištrynimą, spausk čia.",
|
||||
"scheduledCancelText": "Norėdama -s nutraukti paskyros ištrynimą, įveskite slaptažodį žemiau:",
|
||||
"scheduledCancel": "To cancel the deletion of your account, click here.",
|
||||
"scheduledCancelText": "To cancel the deletion of your account, please enter your password below:",
|
||||
"scheduledCancelButton": "To cancel the deletion of your account, please press the button below:",
|
||||
"scheduledCancelConfirm": "Atšaukti mano paskyros ištrynimą",
|
||||
"scheduledCancelConfirm": "Cancel the deletion of my account",
|
||||
"scheduledCancelSuccess": "We will not delete your account."
|
||||
},
|
||||
"export": {
|
||||
"title": "Export your Vikunja data",
|
||||
"description": "Tu gali prašyti gauti visus Vikunja duomenis. Į tai įeina, Projektai, Užduotys ir viskas, kas su jais susiję. Tu gali savo duomenis vėliau įkelti į bet kurią Vikunja aplinką naudojantis migracijos funkcija.",
|
||||
"description": "You can request a copy of all your Vikunja data. This includes Projects, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.",
|
||||
"descriptionPasswordRequired": "Please enter your password to proceed:",
|
||||
"request": "Request a copy of my Vikunja Data",
|
||||
"success": "You've successfully requested your Vikunja Data! We will send you an email once it's ready to download.",
|
||||
@@ -256,7 +256,7 @@
|
||||
},
|
||||
"duplicate": {
|
||||
"title": "Duplicate this project",
|
||||
"label": "Dubliuoti",
|
||||
"label": "Duplicate",
|
||||
"text": "Select a parent project which should hold the duplicated project:",
|
||||
"success": "The project was successfully duplicated."
|
||||
},
|
||||
@@ -265,9 +265,9 @@
|
||||
"title": "Edit \"{project}\"",
|
||||
"titlePlaceholder": "The project title goes here…",
|
||||
"identifierTooltip": "The project identifier can be used to uniquely identify a task across projects. You can set it to empty to disable it.",
|
||||
"identifier": "Projekto identifikatorius",
|
||||
"identifierPlaceholder": "Projekto identifikatorius bus čia…",
|
||||
"description": "Aprašymas",
|
||||
"identifier": "Project Identifier",
|
||||
"identifierPlaceholder": "The project identifier goes here…",
|
||||
"description": "Description",
|
||||
"descriptionPlaceholder": "Enter a description for this project, hit '/' for more options…",
|
||||
"color": "Color",
|
||||
"success": "The project was successfully updated."
|
||||
@@ -281,23 +281,23 @@
|
||||
"what": "What is a share link?",
|
||||
"explanation": "Share Links allow you to easily share a project with other users who don't have an account on Vikunja.",
|
||||
"create": "Create a link share",
|
||||
"name": "Vardas (pasirinktinai)",
|
||||
"namePlaceholder": "pvz.: Lorem Ipsum",
|
||||
"nameExplanation": "Visi veiksmai atlikti po pasidalinta nuoroda matysis šiuo pavadinimu.",
|
||||
"password": "Slaptažodis (pasirinktinai)",
|
||||
"passwordExplanation": "Prisijungiant, vartotojas privalės įvesti savo slaptažodį.",
|
||||
"noName": "Vardas nenustatytas",
|
||||
"remove": "Pašalinti pasidalinimo nuorodą",
|
||||
"name": "Name (optional)",
|
||||
"namePlaceholder": "e.g. Lorem Ipsum",
|
||||
"nameExplanation": "All actions done by this link share will show up with the name.",
|
||||
"password": "Password (optional)",
|
||||
"passwordExplanation": "When signing in, the user will be required to enter this password.",
|
||||
"noName": "No name set",
|
||||
"remove": "Remove a link share",
|
||||
"removeText": "Are you sure you want to remove this link share? It will no longer be possible to access this project with this link share. This cannot be undone!",
|
||||
"createSuccess": "Pasidalinimo nuoroda buvo sėkmingai sukurta.",
|
||||
"createSuccess": "The link share was successfully created.",
|
||||
"deleteSuccess": "The link share was successfully deleted",
|
||||
"view": "Peržiūra",
|
||||
"sharedBy": "Pasidalino {0}"
|
||||
"view": "View",
|
||||
"sharedBy": "Shared by {0}"
|
||||
},
|
||||
"userTeam": {
|
||||
"typeUser": "vartotojas | vartotojai",
|
||||
"typeTeam": "komanda | komandos",
|
||||
"shared": "Pasidalinta su šiais {type}",
|
||||
"typeUser": "user | users",
|
||||
"typeTeam": "team | teams",
|
||||
"shared": "Shared with these {type}",
|
||||
"you": "You",
|
||||
"notShared": "Not shared with any {type} yet.",
|
||||
"removeHeader": "Remove a {type} from the {sharable}",
|
||||
@@ -332,11 +332,11 @@
|
||||
"title": "Gantt",
|
||||
"size": "Size",
|
||||
"default": "Default",
|
||||
"month": "Mėnuo",
|
||||
"day": "Diena",
|
||||
"hour": "Valanda",
|
||||
"month": "Month",
|
||||
"day": "Day",
|
||||
"hour": "Hour",
|
||||
"range": "Date Range",
|
||||
"noDates": "Ši užduotis dar neturi nurodytos datos."
|
||||
"noDates": "This task has no dates set."
|
||||
},
|
||||
"table": {
|
||||
"title": "Table",
|
||||
@@ -373,113 +373,113 @@
|
||||
}
|
||||
},
|
||||
"webhooks": {
|
||||
"title": "„Webhook“'ai",
|
||||
"targetUrl": "Tikslinė nuoroda",
|
||||
"targetUrlInvalid": "Prašome nurodyti veikiančia nuorodą.",
|
||||
"events": "Įvykiai",
|
||||
"title": "Webhooks",
|
||||
"targetUrl": "Target URL",
|
||||
"targetUrlInvalid": "Please provide a valid URL.",
|
||||
"events": "Events",
|
||||
"eventsHint": "Select all events this webhook should recieve updates for (within the current project).",
|
||||
"mustSelectEvents": "Turi pasirinkti bent vieną įvykį.",
|
||||
"delete": "Ištrinti šį webhook'ą",
|
||||
"mustSelectEvents": "You must select at least one event.",
|
||||
"delete": "Delete this webhook",
|
||||
"deleteText": "Are you sure you want to delete this webhook? External targets will not be notified of its events anymore.",
|
||||
"deleteSuccess": "Webhook'as buvo sėkmingai ištrintas.",
|
||||
"create": "Sukurti ryšį",
|
||||
"secret": "Paslaptis",
|
||||
"deleteSuccess": "The webhook was successfully deleted.",
|
||||
"create": "Create webhook",
|
||||
"secret": "Secret",
|
||||
"secretHint": "If provided, all requests to the webhook target URL will be signed using HMAC.",
|
||||
"secretDocs": "Check out the docs for more details about how to use secrets."
|
||||
},
|
||||
"views": {
|
||||
"header": "Keisti vaizdo nustatymus",
|
||||
"header": "Edit views",
|
||||
"title": "Title",
|
||||
"actions": "Actions",
|
||||
"kind": "Kind",
|
||||
"bucketConfigMode": "Bucket configuration mode",
|
||||
"bucketConfig": "Telkinio konfigūracija",
|
||||
"bucketConfig": "Bucket configuration",
|
||||
"bucketConfigManual": "Manual",
|
||||
"filter": "Filtras",
|
||||
"create": "Sukurti atvaizdavimą",
|
||||
"createSuccess": "Atvaizdavimas buvo sėkmingai sukurtas.",
|
||||
"filter": "Filter",
|
||||
"create": "Create view",
|
||||
"createSuccess": "The view was created successfully.",
|
||||
"titleRequired": "Please provide a title.",
|
||||
"delete": "Ištrinti šį atvaizdavimą",
|
||||
"delete": "Delete this view",
|
||||
"deleteText": "Are you sure you want to remove this view? It will no longer be possible to use it to view tasks in this project. This action won't delete any tasks. This cannot be undone!",
|
||||
"deleteSuccess": "The view was deleted successfully.",
|
||||
"onlyAdminsCanEdit": "Tik projekto administratoriai gali keisti atvaizdavimą.",
|
||||
"updateSuccess": "Atvaizdavimas buvo sėkmingai atnaujintas."
|
||||
"onlyAdminsCanEdit": "Only project admins can edit views.",
|
||||
"updateSuccess": "The view was updated successfully."
|
||||
}
|
||||
},
|
||||
"filters": {
|
||||
"title": "Filtrai",
|
||||
"clear": "Anuliuoti filtrus",
|
||||
"showResults": "Rodyti rezultatus",
|
||||
"title": "Filters",
|
||||
"clear": "Clear Filters",
|
||||
"showResults": "Show results",
|
||||
"attributes": {
|
||||
"title": "Pavadinimas",
|
||||
"titlePlaceholder": "Išsaugoto filtro pavadinimas rašomas čia…",
|
||||
"description": "Aprašymas",
|
||||
"descriptionPlaceholder": "Įvesti filtro aprašymą, spausti '/' norint gauti daugiau pasirinkčių…",
|
||||
"includeNulls": "Įtraukti Užduotis, kurioms nenurodytos vertės",
|
||||
"requireAll": "Reikalauti, kad visi filtrai būtų tikri, kad užduotys būtų rodomos",
|
||||
"showDoneTasks": "Rodyti užbaigtas užduotis",
|
||||
"sortAlphabetically": "Rūšiuoti alfabetiškai",
|
||||
"enablePriority": "Įgalinti filtrą pagal prioritetą",
|
||||
"enablePercentDone": "Įgalinti filtrą pagal progresą",
|
||||
"dueDateRange": "Termino datos rėžis",
|
||||
"startDateRange": "Pradžios datos rėžis",
|
||||
"endDateRange": "Pabaigos datos rėžis",
|
||||
"reminderRange": "Priminimo datos rėžis"
|
||||
"title": "Title",
|
||||
"titlePlaceholder": "The saved filter title goes here…",
|
||||
"description": "Description",
|
||||
"descriptionPlaceholder": "Add a description for this filter here, hit '/' for more options…",
|
||||
"includeNulls": "Include Tasks which don't have a value set",
|
||||
"requireAll": "Require all filters to be true for a task to show up",
|
||||
"showDoneTasks": "Show Done Tasks",
|
||||
"sortAlphabetically": "Sort Alphabetically",
|
||||
"enablePriority": "Enable Filter By Priority",
|
||||
"enablePercentDone": "Enable Filter By Progress",
|
||||
"dueDateRange": "Due Date Range",
|
||||
"startDateRange": "Start Date Range",
|
||||
"endDateRange": "End Date Range",
|
||||
"reminderRange": "Reminder Date Range"
|
||||
},
|
||||
"create": {
|
||||
"title": "Naujas išsaugotas filtras",
|
||||
"description": "Išsaugotas filtras yra virtualus projektas, kuris yra generuojamas iš pasirinktų filtrų, kiekvieną kartą jį paleidžiant.",
|
||||
"action": "Sukurti išsaugotą filtrą",
|
||||
"titleRequired": "Prašome nurodyti filtro pavadinimą."
|
||||
"title": "New Saved Filter",
|
||||
"description": "A saved filter is a virtual project which is computed from a set of filters each time it is accessed.",
|
||||
"action": "Create saved filter",
|
||||
"titleRequired": "Please provide a title for the filter."
|
||||
},
|
||||
"delete": {
|
||||
"header": "Ištrinti šį užsaugotą filtrą",
|
||||
"text": "Ar esi tikra-s, kad nori ištrinti išsaugotą filtrą?",
|
||||
"success": "Filtras ištrintas sėkmingai."
|
||||
"header": "Delete this saved filter",
|
||||
"text": "Are you sure you want to delete this saved filter?",
|
||||
"success": "The filter was deleted successfully."
|
||||
},
|
||||
"edit": {
|
||||
"title": "Keisti šį išsaugotą filtrą",
|
||||
"success": "Filtras išsaugotas sėkmingai."
|
||||
"title": "Edit This Saved Filter",
|
||||
"success": "The filter was saved successfully."
|
||||
},
|
||||
"query": {
|
||||
"title": "Užklausa",
|
||||
"placeholder": "Ieškokite ar filtruokita užklausą…",
|
||||
"title": "Query",
|
||||
"placeholder": "Type a search or filter query…",
|
||||
"help": {
|
||||
"intro": "Norėdami filtruoti užduotis, galite naudoti sintaksę panašią į SQL. Galimi filtravimo laukai įtraukia:",
|
||||
"link": "Kaip tai veikia?",
|
||||
"intro": "To filter tasks, you can use a query syntax similar to SQL. The available fields for filtering include:",
|
||||
"link": "How does this work?",
|
||||
"canUseDatemath": "You can date math to set relative dates. Click on the date value in a query to find out more.",
|
||||
"fields": {
|
||||
"done": "Ar užduotis atlikta ar ne",
|
||||
"priority": "Užduoties prioriteto lygis (1-5)",
|
||||
"percentDone": "Užduoties baigtumo lygis (0-100)",
|
||||
"dueDate": "Užduoties termino data",
|
||||
"startDate": "Užduoties pradžios data",
|
||||
"endDate": "Užduoties pabaigos data",
|
||||
"doneAt": "Data ir laikas, kada užduotis buvo atlikta",
|
||||
"assignees": "Užduočiai priskirti vartotojai",
|
||||
"labels": "Etiketės sietinos su užduotimi",
|
||||
"done": "Whether the task is completed or not",
|
||||
"priority": "The priority level of the task (1-5)",
|
||||
"percentDone": "The percentage of completion for the task (0-100)",
|
||||
"dueDate": "The due date of the task",
|
||||
"startDate": "The start date of the task",
|
||||
"endDate": "The end date of the task",
|
||||
"doneAt": "The date and time when the task was completed",
|
||||
"assignees": "The assignees of the task",
|
||||
"labels": "The labels associated with the task",
|
||||
"project": "The project the task belongs to (only available for saved filters, not on a project level)"
|
||||
},
|
||||
"operators": {
|
||||
"intro": "The available operators for filtering include:",
|
||||
"notEqual": "Ne lygu",
|
||||
"equal": "Lygu",
|
||||
"greaterThan": "Daugiau už",
|
||||
"greaterThanOrEqual": "Daugiau už ar lygu",
|
||||
"lessThan": "Mažiau nei",
|
||||
"lessThanOrEqual": "Mažiau negu ar lygu",
|
||||
"like": "Atitinka šabloną (nadojama wildcard %)",
|
||||
"notEqual": "Not equal to",
|
||||
"equal": "Equal to",
|
||||
"greaterThan": "Greater than",
|
||||
"greaterThanOrEqual": "Greater than or equal to",
|
||||
"lessThan": "Less than",
|
||||
"lessThanOrEqual": "Less than or equal to",
|
||||
"like": "Matches a pattern (using wildcard %)",
|
||||
"in": "Matches any value in a comma-seperated list of values"
|
||||
},
|
||||
"logicalOperators": {
|
||||
"intro": "To combine multiple conditions, you can use the following logical operators:",
|
||||
"and": "AND operator, matches if all conditions are true",
|
||||
"or": "OR operator, matches if any of the conditions are true",
|
||||
"parentheses": "Skliausteliai sąlygų grupavimui"
|
||||
"parentheses": "Parentheses for grouping conditions"
|
||||
},
|
||||
"examples": {
|
||||
"intro": "Čia pateikiami keli filtravimo užklausos pavyzdžiai:",
|
||||
"priorityEqual": "Atitinka užduotis su 4 lygio prioritetu",
|
||||
"intro": "Here are some examples of filter queries:",
|
||||
"priorityEqual": "Matches tasks with priority level 4",
|
||||
"dueDatePast": "Matches tasks with a due date in the past",
|
||||
"undoneHighPriority": "Matches undone tasks with priority level 3 or higher",
|
||||
"assigneesIn": "Matches tasks assigned to either \"user1\" or \"user2\"",
|
||||
@@ -490,69 +490,69 @@
|
||||
},
|
||||
"migrate": {
|
||||
"title": "Import from other services",
|
||||
"titleService": "Importuoti duomenis iš {name} į Vikunja",
|
||||
"titleService": "Import your data from {name} into Vikunja",
|
||||
"import": "Import your data into Vikunja",
|
||||
"description": "Paspauskite ant trečiosios šalies logotipo norint pradėti.",
|
||||
"descriptionDo": "Vikunja importuos visus sąrašus, užduotis, užrašus, priminimus ir dokumentus prie kurių tu turi prieigą.",
|
||||
"authorize": "Autorizuoti Vikunja prieigą prie tavo {name} paskyros, spauskite mygtuką žemiau.",
|
||||
"getStarted": "Pradėti",
|
||||
"inProgress": "Importavimas progrese…",
|
||||
"alreadyMigrated1": "Atrodo, kad jau importavai savo info is {name} {date}.",
|
||||
"description": "Click on the logo of one of the third-party services below to get started.",
|
||||
"descriptionDo": "Vikunja will import all lists, tasks, notes, reminders and files you have access to.",
|
||||
"authorize": "To authorize Vikunja to access your {name} Account, click the button below.",
|
||||
"getStarted": "Get Started",
|
||||
"inProgress": "Importing in progress…",
|
||||
"alreadyMigrated1": "It looks like you've already imported your stuff from {name} at {date}.",
|
||||
"alreadyMigrated2": "Importing again is possible, but might create duplicates. Are you sure?",
|
||||
"confirm": "I am sure, please start migrating now!",
|
||||
"importUpload": "Importuoti duomenis iš {name} į Vikunja, spausk mygtuką žemiau, norėdamas pasirinkti failą.",
|
||||
"upload": "Įkelti failą",
|
||||
"importUpload": "To import data from {name} into Vikunja, click the button below to select a file.",
|
||||
"upload": "Upload file",
|
||||
"migrationStartedWillReciveEmail": "Vikunja will now import your lists/projects, tasks, notes, reminders and files from {service}. As this will take a while, we will send you an email once done. You can close this window now.",
|
||||
"migrationInProgress": "A migration is currently in progress. Please wait until it is done."
|
||||
},
|
||||
"label": {
|
||||
"title": "Etiketės",
|
||||
"manage": "Tvarkyti etiketes",
|
||||
"description": "Paspausk ant etiketės norėdamas ją redaguoti. Tu gali keisti etiketes, kurias pats sukūrei, tu gali naudoti visas etiketes, kurios yra susietos su užduotimis, projektų, prie kurių tu turi prieigą.",
|
||||
"newCTA": "Šiuo metu nėra jokių etikečių.",
|
||||
"search": "Rašykite čia norėdami ieškoti etikečių…",
|
||||
"title": "Labels",
|
||||
"manage": "Manage labels",
|
||||
"description": "Click on a label to edit it. You can edit all labels you created, you can use all labels which are associated with a task to whose project you have access.",
|
||||
"newCTA": "You currently do not have any labels.",
|
||||
"search": "Type to search for a label…",
|
||||
"create": {
|
||||
"header": "Nauja etiketė",
|
||||
"title": "Sukurti etiketę",
|
||||
"titleRequired": "Prašau nurodyti pavadinimą.",
|
||||
"success": "Etiketė buvo sėkmingai sukurta."
|
||||
"header": "New label",
|
||||
"title": "Create a label",
|
||||
"titleRequired": "Please specify a title.",
|
||||
"success": "The label was successfully created."
|
||||
},
|
||||
"edit": {
|
||||
"header": "Redaguoti etiketę",
|
||||
"forbidden": "Tau neleidžiama redaguoti šios etiketės, kadangi ji tau nepriklauso.",
|
||||
"success": "Etiketė buvo sėkmingai atnaujinta."
|
||||
"header": "Edit Label",
|
||||
"forbidden": "You are not allowed to edit this label because you don't own it.",
|
||||
"success": "The label was successfully updated."
|
||||
},
|
||||
"deleteSuccess": "Etiketė buvo sėkmingai ištrinta.",
|
||||
"deleteSuccess": "The label was successfully deleted.",
|
||||
"attributes": {
|
||||
"title": "Pavadinimas",
|
||||
"titlePlaceholder": "Etiketės pavadinimas rašomas čia…",
|
||||
"description": "Aprašymas",
|
||||
"descriptionPlaceholder": "Etiketės aprašas",
|
||||
"color": "Spalva"
|
||||
"title": "Title",
|
||||
"titlePlaceholder": "The label title goes here…",
|
||||
"description": "Description",
|
||||
"descriptionPlaceholder": "Label description",
|
||||
"color": "Color"
|
||||
}
|
||||
},
|
||||
"sharing": {
|
||||
"authenticating": "Authenticating…",
|
||||
"passwordRequired": "Šis pasidalintas projektas reikalauja slaptažodžio. Įveskite jį žemiau:",
|
||||
"passwordRequired": "This shared project requires a password. Please enter it below:",
|
||||
"error": "An error occurred.",
|
||||
"invalidPassword": "Slaptažodis neteisingas."
|
||||
"invalidPassword": "The password is invalid."
|
||||
},
|
||||
"navigation": {
|
||||
"overview": "Apžvalga",
|
||||
"overview": "Overview",
|
||||
"upcoming": "Upcoming",
|
||||
"settings": "Nustatymai",
|
||||
"settings": "Settings",
|
||||
"imprint": "Imprint",
|
||||
"privacy": "Privacy Policy"
|
||||
},
|
||||
"misc": {
|
||||
"loading": "Kraunama…",
|
||||
"save": "Išsaugoti",
|
||||
"delete": "Ištrinti",
|
||||
"confirm": "Patvirtinti",
|
||||
"cancel": "Atšaukti",
|
||||
"refresh": "Atnaujinti",
|
||||
"disable": "Išjungti",
|
||||
"copy": "Kopijuoti į iškarpinę",
|
||||
"loading": "Loading…",
|
||||
"save": "Save",
|
||||
"delete": "Delete",
|
||||
"confirm": "Confirm",
|
||||
"cancel": "Cancel",
|
||||
"refresh": "Refresh",
|
||||
"disable": "Disable",
|
||||
"copy": "Copy to clipboard",
|
||||
"copyError": "Copy to clipboard failed",
|
||||
"search": "Search",
|
||||
"searchPlaceholder": "Type to search…",
|
||||
@@ -565,33 +565,33 @@
|
||||
"saving": "Saving…",
|
||||
"saved": "Saved!",
|
||||
"default": "Default",
|
||||
"close": "Uždaryti",
|
||||
"download": "Atsisiųsti",
|
||||
"showMenu": "Rodyti meniu",
|
||||
"hideMenu": "Paslėpti meniu",
|
||||
"forExample": "Pavyzdžiui:",
|
||||
"welcomeBack": "Sveiki sugrįžę!",
|
||||
"custom": "Pasirinktinai",
|
||||
"close": "Close",
|
||||
"download": "Download",
|
||||
"showMenu": "Show the menu",
|
||||
"hideMenu": "Hide the menu",
|
||||
"forExample": "For example:",
|
||||
"welcomeBack": "Welcome Back!",
|
||||
"custom": "Custom",
|
||||
"id": "ID",
|
||||
"created": "Sukurta",
|
||||
"createdBy": "Sukurta {0}",
|
||||
"actions": "Veiksmai",
|
||||
"cannotBeUndone": "Atšaukti negalėsite!"
|
||||
"created": "Created at",
|
||||
"createdBy": "Created by {0}",
|
||||
"actions": "Actions",
|
||||
"cannotBeUndone": "This cannot be undone!"
|
||||
},
|
||||
"input": {
|
||||
"resetColor": "Atstatyti spalvas",
|
||||
"resetColor": "Reset Color",
|
||||
"datepicker": {
|
||||
"today": "Šiandien",
|
||||
"tomorrow": "Rytoj",
|
||||
"nextMonday": "Kitą pirmadienį",
|
||||
"thisWeekend": "Šį savaitgalį",
|
||||
"laterThisWeek": "Vėliau šią savaitę",
|
||||
"nextWeek": "Kitą savaitę",
|
||||
"today": "Today",
|
||||
"tomorrow": "Tomorrow",
|
||||
"nextMonday": "Next Monday",
|
||||
"thisWeekend": "This Weekend",
|
||||
"laterThisWeek": "Later This Week",
|
||||
"nextWeek": "Next Week",
|
||||
"chooseDate": "Choose a date"
|
||||
},
|
||||
"editor": {
|
||||
"edit": "Edit",
|
||||
"done": "Atlikta",
|
||||
"done": "Done",
|
||||
"heading1": "Heading 1",
|
||||
"heading1Tooltip": "Big section heading.",
|
||||
"heading2": "Heading 2",
|
||||
@@ -772,9 +772,9 @@
|
||||
},
|
||||
"actions": {
|
||||
"assign": "Assign to User",
|
||||
"label": "Pridėti etiketes",
|
||||
"priority": "Nustatyti prioritetą",
|
||||
"dueDate": "Nustatyto termino datą",
|
||||
"label": "Add Labels",
|
||||
"priority": "Set Priority",
|
||||
"dueDate": "Set Due Date",
|
||||
"startDate": "Set Start Date",
|
||||
"endDate": "Set End Date",
|
||||
"reminders": "Set Reminders",
|
||||
@@ -783,9 +783,9 @@
|
||||
"attachments": "Add Attachments",
|
||||
"relatedTasks": "Add Relation",
|
||||
"moveProject": "Move",
|
||||
"color": "Nustatyto spalvą",
|
||||
"delete": "Ištrinti",
|
||||
"favorite": "Pridėti prie mėgstamiausių",
|
||||
"color": "Set Color",
|
||||
"delete": "Delete",
|
||||
"favorite": "Add to Favorites",
|
||||
"unfavorite": "Remove from Favorites"
|
||||
}
|
||||
},
|
||||
@@ -798,7 +798,7 @@
|
||||
"done": "Done",
|
||||
"dueDate": "Due Date",
|
||||
"endDate": "End Date",
|
||||
"labels": "Etiketės",
|
||||
"labels": "Labels",
|
||||
"percentDone": "Progress",
|
||||
"priority": "Priority",
|
||||
"relatedTasks": "Related Tasks",
|
||||
@@ -820,7 +820,7 @@
|
||||
"subscribeSuccessProject": "You are now subscribed to this project",
|
||||
"unsubscribeSuccessProject": "You are now unsubscribed to this project",
|
||||
"subscribeSuccessTask": "You are now subscribed to this task",
|
||||
"unsubscribeSuccessTask": "Užsiprenumeravai užduoties naujienas"
|
||||
"unsubscribeSuccessTask": "You are now unsubscribed to this task"
|
||||
},
|
||||
"attachment": {
|
||||
"title": "Attachments",
|
||||
@@ -830,7 +830,7 @@
|
||||
"drop": "Drop files here to upload",
|
||||
"delete": "Delete attachment",
|
||||
"deleteTooltip": "Delete this attachment",
|
||||
"deleteText1": "Ar esi tikra -s, kad nori ištrinti šį prisegtuką {filename}?",
|
||||
"deleteText1": "Are you sure you want to delete the attachment {filename}?",
|
||||
"copyUrl": "Copy URL",
|
||||
"copyUrlTooltip": "Copy the url of this attachment for usage in text",
|
||||
"setAsCover": "Make cover",
|
||||
@@ -858,8 +858,8 @@
|
||||
"1week": "1 week"
|
||||
},
|
||||
"description": {
|
||||
"placeholder": "Įvesti aprašą, spausti '/' norint gauti daugiau pasirinkčių…",
|
||||
"empty": "Aprašo kol kas nėra."
|
||||
"placeholder": "Enter a description, hit '/' for more options…",
|
||||
"empty": "No description available yet."
|
||||
},
|
||||
"assignee": {
|
||||
"placeholder": "Type to assign a user…",
|
||||
@@ -868,16 +868,16 @@
|
||||
"unassignSuccess": "The user has been unassigned successfully."
|
||||
},
|
||||
"label": {
|
||||
"placeholder": "Rašykite noredami pridėti etiketę…",
|
||||
"createPlaceholder": "Pridėti tai, kaip naują etiketę",
|
||||
"addSuccess": "Etiketė buvo sėkmingai pridėta.",
|
||||
"createSuccess": "Etiketė buvo sėkmingai sukurta.",
|
||||
"removeSuccess": "Etiketė buvo sėkmingai anuliuota.",
|
||||
"addCreateSuccess": "Etiketė buvo sėkmingai sukurta ir pridėta.",
|
||||
"placeholder": "Type to add a label…",
|
||||
"createPlaceholder": "Add this as new label",
|
||||
"addSuccess": "The label has been added successfully.",
|
||||
"createSuccess": "The label has been created successfully.",
|
||||
"removeSuccess": "The label has been removed successfully.",
|
||||
"addCreateSuccess": "The label has been created and added successfully.",
|
||||
"delete": {
|
||||
"header": "Ištrinti šią etiketę",
|
||||
"text1": "Ar esi tikra(-s), kad nori ištrinti šią etiketę?",
|
||||
"text2": "Šis veiksmas ištins tai iš visų užduočių ir nebus galima atkurti."
|
||||
"header": "Delete this label",
|
||||
"text1": "Are you sure you want to delete this label?",
|
||||
"text2": "This will remove it from all tasks and cannot be restored."
|
||||
}
|
||||
},
|
||||
"priority": {
|
||||
@@ -945,16 +945,16 @@
|
||||
"title": "Quick Add Magic",
|
||||
"intro": "When creating a task, you can use special keywords to directly add attributes to the newly created task. This allows to add commonly used attributes to tasks much faster.",
|
||||
"multiple": "You can use this multiple times.",
|
||||
"label1": "Norėdama -s pridėti etiketę, paprasčiausiai naudoti etiketės prefikso pavadinimą su {prefix}.",
|
||||
"label2": "Vikunja pirmiausiai patikrins ar etiketė egzistuoja, ir sukurs, jei neegzistuoja.",
|
||||
"label3": "Norint naudoti tarpus, paprasčiausiai pridėkite \" ar ' prieš etiketės pavadinimą.",
|
||||
"label4": "Pavyzdžiui: {prefix} \"Etiketė su tarpais\".",
|
||||
"label1": "To add a label, simply prefix the name of the label with {prefix}.",
|
||||
"label2": "Vikunja will first check if the label already exist and create it if not.",
|
||||
"label3": "To use spaces, simply add a \" or ' around the label name.",
|
||||
"label4": "For example: {prefix}\"Label with spaces\".",
|
||||
"priority1": "To set a task's priority, add a number 1-5, prefixed with a {prefix}.",
|
||||
"priority2": "The higher the number, the higher the priority.",
|
||||
"assignees": "Norint tiesiogiai priskirti užduotį vartotojui, pridėkite vartotojo vardą kaip prefiksą su {prefix} prie užduoties.",
|
||||
"project1": "Nustatyti užduoties projektą, įveskite prefiksą su {prefix}.",
|
||||
"assignees": "To directly assign the task to a user, add their username prefixed with {prefix} to the task.",
|
||||
"project1": "To set a project for the task to appear in, enter its name prefixed with {prefix}.",
|
||||
"project2": "This will return an error if the project does not exist.",
|
||||
"project3": "Norint naudoti tarpus, paprasčiausiai pridėkite \" ar ' apie projekto pavadinimą.",
|
||||
"project3": "To use spaces, simply add a \" or ' around the project name.",
|
||||
"project4": "For example: {prefix}\"Project with spaces\".",
|
||||
"dateAndTime": "Date and time",
|
||||
"date": "Any date will be used as the due date of the new task. You can use dates in any of these formats:",
|
||||
@@ -963,7 +963,7 @@
|
||||
"dateNth": "will use the {day}th of the current month",
|
||||
"dateTime": "Combine any of the date formats with \"{time}\" (or {timePM}) to set a time.",
|
||||
"repeats": "Repeating tasks",
|
||||
"repeatsDescription": "Norėdama -s nustatyti, kad užduotis kartotųsi tam tikru intervalu, paprasčiausiai pridėk '{suffix}' prie užduoties teksto. Kiekis turi būti išreikštas skaičiumi, tačiau gali būti ir praleistas (žr. pavyzdžius)."
|
||||
"repeatsDescription": "To set a task as repeating in an interval, simply add '{suffix}' to the task text. The amount needs to be a number and can be omitted to use just the type (see examples)."
|
||||
}
|
||||
},
|
||||
"team": {
|
||||
@@ -1005,15 +1005,15 @@
|
||||
}
|
||||
},
|
||||
"attributes": {
|
||||
"name": "Komandos Pavadinimas",
|
||||
"namePlaceholder": "Komandos pavadinimas rašomas čia…",
|
||||
"nameRequired": "Prašome nurodyti vardą.",
|
||||
"description": "Aprašymas",
|
||||
"descriptionPlaceholder": "Aprašykite komandą čia, spauskite '/' dėl daugiau opcijų…",
|
||||
"name": "Team Name",
|
||||
"namePlaceholder": "The team's name goes here…",
|
||||
"nameRequired": "Please specify a name.",
|
||||
"description": "Description",
|
||||
"descriptionPlaceholder": "Describe the team here, hit '/' for more options…",
|
||||
"admin": "Admin",
|
||||
"member": "Member",
|
||||
"isPublic": "Public Team",
|
||||
"isPublicDescription": "Padaryk komandą viešai randamą. Kai įgalinta, bet kas gali pasidalinti projektu su komanda, net nebūdama -s tiesioginiu komandos nariu."
|
||||
"isPublicDescription": "Make the team publicly discoverable. When enabled, anyone can share projects with this team even when not being a direct member."
|
||||
}
|
||||
},
|
||||
"keyboardShortcuts": {
|
||||
@@ -1029,14 +1029,14 @@
|
||||
"title": "Task Page",
|
||||
"done": "Mark task done / undone",
|
||||
"assign": "Assign this task to a user",
|
||||
"labels": "Pridėti etiketes šiai užduočiai",
|
||||
"labels": "Add labels to this task",
|
||||
"dueDate": "Change the due date of this task",
|
||||
"attachment": "Add an attachment to this task",
|
||||
"related": "Modify related tasks of this task",
|
||||
"color": "Change the color of this task",
|
||||
"move": "Move this task to another project",
|
||||
"reminder": "Manage reminders of this task",
|
||||
"description": "Praskleisti redagavimą užduoties apraše",
|
||||
"description": "Toggle editing of the task description",
|
||||
"delete": "Delete this task",
|
||||
"priority": "Change the priority of this task",
|
||||
"favorite": "Mark this task as favorite / unfavorite",
|
||||
@@ -1053,7 +1053,7 @@
|
||||
"title": "Navigation",
|
||||
"overview": "Navigate to overview",
|
||||
"upcoming": "Navigate to upcoming tasks",
|
||||
"labels": "Eiti į etiketes",
|
||||
"labels": "Navigate to labels",
|
||||
"teams": "Navigate to teams",
|
||||
"projects": "Navigate to projects"
|
||||
}
|
||||
@@ -1100,14 +1100,14 @@
|
||||
"quickActions": {
|
||||
"commands": "Commands",
|
||||
"placeholder": "Type a command or search…",
|
||||
"hint": "Gai naudoti {project} sutrumpinti projektų paiešką. Sujungti {project} ar {label} (etiketes) paieškos užklausoje norint ieškoti užduoties su tomis etiketėmis ar tame projekte. Naudok {assignee} norėdama(-s) ieškoti komandu.",
|
||||
"hint": "You can use {project} to limit the search to a project. Combine {project} or {label} (labels) with a search query to search for a task with these labels or on that project. Use {assignee} to only search for teams.",
|
||||
"tasks": "Tasks",
|
||||
"projects": "Projects",
|
||||
"teams": "Teams",
|
||||
"labels": "Etiketės",
|
||||
"labels": "Labels",
|
||||
"newProject": "Enter the title of the new project…",
|
||||
"newTask": "Enter the title of the new task…",
|
||||
"newTeam": "Įveskite naujos komandos pavadinimą…",
|
||||
"newTeam": "Enter the name of the new team…",
|
||||
"createTask": "Create a task in the current project ({title})",
|
||||
"createProject": "Create a project",
|
||||
"cmds": {
|
||||
@@ -1131,15 +1131,15 @@
|
||||
"error": "Error",
|
||||
"success": "Success",
|
||||
"0001": "You're not allowed to do that.",
|
||||
"1001": "Vartotojas tokiu vardu jau egzistuoja.",
|
||||
"1001": "A user with this username already exists.",
|
||||
"1002": "A user with this email address already exists.",
|
||||
"1004": "Nenurodytas vartotojo vardas ir slaptažodis.",
|
||||
"1004": "No username and password specified.",
|
||||
"1005": "The user does not exist.",
|
||||
"1006": "Could not get the user id.",
|
||||
"1008": "No password reset token provided.",
|
||||
"1009": "Invalid password reset token.",
|
||||
"1010": "Invalid email confirm token.",
|
||||
"1011": "Neteisingas prisijungimo vardas arba slaptažodis.",
|
||||
"1011": "Wrong username or password.",
|
||||
"1012": "Email address of the user not confirmed.",
|
||||
"1013": "New password is empty.",
|
||||
"1014": "Old password is empty.",
|
||||
@@ -1172,9 +1172,9 @@
|
||||
"4015": "The task comment does not exist.",
|
||||
"4016": "Invalid task field.",
|
||||
"4017": "Invalid task filter comparator.",
|
||||
"4018": "Neteisingas užduoties filtro jungtukas.",
|
||||
"4019": "Neteisinga užduotis filtro vertė.",
|
||||
"6001": "Komandos pavadinimas negali būti tuščias.",
|
||||
"4018": "Invalid task filter concatenator.",
|
||||
"4019": "Invalid task filter value.",
|
||||
"6001": "The team name cannot be empty.",
|
||||
"6002": "The team does not exist.",
|
||||
"6004": "The team already has access to that project.",
|
||||
"6005": "The user is already a member of that team.",
|
||||
@@ -1182,35 +1182,35 @@
|
||||
"6007": "The team does not have access to the project to perform that action.",
|
||||
"7002": "The user already has access to that project.",
|
||||
"7003": "You do not have access to that project.",
|
||||
"8001": "Ši etiketė jau yra prie šios užduoties.",
|
||||
"8002": "Etiketė neegzistuoja.",
|
||||
"8001": "This label already exists on that task.",
|
||||
"8002": "The label does not exist.",
|
||||
"8003": "You do not have access to this label.",
|
||||
"9001": "The right is invalid.",
|
||||
"10001": "Šaltinis neegzistuoja.",
|
||||
"10001": "The bucket does not exist.",
|
||||
"10002": "The bucket does not belong to that project.",
|
||||
"10003": "You cannot remove the last bucket on a project.",
|
||||
"10004": "You cannot add the task to this bucket as it already exceeded the limit of tasks it can hold.",
|
||||
"10005": "There can be only one done bucket per project.",
|
||||
"11001": "Išsaugotas filtras neegzistuoja.",
|
||||
"11002": "Išsaugotu filtru negalima pasidalinti.",
|
||||
"11001": "The saved filter does not exist.",
|
||||
"11002": "Saved filters are not available for link shares.",
|
||||
"12001": "The subscription entity type is invalid.",
|
||||
"12002": "You are already subscribed to the entity itself or a parent entity.",
|
||||
"13001": "Šis dalinimasis nuoroda reikalauja slaptažodžio identifikavimuisi, bet jis nebuvo pateiktas.",
|
||||
"13002": "Pateikta slaptažodžio dalinimosi nuoroda negalioja."
|
||||
"13001": "This link share requires a password for authentication, but none was provided.",
|
||||
"13002": "The provided link share password was invalid."
|
||||
},
|
||||
"about": {
|
||||
"title": "Apie",
|
||||
"version": "Versija: {version}"
|
||||
"title": "About",
|
||||
"version": "Version: {version}"
|
||||
},
|
||||
"time": {
|
||||
"units": {
|
||||
"seconds": "sekundė|sekundės",
|
||||
"minutes": "minutė|minutės",
|
||||
"hours": "valanda|valandos",
|
||||
"days": "diena|dienos",
|
||||
"weeks": "savaitė|savaitės",
|
||||
"months": "mėnesis|mėnesiai",
|
||||
"years": "metai|metai"
|
||||
"seconds": "second|seconds",
|
||||
"minutes": "minute|minutes",
|
||||
"hours": "hour|hours",
|
||||
"days": "day|days",
|
||||
"weeks": "week|weeks",
|
||||
"months": "month|months",
|
||||
"years": "year|years"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -61,7 +61,7 @@
|
||||
"usernameMustNotLookLikeUrl": "The username must not look like a URL.",
|
||||
"passwordRequired": "Please provide a password.",
|
||||
"passwordNotMin": "Password must have at least 8 characters.",
|
||||
"passwordNotMax": "Password must have at most 72 characters.",
|
||||
"passwordNotMax": "Password must have at most 250 characters.",
|
||||
"showPassword": "Show the password",
|
||||
"hidePassword": "Hide the password",
|
||||
"noAccountYet": "Don't have an account yet?",
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
"usernameMustNotLookLikeUrl": "The username must not look like a URL.",
|
||||
"passwordRequired": "Angi et passord.",
|
||||
"passwordNotMin": "Password must have at least 8 characters.",
|
||||
"passwordNotMax": "Password must have at most 72 characters.",
|
||||
"passwordNotMax": "Password must have at most 250 characters.",
|
||||
"showPassword": "Vis passord",
|
||||
"hidePassword": "Skjul passord",
|
||||
"noAccountYet": "Har du ikke konto ennå?",
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
"usernameMustNotLookLikeUrl": "Nazwa użytkownika nie może wyglądać jak adres URL.",
|
||||
"passwordRequired": "Proszę podać hasło.",
|
||||
"passwordNotMin": "Hasło musi zawierać co najmniej 8 znaków.",
|
||||
"passwordNotMax": "Password must have at most 72 characters.",
|
||||
"passwordNotMax": "Hasło musi zawierać co najwyżej 250 znaków.",
|
||||
"showPassword": "Pokaż hasło",
|
||||
"hidePassword": "Ukryj hasło",
|
||||
"noAccountYet": "Nie masz jeszcze konta?",
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
"usernameMustNotLookLikeUrl": "The username must not look like a URL.",
|
||||
"passwordRequired": "Por favor, insira uma senha.",
|
||||
"passwordNotMin": "Password must have at least 8 characters.",
|
||||
"passwordNotMax": "Password must have at most 72 characters.",
|
||||
"passwordNotMax": "Password must have at most 250 characters.",
|
||||
"showPassword": "Exibir senha",
|
||||
"hidePassword": "Ocultar senha",
|
||||
"noAccountYet": "Não possui uma conta ainda?",
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
"usernameMustNotLookLikeUrl": "O nome de utilizador não se deve assemelhar a um URL.",
|
||||
"passwordRequired": "Por favor, fornece uma palavra-passe.",
|
||||
"passwordNotMin": "A palavra-passe deve ter no mínimo 8 caracteres.",
|
||||
"passwordNotMax": "Password must have at most 72 characters.",
|
||||
"passwordNotMax": "A palavra-passe deve ter no máximo 250 caracteres.",
|
||||
"showPassword": "Mostrar a palavra-passe",
|
||||
"hidePassword": "Esconder a palavra-passe",
|
||||
"noAccountYet": "Ainda não tens uma conta?",
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
"usernameMustNotLookLikeUrl": "The username must not look like a URL.",
|
||||
"passwordRequired": "Please provide a password.",
|
||||
"passwordNotMin": "Password must have at least 8 characters.",
|
||||
"passwordNotMax": "Password must have at most 72 characters.",
|
||||
"passwordNotMax": "Password must have at most 250 characters.",
|
||||
"showPassword": "Show the password",
|
||||
"hidePassword": "Hide the password",
|
||||
"noAccountYet": "Don't have an account yet?",
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
"usernameMustNotLookLikeUrl": "Имя пользователя не должно быть похожим на URL.",
|
||||
"passwordRequired": "Введите пароль.",
|
||||
"passwordNotMin": "Пароль должен содержать не меньше 8 символов.",
|
||||
"passwordNotMax": "Password must have at most 72 characters.",
|
||||
"passwordNotMax": "Пароль должен содержать не больше 250 символов.",
|
||||
"showPassword": "Показать пароль",
|
||||
"hidePassword": "Скрыть пароль",
|
||||
"noAccountYet": "Ещё нет аккаунта?",
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
"usernameMustNotLookLikeUrl": "The username must not look like a URL.",
|
||||
"passwordRequired": "Please provide a password.",
|
||||
"passwordNotMin": "Password must have at least 8 characters.",
|
||||
"passwordNotMax": "Password must have at most 72 characters.",
|
||||
"passwordNotMax": "Password must have at most 250 characters.",
|
||||
"showPassword": "Show the password",
|
||||
"hidePassword": "Hide the password",
|
||||
"noAccountYet": "Don't have an account yet?",
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
"usernameMustNotLookLikeUrl": "Uporabniško ime ne sme izgledati kot URL.",
|
||||
"passwordRequired": "Prosim vnesite geslo.",
|
||||
"passwordNotMin": "Geslo mora imeti vsaj 8 znakov.",
|
||||
"passwordNotMax": "Geslo mora imeti največ 72 znakov.",
|
||||
"passwordNotMax": "Geslo mora imeti največ 250 znakov.",
|
||||
"showPassword": "Prikažite geslo",
|
||||
"hidePassword": "Skrijte geslo",
|
||||
"noAccountYet": "Še nimate računa?",
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
"usernameMustNotLookLikeUrl": "The username must not look like a URL.",
|
||||
"passwordRequired": "Please provide a password.",
|
||||
"passwordNotMin": "Password must have at least 8 characters.",
|
||||
"passwordNotMax": "Password must have at most 72 characters.",
|
||||
"passwordNotMax": "Password must have at most 250 characters.",
|
||||
"showPassword": "Show the password",
|
||||
"hidePassword": "Hide the password",
|
||||
"noAccountYet": "Don't have an account yet?",
|
||||
|
||||
@@ -60,8 +60,8 @@
|
||||
"usernameMustNotContainSpace": "The username must not contain spaces.",
|
||||
"usernameMustNotLookLikeUrl": "The username must not look like a URL.",
|
||||
"passwordRequired": "Vänligen ange ett lösenord.",
|
||||
"passwordNotMin": "Lösenord måste innehålla minst 8 tecken.",
|
||||
"passwordNotMax": "Password must have at most 72 characters.",
|
||||
"passwordNotMin": "Password must have at least 8 characters.",
|
||||
"passwordNotMax": "Password must have at most 250 characters.",
|
||||
"showPassword": "Show the password",
|
||||
"hidePassword": "Hide the password",
|
||||
"noAccountYet": "Har du inget konto än?",
|
||||
@@ -74,7 +74,7 @@
|
||||
"newPasswordTitle": "Uppdatera ditt lösenord",
|
||||
"newPassword": "Nytt lösenord",
|
||||
"newPasswordConfirm": "New password confirmation",
|
||||
"currentPassword": "Nuvarande lösenord",
|
||||
"currentPassword": "Current password",
|
||||
"currentPasswordPlaceholder": "Ditt nuvarande lösenord",
|
||||
"passwordsDontMatch": "The new password and its confirmation don't match.",
|
||||
"passwordUpdateSuccess": "The password was successfully updated.",
|
||||
@@ -83,7 +83,7 @@
|
||||
"updateEmailSuccess": "Your email address was successfully updated. We've sent you a link to confirm it.",
|
||||
"general": {
|
||||
"title": "General Settings",
|
||||
"name": "Mitt namn",
|
||||
"name": "My Name",
|
||||
"newName": "The new name",
|
||||
"savedSuccess": "The settings were successfully updated.",
|
||||
"emailReminders": "Send me reminders for tasks via email",
|
||||
@@ -325,7 +325,7 @@
|
||||
"add": "Lägg till",
|
||||
"addPlaceholder": "Add a task…",
|
||||
"empty": "This project is currently empty.",
|
||||
"newTaskCta": "Skapa en uppgift.",
|
||||
"newTaskCta": "Create a task.",
|
||||
"editTask": "Redigera uppgift"
|
||||
},
|
||||
"gantt": {
|
||||
@@ -396,7 +396,7 @@
|
||||
"bucketConfig": "Bucket configuration",
|
||||
"bucketConfigManual": "Manual",
|
||||
"filter": "Filter",
|
||||
"create": "Skapa vy",
|
||||
"create": "Create view",
|
||||
"createSuccess": "The view was created successfully.",
|
||||
"titleRequired": "Please provide a title.",
|
||||
"delete": "Delete this view",
|
||||
@@ -575,7 +575,7 @@
|
||||
"id": "ID",
|
||||
"created": "Created at",
|
||||
"createdBy": "Created by {0}",
|
||||
"actions": "Åtgärder",
|
||||
"actions": "Actions",
|
||||
"cannotBeUndone": "This cannot be undone!"
|
||||
},
|
||||
"input": {
|
||||
@@ -1111,7 +1111,7 @@
|
||||
"createTask": "Create a task in the current project ({title})",
|
||||
"createProject": "Skapa ett projekt",
|
||||
"cmds": {
|
||||
"newTask": "Ny uppgift",
|
||||
"newTask": "New task",
|
||||
"newProject": "Nytt projekt",
|
||||
"newTeam": "Nytt team"
|
||||
}
|
||||
@@ -1122,10 +1122,10 @@
|
||||
"altFormatShort": "j M Y"
|
||||
},
|
||||
"reaction": {
|
||||
"reactedWith": "{user} reagerade med {value}",
|
||||
"reactedWithAnd": "{users} och {lastUser} reagerade med {value}",
|
||||
"reactedWith": "{user} reacted with {value}",
|
||||
"reactedWithAnd": "{users} and {lastUser} reacted with {value}",
|
||||
"reactedWithAndMany": "{users} and {num} more reacted reacted with {value}",
|
||||
"add": "Lägg till din reaktion"
|
||||
"add": "Add your reaction"
|
||||
},
|
||||
"error": {
|
||||
"error": "Error",
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
"usernameMustNotLookLikeUrl": "The username must not look like a URL.",
|
||||
"passwordRequired": "Please provide a password.",
|
||||
"passwordNotMin": "Password must have at least 8 characters.",
|
||||
"passwordNotMax": "Password must have at most 72 characters.",
|
||||
"passwordNotMax": "Password must have at most 250 characters.",
|
||||
"showPassword": "Show the password",
|
||||
"hidePassword": "Hide the password",
|
||||
"noAccountYet": "Don't have an account yet?",
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
"usernameMustNotLookLikeUrl": "Ім'я вживача не має виглядати як посилання.",
|
||||
"passwordRequired": "Будь ласка, введіть пароль.",
|
||||
"passwordNotMin": "Пароль має містити принаймні 8 знаків.",
|
||||
"passwordNotMax": "Password must have at most 72 characters.",
|
||||
"passwordNotMax": "Пароль має містити не більше 250 знаків.",
|
||||
"showPassword": "Показати пароль",
|
||||
"hidePassword": "Сховати пароль",
|
||||
"noAccountYet": "Досі немає обліковки?",
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
"usernameMustNotLookLikeUrl": "The username must not look like a URL.",
|
||||
"passwordRequired": "Vui lòng cung cấp một mật khẩu.",
|
||||
"passwordNotMin": "Password must have at least 8 characters.",
|
||||
"passwordNotMax": "Password must have at most 72 characters.",
|
||||
"passwordNotMax": "Password must have at most 250 characters.",
|
||||
"showPassword": "Hiển thị mật khẩu",
|
||||
"hidePassword": "Ẩn mật khẩu",
|
||||
"noAccountYet": "Bạn chưa có tài khoản?",
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
"usernameMustNotLookLikeUrl": "用户名不能像一个 URL。",
|
||||
"passwordRequired": "请提供密码",
|
||||
"passwordNotMin": "密码至少有8个字符",
|
||||
"passwordNotMax": "Password must have at most 72 characters.",
|
||||
"passwordNotMax": "密码不能超过250个字符",
|
||||
"showPassword": "显示密码",
|
||||
"hidePassword": "隐藏密码",
|
||||
"noAccountYet": "还没有账号?",
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
"usernameMustNotLookLikeUrl": "The username must not look like a URL.",
|
||||
"passwordRequired": "Please provide a password.",
|
||||
"passwordNotMin": "Password must have at least 8 characters.",
|
||||
"passwordNotMax": "Password must have at most 72 characters.",
|
||||
"passwordNotMax": "Password must have at most 250 characters.",
|
||||
"showPassword": "Show the password",
|
||||
"hidePassword": "Hide the password",
|
||||
"noAccountYet": "Don't have an account yet?",
|
||||
|
||||
@@ -25,7 +25,6 @@ export const DAYJS_LOCALE_MAPPING = {
|
||||
'pt-BR': 'pt',
|
||||
'hr-HR': 'hr',
|
||||
'uk-UA': 'uk',
|
||||
'lt-LT': 'lt',
|
||||
} as Record<SupportedLocale, ISOLanguage>
|
||||
|
||||
export const DAYJS_LANGUAGE_IMPORTS = {
|
||||
@@ -49,7 +48,6 @@ export const DAYJS_LANGUAGE_IMPORTS = {
|
||||
'sl-si': () => import('dayjs/locale/sl'),
|
||||
'pt-br': () => import('dayjs/locale/pt-br'),
|
||||
'uk-ua': () => import('dayjs/locale/uk'),
|
||||
'lt-lt': () => import('dayjs/locale/lt'),
|
||||
} as Record<SupportedLocale, () => Promise<ILocale>>
|
||||
|
||||
export function useDayjsLanguageSync(dayjsGlobal: typeof dayjs) {
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import type {IAbstract} from './IAbstract'
|
||||
import type {IUser} from './IUser'
|
||||
|
||||
// FIXME: what makes this different from TaskFilterParams?
|
||||
interface Filters {
|
||||
sort_by: ('start_date' | 'done' | 'id' | 'position')[],
|
||||
order_by: ('asc' | 'desc')[],
|
||||
sortBy: ('start_date' | 'done' | 'id' | 'position')[],
|
||||
orderBy: ('asc' | 'desc')[],
|
||||
filter: string,
|
||||
filter_include_nulls: boolean,
|
||||
filterIncludeNulls: boolean,
|
||||
s: string,
|
||||
}
|
||||
|
||||
|
||||
@@ -7,10 +7,6 @@ import type { IAttachment } from '@/modelTypes/IAttachment'
|
||||
|
||||
export const SUPPORTED_IMAGE_SUFFIX = ['.jpg', '.png', '.bmp', '.gif']
|
||||
|
||||
export function canPreview(attachment: IAttachment): boolean {
|
||||
return SUPPORTED_IMAGE_SUFFIX.some((suffix) => attachment.file.name.toLowerCase().endsWith(suffix))
|
||||
}
|
||||
|
||||
export default class AttachmentModel extends AbstractModel<IAttachment> implements IAttachment {
|
||||
id = 0
|
||||
taskId = 0
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { objectToSnakeCase } from '@/helpers/case'
|
||||
import AbstractModel from './abstractModel'
|
||||
import UserModel from '@/models/user'
|
||||
|
||||
@@ -10,10 +9,10 @@ export default class SavedFilterModel extends AbstractModel<ISavedFilter> implem
|
||||
title = ''
|
||||
description = ''
|
||||
filters: ISavedFilter['filters'] = {
|
||||
sort_by: ['done', 'id'],
|
||||
order_by: ['asc', 'desc'],
|
||||
sortBy: ['done', 'id'],
|
||||
orderBy: ['asc', 'desc'],
|
||||
filter: 'done = false',
|
||||
filter_include_nulls: true,
|
||||
filterIncludeNulls: true,
|
||||
s: '',
|
||||
}
|
||||
|
||||
@@ -27,10 +26,6 @@ export default class SavedFilterModel extends AbstractModel<ISavedFilter> implem
|
||||
|
||||
this.owner = new UserModel(this.owner)
|
||||
|
||||
// Filters are in snake_case for the API - this makes it consistent with the way filter params are used with one-off filters.
|
||||
// Should probably be camelCase everywhere, but that's a task for another day.
|
||||
this.filters = objectToSnakeCase(this.filters)
|
||||
|
||||
this.created = new Date(this.created)
|
||||
this.updated = new Date(this.updated)
|
||||
}
|
||||
|
||||
@@ -5,13 +5,6 @@ import type { IAttachment } from '@/modelTypes/IAttachment'
|
||||
|
||||
import {downloadBlob} from '@/helpers/downloadBlob'
|
||||
|
||||
export enum PREVIEW_SIZE {
|
||||
SM = 'sm',
|
||||
MD = 'md',
|
||||
LG = 'lg',
|
||||
XL = 'xl',
|
||||
}
|
||||
|
||||
export default class AttachmentService extends AbstractService<IAttachment> {
|
||||
constructor() {
|
||||
super({
|
||||
@@ -44,13 +37,8 @@ export default class AttachmentService extends AbstractService<IAttachment> {
|
||||
return data
|
||||
}
|
||||
|
||||
getBlobUrl(model: IAttachment, size?: PREVIEW_SIZE) {
|
||||
let mainUrl = '/tasks/' + model.taskId + '/attachments/' + model.id
|
||||
if (size !== undefined) {
|
||||
mainUrl += `?preview_size=${size}`
|
||||
}
|
||||
|
||||
return AbstractService.prototype.getBlobUrl.call(this, mainUrl)
|
||||
getBlobUrl(model: IAttachment) {
|
||||
return AbstractService.prototype.getBlobUrl.call(this, '/tasks/' + model.taskId + '/attachments/' + model.id)
|
||||
}
|
||||
|
||||
async download(model: IAttachment) {
|
||||
|
||||
@@ -13,6 +13,7 @@ import SavedFilterModel from '@/models/savedFilter'
|
||||
import {useBaseStore} from '@/stores/base'
|
||||
import {useProjectStore} from '@/stores/projects'
|
||||
|
||||
import {objectToSnakeCase, objectToCamelCase} from '@/helpers/case'
|
||||
import {success} from '@/message'
|
||||
import ProjectModel from '@/models/project'
|
||||
|
||||
@@ -54,6 +55,23 @@ export default class SavedFilterService extends AbstractService<ISavedFilter> {
|
||||
modelFactory(data) {
|
||||
return new SavedFilterModel(data)
|
||||
}
|
||||
|
||||
processModel(model) {
|
||||
// Make filters from this.filters camelCase and set them to the model property:
|
||||
// That's easier than making the whole filter component configurable since that still needs to provide
|
||||
// the filter values in snake_sćase for url parameters.
|
||||
model.filters = objectToCamelCase(model.filters)
|
||||
|
||||
return model
|
||||
}
|
||||
|
||||
beforeUpdate(model) {
|
||||
return this.processModel(model)
|
||||
}
|
||||
|
||||
beforeCreate(model) {
|
||||
return this.processModel(model)
|
||||
}
|
||||
}
|
||||
|
||||
export function useSavedFilter(projectId?: MaybeRefOrGetter<IProject['id']>) {
|
||||
@@ -80,7 +98,10 @@ export function useSavedFilter(projectId?: MaybeRefOrGetter<IProject['id']>) {
|
||||
// We assume the projectId in the route is the pseudoproject
|
||||
const savedFilterId = getSavedFilterIdFromProjectId(watchedProjectId)
|
||||
|
||||
filter.value = await filterService.get(new SavedFilterModel({id: savedFilterId}))
|
||||
filter.value = new SavedFilterModel({id: savedFilterId})
|
||||
const response = await filterService.get(filter.value)
|
||||
response.filters = objectToSnakeCase(response.filters)
|
||||
filter.value = response
|
||||
await validateTitleField()
|
||||
}, {immediate: true})
|
||||
|
||||
@@ -94,6 +115,7 @@ export function useSavedFilter(projectId?: MaybeRefOrGetter<IProject['id']>) {
|
||||
const response = await filterService.update(filter.value)
|
||||
await projectStore.loadAllProjects()
|
||||
success({message: t('filters.edit.success')})
|
||||
response.filters = objectToSnakeCase(response.filters)
|
||||
filter.value = response
|
||||
await useBaseStore().setCurrentProject(new ProjectModel({
|
||||
id: getProjectId(filter.value),
|
||||
|
||||
@@ -31,17 +31,9 @@ export default class TaskCollectionService extends AbstractService<ITask> {
|
||||
constructor() {
|
||||
super({
|
||||
getAll: '/projects/{projectId}/views/{viewId}/tasks',
|
||||
// /projects/{projectId}/tasks when viewId is not provided
|
||||
})
|
||||
}
|
||||
|
||||
getReplacedRoute(path: string, pathparams: Record<string, unknown>): string {
|
||||
if (!pathparams.viewId) {
|
||||
return super.getReplacedRoute('/projects/{projectId}/tasks', pathparams)
|
||||
}
|
||||
return super.getReplacedRoute(path, pathparams)
|
||||
}
|
||||
|
||||
modelFactory(data) {
|
||||
// FIXME: There must be a better way for this…
|
||||
if (typeof data.project_view_id !== 'undefined') {
|
||||
|
||||
@@ -194,8 +194,8 @@ export const useKanbanStore = defineStore('kanban', () => {
|
||||
...oldBucket,
|
||||
count: (oldBucket?.count || 0) + 1,
|
||||
tasks: [
|
||||
task,
|
||||
...oldBucket.tasks,
|
||||
task,
|
||||
],
|
||||
}
|
||||
buckets.value[bucketIndex] = newBucket
|
||||
|
||||
@@ -44,12 +44,12 @@ export const useLabelStore = defineStore('label', () => {
|
||||
|
||||
|
||||
// **
|
||||
// * Checks if a list of labels is available in the store and filters them then query
|
||||
// * Checks if a project of labels is available in the store and filters them then query
|
||||
// **
|
||||
const filterLabelsByQuery = computed(() => {
|
||||
return (labelsToHide: ILabel[], query: string) => {
|
||||
const labelIdsToHide: number[] = labelsToHide.map(({id}) => id)
|
||||
|
||||
|
||||
return search(query)
|
||||
?.filter(value => !labelIdsToHide.includes(value))
|
||||
.map(id => labels.value[id])
|
||||
|
||||
@@ -66,7 +66,7 @@ export const useProjectStore = defineStore('project', () => {
|
||||
return search(query)
|
||||
?.filter(value => value > 0)
|
||||
.map(id => projects.value[id])
|
||||
.filter(project => project?.isArchived === includeArchived)
|
||||
.filter(project => project.isArchived === includeArchived)
|
||||
|| []
|
||||
}
|
||||
})
|
||||
@@ -76,7 +76,7 @@ export const useProjectStore = defineStore('project', () => {
|
||||
return search(query)
|
||||
?.filter(value => getSavedFilterIdFromProjectId(value) > 0)
|
||||
.map(id => projects.value[id])
|
||||
.filter(project => project?.isArchived === includeArchived)
|
||||
.filter(project => project.isArchived === includeArchived)
|
||||
|| []
|
||||
}
|
||||
})
|
||||
|
||||
@@ -414,7 +414,6 @@ export const useTaskStore = defineStore('task', () => {
|
||||
bucketId,
|
||||
projectId,
|
||||
position,
|
||||
index,
|
||||
} :
|
||||
Partial<ITask>,
|
||||
) {
|
||||
@@ -430,7 +429,6 @@ export const useTaskStore = defineStore('task', () => {
|
||||
projectId,
|
||||
bucketId,
|
||||
position,
|
||||
index,
|
||||
}))
|
||||
} finally {
|
||||
cancel()
|
||||
@@ -469,7 +467,6 @@ export const useTaskStore = defineStore('task', () => {
|
||||
assignees,
|
||||
bucketId: bucketId || 0,
|
||||
position,
|
||||
index,
|
||||
})
|
||||
task.repeatAfter = parsedTask.repeats
|
||||
|
||||
|
||||
@@ -5,16 +5,17 @@
|
||||
outline: none;
|
||||
}
|
||||
|
||||
a, button {
|
||||
&:focus-visible {
|
||||
box-shadow: 0 0 0 2px hsla(var(--primary-hsl), 0.5);
|
||||
}
|
||||
:focus {
|
||||
box-shadow: 0 0 0 2px hsla(var(--primary-hsl), 0.5);
|
||||
}
|
||||
|
||||
@supports not selector(:focus-visible) {
|
||||
&:focus {
|
||||
box-shadow: 0 0 0 2px hsla(var(--primary-hsl), 0.5);
|
||||
}
|
||||
}
|
||||
:focus:not(:focus-visible) {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
:focus-visible,
|
||||
:-moz-focusring {
|
||||
box-shadow: 0 0 0 2px hsla(var(--primary-hsl), 0.5);
|
||||
}
|
||||
|
||||
:root {
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ import {getFullBaseUrl} from './helpers/getFullBaseUrl'
|
||||
declare let self: ServiceWorkerGlobalScope
|
||||
|
||||
const fullBaseUrl = getFullBaseUrl()
|
||||
const workboxVersion = 'v7.1.0'
|
||||
const workboxVersion = 'v7.0.0'
|
||||
|
||||
importScripts(`${fullBaseUrl}workbox-${workboxVersion}/workbox-sw.js`)
|
||||
workbox.setConfig({
|
||||
|
||||
@@ -42,7 +42,6 @@
|
||||
<ProjectCardGrid
|
||||
v-cy="'projectCardGrid'"
|
||||
:projects="projectHistory"
|
||||
:show-even-number-of-projects="true"
|
||||
/>
|
||||
</div>
|
||||
<ShowTasks
|
||||
|
||||
@@ -63,7 +63,6 @@
|
||||
:disabled="filterService.loading"
|
||||
class="has-no-shadow has-no-border"
|
||||
:has-footer="false"
|
||||
:change-immediately="true"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -99,7 +99,7 @@ async function saveView(view: IProjectView) {
|
||||
if (view?.viewKind !== 'kanban') {
|
||||
view.bucketConfigurationMode = 'none'
|
||||
}
|
||||
const result = await projectViewService.update(view)
|
||||
const result = await ProjectViewService.update(view)
|
||||
projectStore.setProjectView(result)
|
||||
viewToEdit.value = null
|
||||
success({message: t('project.views.updateSuccess')})
|
||||
|
||||
@@ -86,7 +86,6 @@ import {useAuthStore} from '@/stores/auth'
|
||||
import {useTaskStore} from '@/stores/tasks'
|
||||
import {useProjectStore} from '@/stores/projects'
|
||||
import type {TaskFilterParams} from '@/services/taskCollection'
|
||||
import TaskCollectionService from '@/services/taskCollection'
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
dateFrom?: Date | string,
|
||||
@@ -106,7 +105,6 @@ const {t} = useI18n({useScope: 'global'})
|
||||
|
||||
const tasks = ref<ITask[]>([])
|
||||
const showNothingToDo = ref<boolean>(false)
|
||||
const taskCollectionService = ref(new TaskCollectionService())
|
||||
|
||||
const projectStore = useProjectStore()
|
||||
|
||||
@@ -133,7 +131,7 @@ const pageTitle = computed(() => {
|
||||
})
|
||||
const hasTasks = computed(() => tasks.value && tasks.value.length > 0)
|
||||
const userAuthenticated = computed(() => authStore.authenticated)
|
||||
const loading = computed(() => taskStore.isLoading || taskCollectionService.value.loading)
|
||||
const loading = computed(() => taskStore.isLoading)
|
||||
|
||||
interface dateStrings {
|
||||
dateFrom: string,
|
||||
@@ -201,9 +199,8 @@ async function loadPendingTasks(from: Date|string, to: Date|string) {
|
||||
}
|
||||
}
|
||||
|
||||
const filterId = authStore.settings.frontendSettings.filterIdUsedOnOverview
|
||||
if (showAll.value && filterId && typeof projectStore.projects[filterId] !== 'undefined') {
|
||||
tasks.value = await taskCollectionService.value.getAll({projectId: filterId}, params)
|
||||
if (showAll.value && authStore.settings.frontendSettings.filterIdUsedOnOverview && typeof projectStore.projects[authStore.settings.frontendSettings.filterIdUsedOnOverview] !== 'undefined') {
|
||||
tasks.value = await taskStore.loadTasks(params, authStore.settings.frontendSettings.filterIdUsedOnOverview)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
:task="task"
|
||||
:can-write="canWrite"
|
||||
@update:task="Object.assign(task, $event)"
|
||||
@close="$emit('close')"
|
||||
/>
|
||||
<h6
|
||||
v-if="project?.id"
|
||||
@@ -971,8 +970,9 @@ function setRelatedTasksActive() {
|
||||
color: var(--text);
|
||||
background-color: var(--site-background) !important;
|
||||
|
||||
@media screen and (max-width: calc(#{$desktop} + 1px)) {
|
||||
@media screen and (max-width: 800px) {
|
||||
border-radius: 0;
|
||||
padding-top: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -127,7 +127,6 @@ import Password from '@/components/input/Password.vue'
|
||||
|
||||
import {useAuthStore} from '@/stores/auth'
|
||||
import {useConfigStore} from '@/stores/config'
|
||||
import {validatePassword} from '@/helpers/validatePasswort'
|
||||
|
||||
const {t} = useI18n()
|
||||
const authStore = useAuthStore()
|
||||
@@ -184,7 +183,7 @@ const validateUsername = useDebounceFn(() => {
|
||||
const everythingValid = computed(() => {
|
||||
return credentials.username !== '' &&
|
||||
credentials.email !== '' &&
|
||||
validatePassword(credentials.password) === true &&
|
||||
credentials.password !== '' &&
|
||||
emailValid.value &&
|
||||
usernameValid.value
|
||||
})
|
||||
|
||||
@@ -6,8 +6,8 @@ module.exports = {
|
||||
},
|
||||
prefix: 'tw-',
|
||||
content: [
|
||||
'./index.html',
|
||||
'./src/**/*.{vue,js,ts}',
|
||||
"./index.html",
|
||||
"./src/**/*.{vue,js,ts}",
|
||||
],
|
||||
theme: {
|
||||
extend: {},
|
||||
|
||||
@@ -1,24 +1,25 @@
|
||||
// Vikunja is a to-do list application to facilitate your life.
|
||||
// Copyright 2018-present Vikunja and contributors. All rights reserved.
|
||||
// Copyright 2018 Vikunja and contributors. All rights reserved.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public Licensee as published by
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public Licensee for more details.
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public Licensee
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
module code.vikunja.io/api
|
||||
|
||||
require (
|
||||
dario.cat/mergo v1.0.1
|
||||
github.com/ThreeDotsLabs/watermill v1.3.7
|
||||
code.vikunja.io/web v0.0.0-20210706160506-d85def955bd3
|
||||
dario.cat/mergo v1.0.0
|
||||
github.com/ThreeDotsLabs/watermill v1.3.5
|
||||
github.com/adlio/trello v1.12.0
|
||||
github.com/arran4/golang-ical v0.3.1
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2
|
||||
@@ -29,9 +30,9 @@ require (
|
||||
github.com/d4l3k/messagediff v1.2.1
|
||||
github.com/disintegration/imaging v1.6.2
|
||||
github.com/dustinkirkland/golang-petname v0.0.0-20240422154211-76c06c4bde6b
|
||||
github.com/gabriel-vasile/mimetype v1.4.5
|
||||
github.com/gabriel-vasile/mimetype v1.4.4
|
||||
github.com/ganigeorgiev/fexpr v0.4.1
|
||||
github.com/getsentry/sentry-go v0.29.0
|
||||
github.com/getsentry/sentry-go v0.28.1
|
||||
github.com/go-sql-driver/mysql v1.8.1
|
||||
github.com/go-testfixtures/testfixtures/v3 v3.11.0
|
||||
github.com/gocarina/gocsv v0.0.0-20231116093920-b87c2d0e983a
|
||||
@@ -49,13 +50,13 @@ require (
|
||||
github.com/labstack/gommon v0.4.2
|
||||
github.com/lib/pq v1.10.9
|
||||
github.com/magefile/mage v1.15.0
|
||||
github.com/mattn/go-sqlite3 v1.14.23
|
||||
github.com/mattn/go-sqlite3 v1.14.22
|
||||
github.com/microcosm-cc/bluemonday v1.0.27
|
||||
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.20.4
|
||||
github.com/redis/go-redis/v9 v9.6.1
|
||||
github.com/prometheus/client_golang v1.19.1
|
||||
github.com/redis/go-redis/v9 v9.5.3
|
||||
github.com/robfig/cron/v3 v3.0.1
|
||||
github.com/samedi/caldav-go v3.0.0+incompatible
|
||||
github.com/spf13/afero v1.11.0
|
||||
@@ -65,17 +66,16 @@ require (
|
||||
github.com/swaggo/swag v1.16.3
|
||||
github.com/tkuchiki/go-timezone v0.2.3
|
||||
github.com/typesense/typesense-go v1.1.0
|
||||
github.com/typesense/typesense-go/v2 v2.0.0
|
||||
github.com/ulule/limiter/v3 v3.11.2
|
||||
github.com/wneessen/go-mail v0.4.4
|
||||
github.com/wneessen/go-mail v0.4.2
|
||||
github.com/yuin/goldmark v1.7.4
|
||||
golang.org/x/crypto v0.27.0
|
||||
golang.org/x/image v0.20.0
|
||||
golang.org/x/oauth2 v0.23.0
|
||||
golang.org/x/sync v0.8.0
|
||||
golang.org/x/sys v0.25.0
|
||||
golang.org/x/term v0.24.0
|
||||
golang.org/x/text v0.18.0
|
||||
golang.org/x/crypto v0.25.0
|
||||
golang.org/x/image v0.18.0
|
||||
golang.org/x/oauth2 v0.21.0
|
||||
golang.org/x/sync v0.7.0
|
||||
golang.org/x/sys v0.22.0
|
||||
golang.org/x/term v0.22.0
|
||||
golang.org/x/text v0.16.0
|
||||
gopkg.in/d4l3k/messagediff.v1 v1.2.1
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
mvdan.cc/xurls/v2 v2.5.0
|
||||
@@ -97,12 +97,12 @@ require (
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
|
||||
github.com/cenkalti/backoff/v3 v3.2.2 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/go-chi/chi/v5 v5.1.0 // indirect
|
||||
github.com/go-chi/chi/v5 v5.0.10 // indirect
|
||||
github.com/go-faster/city v1.0.1 // indirect
|
||||
github.com/go-faster/errors v0.7.1 // indirect
|
||||
github.com/go-jose/go-jose/v4 v4.0.2 // indirect
|
||||
@@ -121,7 +121,7 @@ require (
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/compress v1.17.9 // indirect
|
||||
github.com/klauspost/compress v1.17.7 // indirect
|
||||
github.com/laurent22/ical-go v0.1.1-0.20181107184520-7e5d6ade8eef // indirect
|
||||
github.com/lithammer/shortuuid/v3 v3.0.7 // indirect
|
||||
github.com/magiconair/properties v1.8.7 // indirect
|
||||
@@ -132,7 +132,6 @@ require (
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/oapi-codegen/runtime v1.1.1 // indirect
|
||||
github.com/oklog/ulid v1.3.1 // indirect
|
||||
github.com/onsi/ginkgo v1.16.4 // indirect
|
||||
@@ -142,16 +141,16 @@ require (
|
||||
github.com/pierrec/lz4/v4 v4.1.21 // indirect
|
||||
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.6.1 // indirect
|
||||
github.com/prometheus/common v0.55.0 // indirect
|
||||
github.com/prometheus/procfs v0.15.1 // indirect
|
||||
github.com/prometheus/client_model v0.5.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
|
||||
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||
github.com/segmentio/asm v1.2.0 // indirect
|
||||
github.com/shopspring/decimal v1.4.0 // indirect
|
||||
github.com/sony/gobreaker v1.0.0 // indirect
|
||||
github.com/sony/gobreaker v0.5.0 // indirect
|
||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||
github.com/spf13/cast v1.6.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
@@ -170,7 +169,7 @@ require (
|
||||
golang.org/x/net v0.27.0 // indirect
|
||||
golang.org/x/time v0.5.0 // indirect
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
|
||||
google.golang.org/protobuf v1.34.2 // indirect
|
||||
google.golang.org/protobuf v1.33.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
|
||||
@@ -180,4 +179,4 @@ replace github.com/samedi/caldav-go => github.com/kolaente/caldav-go v3.0.1-0.20
|
||||
|
||||
go 1.22
|
||||
|
||||
toolchain go1.23.1
|
||||
toolchain go1.22.5
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
code.vikunja.io/web v0.0.0-20210706160506-d85def955bd3 h1:MXl7Ff9a/ndTpuEmQKIGhqReE9hWhD4T/+AzK4AXUYc=
|
||||
code.vikunja.io/web v0.0.0-20210706160506-d85def955bd3/go.mod h1:OgFO06HN1KpA4S7Dw/QAIeygiUPSeGJJn1ykz/sjZdU=
|
||||
dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
|
||||
dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
||||
dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
|
||||
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
||||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:lSA0F4e9A2NcQSqGqTOXqu2aRi/XEQxDCBwM8yJtE6s=
|
||||
@@ -18,17 +18,17 @@ github.com/ClickHouse/clickhouse-go/v2 v2.24.0/go.mod h1:iDTViXk2Fgvf1jn2dbJd1ys
|
||||
github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
|
||||
github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
|
||||
github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
|
||||
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
|
||||
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk=
|
||||
github.com/ThreeDotsLabs/watermill v1.3.5 h1:50JEPEhMGZQMh08ct0tfO1PsgMOAOhV3zxK2WofkbXg=
|
||||
github.com/ThreeDotsLabs/watermill v1.3.5/go.mod h1:O/u/Ptyrk5MPTxSeWM5vzTtZcZfxXfO9PK9eXTYiFZY=
|
||||
github.com/ThreeDotsLabs/watermill v1.3.7 h1:NV0PSTmuACVEOV4dMxRnmGXrmbz8U83LENOvpHekN7o=
|
||||
github.com/ThreeDotsLabs/watermill v1.3.7/go.mod h1:lBnrLbxOjeMRgcJbv+UiZr8Ylz8RkJ4m6i/VN/Nk+to=
|
||||
github.com/adlio/trello v1.12.0 h1:JqOE2GFHQ9YtEviRRRSnicSxPbt4WFOxhqXzjMOw8lw=
|
||||
github.com/adlio/trello v1.12.0/go.mod h1:I4Lti4jf2KxjTNgTqs5W3lLuE78QZZdYbbPnQQGwjOo=
|
||||
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
|
||||
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
|
||||
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
||||
github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ=
|
||||
github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk=
|
||||
github.com/arran4/golang-ical v0.3.1 h1:v13B3eQZ9VDHTAvT6M11vVzxYgcYmjyPBE2eAZl3VZk=
|
||||
@@ -56,8 +56,6 @@ github.com/cenkalti/backoff/v3 v3.2.2 h1:cfUAAO3yvKMYKPrvhDuHSwQnhZNk/RMHKdZqKTx
|
||||
github.com/cenkalti/backoff/v3 v3.2.2/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs=
|
||||
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY=
|
||||
github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic=
|
||||
github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
@@ -79,8 +77,10 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
|
||||
github.com/denisenkom/go-mssqldb v0.12.3 h1:pBSGx9Tq67pBOTLmxNuirNTeB8Vjmf886Kx+8Y+8shw=
|
||||
github.com/denisenkom/go-mssqldb v0.12.3/go.mod h1:k0mtMFOnU+AihqFxPMiF05rtiDrorD1Vrm1KEz5hxDo=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||
github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
|
||||
@@ -99,18 +99,12 @@ github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nos
|
||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||
github.com/gabriel-vasile/mimetype v1.4.4 h1:QjV6pZ7/XZ7ryI2KuyeEDE8wnh7fHP9YnQy+R0LnH8I=
|
||||
github.com/gabriel-vasile/mimetype v1.4.4/go.mod h1:JwLei5XPtWdGiMFB5Pjle1oEeoSeEuJfJE+TtfvdB/s=
|
||||
github.com/gabriel-vasile/mimetype v1.4.5 h1:J7wGKdGu33ocBOhGy0z653k/lFKLFDPJMG8Gql0kxn4=
|
||||
github.com/gabriel-vasile/mimetype v1.4.5/go.mod h1:ibHel+/kbxn9x2407k1izTA1S81ku1z/DlgOW2QE0M4=
|
||||
github.com/ganigeorgiev/fexpr v0.4.1 h1:hpUgbUEEWIZhSDBtf4M9aUNfQQ0BZkGRaMePy7Gcx5k=
|
||||
github.com/ganigeorgiev/fexpr v0.4.1/go.mod h1:RyGiGqmeXhEQ6+mlGdnUleLHgtzzu/VGO2WtJkF5drE=
|
||||
github.com/getsentry/sentry-go v0.28.1 h1:zzaSm/vHmGllRM6Tpx1492r0YDzauArdBfkJRtY6P5k=
|
||||
github.com/getsentry/sentry-go v0.28.1/go.mod h1:1fQZ+7l7eeJ3wYi82q5Hg8GqAPgefRq+FP/QhafYVgg=
|
||||
github.com/getsentry/sentry-go v0.29.0 h1:YtWluuCFg9OfcqnaujpY918N/AhCCwarIDWOYSBAjCA=
|
||||
github.com/getsentry/sentry-go v0.29.0/go.mod h1:jhPesDAL0Q0W2+2YEuVOvdWmVtdsr1+jtBrlDEVWwLY=
|
||||
github.com/go-chi/chi/v5 v5.0.10 h1:rLz5avzKpjqxrYwXNfmjkrYYXOyLJd37pz53UFHC6vk=
|
||||
github.com/go-chi/chi/v5 v5.0.10/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||
github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw=
|
||||
github.com/go-chi/chi/v5 v5.1.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
|
||||
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
|
||||
github.com/go-faster/city v1.0.1 h1:4WAxSZ3V2Ws4QRDrscLEDcibJY8uf41H6AhXDrNDcGw=
|
||||
@@ -134,6 +128,7 @@ github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh
|
||||
github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
|
||||
github.com/go-openapi/swag v0.22.8 h1:/9RjDSQ0vbFR+NyjGMkFTsA1IA0fmhKSThmfGZjicbw=
|
||||
github.com/go-openapi/swag v0.22.8/go.mod h1:6QT22icPLEqAM/z/TChgb4WAveCHF92+2gF0CNjHpPI=
|
||||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
|
||||
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
|
||||
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
||||
@@ -284,8 +279,6 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o
|
||||
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg=
|
||||
github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
|
||||
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||
github.com/kolaente/caldav-go v3.0.1-0.20190610114120-2a4eb8b5dcc9+incompatible h1:q7DbyV+sFjEoTuuUdRDNl2nlyfztkZgxVVCV7JhzIkY=
|
||||
github.com/kolaente/caldav-go v3.0.1-0.20190610114120-2a4eb8b5dcc9+incompatible/go.mod h1:y1UhTNI4g0hVymJrI6yJ5/ohy09hNBeU8iJEZjgdDOw=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
@@ -300,8 +293,10 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/labstack/echo-jwt/v4 v4.2.0 h1:odSISV9JgcSCuhgQSV/6Io3i7nUmfM/QkBeR5GVJj5c=
|
||||
github.com/labstack/echo-jwt/v4 v4.2.0/go.mod h1:MA2RqdXdEn4/uEglx0HcUOgQSyBaTh5JcaHIan3biwU=
|
||||
github.com/labstack/echo/v4 v4.1.16/go.mod h1:awO+5TzAjvL8XpibdsfXxPgHr+orhtXZJZIQCVjogKI=
|
||||
github.com/labstack/echo/v4 v4.12.0 h1:IKpw49IMryVB2p1a4dzwlhP1O2Tf2E0Ir/450lH+kI0=
|
||||
github.com/labstack/echo/v4 v4.12.0/go.mod h1:UP9Cr2DJXbOK3Kr9ONYzNowSh7HP0aG0ShAyycHSJvM=
|
||||
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
|
||||
github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
|
||||
github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU=
|
||||
github.com/laurent22/ical-go v0.1.1-0.20181107184520-7e5d6ade8eef h1:RZnRnSID1skF35j/15KJ6hKZkdIC/teQClJK5wP5LU4=
|
||||
@@ -309,6 +304,7 @@ github.com/laurent22/ical-go v0.1.1-0.20181107184520-7e5d6ade8eef/go.mod h1:4LAT
|
||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.7.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
||||
@@ -327,11 +323,15 @@ github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJ
|
||||
github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A=
|
||||
github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA=
|
||||
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
|
||||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
@@ -339,12 +339,11 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus=
|
||||
github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
|
||||
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
github.com/mattn/go-sqlite3 v1.14.23 h1:gbShiuAP1W5j9UOksQ06aiiqPMxYecovVGwmTxWtuw0=
|
||||
github.com/mattn/go-sqlite3 v1.14.23/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk=
|
||||
github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
@@ -356,8 +355,6 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8=
|
||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||
@@ -401,28 +398,14 @@ github.com/pquerna/otp v1.4.0 h1:wZvl1TIVxKRThZIBiwOOHOGP/1+nZyWBil9Y2XNEDzg=
|
||||
github.com/pquerna/otp v1.4.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
|
||||
github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE=
|
||||
github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho=
|
||||
github.com/prometheus/client_golang v1.20.2 h1:5ctymQzZlyOON1666svgwn3s6IKWgfbjsejTMiXIyjg=
|
||||
github.com/prometheus/client_golang v1.20.2/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
|
||||
github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4=
|
||||
github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
|
||||
github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI=
|
||||
github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
|
||||
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
|
||||
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
|
||||
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
||||
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
||||
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/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc=
|
||||
github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8=
|
||||
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
|
||||
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
|
||||
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
|
||||
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
|
||||
github.com/redis/go-redis/v9 v9.5.3 h1:fOAp1/uJG+ZtcITgZOfYFmTKPE7n4Vclj1wZFgRciUU=
|
||||
github.com/redis/go-redis/v9 v9.5.3/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M=
|
||||
github.com/redis/go-redis/v9 v9.6.1 h1:HHDteefn6ZkTtY5fGUE8tj8uy85AHk6zP7CpzIAM0y4=
|
||||
github.com/redis/go-redis/v9 v9.6.1/go.mod h1:0C0c6ycQsdpVNQpxb1njEQIqkx5UcsM8FJCQLgE9+RA=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
@@ -456,8 +439,6 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sony/gobreaker v0.5.0 h1:dRCvqm0P490vZPmy7ppEk2qCnCieBooFJ+YoXGYB+yg=
|
||||
github.com/sony/gobreaker v0.5.0/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
|
||||
github.com/sony/gobreaker v1.0.0 h1:feX5fGGXSl3dYd4aHZItw+FpHLvvoaqkawKjVNiFMNQ=
|
||||
github.com/sony/gobreaker v1.0.0/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
|
||||
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
|
||||
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
|
||||
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
|
||||
@@ -503,17 +484,19 @@ github.com/tkuchiki/go-timezone v0.2.3 h1:D3TVdIPrFsu9lxGxqNX2wsZwn1MZtTqTW0mdev
|
||||
github.com/tkuchiki/go-timezone v0.2.3/go.mod h1:oFweWxYl35C/s7HMVZXiA19Jr9Y0qJHMaG/J2TES4LY=
|
||||
github.com/typesense/typesense-go v1.1.0 h1:QocehDarVXRArMIosPIdawiVFZZbnRkPJxwnAGOFkzw=
|
||||
github.com/typesense/typesense-go v1.1.0/go.mod h1:KcPODU7ltrcUFC/gygMTkAAfZ9M8/q6ayrdl1MnE1kI=
|
||||
github.com/typesense/typesense-go/v2 v2.0.0/go.mod h1:7V1ZBSfmdciL6yb2bPtWha+W53gV5WZhyOSpVgDJfao=
|
||||
github.com/ulule/limiter/v3 v3.11.2 h1:P4yOrxoEMJbOTfRJR2OzjL90oflzYPPmWg+dvwN2tHA=
|
||||
github.com/ulule/limiter/v3 v3.11.2/go.mod h1:QG5GnFOCV+k7lrL5Y8kgEeeflPH3+Cviqlqa8SVSQxI=
|
||||
github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M=
|
||||
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
|
||||
github.com/valyala/fasttemplate v1.1.0/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
|
||||
github.com/valyala/fasttemplate v1.2.0/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
|
||||
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
|
||||
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||
github.com/wneessen/go-mail v0.4.4 h1:rI8wJzPYymUpUth87vFV3k313bmnid4v+FwhBAYYLFM=
|
||||
github.com/wneessen/go-mail v0.4.4/go.mod h1:zxOlafWCP/r6FEhAaRgH4IC1vg2YXxO0Nar9u0IScZ8=
|
||||
github.com/wneessen/go-mail v0.4.2 h1:wISuU9LOGqrA7pxy7OipRtwoExXTzuGKmAjb8gYwc00=
|
||||
github.com/wneessen/go-mail v0.4.2/go.mod h1:zxOlafWCP/r6FEhAaRgH4IC1vg2YXxO0Nar9u0IScZ8=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
||||
github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g=
|
||||
github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8=
|
||||
@@ -548,11 +531,14 @@ go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
@@ -562,15 +548,11 @@ golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0
|
||||
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
||||
golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
|
||||
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
|
||||
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
|
||||
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
|
||||
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=
|
||||
golang.org/x/image v0.18.0 h1:jGzIakQa/ZXI1I0Fxvaa9W7yP25TqT6cHIHn+6CqvSQ=
|
||||
golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E=
|
||||
golang.org/x/image v0.20.0 h1:7cVCUjQwfL18gyBJOmYvptfSHS8Fb3YUDtfLIZ7Nbpw=
|
||||
golang.org/x/image v0.20.0/go.mod h1:0a88To4CYVBAHp5FXJm8o7QbUl37Vd85ply1vyD8auM=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
@@ -579,13 +561,17 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
|
||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM=
|
||||
@@ -598,8 +584,6 @@ golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
|
||||
golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
|
||||
golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs=
|
||||
golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
||||
golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs=
|
||||
golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -608,8 +592,6 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -625,6 +607,7 @@ golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200808120158-1030fc2bf1d9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -639,16 +622,12 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
|
||||
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
|
||||
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk=
|
||||
golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4=
|
||||
golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM=
|
||||
golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
@@ -658,8 +637,6 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
|
||||
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
||||
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
|
||||
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
@@ -697,8 +674,6 @@ 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.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
||||
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
||||
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=
|
||||
@@ -774,9 +749,11 @@ src.techknowlogick.com/xgo v1.7.1-0.20240403232151-e01c4fbef884 h1:Ttvt8FCpUXfC8
|
||||
src.techknowlogick.com/xgo v1.7.1-0.20240403232151-e01c4fbef884/go.mod h1:31CE1YKtDOrKTk9PSnjTpe6YbO6W/0LTYZ1VskL09oU=
|
||||
src.techknowlogick.com/xormigrate v1.7.1 h1:RKGLLUAqJ+zO8iZ7eOc7oLH7f0cs2gfXSZSvBRBHnlY=
|
||||
src.techknowlogick.com/xormigrate v1.7.1/go.mod h1:YGNBdj8prENlySwIKmfoEXp7ILGjAltyKFXD0qLgD7U=
|
||||
xorm.io/builder v0.3.7/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
|
||||
xorm.io/builder v0.3.11-0.20220531020008-1bd24a7dc978/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
|
||||
xorm.io/builder v0.3.13 h1:a3jmiVVL19psGeXx8GIurTp7p0IIgqeDmwhcR6BAOAo=
|
||||
xorm.io/builder v0.3.13/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
|
||||
xorm.io/xorm v1.0.5/go.mod h1:uF9EtbhODq5kNWxMbnBEj8hRRZnlcNSz2t2N7HW/+A4=
|
||||
xorm.io/xorm v1.3.3/go.mod h1:qFJGFoVYbbIdnz2vaL5OxSQ2raleMpyRRalnq3n9OJo=
|
||||
xorm.io/xorm v1.3.9 h1:TUovzS0ko+IQ1XnNLfs5dqK1cJl1H5uHpWbWqAQ04nU=
|
||||
xorm.io/xorm v1.3.9/go.mod h1:LsCCffeeYp63ssk0pKumP6l96WZcHix7ChpurcLNuMw=
|
||||
|
||||
+1
-21
@@ -464,26 +464,6 @@ func (Build) Build() {
|
||||
runAndStreamOutput("go", "build", Goflags[0], "-tags", Tags, "-ldflags", "-s -w "+Ldflags, "-o", Executable)
|
||||
}
|
||||
|
||||
func (Build) SaveVersionToFile() error {
|
||||
// Open the file for writing. If the file doesn't exist, create it.
|
||||
// If it exists, truncate it.
|
||||
file, err := os.Create("VERSION")
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating VERSION file: %w", err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
// Write the version number to the file
|
||||
_, err = file.WriteString(VersionNumber)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error writing to VERSION file: %w", err)
|
||||
}
|
||||
|
||||
fmt.Println("Version number saved successfully to VERSION file")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type Release mg.Namespace
|
||||
|
||||
// Runs all steps in the right order to create release packages for various platforms
|
||||
@@ -813,7 +793,7 @@ func init() {
|
||||
ID: "` + date + `",
|
||||
Description: "",
|
||||
Migrate: func(tx *xorm.Engine) error {
|
||||
return tx.Sync(` + str + date + `{})
|
||||
return tx.Sync2(` + str + date + `{})
|
||||
},
|
||||
Rollback: func(tx *xorm.Engine) error {
|
||||
return nil
|
||||
|
||||
@@ -92,8 +92,7 @@ func getCaldavColor(color string) (caldavcolor string) {
|
||||
return `
|
||||
X-APPLE-CALENDAR-COLOR:` + color + `
|
||||
X-OUTLOOK-COLOR:` + color + `
|
||||
X-FUNAMBOL-COLOR:` + color + `
|
||||
COLOR:` + color
|
||||
X-FUNAMBOL-COLOR:` + color
|
||||
}
|
||||
|
||||
func formatDuration(duration time.Duration) string {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user