mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-11-21 04:36:53 -06:00
Compare commits
7 Commits
chore/impr
...
feature-au
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
76ba7da62a | ||
|
|
531a381c98 | ||
|
|
b31c81f1e0 | ||
|
|
598b6e4e21 | ||
|
|
377942c4f2 | ||
|
|
a094dfb67e | ||
|
|
c1a1ada6d7 |
@@ -11,10 +11,6 @@ end_of_line = lf
|
|||||||
charset = utf-8
|
charset = utf-8
|
||||||
max_line_length = 79
|
max_line_length = 79
|
||||||
|
|
||||||
[*.sh]
|
|
||||||
indent_style = tab
|
|
||||||
indent_size = 1
|
|
||||||
|
|
||||||
[{*.html,*.css,*.js}]
|
[{*.html,*.css,*.js}]
|
||||||
max_line_length = off
|
max_line_length = off
|
||||||
|
|
||||||
|
|||||||
50
.github/dependabot.yml
vendored
50
.github/dependabot.yml
vendored
@@ -41,56 +41,30 @@ updates:
|
|||||||
- "backend"
|
- "backend"
|
||||||
- "dependencies"
|
- "dependencies"
|
||||||
groups:
|
groups:
|
||||||
# Development & CI/CD Tooling
|
|
||||||
development:
|
development:
|
||||||
patterns:
|
patterns:
|
||||||
- "*pytest*"
|
- "*pytest*"
|
||||||
- "ruff"
|
- "ruff"
|
||||||
- "mkdocs-material"
|
- "mkdocs-material"
|
||||||
- "pre-commit*"
|
- "pre-commit*"
|
||||||
# Django & DRF Ecosystem
|
django:
|
||||||
django-ecosystem:
|
|
||||||
patterns:
|
patterns:
|
||||||
- "*django*"
|
- "*django*"
|
||||||
- "drf-*"
|
- "drf-*"
|
||||||
- "djangorestframework"
|
major-versions:
|
||||||
- "whitenoise"
|
|
||||||
- "bleach"
|
|
||||||
- "jinja2"
|
|
||||||
# Async, Task Queuing & Caching
|
|
||||||
async-tasks:
|
|
||||||
patterns:
|
|
||||||
- "celery*"
|
|
||||||
- "channels*"
|
|
||||||
- "flower"
|
|
||||||
- "redis"
|
|
||||||
# Document, PDF, and OCR Processing
|
|
||||||
document-processing:
|
|
||||||
patterns:
|
|
||||||
- "ocrmypdf"
|
|
||||||
- "pdf2image"
|
|
||||||
- "pyzbar"
|
|
||||||
- "zxing-cpp"
|
|
||||||
- "tika-client"
|
|
||||||
- "gotenberg-client"
|
|
||||||
- "python-magic"
|
|
||||||
- "python-gnupg"
|
|
||||||
# Data, NLP, and Search
|
|
||||||
data-nlp-search:
|
|
||||||
patterns:
|
|
||||||
- "nltk"
|
|
||||||
- "scikit-learn"
|
|
||||||
- "langdetect"
|
|
||||||
- "rapidfuzz"
|
|
||||||
- "whoosh-reloaded"
|
|
||||||
# Utilities (Patch Updates)
|
|
||||||
utilities-patch:
|
|
||||||
update-types:
|
update-types:
|
||||||
- "patch"
|
- "major"
|
||||||
# Utilities (Minor Updates)
|
small-changes:
|
||||||
utilities-minor:
|
|
||||||
update-types:
|
update-types:
|
||||||
- "minor"
|
- "minor"
|
||||||
|
- "patch"
|
||||||
|
exclude-patterns:
|
||||||
|
- "*django*"
|
||||||
|
- "drf-*"
|
||||||
|
pre-built:
|
||||||
|
patterns:
|
||||||
|
- psycopg*
|
||||||
|
- zxing-cpp
|
||||||
# Enable updates for GitHub Actions
|
# Enable updates for GitHub Actions
|
||||||
- package-ecosystem: "github-actions"
|
- package-ecosystem: "github-actions"
|
||||||
target-branch: "dev"
|
target-branch: "dev"
|
||||||
|
|||||||
39
.github/workflows/ci.yml
vendored
39
.github/workflows/ci.yml
vendored
@@ -353,9 +353,9 @@ jobs:
|
|||||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||||
run: cd src-ui && pnpm run build --configuration=production
|
run: cd src-ui && pnpm run build --configuration=production
|
||||||
build-docker-image:
|
build-docker-image:
|
||||||
name: Build Docker image for ${{ github.event_name == 'pull_request' && github.head_ref || github.ref_name }}
|
name: Build Docker image for ${{ github.ref_name }}
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
if: (github.event_name == 'push' && (startsWith(github.ref, 'refs/heads/feature-') || startsWith(github.ref, 'refs/heads/fix-') || github.ref == 'refs/heads/dev' || github.ref == 'refs/heads/beta' || contains(github.ref, 'beta.rc') || startsWith(github.ref, 'refs/tags/v') || startsWith(github.ref, 'refs/heads/l10n_'))) || (github.event_name == 'pull_request' && (startsWith(github.head_ref, 'feature-') || startsWith(github.head_ref, 'fix-') || github.head_ref == 'dev' || github.head_ref == 'beta' || contains(github.head_ref, 'beta.rc') || startsWith(github.head_ref, 'l10n_')))
|
if: github.event_name == 'push' && (startsWith(github.ref, 'refs/heads/feature-') || startsWith(github.ref, 'refs/heads/fix-') || github.ref == 'refs/heads/dev' || github.ref == 'refs/heads/beta' || contains(github.ref, 'beta.rc') || startsWith(github.ref, 'refs/tags/v') || startsWith(github.ref, 'refs/heads/l10n_'))
|
||||||
concurrency:
|
concurrency:
|
||||||
group: ${{ github.workflow }}-build-docker-image-${{ github.ref_name }}
|
group: ${{ github.workflow }}-build-docker-image-${{ github.ref_name }}
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
@@ -364,23 +364,6 @@ jobs:
|
|||||||
- tests-frontend
|
- tests-frontend
|
||||||
- tests-frontend-e2e
|
- tests-frontend-e2e
|
||||||
steps:
|
steps:
|
||||||
- name: Prepare build variables
|
|
||||||
id: build-vars
|
|
||||||
uses: actions/github-script@v8
|
|
||||||
with:
|
|
||||||
result-encoding: string
|
|
||||||
script: |
|
|
||||||
const isPR = context.eventName === 'pull_request';
|
|
||||||
const defaultRefName = context.ref.replace('refs/heads/', '');
|
|
||||||
const headRef = isPR ? context.payload.pull_request.head.ref : defaultRefName;
|
|
||||||
const buildRef = isPR ? `refs/heads/${headRef}` : context.ref;
|
|
||||||
const buildCacheKey = headRef.split('/').join('-');
|
|
||||||
const canPush = context.eventName === 'push' || (isPR && context.payload.pull_request.head.repo.full_name === `${context.repo.owner}/${context.repo.repo}`);
|
|
||||||
|
|
||||||
core.setOutput('build-ref', buildRef);
|
|
||||||
core.setOutput('build-ref-name', headRef);
|
|
||||||
core.setOutput('build-cache-key', buildCacheKey);
|
|
||||||
core.setOutput('can-push', canPush ? 'true' : 'false');
|
|
||||||
- name: Check pushing to Docker Hub
|
- name: Check pushing to Docker Hub
|
||||||
id: push-other-places
|
id: push-other-places
|
||||||
# Only push to Dockerhub from the main repo AND the ref is either:
|
# Only push to Dockerhub from the main repo AND the ref is either:
|
||||||
@@ -389,11 +372,8 @@ jobs:
|
|||||||
# beta
|
# beta
|
||||||
# a tag
|
# a tag
|
||||||
# Otherwise forks would require a Docker Hub account and secrets setup
|
# Otherwise forks would require a Docker Hub account and secrets setup
|
||||||
env:
|
|
||||||
BUILD_REF: ${{ steps.build-vars.outputs.build-ref }}
|
|
||||||
BUILD_REF_NAME: ${{ steps.build-vars.outputs.build-ref-name }}
|
|
||||||
run: |
|
run: |
|
||||||
if [[ ${{ github.repository_owner }} == "paperless-ngx" && ( "$BUILD_REF_NAME" == "dev" || "$BUILD_REF_NAME" == "beta" || $BUILD_REF == refs/tags/v* || $BUILD_REF == *beta.rc* ) ]] ; then
|
if [[ ${{ github.repository_owner }} == "paperless-ngx" && ( ${{ github.ref_name }} == "dev" || ${{ github.ref_name }} == "beta" || ${{ startsWith(github.ref, 'refs/tags/v') }} == "true" ) ]] ; then
|
||||||
echo "Enabling DockerHub image push"
|
echo "Enabling DockerHub image push"
|
||||||
echo "enable=true" >> $GITHUB_OUTPUT
|
echo "enable=true" >> $GITHUB_OUTPUT
|
||||||
else
|
else
|
||||||
@@ -417,8 +397,6 @@ jobs:
|
|||||||
tags: |
|
tags: |
|
||||||
# Tag branches with branch name
|
# Tag branches with branch name
|
||||||
type=ref,event=branch
|
type=ref,event=branch
|
||||||
# Pull requests need a sanitized branch tag for pushing images
|
|
||||||
type=raw,value=${{ steps.build-vars.outputs.build-cache-key }},enable=${{ github.event_name == 'pull_request' }}
|
|
||||||
# Process semver tags
|
# Process semver tags
|
||||||
# For a tag x.y.z or vX.Y.Z, output an x.y.z and x.y image tag
|
# For a tag x.y.z or vX.Y.Z, output an x.y.z and x.y image tag
|
||||||
type=semver,pattern={{version}}
|
type=semver,pattern={{version}}
|
||||||
@@ -461,7 +439,7 @@ jobs:
|
|||||||
context: .
|
context: .
|
||||||
file: ./Dockerfile
|
file: ./Dockerfile
|
||||||
platforms: linux/amd64,linux/arm64
|
platforms: linux/amd64,linux/arm64
|
||||||
push: ${{ steps.build-vars.outputs.can-push == 'true' }}
|
push: ${{ github.event_name != 'pull_request' }}
|
||||||
tags: ${{ steps.docker-meta.outputs.tags }}
|
tags: ${{ steps.docker-meta.outputs.tags }}
|
||||||
labels: ${{ steps.docker-meta.outputs.labels }}
|
labels: ${{ steps.docker-meta.outputs.labels }}
|
||||||
build-args: |
|
build-args: |
|
||||||
@@ -469,20 +447,18 @@ jobs:
|
|||||||
# Get cache layers from this branch, then dev
|
# Get cache layers from this branch, then dev
|
||||||
# This allows new branches to get at least some cache benefits, generally from dev
|
# This allows new branches to get at least some cache benefits, generally from dev
|
||||||
cache-from: |
|
cache-from: |
|
||||||
type=registry,ref=ghcr.io/${{ steps.set-ghcr-repository.outputs.ghcr-repository }}/builder/cache/app:${{ steps.build-vars.outputs.build-cache-key }}
|
type=registry,ref=ghcr.io/${{ steps.set-ghcr-repository.outputs.ghcr-repository }}/builder/cache/app:${{ github.ref_name }}
|
||||||
type=registry,ref=ghcr.io/${{ steps.set-ghcr-repository.outputs.ghcr-repository }}/builder/cache/app:dev
|
type=registry,ref=ghcr.io/${{ steps.set-ghcr-repository.outputs.ghcr-repository }}/builder/cache/app:dev
|
||||||
cache-to: ${{ steps.build-vars.outputs.can-push == 'true' && format('type=registry,mode=max,ref=ghcr.io/{0}/builder/cache/app:{1}', steps.set-ghcr-repository.outputs.ghcr-repository, steps.build-vars.outputs.build-cache-key) || '' }}
|
cache-to: |
|
||||||
|
type=registry,mode=max,ref=ghcr.io/${{ steps.set-ghcr-repository.outputs.ghcr-repository }}/builder/cache/app:${{ github.ref_name }}
|
||||||
- name: Inspect image
|
- name: Inspect image
|
||||||
if: steps.build-vars.outputs.can-push == 'true'
|
|
||||||
run: |
|
run: |
|
||||||
docker buildx imagetools inspect ${{ fromJSON(steps.docker-meta.outputs.json).tags[0] }}
|
docker buildx imagetools inspect ${{ fromJSON(steps.docker-meta.outputs.json).tags[0] }}
|
||||||
- name: Export frontend artifact from docker
|
- name: Export frontend artifact from docker
|
||||||
if: steps.build-vars.outputs.can-push == 'true'
|
|
||||||
run: |
|
run: |
|
||||||
docker create --name frontend-extract ${{ fromJSON(steps.docker-meta.outputs.json).tags[0] }}
|
docker create --name frontend-extract ${{ fromJSON(steps.docker-meta.outputs.json).tags[0] }}
|
||||||
docker cp frontend-extract:/usr/src/paperless/src/documents/static/frontend src/documents/static/frontend/
|
docker cp frontend-extract:/usr/src/paperless/src/documents/static/frontend src/documents/static/frontend/
|
||||||
- name: Upload frontend artifact
|
- name: Upload frontend artifact
|
||||||
if: steps.build-vars.outputs.can-push == 'true'
|
|
||||||
uses: actions/upload-artifact@v5
|
uses: actions/upload-artifact@v5
|
||||||
with:
|
with:
|
||||||
name: frontend-compiled
|
name: frontend-compiled
|
||||||
@@ -493,7 +469,6 @@ jobs:
|
|||||||
needs:
|
needs:
|
||||||
- build-docker-image
|
- build-docker-image
|
||||||
- documentation
|
- documentation
|
||||||
if: github.event_name == 'push'
|
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
|
|||||||
@@ -49,12 +49,12 @@ repos:
|
|||||||
- 'prettier-plugin-organize-imports@4.1.0'
|
- 'prettier-plugin-organize-imports@4.1.0'
|
||||||
# Python hooks
|
# Python hooks
|
||||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||||
rev: v0.14.5
|
rev: v0.14.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: ruff-check
|
- id: ruff-check
|
||||||
- id: ruff-format
|
- id: ruff-format
|
||||||
- repo: https://github.com/tox-dev/pyproject-fmt
|
- repo: https://github.com/tox-dev/pyproject-fmt
|
||||||
rev: "v2.11.1"
|
rev: "v2.11.0"
|
||||||
hooks:
|
hooks:
|
||||||
- id: pyproject-fmt
|
- id: pyproject-fmt
|
||||||
# Dockerfile hooks
|
# Dockerfile hooks
|
||||||
@@ -64,11 +64,11 @@ repos:
|
|||||||
- id: hadolint
|
- id: hadolint
|
||||||
# Shell script hooks
|
# Shell script hooks
|
||||||
- repo: https://github.com/lovesegfault/beautysh
|
- repo: https://github.com/lovesegfault/beautysh
|
||||||
rev: v6.4.2
|
rev: v6.2.1
|
||||||
hooks:
|
hooks:
|
||||||
- id: beautysh
|
- id: beautysh
|
||||||
types: [file]
|
additional_dependencies:
|
||||||
files: (\.sh$|/run$|/finish$)
|
- setuptools
|
||||||
args:
|
args:
|
||||||
- "--tab"
|
- "--tab"
|
||||||
- repo: https://github.com/shellcheck-py/shellcheck-py
|
- repo: https://github.com/shellcheck-py/shellcheck-py
|
||||||
@@ -76,7 +76,7 @@ repos:
|
|||||||
hooks:
|
hooks:
|
||||||
- id: shellcheck
|
- id: shellcheck
|
||||||
- repo: https://github.com/google/yamlfmt
|
- repo: https://github.com/google/yamlfmt
|
||||||
rev: v0.20.0
|
rev: v0.18.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: yamlfmt
|
- id: yamlfmt
|
||||||
exclude: "^src-ui/pnpm-lock.yaml"
|
exclude: "^src-ui/pnpm-lock.yaml"
|
||||||
|
|||||||
@@ -29,5 +29,5 @@ if find /run/s6/container_environment/*"_FILE" -maxdepth 1 > /dev/null 2>&1; the
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
else
|
else
|
||||||
echo "${log_prefix} No *_FILE environment found"
|
echo "${log_prefix} No *_FILE environment found"
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -12,24 +12,24 @@ declare -i DELAY=0
|
|||||||
declare -i STARTED_AT=${EPOCHSECONDS:?EPOCHSECONDS var unset}
|
declare -i STARTED_AT=${EPOCHSECONDS:?EPOCHSECONDS var unset}
|
||||||
|
|
||||||
delay_next_attempt() {
|
delay_next_attempt() {
|
||||||
local -i elapsed=$(( EPOCHSECONDS - STARTED_AT ))
|
local -i elapsed=$(( EPOCHSECONDS - STARTED_AT ))
|
||||||
local -ri remaining=$(( TIMEOUT - elapsed ))
|
local -ri remaining=$(( TIMEOUT - elapsed ))
|
||||||
|
|
||||||
if (( remaining <= 0 )); then
|
if (( remaining <= 0 )); then
|
||||||
echo "${LOG_PREFIX} Unable to connect after $elapsed seconds."
|
echo "${LOG_PREFIX} Unable to connect after $elapsed seconds."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
DELAY+=1
|
DELAY+=1
|
||||||
|
|
||||||
# clamp to remaining time
|
# clamp to remaining time
|
||||||
if (( DELAY > remaining )); then
|
if (( DELAY > remaining )); then
|
||||||
DELAY=$remaining
|
DELAY=$remaining
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ATTEMPT+=1
|
ATTEMPT+=1
|
||||||
echo "${LOG_PREFIX} Attempt $ATTEMPT failed! Trying again in $DELAY seconds..."
|
echo "${LOG_PREFIX} Attempt $ATTEMPT failed! Trying again in $DELAY seconds..."
|
||||||
sleep "$DELAY"
|
sleep "$DELAY"
|
||||||
}
|
}
|
||||||
|
|
||||||
wait_for_postgres() {
|
wait_for_postgres() {
|
||||||
@@ -40,7 +40,7 @@ wait_for_postgres() {
|
|||||||
local -r user="${PAPERLESS_DBUSER:-paperless}"
|
local -r user="${PAPERLESS_DBUSER:-paperless}"
|
||||||
|
|
||||||
while ! pg_isready -h "${host}" -p "${port}" --username "${user}"; do
|
while ! pg_isready -h "${host}" -p "${port}" --username "${user}"; do
|
||||||
delay_next_attempt
|
delay_next_attempt
|
||||||
done
|
done
|
||||||
echo "${LOG_PREFIX} Connected to PostgreSQL"
|
echo "${LOG_PREFIX} Connected to PostgreSQL"
|
||||||
}
|
}
|
||||||
@@ -52,7 +52,7 @@ wait_for_mariadb() {
|
|||||||
local -r port="${PAPERLESS_DBPORT:-3306}"
|
local -r port="${PAPERLESS_DBPORT:-3306}"
|
||||||
|
|
||||||
while ! mariadb-admin --host="$host" --port="$port" ping --silent >/dev/null 2>&1; do
|
while ! mariadb-admin --host="$host" --port="$port" ping --silent >/dev/null 2>&1; do
|
||||||
delay_next_attempt
|
delay_next_attempt
|
||||||
done
|
done
|
||||||
echo "${LOG_PREFIX} Connected to MariaDB"
|
echo "${LOG_PREFIX} Connected to MariaDB"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,11 +10,11 @@ export GRANIAN_WORKERS=${GRANIAN_WORKERS:-${PAPERLESS_WEBSERVER_WORKERS:-1}}
|
|||||||
|
|
||||||
# Only set GRANIAN_URL_PATH_PREFIX if PAPERLESS_FORCE_SCRIPT_NAME is set
|
# Only set GRANIAN_URL_PATH_PREFIX if PAPERLESS_FORCE_SCRIPT_NAME is set
|
||||||
if [[ -n "${PAPERLESS_FORCE_SCRIPT_NAME}" ]]; then
|
if [[ -n "${PAPERLESS_FORCE_SCRIPT_NAME}" ]]; then
|
||||||
export GRANIAN_URL_PATH_PREFIX=${PAPERLESS_FORCE_SCRIPT_NAME}
|
export GRANIAN_URL_PATH_PREFIX=${PAPERLESS_FORCE_SCRIPT_NAME}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -n "${USER_IS_NON_ROOT}" ]]; then
|
if [[ -n "${USER_IS_NON_ROOT}" ]]; then
|
||||||
exec granian --interface asginl --ws --loop uvloop "paperless.asgi:application"
|
exec granian --interface asginl --ws --loop uvloop "paperless.asgi:application"
|
||||||
else
|
else
|
||||||
exec s6-setuidgid paperless granian --interface asginl --ws --loop uvloop "paperless.asgi:application"
|
exec s6-setuidgid paperless granian --interface asginl --ws --loop uvloop "paperless.asgi:application"
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@angular/cdk": "^20.2.13",
|
"@angular/cdk": "^20.2.13",
|
||||||
|
"@angular/cdk-experimental": "^20.2.14",
|
||||||
"@angular/common": "~20.3.12",
|
"@angular/common": "~20.3.12",
|
||||||
"@angular/compiler": "~20.3.12",
|
"@angular/compiler": "~20.3.12",
|
||||||
"@angular/core": "~20.3.12",
|
"@angular/core": "~20.3.12",
|
||||||
|
|||||||
15
src-ui/pnpm-lock.yaml
generated
15
src-ui/pnpm-lock.yaml
generated
@@ -11,6 +11,9 @@ importers:
|
|||||||
'@angular/cdk':
|
'@angular/cdk':
|
||||||
specifier: ^20.2.13
|
specifier: ^20.2.13
|
||||||
version: 20.2.13(@angular/common@20.3.12(@angular/core@20.3.12(@angular/compiler@20.3.12)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.12(@angular/compiler@20.3.12)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2)
|
version: 20.2.13(@angular/common@20.3.12(@angular/core@20.3.12(@angular/compiler@20.3.12)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.12(@angular/compiler@20.3.12)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2)
|
||||||
|
'@angular/cdk-experimental':
|
||||||
|
specifier: ^20.2.14
|
||||||
|
version: 20.2.14(@angular/cdk@20.2.13(@angular/common@20.3.12(@angular/core@20.3.12(@angular/compiler@20.3.12)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.12(@angular/compiler@20.3.12)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.12(@angular/compiler@20.3.12)(rxjs@7.8.2)(zone.js@0.15.1))
|
||||||
'@angular/common':
|
'@angular/common':
|
||||||
specifier: ~20.3.12
|
specifier: ~20.3.12
|
||||||
version: 20.3.12(@angular/core@20.3.12(@angular/compiler@20.3.12)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2)
|
version: 20.3.12(@angular/core@20.3.12(@angular/compiler@20.3.12)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2)
|
||||||
@@ -495,6 +498,12 @@ packages:
|
|||||||
vitest:
|
vitest:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@angular/cdk-experimental@20.2.14':
|
||||||
|
resolution: {integrity: sha512-oTqd8fV9m8HfzIpd1GXJ9OOKhTV/2D3hPfhZjG4puTQ5JeWcljVR2T/fZHpWGnNRoHJL5MkIkQP6338uJbX22Q==}
|
||||||
|
peerDependencies:
|
||||||
|
'@angular/cdk': 20.2.14
|
||||||
|
'@angular/core': ^20.0.0 || ^21.0.0
|
||||||
|
|
||||||
'@angular/cdk@20.2.13':
|
'@angular/cdk@20.2.13':
|
||||||
resolution: {integrity: sha512-h1jTkCmJ/rEQQMkxgKFMCBOrMfjZEnppgdekNmSTerwdVp4vdosTDTzFH/kwiOGFeRClffmvqQ2XLG8mQOKOtA==}
|
resolution: {integrity: sha512-h1jTkCmJ/rEQQMkxgKFMCBOrMfjZEnppgdekNmSTerwdVp4vdosTDTzFH/kwiOGFeRClffmvqQ2XLG8mQOKOtA==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -7443,6 +7452,12 @@ snapshots:
|
|||||||
- tsx
|
- tsx
|
||||||
- yaml
|
- yaml
|
||||||
|
|
||||||
|
'@angular/cdk-experimental@20.2.14(@angular/cdk@20.2.13(@angular/common@20.3.12(@angular/core@20.3.12(@angular/compiler@20.3.12)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.12(@angular/compiler@20.3.12)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.12(@angular/compiler@20.3.12)(rxjs@7.8.2)(zone.js@0.15.1))':
|
||||||
|
dependencies:
|
||||||
|
'@angular/cdk': 20.2.13(@angular/common@20.3.12(@angular/core@20.3.12(@angular/compiler@20.3.12)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.12(@angular/compiler@20.3.12)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2)
|
||||||
|
'@angular/core': 20.3.12(@angular/compiler@20.3.12)(rxjs@7.8.2)(zone.js@0.15.1)
|
||||||
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@angular/cdk@20.2.13(@angular/common@20.3.12(@angular/core@20.3.12(@angular/compiler@20.3.12)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.12(@angular/compiler@20.3.12)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2)':
|
'@angular/cdk@20.2.13(@angular/common@20.3.12(@angular/core@20.3.12(@angular/compiler@20.3.12)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.12(@angular/compiler@20.3.12)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@angular/common': 20.3.12(@angular/core@20.3.12(@angular/compiler@20.3.12)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2)
|
'@angular/common': 20.3.12(@angular/core@20.3.12(@angular/compiler@20.3.12)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2)
|
||||||
|
|||||||
@@ -145,6 +145,10 @@ HTMLCanvasElement.prototype.getContext = <
|
|||||||
typeof HTMLCanvasElement.prototype.getContext
|
typeof HTMLCanvasElement.prototype.getContext
|
||||||
>jest.fn()
|
>jest.fn()
|
||||||
|
|
||||||
|
if (!HTMLElement.prototype.scrollTo) {
|
||||||
|
HTMLElement.prototype.scrollTo = jest.fn()
|
||||||
|
}
|
||||||
|
|
||||||
jest.mock('uuid', () => ({
|
jest.mock('uuid', () => ({
|
||||||
v4: jest.fn(() =>
|
v4: jest.fn(() =>
|
||||||
'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (char: string) => {
|
'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (char: string) => {
|
||||||
|
|||||||
@@ -41,21 +41,15 @@
|
|||||||
}
|
}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div [ngbNavOutlet]="nav" class="mt-2"></div>
|
<cdk-virtual-scroll-viewport autosize class="bg-dark text-light font-monospace log-container" #logContainer>
|
||||||
|
|
||||||
<cdk-virtual-scroll-viewport
|
|
||||||
itemSize="20"
|
|
||||||
class="bg-dark p-3 text-light font-monospace log-container"
|
|
||||||
#logContainer>
|
|
||||||
@if (loading && !logFiles.length) {
|
@if (loading && !logFiles.length) {
|
||||||
<div>
|
<div>
|
||||||
<div class="spinner-border spinner-border-sm me-2" role="status"></div>
|
<div class="spinner-border spinner-border-sm me-2" role="status"></div>
|
||||||
<ng-container i18n>Loading...</ng-container>
|
<ng-container i18n>Loading...</ng-container>
|
||||||
</div>
|
</div>
|
||||||
|
} @else {
|
||||||
|
<div class="p-3">
|
||||||
|
<p *cdkVirtualFor="let log of logs" class="m-0 p-0" [ngClass]="'log-entry-' + log.level">{{log.message}}</p>
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
<p *cdkVirtualFor="let log of logs"
|
|
||||||
class="m-0 p-0"
|
|
||||||
[ngClass]="'log-entry-' + log.level">
|
|
||||||
{{log.message}}
|
|
||||||
</p>
|
|
||||||
</cdk-virtual-scroll-viewport>
|
</cdk-virtual-scroll-viewport>
|
||||||
|
|||||||
@@ -16,9 +16,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.log-container {
|
.log-container {
|
||||||
overflow-y: scroll;
|
height: calc(100vh - 190px);
|
||||||
height: calc(100vh - 200px);
|
|
||||||
top: 0;
|
|
||||||
|
|
||||||
p {
|
p {
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
import { ScrollingModule } from '@angular/cdk-experimental/scrolling'
|
||||||
import {
|
import {
|
||||||
|
CdkVirtualForOf,
|
||||||
CdkVirtualScrollViewport,
|
CdkVirtualScrollViewport,
|
||||||
ScrollingModule,
|
|
||||||
} from '@angular/cdk/scrolling'
|
} from '@angular/cdk/scrolling'
|
||||||
import { CommonModule } from '@angular/common'
|
import { CommonModule } from '@angular/common'
|
||||||
import {
|
import {
|
||||||
@@ -28,6 +29,7 @@ import { LoadingComponentWithPermissions } from '../../loading-component/loading
|
|||||||
CommonModule,
|
CommonModule,
|
||||||
FormsModule,
|
FormsModule,
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
|
CdkVirtualForOf,
|
||||||
CdkVirtualScrollViewport,
|
CdkVirtualScrollViewport,
|
||||||
ScrollingModule,
|
ScrollingModule,
|
||||||
],
|
],
|
||||||
@@ -143,8 +145,9 @@ export class LogsComponent
|
|||||||
|
|
||||||
scrollToBottom(): void {
|
scrollToBottom(): void {
|
||||||
this.changedetectorRef.detectChanges()
|
this.changedetectorRef.detectChanges()
|
||||||
if (this.logContainer) {
|
setTimeout(() => {
|
||||||
this.logContainer.scrollToIndex(this.logs.length - 1)
|
this.logContainer?.checkViewportSize()
|
||||||
}
|
this.logContainer?.scrollTo({ bottom: 0 })
|
||||||
|
}, 50)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user