forked from vikunja/frontend
Compare commits
6 Commits
9312aa14fa
...
8fa8b03aa6
Author | SHA1 | Date | |
---|---|---|---|
8fa8b03aa6 | |||
e4499f44b7 | |||
b799233bca | |||
be0ae4bc29 | |||
60d99f3bba | |||
fa666d2817 |
87
Dockerfile
87
Dockerfile
|
@ -1,49 +1,68 @@
|
||||||
# Stage 1: Build application
|
# syntax=docker/dockerfile:1
|
||||||
FROM --platform=$BUILDPLATFORM node:18-alpine AS compile-image
|
# ┬─┐┬ ┐o┬ ┬─┐
|
||||||
|
# │─││ │││ │ │
|
||||||
|
# ┘─┘┘─┘┘┘─┘┘─┘
|
||||||
|
|
||||||
|
FROM node:18-alpine AS builder
|
||||||
|
|
||||||
WORKDIR /build
|
WORKDIR /build
|
||||||
|
|
||||||
ARG USE_RELEASE=false
|
ARG USE_RELEASE=false
|
||||||
ARG RELEASE_VERSION=main
|
ARG RELEASE_VERSION=main
|
||||||
|
|
||||||
ENV PNPM_CACHE_FOLDER .cache/pnpm/
|
ENV PNPM_CACHE_FOLDER .cache/pnpm/
|
||||||
ADD . ./
|
|
||||||
|
|
||||||
RUN \
|
COPY package.json ./
|
||||||
if [ $USE_RELEASE = true ]; then \
|
COPY pnpm-lock.yaml ./
|
||||||
wget https://dl.vikunja.io/frontend/vikunja-frontend-$RELEASE_VERSION.zip -O frontend-release.zip && \
|
|
||||||
unzip frontend-release.zip -d dist/ && \
|
|
||||||
exit 0; \
|
|
||||||
fi && \
|
|
||||||
# https://pnpm.io/installation#using-corepack
|
|
||||||
corepack enable && \
|
|
||||||
# we don't use corepack prepare here by intend since
|
|
||||||
# we have renovate to keep our dependencies up to date
|
|
||||||
# Build the frontend
|
|
||||||
pnpm install && \
|
|
||||||
apk add --no-cache git && \
|
|
||||||
echo '{"VERSION": "'$(git describe --tags --always --abbrev=10 | sed 's/-/+/' | sed 's/^v//' | sed 's/-g/-/')'"}' > src/version.json && \
|
|
||||||
pnpm run build
|
|
||||||
|
|
||||||
# Stage 2: copy
|
RUN if [ "$USE_RELEASE" != true ]; then \
|
||||||
FROM nginx:alpine
|
# https://pnpm.io/installation#using-corepack
|
||||||
|
corepack enable && \
|
||||||
|
pnpm install; \
|
||||||
|
fi
|
||||||
|
|
||||||
COPY nginx.conf /etc/nginx/nginx.conf
|
COPY . ./
|
||||||
COPY scripts/run.sh /run.sh
|
|
||||||
|
|
||||||
# copy compiled files from stage 1
|
RUN if [ "$USE_RELEASE" != true ]; then \
|
||||||
COPY --from=compile-image /build/dist /usr/share/nginx/html
|
apk add --no-cache --virtual .build-deps git jq && \
|
||||||
|
git describe --tags --always --abbrev=10 | sed 's/-/+/; s/^v//; s/-g/-/' | \
|
||||||
|
xargs -0 -I{} jq -Mcnr --arg version {} '{VERSION:$version}' | \
|
||||||
|
tee src/version.json && \
|
||||||
|
apk del .build-deps; \
|
||||||
|
fi
|
||||||
|
|
||||||
# Unprivileged user
|
RUN if [ "$USE_RELEASE" = true ]; then \
|
||||||
ENV PUID 1000
|
wget "https://dl.vikunja.io/frontend/vikunja-frontend-${RELEASE_VERSION}.zip" -O frontend-release.zip && \
|
||||||
ENV PGID 1000
|
unzip frontend-release.zip -d dist/; \
|
||||||
|
else \
|
||||||
|
# we don't use corepack prepare here by intend since
|
||||||
|
# we have renovate to keep our dependencies up to date
|
||||||
|
# Build the frontend
|
||||||
|
pnpm run build; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ┌┐┐┌─┐o┌┐┐┐ │
|
||||||
|
# ││││ ┬││││┌┼┘
|
||||||
|
# ┘└┘┘─┘┘┘└┘┘ └
|
||||||
|
|
||||||
|
FROM nginx:stable-alpine AS runner
|
||||||
|
WORKDIR /usr/share/nginx/html
|
||||||
LABEL maintainer="maintainers@vikunja.io"
|
LABEL maintainer="maintainers@vikunja.io"
|
||||||
|
|
||||||
RUN apk add --no-cache \
|
ENV VIKUNJA_HTTP_PORT 80
|
||||||
# for sh file
|
ENV VIKUNJA_HTTP2_PORT 81
|
||||||
bash \
|
ENV VIKUNJA_LOG_FORMAT main
|
||||||
# installs usermod and groupmod
|
ENV VIKUNJA_API_URL http://localhost:3456/api/v1
|
||||||
shadow
|
ENV VIKUNJA_SENTRY_ENABLED false
|
||||||
|
ENV VIKUNJA_SENTRY_DSN https://85694a2d757547cbbc90cd4b55c5a18d@o1047380.ingest.sentry.io/6024480
|
||||||
|
|
||||||
CMD "/run.sh"
|
COPY docker/injector.sh /docker-entrypoint.d/50-injector.sh
|
||||||
|
COPY docker/nginx.conf /etc/nginx/nginx.conf
|
||||||
|
COPY docker/templates/. /etc/nginx/templates/
|
||||||
|
# copy compiled files from stage 1
|
||||||
|
COPY --from=builder /build/dist ./
|
||||||
|
# manage permissions
|
||||||
|
RUN chmod 0755 /docker-entrypoint.d/*.sh /etc/nginx/templates && \
|
||||||
|
chmod -R 0644 /etc/nginx/nginx.conf && \
|
||||||
|
chown -R nginx:nginx ./ /etc/nginx/conf.d /etc/nginx/templates
|
||||||
|
# unprivileged user
|
||||||
|
USER nginx
|
||||||
|
|
|
@ -18,6 +18,14 @@ If you find any security-related issues you don't want to disclose publicly, ple
|
||||||
## Docker
|
## Docker
|
||||||
|
|
||||||
There is a [docker image available](https://hub.docker.com/r/vikunja/api) with support for http/2 and aggressive caching enabled.
|
There is a [docker image available](https://hub.docker.com/r/vikunja/api) with support for http/2 and aggressive caching enabled.
|
||||||
|
In order to build it from sources run the command below. (Docker >= v19.03)
|
||||||
|
|
||||||
|
```shell
|
||||||
|
export DOCKER_BUILDKIT=1
|
||||||
|
docker build -t vikunja/frontend .
|
||||||
|
```
|
||||||
|
|
||||||
|
Refer to Refer [to multi-platform documentation](https://docs.docker.com/build/building/multi-platform/) in order to build for the different platform.
|
||||||
|
|
||||||
## Project setup
|
## Project setup
|
||||||
|
|
||||||
|
|
15
docker/injector.sh
Normal file
15
docker/injector.sh
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
#!/usr/bin/env sh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "info: API URL is $VIKUNJA_API_URL"
|
||||||
|
echo "info: Sentry enabled: $VIKUNJA_SENTRY_ENABLED"
|
||||||
|
|
||||||
|
# Escape the variable to prevent sed from complaining
|
||||||
|
VIKUNJA_API_URL="$(echo "$VIKUNJA_API_URL" | sed -r 's/([:;])/\\\1/g')"
|
||||||
|
VIKUNJA_SENTRY_DSN="$(echo "$VIKUNJA_SENTRY_DSN" | sed -r 's/([:;])/\\\1/g')"
|
||||||
|
|
||||||
|
sed -ri "s:^(\s*window.API_URL\s*=)\s*.+:\1 '${VIKUNJA_API_URL}':g" /usr/share/nginx/html/index.html
|
||||||
|
sed -ri "s:^(\s*window.SENTRY_ENABLED\s*=)\s*.+:\1 ${VIKUNJA_SENTRY_ENABLED}:g" /usr/share/nginx/html/index.html
|
||||||
|
sed -ri "s:^(\s*window.SENTRY_DSN\s*=)\s*.+:\1 '${VIKUNJA_SENTRY_DSN}':g" /usr/share/nginx/html/index.html
|
||||||
|
|
||||||
|
date -uIseconds | xargs echo 'info: started at'
|
112
docker/nginx.conf
Normal file
112
docker/nginx.conf
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
# Generated by nginxconfig.io
|
||||||
|
# https://www.digitalocean.com/community/tools/nginx?domains.0.server.domain=localhost&domains.0.server.documentRoot=%2Fusr%2Fshare%2Fnginx%2Fhtml&domains.0.server.cdnSubdomain=true&domains.0.https.https=false&domains.0.php.php=false&domains.0.routing.index=index.html&domains.0.routing.fallbackHtml=true&domains.0.routing.fallbackPhp=false&global.performance.assetsExpiration=1d&global.performance.mediaExpiration=1d&global.performance.svgExpiration=1d&global.performance.fontsExpiration=1d&global.logging.accessLog=%2Fdev%2Fstdout&global.logging.errorLog=%2Fdev%2Fstderr%20warn&global.logging.logNotFound=true&global.nginx.user=nginx&global.nginx.pid=%2Fvar%2Frun%2Fnginx.pid&global.nginx.clientMaxBodySize=50&global.docker.dockerfile=true&global.tools.modularizedStructure=false&global.tools.symlinkVhost=false
|
||||||
|
# and then edited manually ;)
|
||||||
|
|
||||||
|
pid /tmp/nginx.pid;
|
||||||
|
worker_processes auto;
|
||||||
|
worker_rlimit_nofile 65535;
|
||||||
|
|
||||||
|
events {
|
||||||
|
multi_accept on;
|
||||||
|
worker_connections 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
http {
|
||||||
|
charset utf-8;
|
||||||
|
sendfile on;
|
||||||
|
tcp_nopush on;
|
||||||
|
tcp_nodelay on;
|
||||||
|
server_tokens off;
|
||||||
|
types_hash_max_size 2048;
|
||||||
|
types_hash_bucket_size 64;
|
||||||
|
|
||||||
|
# rootless
|
||||||
|
client_body_temp_path /tmp/client_temp;
|
||||||
|
proxy_temp_path /tmp/proxy_temp_path;
|
||||||
|
fastcgi_temp_path /tmp/fastcgi_temp;
|
||||||
|
uwsgi_temp_path /tmp/uwsgi_temp;
|
||||||
|
scgi_temp_path /tmp/scgi_temp;
|
||||||
|
|
||||||
|
# MIME
|
||||||
|
include mime.types;
|
||||||
|
default_type application/octet-stream;
|
||||||
|
types {
|
||||||
|
application/manifest+json webmanifest;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Logging
|
||||||
|
log_format json escape=json
|
||||||
|
'{'
|
||||||
|
'"bytes_sent": "$bytes_sent",'
|
||||||
|
'"http_user_agent": "$http_user_agent",'
|
||||||
|
'"nginx_version": "$nginx_version",'
|
||||||
|
'"query_string": "$query_string",'
|
||||||
|
'"realip_remote_addr": "$realip_remote_addr",'
|
||||||
|
'"remote_addr": "$remote_addr",'
|
||||||
|
'"remote_user": "$remote_user",'
|
||||||
|
'"request_length": "$request_length",'
|
||||||
|
'"request_method": "$request_method",'
|
||||||
|
'"request_time": "$request_time",'
|
||||||
|
'"server_addr": "$server_addr",'
|
||||||
|
'"server_port": "$server_port",'
|
||||||
|
'"server_protocol": "$server_protocol",'
|
||||||
|
'"status": "$status",'
|
||||||
|
'"time_local": "$time_local",'
|
||||||
|
'"uri": "$uri"'
|
||||||
|
'}';
|
||||||
|
|
||||||
|
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||||
|
'$status $body_bytes_sent "$http_referer" '
|
||||||
|
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||||
|
|
||||||
|
access_log /dev/stdout main;
|
||||||
|
error_log /dev/stderr warn;
|
||||||
|
|
||||||
|
keepalive_timeout 65;
|
||||||
|
|
||||||
|
# compression
|
||||||
|
gzip on;
|
||||||
|
gzip_vary on;
|
||||||
|
gzip_proxied any;
|
||||||
|
gzip_comp_level 6;
|
||||||
|
gzip_buffers 16 8k;
|
||||||
|
gzip_http_version 1.1;
|
||||||
|
gzip_min_length 256;
|
||||||
|
gzip_types
|
||||||
|
text/plain
|
||||||
|
text/css
|
||||||
|
application/json
|
||||||
|
application/x-javascript
|
||||||
|
application/javascript
|
||||||
|
text/xml
|
||||||
|
application/xml
|
||||||
|
application/xml+rss
|
||||||
|
text/javascript
|
||||||
|
application/vnd.ms-fontobject
|
||||||
|
application/x-font-ttf
|
||||||
|
font/opentype
|
||||||
|
image/svg+xml
|
||||||
|
image/x-icon
|
||||||
|
audio/wav;
|
||||||
|
|
||||||
|
map_hash_max_size 128;
|
||||||
|
map_hash_bucket_size 128;
|
||||||
|
|
||||||
|
map $sent_http_content_type $expires {
|
||||||
|
default off;
|
||||||
|
text/css max;
|
||||||
|
application/javascript max;
|
||||||
|
text/javascript max;
|
||||||
|
application/vnd.ms-fontobject max;
|
||||||
|
application/x-font-ttf max;
|
||||||
|
font/opentype max;
|
||||||
|
font/woff2 max;
|
||||||
|
image/svg+xml max;
|
||||||
|
image/x-icon max;
|
||||||
|
audio/wav max;
|
||||||
|
~images/ max;
|
||||||
|
~font/ max;
|
||||||
|
}
|
||||||
|
|
||||||
|
include /etc/nginx/conf.d/*.conf;
|
||||||
|
}
|
71
docker/templates/default.conf.template
Normal file
71
docker/templates/default.conf.template
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
server {
|
||||||
|
listen ${VIKUNJA_HTTP_PORT};
|
||||||
|
listen [::]:${VIKUNJA_HTTP_PORT};
|
||||||
|
## Needed when behind HAProxy with SSL termination + HTTP/2 support
|
||||||
|
listen ${VIKUNJA_HTTP2_PORT} default_server http2 proxy_protocol;
|
||||||
|
listen [::]:${VIKUNJA_HTTP2_PORT} default_server http2 proxy_protocol;
|
||||||
|
|
||||||
|
server_name _;
|
||||||
|
expires $expires;
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
access_log /dev/stdout ${VIKUNJA_LOG_FORMAT};
|
||||||
|
# security headers
|
||||||
|
add_header X-XSS-Protection "1; mode=block" always;
|
||||||
|
add_header X-Content-Type-Options "nosniff" always;
|
||||||
|
add_header Referrer-Policy "no-referrer-when-downgrade" always;
|
||||||
|
add_header Content-Security-Policy "default-src 'self' http: https: ws: wss: data: blob: 'unsafe-inline'; frame-ancestors 'self';" always;
|
||||||
|
add_header Permissions-Policy "interest-cohort=()" always;
|
||||||
|
|
||||||
|
# . files
|
||||||
|
location ~ /\.(?!well-known) {
|
||||||
|
deny all;
|
||||||
|
}
|
||||||
|
|
||||||
|
# assume that everything else is handled by the application router, by injecting the index.html.
|
||||||
|
location / {
|
||||||
|
autoindex off;
|
||||||
|
expires off;
|
||||||
|
add_header Cache-Control "public, max-age=0, s-maxage=0, must-revalidate" always;
|
||||||
|
try_files $uri /index.html =404;
|
||||||
|
}
|
||||||
|
|
||||||
|
# favicon.ico
|
||||||
|
location = /favicon.ico {
|
||||||
|
log_not_found off;
|
||||||
|
access_log off;
|
||||||
|
}
|
||||||
|
|
||||||
|
# robots.txt
|
||||||
|
location = /robots.txt {
|
||||||
|
log_not_found off;
|
||||||
|
access_log off;
|
||||||
|
expires -1; # no-cache
|
||||||
|
}
|
||||||
|
|
||||||
|
location = /ready {
|
||||||
|
return 200 "";
|
||||||
|
access_log off;
|
||||||
|
expires -1; # no-cache
|
||||||
|
}
|
||||||
|
|
||||||
|
# all assets contain hash in filename, cache forever
|
||||||
|
location ^~ /assets/ {
|
||||||
|
add_header Cache-Control "public, max-age=31536000, s-maxage=31536000, immutable";
|
||||||
|
try_files $uri =404;
|
||||||
|
}
|
||||||
|
|
||||||
|
# all workbox scripts are compiled with hash in filename, cache forever3
|
||||||
|
location ^~ /workbox- {
|
||||||
|
add_header Cache-Control "public, max-age=31536000, s-maxage=31536000, immutable";
|
||||||
|
try_files $uri =404;
|
||||||
|
}
|
||||||
|
|
||||||
|
# assets, media
|
||||||
|
location ~* .(txt|webmanifest|css|js|mjs|map|svg|jpg|jpeg|png|ico|ttf|woff|woff2|wav)$ {
|
||||||
|
try_files $uri $uri/ =404;
|
||||||
|
}
|
||||||
|
|
||||||
|
error_page 500 502 503 504 /50x.html;
|
||||||
|
location = /50x.html { }
|
||||||
|
|
||||||
|
}
|
117
nginx.conf
117
nginx.conf
|
@ -1,117 +0,0 @@
|
||||||
user nginx;
|
|
||||||
worker_processes 1;
|
|
||||||
|
|
||||||
error_log /var/log/nginx/error.log warn;
|
|
||||||
pid /var/run/nginx.pid;
|
|
||||||
|
|
||||||
|
|
||||||
events {
|
|
||||||
worker_connections 1024;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
http {
|
|
||||||
include /etc/nginx/mime.types;
|
|
||||||
default_type application/octet-stream;
|
|
||||||
|
|
||||||
types {
|
|
||||||
application/manifest+json webmanifest;
|
|
||||||
}
|
|
||||||
|
|
||||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
|
||||||
'$status $body_bytes_sent "$http_referer" '
|
|
||||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
|
||||||
|
|
||||||
access_log /var/log/nginx/access.log main;
|
|
||||||
|
|
||||||
sendfile on;
|
|
||||||
#tcp_nopush on;
|
|
||||||
|
|
||||||
keepalive_timeout 65;
|
|
||||||
|
|
||||||
gzip on;
|
|
||||||
|
|
||||||
gzip_vary on;
|
|
||||||
gzip_proxied any;
|
|
||||||
gzip_comp_level 6;
|
|
||||||
gzip_buffers 16 8k;
|
|
||||||
gzip_http_version 1.1;
|
|
||||||
gzip_min_length 256;
|
|
||||||
gzip_types
|
|
||||||
text/plain
|
|
||||||
text/css
|
|
||||||
application/json
|
|
||||||
application/x-javascript
|
|
||||||
application/javascript
|
|
||||||
text/xml
|
|
||||||
application/xml
|
|
||||||
application/xml+rss
|
|
||||||
text/javascript
|
|
||||||
application/vnd.ms-fontobject
|
|
||||||
application/x-font-ttf
|
|
||||||
font/opentype
|
|
||||||
image/svg+xml
|
|
||||||
image/x-icon
|
|
||||||
audio/wav;
|
|
||||||
|
|
||||||
map_hash_max_size 128;
|
|
||||||
map_hash_bucket_size 128;
|
|
||||||
|
|
||||||
# Expires map
|
|
||||||
map $sent_http_content_type $expires {
|
|
||||||
default off;
|
|
||||||
text/css max;
|
|
||||||
application/javascript max;
|
|
||||||
text/javascript max;
|
|
||||||
application/vnd.ms-fontobject max;
|
|
||||||
application/x-font-ttf max;
|
|
||||||
font/opentype max;
|
|
||||||
font/woff2 max;
|
|
||||||
image/svg+xml max;
|
|
||||||
image/x-icon max;
|
|
||||||
audio/wav max;
|
|
||||||
~images/ max;
|
|
||||||
~font/ max;
|
|
||||||
}
|
|
||||||
|
|
||||||
server {
|
|
||||||
listen 80;
|
|
||||||
listen [::]:80;
|
|
||||||
listen 81 default_server http2 proxy_protocol; ## Needed when behind HAProxy with SSL termination + HTTP/2 support
|
|
||||||
listen [::]:81 default_server http2 proxy_protocol; ## Needed when behind HAProxy with SSL termination + HTTP/2 support
|
|
||||||
|
|
||||||
server_name _;
|
|
||||||
|
|
||||||
expires $expires;
|
|
||||||
|
|
||||||
root /usr/share/nginx/html;
|
|
||||||
|
|
||||||
# all assets contain hash in filename, cache forever
|
|
||||||
location ^~ /assets/ {
|
|
||||||
add_header Cache-Control "public, max-age=31536000, s-maxage=31536000, immutable";
|
|
||||||
try_files $uri =404;
|
|
||||||
}
|
|
||||||
|
|
||||||
# all workbox scripts are compiled with hash in filename, cache forever3
|
|
||||||
location ^~ /workbox- {
|
|
||||||
add_header Cache-Control "public, max-age=31536000, s-maxage=31536000, immutable";
|
|
||||||
try_files $uri =404;
|
|
||||||
}
|
|
||||||
|
|
||||||
# assume that everything else is handled by the application router, by injecting the index.html.
|
|
||||||
location / {
|
|
||||||
autoindex off;
|
|
||||||
expires off;
|
|
||||||
add_header Cache-Control "public, max-age=0, s-maxage=0, must-revalidate" always;
|
|
||||||
try_files $uri /index.html =404;
|
|
||||||
}
|
|
||||||
|
|
||||||
location ~* .(txt|webmanifest|css|js|mjs|map|svg|jpg|jpeg|png|ico|ttf|woff|woff2|wav)$ {
|
|
||||||
try_files $uri $uri/ =404;
|
|
||||||
}
|
|
||||||
|
|
||||||
error_page 500 502 503 504 /50x.html;
|
|
||||||
location = /50x.html {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -13,7 +13,7 @@
|
||||||
},
|
},
|
||||||
"homepage": "https://vikunja.io/",
|
"homepage": "https://vikunja.io/",
|
||||||
"funding": "https://opencollective.com/vikunja",
|
"funding": "https://opencollective.com/vikunja",
|
||||||
"packageManager": "pnpm@7.26.1",
|
"packageManager": "pnpm@7.26.2",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"todo",
|
"todo",
|
||||||
"productivity",
|
"productivity",
|
||||||
|
@ -34,7 +34,7 @@
|
||||||
"test:e2e-record": "start-server-and-test preview http://127.0.0.1:4173 'cypress run --e2e --browser chrome --record'",
|
"test:e2e-record": "start-server-and-test preview http://127.0.0.1:4173 'cypress run --e2e --browser chrome --record'",
|
||||||
"test:e2e-dev-dev": "start-server-and-test preview:dev http://127.0.0.1:4173 'cypress open --e2e'",
|
"test:e2e-dev-dev": "start-server-and-test preview:dev http://127.0.0.1:4173 'cypress open --e2e'",
|
||||||
"test:e2e-dev": "start-server-and-test preview http://127.0.0.1:4173 'cypress open --e2e'",
|
"test:e2e-dev": "start-server-and-test preview http://127.0.0.1:4173 'cypress open --e2e'",
|
||||||
"test:unit": "vitest",
|
"test:unit": "vitest --dir ./src",
|
||||||
"typecheck": "vue-tsc --noEmit && vue-tsc --noEmit -p tsconfig.vitest.json --composite false",
|
"typecheck": "vue-tsc --noEmit && vue-tsc --noEmit -p tsconfig.vitest.json --composite false",
|
||||||
"browserslist:update": "pnpm dlx browserslist@latest --update-db",
|
"browserslist:update": "pnpm dlx browserslist@latest --update-db",
|
||||||
"fonts:update": "pnpm fonts:download && pnpm fonts:subset",
|
"fonts:update": "pnpm fonts:download && pnpm fonts:subset",
|
||||||
|
@ -58,7 +58,7 @@
|
||||||
"@types/is-touch-device": "1.0.0",
|
"@types/is-touch-device": "1.0.0",
|
||||||
"@types/lodash.clonedeep": "4.5.7",
|
"@types/lodash.clonedeep": "4.5.7",
|
||||||
"@types/sortablejs": "1.15.0",
|
"@types/sortablejs": "1.15.0",
|
||||||
"@vueuse/core": "9.11.1",
|
"@vueuse/core": "9.12.0",
|
||||||
"axios": "1.2.6",
|
"axios": "1.2.6",
|
||||||
"blurhash": "2.0.4",
|
"blurhash": "2.0.4",
|
||||||
"bulma-css-variables": "0.9.33",
|
"bulma-css-variables": "0.9.33",
|
||||||
|
@ -121,7 +121,7 @@
|
||||||
"csstype": "3.1.1",
|
"csstype": "3.1.1",
|
||||||
"cypress": "12.4.1",
|
"cypress": "12.4.1",
|
||||||
"esbuild": "0.17.5",
|
"esbuild": "0.17.5",
|
||||||
"eslint": "8.32.0",
|
"eslint": "8.33.0",
|
||||||
"eslint-plugin-vue": "9.9.0",
|
"eslint-plugin-vue": "9.9.0",
|
||||||
"happy-dom": "8.1.5",
|
"happy-dom": "8.1.5",
|
||||||
"histoire": "0.12.4",
|
"histoire": "0.12.4",
|
||||||
|
|
|
@ -36,7 +36,7 @@ specifiers:
|
||||||
'@vue/eslint-config-typescript': 11.0.2
|
'@vue/eslint-config-typescript': 11.0.2
|
||||||
'@vue/test-utils': 2.2.8
|
'@vue/test-utils': 2.2.8
|
||||||
'@vue/tsconfig': 0.1.3
|
'@vue/tsconfig': 0.1.3
|
||||||
'@vueuse/core': 9.11.1
|
'@vueuse/core': 9.12.0
|
||||||
autoprefixer: 10.4.13
|
autoprefixer: 10.4.13
|
||||||
axios: 1.2.6
|
axios: 1.2.6
|
||||||
blurhash: 2.0.4
|
blurhash: 2.0.4
|
||||||
|
@ -52,7 +52,7 @@ specifiers:
|
||||||
dompurify: 2.4.3
|
dompurify: 2.4.3
|
||||||
easymde: 2.18.0
|
easymde: 2.18.0
|
||||||
esbuild: 0.17.5
|
esbuild: 0.17.5
|
||||||
eslint: 8.32.0
|
eslint: 8.33.0
|
||||||
eslint-plugin-vue: 9.9.0
|
eslint-plugin-vue: 9.9.0
|
||||||
fast-deep-equal: 3.1.3
|
fast-deep-equal: 3.1.3
|
||||||
flatpickr: 4.6.13
|
flatpickr: 4.6.13
|
||||||
|
@ -112,7 +112,7 @@ dependencies:
|
||||||
'@types/is-touch-device': 1.0.0
|
'@types/is-touch-device': 1.0.0
|
||||||
'@types/lodash.clonedeep': 4.5.7
|
'@types/lodash.clonedeep': 4.5.7
|
||||||
'@types/sortablejs': 1.15.0
|
'@types/sortablejs': 1.15.0
|
||||||
'@vueuse/core': 9.11.1_vue@3.2.45
|
'@vueuse/core': 9.12.0_vue@3.2.45
|
||||||
axios: 1.2.6
|
axios: 1.2.6
|
||||||
blurhash: 2.0.4
|
blurhash: 2.0.4
|
||||||
bulma-css-variables: 0.9.33
|
bulma-css-variables: 0.9.33
|
||||||
|
@ -162,11 +162,11 @@ devDependencies:
|
||||||
'@types/marked': 4.0.8
|
'@types/marked': 4.0.8
|
||||||
'@types/node': 18.11.18
|
'@types/node': 18.11.18
|
||||||
'@types/postcss-preset-env': 7.7.0
|
'@types/postcss-preset-env': 7.7.0
|
||||||
'@typescript-eslint/eslint-plugin': 5.49.0_iu322prlnwsygkcra5kbpy22si
|
'@typescript-eslint/eslint-plugin': 5.49.0_rsaczafy73x3xqauzesvzbsgzy
|
||||||
'@typescript-eslint/parser': 5.49.0_7uibuqfxkfaozanbtbziikiqje
|
'@typescript-eslint/parser': 5.49.0_zkdaqh7it7uc4cvz2haft7rc6u
|
||||||
'@vitejs/plugin-legacy': 3.0.2_terser@5.10.0+vite@4.0.4
|
'@vitejs/plugin-legacy': 3.0.2_terser@5.10.0+vite@4.0.4
|
||||||
'@vitejs/plugin-vue': 4.0.0_vite@4.0.4+vue@3.2.45
|
'@vitejs/plugin-vue': 4.0.0_vite@4.0.4+vue@3.2.45
|
||||||
'@vue/eslint-config-typescript': 11.0.2_5gm7ezxcdo2zu65gboxarjsumy
|
'@vue/eslint-config-typescript': 11.0.2_w5nyi6nqxtergbgmiezudsbkue
|
||||||
'@vue/test-utils': 2.2.8_o3nmwetfthgqihjljurbyiqgn4
|
'@vue/test-utils': 2.2.8_o3nmwetfthgqihjljurbyiqgn4
|
||||||
'@vue/tsconfig': 0.1.3_@types+node@18.11.18
|
'@vue/tsconfig': 0.1.3_@types+node@18.11.18
|
||||||
autoprefixer: 10.4.13_postcss@8.4.21
|
autoprefixer: 10.4.13_postcss@8.4.21
|
||||||
|
@ -175,8 +175,8 @@ devDependencies:
|
||||||
csstype: 3.1.1
|
csstype: 3.1.1
|
||||||
cypress: 12.4.1
|
cypress: 12.4.1
|
||||||
esbuild: 0.17.5
|
esbuild: 0.17.5
|
||||||
eslint: 8.32.0
|
eslint: 8.33.0
|
||||||
eslint-plugin-vue: 9.9.0_eslint@8.32.0
|
eslint-plugin-vue: 9.9.0_eslint@8.33.0
|
||||||
happy-dom: 8.1.5
|
happy-dom: 8.1.5
|
||||||
histoire: 0.12.4_jtbuayq2ea5xwom4rabzheoelm
|
histoire: 0.12.4_jtbuayq2ea5xwom4rabzheoelm
|
||||||
netlify-cli: 12.9.1_@types+node@18.11.18
|
netlify-cli: 12.9.1_@types+node@18.11.18
|
||||||
|
@ -2383,7 +2383,7 @@ packages:
|
||||||
dayjs: ^1.11.5
|
dayjs: ^1.11.5
|
||||||
vue: ^3.2.40
|
vue: ^3.2.40
|
||||||
dependencies:
|
dependencies:
|
||||||
'@vueuse/core': 9.11.1_vue@3.2.45
|
'@vueuse/core': 9.12.0_vue@3.2.45
|
||||||
dayjs: 1.11.7
|
dayjs: 1.11.7
|
||||||
vue: 3.2.45
|
vue: 3.2.45
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
|
@ -4004,7 +4004,7 @@ packages:
|
||||||
dev: true
|
dev: true
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
/@typescript-eslint/eslint-plugin/5.49.0_iu322prlnwsygkcra5kbpy22si:
|
/@typescript-eslint/eslint-plugin/5.49.0_rsaczafy73x3xqauzesvzbsgzy:
|
||||||
resolution: {integrity: sha512-IhxabIpcf++TBaBa1h7jtOWyon80SXPRLDq0dVz5SLFC/eW6tofkw/O7Ar3lkx5z5U6wzbKDrl2larprp5kk5Q==}
|
resolution: {integrity: sha512-IhxabIpcf++TBaBa1h7jtOWyon80SXPRLDq0dVz5SLFC/eW6tofkw/O7Ar3lkx5z5U6wzbKDrl2larprp5kk5Q==}
|
||||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
@ -4015,12 +4015,12 @@ packages:
|
||||||
typescript:
|
typescript:
|
||||||
optional: true
|
optional: true
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/parser': 5.49.0_7uibuqfxkfaozanbtbziikiqje
|
'@typescript-eslint/parser': 5.49.0_zkdaqh7it7uc4cvz2haft7rc6u
|
||||||
'@typescript-eslint/scope-manager': 5.49.0
|
'@typescript-eslint/scope-manager': 5.49.0
|
||||||
'@typescript-eslint/type-utils': 5.49.0_7uibuqfxkfaozanbtbziikiqje
|
'@typescript-eslint/type-utils': 5.49.0_zkdaqh7it7uc4cvz2haft7rc6u
|
||||||
'@typescript-eslint/utils': 5.49.0_7uibuqfxkfaozanbtbziikiqje
|
'@typescript-eslint/utils': 5.49.0_zkdaqh7it7uc4cvz2haft7rc6u
|
||||||
debug: 4.3.4
|
debug: 4.3.4
|
||||||
eslint: 8.32.0
|
eslint: 8.33.0
|
||||||
ignore: 5.2.0
|
ignore: 5.2.0
|
||||||
natural-compare-lite: 1.4.0
|
natural-compare-lite: 1.4.0
|
||||||
regexpp: 3.2.0
|
regexpp: 3.2.0
|
||||||
|
@ -4031,7 +4031,7 @@ packages:
|
||||||
- supports-color
|
- supports-color
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@typescript-eslint/parser/5.49.0_7uibuqfxkfaozanbtbziikiqje:
|
/@typescript-eslint/parser/5.49.0_zkdaqh7it7uc4cvz2haft7rc6u:
|
||||||
resolution: {integrity: sha512-veDlZN9mUhGqU31Qiv2qEp+XrJj5fgZpJ8PW30sHU+j/8/e5ruAhLaVDAeznS7A7i4ucb/s8IozpDtt9NqCkZg==}
|
resolution: {integrity: sha512-veDlZN9mUhGqU31Qiv2qEp+XrJj5fgZpJ8PW30sHU+j/8/e5ruAhLaVDAeznS7A7i4ucb/s8IozpDtt9NqCkZg==}
|
||||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
@ -4045,7 +4045,7 @@ packages:
|
||||||
'@typescript-eslint/types': 5.49.0
|
'@typescript-eslint/types': 5.49.0
|
||||||
'@typescript-eslint/typescript-estree': 5.49.0_typescript@4.9.4
|
'@typescript-eslint/typescript-estree': 5.49.0_typescript@4.9.4
|
||||||
debug: 4.3.4
|
debug: 4.3.4
|
||||||
eslint: 8.32.0
|
eslint: 8.33.0
|
||||||
typescript: 4.9.4
|
typescript: 4.9.4
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
@ -4059,7 +4059,7 @@ packages:
|
||||||
'@typescript-eslint/visitor-keys': 5.49.0
|
'@typescript-eslint/visitor-keys': 5.49.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@typescript-eslint/type-utils/5.49.0_7uibuqfxkfaozanbtbziikiqje:
|
/@typescript-eslint/type-utils/5.49.0_zkdaqh7it7uc4cvz2haft7rc6u:
|
||||||
resolution: {integrity: sha512-eUgLTYq0tR0FGU5g1YHm4rt5H/+V2IPVkP0cBmbhRyEmyGe4XvJ2YJ6sYTmONfjmdMqyMLad7SB8GvblbeESZA==}
|
resolution: {integrity: sha512-eUgLTYq0tR0FGU5g1YHm4rt5H/+V2IPVkP0cBmbhRyEmyGe4XvJ2YJ6sYTmONfjmdMqyMLad7SB8GvblbeESZA==}
|
||||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
@ -4070,9 +4070,9 @@ packages:
|
||||||
optional: true
|
optional: true
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/typescript-estree': 5.49.0_typescript@4.9.4
|
'@typescript-eslint/typescript-estree': 5.49.0_typescript@4.9.4
|
||||||
'@typescript-eslint/utils': 5.49.0_7uibuqfxkfaozanbtbziikiqje
|
'@typescript-eslint/utils': 5.49.0_zkdaqh7it7uc4cvz2haft7rc6u
|
||||||
debug: 4.3.4
|
debug: 4.3.4
|
||||||
eslint: 8.32.0
|
eslint: 8.33.0
|
||||||
tsutils: 3.21.0_typescript@4.9.4
|
tsutils: 3.21.0_typescript@4.9.4
|
||||||
typescript: 4.9.4
|
typescript: 4.9.4
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
|
@ -4126,7 +4126,7 @@ packages:
|
||||||
- supports-color
|
- supports-color
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@typescript-eslint/utils/5.49.0_7uibuqfxkfaozanbtbziikiqje:
|
/@typescript-eslint/utils/5.49.0_zkdaqh7it7uc4cvz2haft7rc6u:
|
||||||
resolution: {integrity: sha512-cPJue/4Si25FViIb74sHCLtM4nTSBXtLx1d3/QT6mirQ/c65bV8arBEebBJJizfq8W2YyMoPI/WWPFWitmNqnQ==}
|
resolution: {integrity: sha512-cPJue/4Si25FViIb74sHCLtM4nTSBXtLx1d3/QT6mirQ/c65bV8arBEebBJJizfq8W2YyMoPI/WWPFWitmNqnQ==}
|
||||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
@ -4137,9 +4137,9 @@ packages:
|
||||||
'@typescript-eslint/scope-manager': 5.49.0
|
'@typescript-eslint/scope-manager': 5.49.0
|
||||||
'@typescript-eslint/types': 5.49.0
|
'@typescript-eslint/types': 5.49.0
|
||||||
'@typescript-eslint/typescript-estree': 5.49.0_typescript@4.9.4
|
'@typescript-eslint/typescript-estree': 5.49.0_typescript@4.9.4
|
||||||
eslint: 8.32.0
|
eslint: 8.33.0
|
||||||
eslint-scope: 5.1.1
|
eslint-scope: 5.1.1
|
||||||
eslint-utils: 3.0.0_eslint@8.32.0
|
eslint-utils: 3.0.0_eslint@8.33.0
|
||||||
semver: 7.3.8
|
semver: 7.3.8
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
@ -4334,7 +4334,7 @@ packages:
|
||||||
resolution: {integrity: sha512-JD5fcdIuFxU4fQyXUu3w2KpAJHzTVdN+p4iOX2lMWSHMOoQdMAcpFLZzm9Z/2nmsoZ1a96QEhZ26e50xLBsgOQ==}
|
resolution: {integrity: sha512-JD5fcdIuFxU4fQyXUu3w2KpAJHzTVdN+p4iOX2lMWSHMOoQdMAcpFLZzm9Z/2nmsoZ1a96QEhZ26e50xLBsgOQ==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@vue/eslint-config-typescript/11.0.2_5gm7ezxcdo2zu65gboxarjsumy:
|
/@vue/eslint-config-typescript/11.0.2_w5nyi6nqxtergbgmiezudsbkue:
|
||||||
resolution: {integrity: sha512-EiKud1NqlWmSapBFkeSrE994qpKx7/27uCGnhdqzllYDpQZroyX/O6bwjEpeuyKamvLbsGdO6PMR2faIf+zFnw==}
|
resolution: {integrity: sha512-EiKud1NqlWmSapBFkeSrE994qpKx7/27uCGnhdqzllYDpQZroyX/O6bwjEpeuyKamvLbsGdO6PMR2faIf+zFnw==}
|
||||||
engines: {node: ^14.17.0 || >=16.0.0}
|
engines: {node: ^14.17.0 || >=16.0.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
@ -4345,12 +4345,12 @@ packages:
|
||||||
typescript:
|
typescript:
|
||||||
optional: true
|
optional: true
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/eslint-plugin': 5.49.0_iu322prlnwsygkcra5kbpy22si
|
'@typescript-eslint/eslint-plugin': 5.49.0_rsaczafy73x3xqauzesvzbsgzy
|
||||||
'@typescript-eslint/parser': 5.49.0_7uibuqfxkfaozanbtbziikiqje
|
'@typescript-eslint/parser': 5.49.0_zkdaqh7it7uc4cvz2haft7rc6u
|
||||||
eslint: 8.32.0
|
eslint: 8.33.0
|
||||||
eslint-plugin-vue: 9.9.0_eslint@8.32.0
|
eslint-plugin-vue: 9.9.0_eslint@8.33.0
|
||||||
typescript: 4.9.4
|
typescript: 4.9.4
|
||||||
vue-eslint-parser: 9.0.3_eslint@8.32.0
|
vue-eslint-parser: 9.0.3_eslint@8.33.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
dev: true
|
dev: true
|
||||||
|
@ -4416,24 +4416,24 @@ packages:
|
||||||
'@types/node': 18.11.18
|
'@types/node': 18.11.18
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@vueuse/core/9.11.1_vue@3.2.45:
|
/@vueuse/core/9.12.0_vue@3.2.45:
|
||||||
resolution: {integrity: sha512-E/cizD1w9ILkq4axYjZrXLkKaBfzloaby2n3NMjUfd6yI/jkfTVgc6iwy/Cw2e++Ld4LphGbO+3MhzizvwUslQ==}
|
resolution: {integrity: sha512-h/Di8Bvf6xRcvS/PvUVheiMYYz3U0tH3X25YxONSaAUBa841ayMwxkuzx/DGUMCW/wHWzD8tRy2zYmOC36r4sg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/web-bluetooth': 0.0.16
|
'@types/web-bluetooth': 0.0.16
|
||||||
'@vueuse/metadata': 9.11.1
|
'@vueuse/metadata': 9.12.0
|
||||||
'@vueuse/shared': 9.11.1_vue@3.2.45
|
'@vueuse/shared': 9.12.0_vue@3.2.45
|
||||||
vue-demi: 0.12.1_vue@3.2.45
|
vue-demi: 0.12.1_vue@3.2.45
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@vue/composition-api'
|
- '@vue/composition-api'
|
||||||
- vue
|
- vue
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@vueuse/metadata/9.11.1:
|
/@vueuse/metadata/9.12.0:
|
||||||
resolution: {integrity: sha512-ABjkrG+VXggNhjfGyw5e/sekxTZfXTwjrYXkkWQmQ7Biyv+Gq9UD6IDNfeGvQZEINI0Qzw6nfuO2UFCd3hlrxQ==}
|
resolution: {integrity: sha512-9oJ9MM9lFLlmvxXUqsR1wLt1uF7EVbP5iYaHJYqk+G2PbMjY6EXvZeTjbdO89HgoF5cI6z49o2zT/jD9SVoNpQ==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@vueuse/shared/9.11.1_vue@3.2.45:
|
/@vueuse/shared/9.12.0_vue@3.2.45:
|
||||||
resolution: {integrity: sha512-UTZYGAjT96hWn4buf4wstZbeheBVNcKPQuej6qpoSkjF1atdaeCD6kqm9uGL2waHfisSgH9mq0qCRiBOk5C/2w==}
|
resolution: {integrity: sha512-TWuJLACQ0BVithVTRbex4Wf1a1VaRuSpVeyEd4vMUWl54PzlE0ciFUshKCXnlLuD0lxIaLK4Ypj3NXYzZh4+SQ==}
|
||||||
dependencies:
|
dependencies:
|
||||||
vue-demi: 0.12.1_vue@3.2.45
|
vue-demi: 0.12.1_vue@3.2.45
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
|
@ -7201,19 +7201,19 @@ packages:
|
||||||
source-map: 0.6.1
|
source-map: 0.6.1
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/eslint-plugin-vue/9.9.0_eslint@8.32.0:
|
/eslint-plugin-vue/9.9.0_eslint@8.33.0:
|
||||||
resolution: {integrity: sha512-YbubS7eK0J7DCf0U2LxvVP7LMfs6rC6UltihIgval3azO3gyDwEGVgsCMe1TmDiEkl6GdMKfRpaME6QxIYtzDQ==}
|
resolution: {integrity: sha512-YbubS7eK0J7DCf0U2LxvVP7LMfs6rC6UltihIgval3azO3gyDwEGVgsCMe1TmDiEkl6GdMKfRpaME6QxIYtzDQ==}
|
||||||
engines: {node: ^14.17.0 || >=16.0.0}
|
engines: {node: ^14.17.0 || >=16.0.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
eslint: ^6.2.0 || ^7.0.0 || ^8.0.0
|
eslint: ^6.2.0 || ^7.0.0 || ^8.0.0
|
||||||
dependencies:
|
dependencies:
|
||||||
eslint: 8.32.0
|
eslint: 8.33.0
|
||||||
eslint-utils: 3.0.0_eslint@8.32.0
|
eslint-utils: 3.0.0_eslint@8.33.0
|
||||||
natural-compare: 1.4.0
|
natural-compare: 1.4.0
|
||||||
nth-check: 2.0.1
|
nth-check: 2.0.1
|
||||||
postcss-selector-parser: 6.0.10
|
postcss-selector-parser: 6.0.10
|
||||||
semver: 7.3.7
|
semver: 7.3.7
|
||||||
vue-eslint-parser: 9.0.3_eslint@8.32.0
|
vue-eslint-parser: 9.0.3_eslint@8.33.0
|
||||||
xml-name-validator: 4.0.0
|
xml-name-validator: 4.0.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
@ -7242,13 +7242,13 @@ packages:
|
||||||
eslint-visitor-keys: 1.3.0
|
eslint-visitor-keys: 1.3.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/eslint-utils/3.0.0_eslint@8.32.0:
|
/eslint-utils/3.0.0_eslint@8.33.0:
|
||||||
resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==}
|
resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==}
|
||||||
engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0}
|
engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
eslint: '>=5'
|
eslint: '>=5'
|
||||||
dependencies:
|
dependencies:
|
||||||
eslint: 8.32.0
|
eslint: 8.33.0
|
||||||
eslint-visitor-keys: 2.1.0
|
eslint-visitor-keys: 2.1.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
@ -7267,8 +7267,8 @@ packages:
|
||||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/eslint/8.32.0:
|
/eslint/8.33.0:
|
||||||
resolution: {integrity: sha512-nETVXpnthqKPFyuY2FNjz/bEd6nbosRgKbkgS/y1C7LJop96gYHWpiguLecMHQ2XCPxn77DS0P+68WzG6vkZSQ==}
|
resolution: {integrity: sha512-WjOpFQgKK8VrCnAtl8We0SUOy/oVZ5NHykyMiagV1M9r8IFpIJX7DduK6n1mpfhlG7T1NLWm2SuD8QB7KFySaA==}
|
||||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -7283,7 +7283,7 @@ packages:
|
||||||
doctrine: 3.0.0
|
doctrine: 3.0.0
|
||||||
escape-string-regexp: 4.0.0
|
escape-string-regexp: 4.0.0
|
||||||
eslint-scope: 7.1.1
|
eslint-scope: 7.1.1
|
||||||
eslint-utils: 3.0.0_eslint@8.32.0
|
eslint-utils: 3.0.0_eslint@8.33.0
|
||||||
eslint-visitor-keys: 3.3.0
|
eslint-visitor-keys: 3.3.0
|
||||||
espree: 9.4.0
|
espree: 9.4.0
|
||||||
esquery: 1.4.0
|
esquery: 1.4.0
|
||||||
|
@ -14776,14 +14776,14 @@ packages:
|
||||||
vue: 3.2.45
|
vue: 3.2.45
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/vue-eslint-parser/9.0.3_eslint@8.32.0:
|
/vue-eslint-parser/9.0.3_eslint@8.33.0:
|
||||||
resolution: {integrity: sha512-yL+ZDb+9T0ELG4VIFo/2anAOz8SvBdlqEnQnvJ3M7Scq56DvtjY0VY88bByRZB0D4J0u8olBcfrXTVONXsh4og==}
|
resolution: {integrity: sha512-yL+ZDb+9T0ELG4VIFo/2anAOz8SvBdlqEnQnvJ3M7Scq56DvtjY0VY88bByRZB0D4J0u8olBcfrXTVONXsh4og==}
|
||||||
engines: {node: ^14.17.0 || >=16.0.0}
|
engines: {node: ^14.17.0 || >=16.0.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
eslint: '>=6.0.0'
|
eslint: '>=6.0.0'
|
||||||
dependencies:
|
dependencies:
|
||||||
debug: 4.3.4
|
debug: 4.3.4
|
||||||
eslint: 8.32.0
|
eslint: 8.33.0
|
||||||
eslint-scope: 7.1.1
|
eslint-scope: 7.1.1
|
||||||
eslint-visitor-keys: 3.3.0
|
eslint-visitor-keys: 3.3.0
|
||||||
espree: 9.4.0
|
espree: 9.4.0
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# This shell script sets the api url based on an environment variable and starts nginx in foreground.
|
|
||||||
|
|
||||||
VIKUNJA_API_URL="${VIKUNJA_API_URL:-"/api/v1"}"
|
|
||||||
VIKUNJA_SENTRY_ENABLED="${VIKUNJA_SENTRY_ENABLED:-"false"}"
|
|
||||||
VIKUNJA_SENTRY_DSN="${VIKUNJA_SENTRY_DSN:-"https://85694a2d757547cbbc90cd4b55c5a18d@o1047380.ingest.sentry.io/6024480"}"
|
|
||||||
VIKUNJA_HTTP_PORT="${VIKUNJA_HTTP_PORT:-80}"
|
|
||||||
VIKUNJA_HTTPS_PORT="${VIKUNJA_HTTPS_PORT:-443}"
|
|
||||||
|
|
||||||
echo "Using $VIKUNJA_API_URL as default api url"
|
|
||||||
|
|
||||||
# Escape the variable to prevent sed from complaining
|
|
||||||
VIKUNJA_API_URL=$(echo $VIKUNJA_API_URL |sed 's/\//\\\//g')
|
|
||||||
|
|
||||||
sed -i "s/http\:\/\/localhost\:3456//g" /usr/share/nginx/html/index.html # replacing in two steps to make sure api urls from releases are properly replaced as well
|
|
||||||
sed -i "s/'\/api\/v1/'$VIKUNJA_API_URL/g" /usr/share/nginx/html/index.html
|
|
||||||
sed -i "s/\.SENTRY_ENABLED = false/\.SENTRY_ENABLED = $VIKUNJA_SENTRY_ENABLED/g" /usr/share/nginx/html/index.html
|
|
||||||
sed -i "s|\.SENTRY_DSN = '.*'|\.SENTRY_DSN = '$VIKUNJA_SENTRY_DSN'|g" /usr/share/nginx/html/index.html
|
|
||||||
|
|
||||||
sed -i "s/listen 80/listen $VIKUNJA_HTTP_PORT/g" /etc/nginx/nginx.conf
|
|
||||||
sed -i "s/listen 443/listen $VIKUNJA_HTTPS_PORT/g" /etc/nginx/nginx.conf
|
|
||||||
|
|
||||||
# Set the uid and gid of the nginx run user
|
|
||||||
usermod --non-unique --uid ${PUID} nginx
|
|
||||||
groupmod --non-unique --gid ${PGID} nginx
|
|
||||||
|
|
||||||
nginx -g "daemon off;"
|
|
|
@ -233,7 +233,7 @@ export const getDateFromTextIn = (text: string, now: Date = new Date()) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const getDateFromWeekday = (text: string): dateFoundResult => {
|
const getDateFromWeekday = (text: string): dateFoundResult => {
|
||||||
const matcher = / (next )?(monday|mon|tuesday|tue|wednesday|wed|thursday|thu|friday|fri|saturday|sat|sunday|sun)($| )/g
|
const matcher = /(^| )(next )?(monday|mon|tuesday|tue|wednesday|wed|thursday|thu|friday|fri|saturday|sat|sunday|sun)($| )/g
|
||||||
const results: string[] | null = matcher.exec(text.toLowerCase()) // The i modifier does not seem to work.
|
const results: string[] | null = matcher.exec(text.toLowerCase()) // The i modifier does not seem to work.
|
||||||
if (results === null) {
|
if (results === null) {
|
||||||
return {
|
return {
|
||||||
|
@ -246,7 +246,7 @@ const getDateFromWeekday = (text: string): dateFoundResult => {
|
||||||
const currentDay: number = date.getDay()
|
const currentDay: number = date.getDay()
|
||||||
let day = 0
|
let day = 0
|
||||||
|
|
||||||
switch (results[2]) {
|
switch (results[3]) {
|
||||||
case 'mon':
|
case 'mon':
|
||||||
case 'monday':
|
case 'monday':
|
||||||
day = 1
|
day = 1
|
||||||
|
|
|
@ -124,6 +124,18 @@ describe('Parse Task Text', () => {
|
||||||
expect(result?.date?.getMonth()).toBe(nextMonday.getMonth())
|
expect(result?.date?.getMonth()).toBe(nextMonday.getMonth())
|
||||||
expect(result?.date?.getDate()).toBe(nextMonday.getDate())
|
expect(result?.date?.getDate()).toBe(nextMonday.getDate())
|
||||||
})
|
})
|
||||||
|
it('should recognize next monday on the beginning of the sentence', () => {
|
||||||
|
const result = parseTaskText('next monday Lorem Ipsum')
|
||||||
|
|
||||||
|
const untilNextMonday = calculateDayInterval('nextMonday')
|
||||||
|
|
||||||
|
expect(result.text).toBe('Lorem Ipsum')
|
||||||
|
const nextMonday = new Date()
|
||||||
|
nextMonday.setDate(nextMonday.getDate() + untilNextMonday)
|
||||||
|
expect(result?.date?.getFullYear()).toBe(nextMonday.getFullYear())
|
||||||
|
expect(result?.date?.getMonth()).toBe(nextMonday.getMonth())
|
||||||
|
expect(result?.date?.getDate()).toBe(nextMonday.getDate())
|
||||||
|
})
|
||||||
it('should recognize next monday and ignore casing', () => {
|
it('should recognize next monday and ignore casing', () => {
|
||||||
const result = parseTaskText('Lorem Ipsum nExt Monday')
|
const result = parseTaskText('Lorem Ipsum nExt Monday')
|
||||||
|
|
||||||
|
@ -216,46 +228,7 @@ describe('Parse Task Text', () => {
|
||||||
expect(result?.date?.getDate()).toBe(date.getDate())
|
expect(result?.date?.getDate()).toBe(date.getDate())
|
||||||
})
|
})
|
||||||
|
|
||||||
const cases = {
|
|
||||||
'monday': 1,
|
|
||||||
'Monday': 1,
|
|
||||||
'mon': 1,
|
|
||||||
'Mon': 1,
|
|
||||||
'tuesday': 2,
|
|
||||||
'Tuesday': 2,
|
|
||||||
'tue': 2,
|
|
||||||
'Tue': 2,
|
|
||||||
'wednesday': 3,
|
|
||||||
'Wednesday': 3,
|
|
||||||
'wed': 3,
|
|
||||||
'Wed': 3,
|
|
||||||
'thursday': 4,
|
|
||||||
'Thursday': 4,
|
|
||||||
'thu': 4,
|
|
||||||
'Thu': 4,
|
|
||||||
'friday': 5,
|
|
||||||
'Friday': 5,
|
|
||||||
'fri': 5,
|
|
||||||
'Fri': 5,
|
|
||||||
'saturday': 6,
|
|
||||||
'Saturday': 6,
|
|
||||||
'sat': 6,
|
|
||||||
'Sat': 6,
|
|
||||||
'sunday': 7,
|
|
||||||
'Sunday': 7,
|
|
||||||
'sun': 7,
|
|
||||||
'Sun': 7,
|
|
||||||
} as Record<string, number>
|
|
||||||
for (const c in cases) {
|
|
||||||
it(`should recognize ${c} as weekday`, () => {
|
|
||||||
const result = parseTaskText(`Lorem Ipsum ${c}`)
|
|
||||||
|
|
||||||
expect(result.text).toBe('Lorem Ipsum')
|
|
||||||
const nextDate = new Date()
|
|
||||||
nextDate.setDate(nextDate.getDate() + ((cases[c] + 7 - nextDate.getDay()) % 7))
|
|
||||||
expect(`${result?.date?.getFullYear()}-${result?.date?.getMonth()}-${result?.date?.getDate()}`).toBe(`${nextDate.getFullYear()}-${nextDate.getMonth()}-${nextDate.getDate()}`)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
it('should recognize weekdays with time', () => {
|
it('should recognize weekdays with time', () => {
|
||||||
const result = parseTaskText('Lorem Ipsum thu at 14:00')
|
const result = parseTaskText('Lorem Ipsum thu at 14:00')
|
||||||
|
|
||||||
|
@ -369,20 +342,34 @@ describe('Parse Task Text', () => {
|
||||||
describe('Parse weekdays', () => {
|
describe('Parse weekdays', () => {
|
||||||
|
|
||||||
const days = {
|
const days = {
|
||||||
'mon': 1,
|
|
||||||
'monday': 1,
|
'monday': 1,
|
||||||
'tue': 2,
|
'Monday': 1,
|
||||||
|
'mon': 1,
|
||||||
|
'Mon': 1,
|
||||||
'tuesday': 2,
|
'tuesday': 2,
|
||||||
'wed': 3,
|
'Tuesday': 2,
|
||||||
|
'tue': 2,
|
||||||
|
'Tue': 2,
|
||||||
'wednesday': 3,
|
'wednesday': 3,
|
||||||
'thu': 4,
|
'Wednesday': 3,
|
||||||
|
'wed': 3,
|
||||||
|
'Wed': 3,
|
||||||
'thursday': 4,
|
'thursday': 4,
|
||||||
'fri': 5,
|
'Thursday': 4,
|
||||||
|
'thu': 4,
|
||||||
|
'Thu': 4,
|
||||||
'friday': 5,
|
'friday': 5,
|
||||||
'sat': 6,
|
'Friday': 5,
|
||||||
|
'fri': 5,
|
||||||
|
'Fri': 5,
|
||||||
'saturday': 6,
|
'saturday': 6,
|
||||||
'sun': 7,
|
'Saturday': 6,
|
||||||
|
'sat': 6,
|
||||||
|
'Sat': 6,
|
||||||
'sunday': 7,
|
'sunday': 7,
|
||||||
|
'Sunday': 7,
|
||||||
|
'sun': 7,
|
||||||
|
'Sun': 7,
|
||||||
} as Record<string, number>
|
} as Record<string, number>
|
||||||
|
|
||||||
const prefix = [
|
const prefix = [
|
||||||
|
@ -399,6 +386,18 @@ describe('Parse Task Text', () => {
|
||||||
const distance = (days[d] + 7 - next.getDay()) % 7
|
const distance = (days[d] + 7 - next.getDay()) % 7
|
||||||
next.setDate(next.getDate() + distance)
|
next.setDate(next.getDate() + distance)
|
||||||
|
|
||||||
|
expect(result.text).toBe('Lorem Ipsum')
|
||||||
|
expect(result?.date?.getFullYear()).toBe(next.getFullYear())
|
||||||
|
expect(result?.date?.getMonth()).toBe(next.getMonth())
|
||||||
|
expect(result?.date?.getDate()).toBe(next.getDate())
|
||||||
|
})
|
||||||
|
it(`should recognize ${p}${d} at the beginning of the text`, () => {
|
||||||
|
const result = parseTaskText(`${p}${d} Lorem Ipsum`)
|
||||||
|
|
||||||
|
const next = new Date()
|
||||||
|
const distance = (days[d] + 7 - next.getDay()) % 7
|
||||||
|
next.setDate(next.getDate() + distance)
|
||||||
|
|
||||||
expect(result.text).toBe('Lorem Ipsum')
|
expect(result.text).toBe('Lorem Ipsum')
|
||||||
expect(result?.date?.getFullYear()).toBe(next.getFullYear())
|
expect(result?.date?.getFullYear()).toBe(next.getFullYear())
|
||||||
expect(result?.date?.getMonth()).toBe(next.getMonth())
|
expect(result?.date?.getMonth()).toBe(next.getMonth())
|
||||||
|
|
Loading…
Reference in New Issue
Block a user