mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-04-09 09:58:20 -05:00
Merge branch 'dev' into removeansible
This commit is contained in:
commit
8bf6fadf0e
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@ -153,7 +153,7 @@ jobs:
|
|||||||
-
|
-
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
node-version: '15'
|
node-version: '16'
|
||||||
-
|
-
|
||||||
name: Configure version on dev branches
|
name: Configure version on dev branches
|
||||||
if: startsWith(github.ref, 'refs/heads/feature-') || github.ref == 'refs/heads/dev'
|
if: startsWith(github.ref, 'refs/heads/feature-') || github.ref == 'refs/heads/dev'
|
||||||
|
@ -75,6 +75,7 @@ The following files need to be changed:
|
|||||||
* src-ui/angular.json (under the _projects/paperless-ui/i18n/locales_ JSON key)
|
* src-ui/angular.json (under the _projects/paperless-ui/i18n/locales_ JSON key)
|
||||||
* src/paperless/settings.py (in the _LANGUAGES_ array)
|
* src/paperless/settings.py (in the _LANGUAGES_ array)
|
||||||
* src-ui/src/app/services/settings.service.ts (inside the _getLanguageOptions_ method)
|
* src-ui/src/app/services/settings.service.ts (inside the _getLanguageOptions_ method)
|
||||||
|
* src-ui/src/app/app.module.ts (import locale from _angular/common/locales_ and call _registerLocaleData_)
|
||||||
|
|
||||||
Please add the language in the correct order, alphabetically by locale.
|
Please add the language in the correct order, alphabetically by locale.
|
||||||
Note that _en-us_ needs to stay on top of the list, as it is the default project language
|
Note that _en-us_ needs to stay on top of the list, as it is the default project language
|
||||||
|
@ -63,8 +63,8 @@ RUN apt-get update \
|
|||||||
build-essential \
|
build-essential \
|
||||||
libpq-dev \
|
libpq-dev \
|
||||||
libqpdf-dev \
|
libqpdf-dev \
|
||||||
&& python3 -m pip install --upgrade --no-cache-dir supervisor \
|
&& python3 -m pip install --default-timeout=1000 --upgrade --no-cache-dir supervisor \
|
||||||
&& python3 -m pip install --no-cache-dir -r ../requirements.txt \
|
&& python3 -m pip install --default-timeout=1000 --no-cache-dir -r ../requirements.txt \
|
||||||
&& apt-get -y purge build-essential libqpdf-dev \
|
&& apt-get -y purge build-essential libqpdf-dev \
|
||||||
&& apt-get -y autoremove --purge \
|
&& apt-get -y autoremove --purge \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
@ -80,6 +80,15 @@ PAPERLESS_DATA_DIR=<path>
|
|||||||
|
|
||||||
Defaults to "../data/", relative to the "src" directory.
|
Defaults to "../data/", relative to the "src" directory.
|
||||||
|
|
||||||
|
PAPERLESS_TRASH_DIR=<path>
|
||||||
|
Instead of removing deleted documents, they are moved to this directory.
|
||||||
|
|
||||||
|
This must be writeable by the user running paperless. When running inside
|
||||||
|
docker, ensure that this path is within a permanent volume (such as
|
||||||
|
"../media/trash") so it won't get lost on upgrades.
|
||||||
|
|
||||||
|
Defaults to empty (i.e. really delete documents).
|
||||||
|
|
||||||
PAPERLESS_MEDIA_ROOT=<path>
|
PAPERLESS_MEDIA_ROOT=<path>
|
||||||
This is where your documents and thumbnails are stored.
|
This is where your documents and thumbnails are stored.
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#PAPERLESS_CONSUMPTION_DIR=../consume
|
#PAPERLESS_CONSUMPTION_DIR=../consume
|
||||||
#PAPERLESS_DATA_DIR=../data
|
#PAPERLESS_DATA_DIR=../data
|
||||||
|
#PAPERLESS_TRASH_DIR=
|
||||||
#PAPERLESS_MEDIA_ROOT=../media
|
#PAPERLESS_MEDIA_ROOT=../media
|
||||||
#PAPERLESS_STATICDIR=../static
|
#PAPERLESS_STATICDIR=../static
|
||||||
#PAPERLESS_FILENAME_FORMAT=
|
#PAPERLESS_FILENAME_FORMAT=
|
||||||
|
1
src-ui/.gitignore
vendored
1
src-ui/.gitignore
vendored
@ -32,6 +32,7 @@ speed-measure-plugin*.json
|
|||||||
.history/*
|
.history/*
|
||||||
|
|
||||||
# misc
|
# misc
|
||||||
|
/.angular/cache
|
||||||
/.sass-cache
|
/.sass-cache
|
||||||
/connect.lock
|
/connect.lock
|
||||||
/coverage
|
/coverage
|
||||||
|
@ -44,7 +44,6 @@
|
|||||||
"polyfills": "src/polyfills.ts",
|
"polyfills": "src/polyfills.ts",
|
||||||
"tsConfig": "tsconfig.app.json",
|
"tsConfig": "tsconfig.app.json",
|
||||||
"localize": true,
|
"localize": true,
|
||||||
"aot": true,
|
|
||||||
"assets": [
|
"assets": [
|
||||||
"src/favicon.ico",
|
"src/favicon.ico",
|
||||||
"src/apple-touch-icon.png",
|
"src/apple-touch-icon.png",
|
||||||
@ -61,7 +60,13 @@
|
|||||||
"scripts": [],
|
"scripts": [],
|
||||||
"allowedCommonJsDependencies": [
|
"allowedCommonJsDependencies": [
|
||||||
"ng2-pdf-viewer"
|
"ng2-pdf-viewer"
|
||||||
]
|
],
|
||||||
|
"vendorChunk": true,
|
||||||
|
"extractLicenses": false,
|
||||||
|
"buildOptimizer": false,
|
||||||
|
"sourceMap": true,
|
||||||
|
"optimization": false,
|
||||||
|
"namedChunks": true
|
||||||
},
|
},
|
||||||
"configurations": {
|
"configurations": {
|
||||||
"production": {
|
"production": {
|
||||||
@ -95,7 +100,8 @@
|
|||||||
"en-US": {
|
"en-US": {
|
||||||
"localize": ["en-US"]
|
"localize": ["en-US"]
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"defaultConfiguration": ""
|
||||||
},
|
},
|
||||||
"serve": {
|
"serve": {
|
||||||
"builder": "@angular-devkit/build-angular:dev-server",
|
"builder": "@angular-devkit/build-angular:dev-server",
|
||||||
@ -111,8 +117,7 @@
|
|||||||
"extract-i18n": {
|
"extract-i18n": {
|
||||||
"builder": "@angular-devkit/build-angular:extract-i18n",
|
"builder": "@angular-devkit/build-angular:extract-i18n",
|
||||||
"options": {
|
"options": {
|
||||||
"browserTarget": "paperless-ui:build",
|
"browserTarget": "paperless-ui:build"
|
||||||
"ivy": true
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"test": {
|
"test": {
|
||||||
@ -134,19 +139,6 @@
|
|||||||
"scripts": []
|
"scripts": []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lint": {
|
|
||||||
"builder": "@angular-devkit/build-angular:tslint",
|
|
||||||
"options": {
|
|
||||||
"tsConfig": [
|
|
||||||
"tsconfig.app.json",
|
|
||||||
"tsconfig.spec.json",
|
|
||||||
"e2e/tsconfig.json"
|
|
||||||
],
|
|
||||||
"exclude": [
|
|
||||||
"**/node_modules/**"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"e2e": {
|
"e2e": {
|
||||||
"builder": "@angular-devkit/build-angular:protractor",
|
"builder": "@angular-devkit/build-angular:protractor",
|
||||||
"options": {
|
"options": {
|
||||||
|
21928
src-ui/package-lock.json
generated
21928
src-ui/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -11,36 +11,35 @@
|
|||||||
},
|
},
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@angular/animations": "~11.2.14",
|
"@angular/animations": "~13.2.2",
|
||||||
"@angular/common": "~11.2.14",
|
"@angular/common": "~13.2.2",
|
||||||
"@angular/compiler": "~11.2.14",
|
"@angular/compiler": "~13.2.2",
|
||||||
"@angular/core": "~11.2.14",
|
"@angular/core": "~13.2.2",
|
||||||
"@angular/forms": "~11.2.14",
|
"@angular/forms": "~13.2.2",
|
||||||
"@angular/localize": "~11.2.14",
|
"@angular/localize": "~13.2.2",
|
||||||
"@angular/platform-browser": "~11.2.14",
|
"@angular/platform-browser": "~13.2.2",
|
||||||
"@angular/platform-browser-dynamic": "~11.2.14",
|
"@angular/platform-browser-dynamic": "~13.2.2",
|
||||||
"@angular/router": "~11.2.14",
|
"@angular/router": "~13.2.2",
|
||||||
"@ng-bootstrap/ng-bootstrap": "^9.1.2",
|
"@ng-bootstrap/ng-bootstrap": "^12.0.0",
|
||||||
"@ng-select/ng-select": "^7.0.0",
|
"@ng-select/ng-select": "^8.1.1",
|
||||||
"@ngneat/dirty-check-forms": "^1.1.0",
|
"@ngneat/dirty-check-forms": "^1.1.0",
|
||||||
"bootstrap": "^4.5.0",
|
"bootstrap": "^5.1.3",
|
||||||
"file-saver": "^2.0.5",
|
"file-saver": "^2.0.5",
|
||||||
"ng2-pdf-viewer": "^6.3.2",
|
"ng2-pdf-viewer": "^8.0.0",
|
||||||
"ngx-bootstrap": "^6.2.0",
|
"ngx-color": "^7.3.3",
|
||||||
"ngx-color": "^6.2.0",
|
"ngx-cookie-service": "^13.1.2",
|
||||||
"ngx-cookie-service": "^10.1.1",
|
"ngx-file-drop": "^13.0.0",
|
||||||
"ngx-file-drop": "^11.1.0",
|
"ngx-infinite-scroll": "^10.0.1",
|
||||||
"ngx-infinite-scroll": "^9.1.0",
|
"rxjs": "~6.6.7",
|
||||||
"rxjs": "~6.6.0",
|
"tslib": "^2.3.1",
|
||||||
"tslib": "^2.0.0",
|
|
||||||
"uuid": "^8.3.1",
|
"uuid": "^8.3.1",
|
||||||
"zone.js": "~0.11.4"
|
"zone.js": "~0.11.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@angular-devkit/build-angular": "~0.1102.13",
|
"@angular-devkit/build-angular": "~13.2.3",
|
||||||
"@angular/cli": "~11.2.14",
|
"@angular/cli": "~13.2.4",
|
||||||
"@angular/compiler-cli": "~11.2.14",
|
"@angular/compiler-cli": "~13.2.2",
|
||||||
"@types/jasmine": "~3.6.0",
|
"@types/jasmine": "~3.10.3",
|
||||||
"@types/jasminewd2": "~2.0.3",
|
"@types/jasminewd2": "~2.0.3",
|
||||||
"@types/node": "^12.11.1",
|
"@types/node": "^12.11.1",
|
||||||
"codelyzer": "^6.0.0",
|
"codelyzer": "^6.0.0",
|
||||||
@ -54,6 +53,6 @@
|
|||||||
"protractor": "~7.0.0",
|
"protractor": "~7.0.0",
|
||||||
"ts-node": "~8.3.0",
|
"ts-node": "~8.3.0",
|
||||||
"tslint": "~6.1.0",
|
"tslint": "~6.1.0",
|
||||||
"typescript": "~4.1.5"
|
"typescript": "~4.5.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,33 +65,37 @@ import { ColorSliderModule } from 'ngx-color/slider';
|
|||||||
import { ColorComponent } from './components/common/input/color/color.component';
|
import { ColorComponent } from './components/common/input/color/color.component';
|
||||||
import { DocumentAsnComponent } from './components/document-asn/document-asn.component';
|
import { DocumentAsnComponent } from './components/document-asn/document-asn.component';
|
||||||
|
|
||||||
import localeFr from '@angular/common/locales/fr';
|
import localeCs from '@angular/common/locales/cs';
|
||||||
import localeNl from '@angular/common/locales/nl';
|
import localeDa from '@angular/common/locales/da';
|
||||||
import localeDe from '@angular/common/locales/de';
|
import localeDe from '@angular/common/locales/de';
|
||||||
import localePt from '@angular/common/locales/pt';
|
|
||||||
import localeIt from '@angular/common/locales/it';
|
|
||||||
import localeEnGb from '@angular/common/locales/en-GB';
|
import localeEnGb from '@angular/common/locales/en-GB';
|
||||||
|
import localeEs from '@angular/common/locales/es';
|
||||||
|
import localeFr from '@angular/common/locales/fr';
|
||||||
|
import localeIt from '@angular/common/locales/it';
|
||||||
|
import localeLb from '@angular/common/locales/lb';
|
||||||
|
import localeNl from '@angular/common/locales/nl';
|
||||||
|
import localePl from '@angular/common/locales/pl';
|
||||||
|
import localePt from '@angular/common/locales/pt';
|
||||||
|
import localeSv from '@angular/common/locales/sv';
|
||||||
import localeRo from '@angular/common/locales/ro';
|
import localeRo from '@angular/common/locales/ro';
|
||||||
import localeRu from '@angular/common/locales/ru';
|
import localeRu from '@angular/common/locales/ru';
|
||||||
import localeEs from '@angular/common/locales/es';
|
|
||||||
import localePl from '@angular/common/locales/pl';
|
|
||||||
import localeSv from '@angular/common/locales/sv';
|
|
||||||
import localeLb from '@angular/common/locales/lb';
|
|
||||||
|
|
||||||
|
|
||||||
registerLocaleData(localeFr)
|
registerLocaleData(localeCs)
|
||||||
registerLocaleData(localeNl)
|
registerLocaleData(localeDa)
|
||||||
registerLocaleData(localeDe)
|
registerLocaleData(localeDe)
|
||||||
|
registerLocaleData(localeEnGb)
|
||||||
|
registerLocaleData(localeEs)
|
||||||
|
registerLocaleData(localeFr)
|
||||||
|
registerLocaleData(localeIt)
|
||||||
|
registerLocaleData(localeLb)
|
||||||
|
registerLocaleData(localeNl)
|
||||||
|
registerLocaleData(localePl)
|
||||||
registerLocaleData(localePt, "pt-BR")
|
registerLocaleData(localePt, "pt-BR")
|
||||||
registerLocaleData(localePt, "pt-PT")
|
registerLocaleData(localePt, "pt-PT")
|
||||||
registerLocaleData(localeIt)
|
|
||||||
registerLocaleData(localeEnGb)
|
|
||||||
registerLocaleData(localeRo)
|
registerLocaleData(localeRo)
|
||||||
registerLocaleData(localeRu)
|
registerLocaleData(localeRu)
|
||||||
registerLocaleData(localeEs)
|
|
||||||
registerLocaleData(localePl)
|
|
||||||
registerLocaleData(localeSv)
|
registerLocaleData(localeSv)
|
||||||
registerLocaleData(localeLb)
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
|
@ -4,43 +4,43 @@
|
|||||||
(click)="isMenuCollapsed = !isMenuCollapsed">
|
(click)="isMenuCollapsed = !isMenuCollapsed">
|
||||||
<span class="navbar-toggler-icon"></span>
|
<span class="navbar-toggler-icon"></span>
|
||||||
</button>
|
</button>
|
||||||
<a class="navbar-brand col-auto col-md-3 col-lg-2 mr-0 px-3 py-3 order-sm-0" routerLink="/dashboard">
|
<a class="navbar-brand col-auto col-md-3 col-lg-2 me-0 px-3 py-3 order-sm-0" routerLink="/dashboard">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 198.43 238.91" width="1em" class="mr-2" fill="currentColor">
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 198.43 238.91" width="1em" class="me-2" fill="currentColor">
|
||||||
<path d="M194.7,0C164.22,70.94,17.64,79.74,64.55,194.06c.58,1.47-10.85,17-18.47,29.9-1.76-6.45-3.81-13.48-3.52-14.07,38.11-45.14-27.26-70.65-30.78-107.58C-4.64,131.62-10.5,182.92,39,212.53c.3,0,2.64,11.14,3.81,16.71a58.55,58.55,0,0,0-2.93,6.45c-1.17,2.93,7.62,2.64,7.62,3.22.88-.29,21.7-36.93,22.28-37.23C187.67,174.72,208.48,68.6,194.7,0ZM134.61,74.75C79.5,124,70.12,160.64,71.88,178.53,53.41,134.85,107.64,86.77,134.61,74.75ZM28.2,145.11c10.55,9.67,28.14,39.28,13.19,56.57C44.91,193.77,46.08,175.89,28.2,145.11Z" transform="translate(0 0)"/>
|
<path d="M194.7,0C164.22,70.94,17.64,79.74,64.55,194.06c.58,1.47-10.85,17-18.47,29.9-1.76-6.45-3.81-13.48-3.52-14.07,38.11-45.14-27.26-70.65-30.78-107.58C-4.64,131.62-10.5,182.92,39,212.53c.3,0,2.64,11.14,3.81,16.71a58.55,58.55,0,0,0-2.93,6.45c-1.17,2.93,7.62,2.64,7.62,3.22.88-.29,21.7-36.93,22.28-37.23C187.67,174.72,208.48,68.6,194.7,0ZM134.61,74.75C79.5,124,70.12,160.64,71.88,178.53,53.41,134.85,107.64,86.77,134.61,74.75ZM28.2,145.11c10.55,9.67,28.14,39.28,13.19,56.57C44.91,193.77,46.08,175.89,28.2,145.11Z" transform="translate(0 0)"/>
|
||||||
</svg>
|
</svg>
|
||||||
<ng-container i18n="app title">Paperless-ngx</ng-container>
|
<ng-container i18n="app title">Paperless-ngx</ng-container>
|
||||||
</a>
|
</a>
|
||||||
<div class="search-form-container flex-grow-1 py-2 pb-3 pb-sm-2 px-3 pl-md-4 mr-sm-auto order-3 order-sm-1">
|
<div class="search-form-container flex-grow-1 py-2 pb-3 pb-sm-2 px-3 ps-md-4 me-sm-auto order-3 order-sm-1">
|
||||||
<form (ngSubmit)="search()" class="form-inline flex-grow-1">
|
<form (ngSubmit)="search()" class="form-inline flex-grow-1">
|
||||||
<input class="form-control form-control-sm" type="text" placeholder="Search documents" aria-label="Search"
|
|
||||||
[formControl]="searchField" [ngbTypeahead]="searchAutoComplete" (selectItem)="itemSelected($event)" i18n-placeholder>
|
|
||||||
<svg width="1em" height="1em">
|
<svg width="1em" height="1em">
|
||||||
<use xlink:href="assets/bootstrap-icons.svg#search"/>
|
<use xlink:href="assets/bootstrap-icons.svg#search"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
<input class="form-control form-control-sm" type="text" placeholder="Search documents" aria-label="Search"
|
||||||
|
[formControl]="searchField" [ngbTypeahead]="searchAutoComplete" (selectItem)="itemSelected($event)" i18n-placeholder>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<ul ngbNav class="order-sm-3">
|
<ul ngbNav class="order-sm-3">
|
||||||
<li ngbDropdown class="nav-item dropdown">
|
<li ngbDropdown class="nav-item dropdown">
|
||||||
<button class="btn text-light" id="userDropdown" ngbDropdownToggle>
|
<button class="btn text-light" id="userDropdown" ngbDropdownToggle>
|
||||||
<span *ngIf="displayName" class="navbar-text small mr-2 text-light d-none d-sm-inline">
|
<span *ngIf="displayName" class="navbar-text small me-2 text-light d-none d-sm-inline">
|
||||||
{{displayName}}
|
{{displayName}}
|
||||||
</span>
|
</span>
|
||||||
<svg width="1.3em" height="1.3em">
|
<svg width="1.3em" height="1.3em">
|
||||||
<use xlink:href="assets/bootstrap-icons.svg#person-circle"/>
|
<use xlink:href="assets/bootstrap-icons.svg#person-circle"/>
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
<div ngbDropdownMenu class="dropdown-menu-right shadow mr-2" aria-labelledby="userDropdown">
|
<div ngbDropdownMenu class="dropdown-menu-end shadow me-2" aria-labelledby="userDropdown">
|
||||||
<div *ngIf="displayName" class="d-sm-none">
|
<div *ngIf="displayName" class="d-sm-none">
|
||||||
<p class="small mb-0 px-3 text-muted" i18n>Logged in as {{displayName}}</p>
|
<p class="small mb-0 px-3 text-muted" i18n>Logged in as {{displayName}}</p>
|
||||||
<div class="dropdown-divider"></div>
|
<div class="dropdown-divider"></div>
|
||||||
</div>
|
</div>
|
||||||
<a ngbDropdownItem class="nav-link" routerLink="settings" (click)="closeMenu()">
|
<a ngbDropdownItem class="nav-link" routerLink="settings" (click)="closeMenu()">
|
||||||
<svg class="sidebaricon mr-2" fill="currentColor">
|
<svg class="sidebaricon me-2" fill="currentColor">
|
||||||
<use xlink:href="assets/bootstrap-icons.svg#gear"/>
|
<use xlink:href="assets/bootstrap-icons.svg#gear"/>
|
||||||
</svg><ng-container i18n>Settings</ng-container>
|
</svg><ng-container i18n>Settings</ng-container>
|
||||||
</a>
|
</a>
|
||||||
<a ngbDropdownItem class="nav-link" href="accounts/logout/">
|
<a ngbDropdownItem class="nav-link" href="accounts/logout/">
|
||||||
<svg class="sidebaricon mr-2" fill="currentColor">
|
<svg class="sidebaricon me-2" fill="currentColor">
|
||||||
<use xlink:href="assets/bootstrap-icons.svg#door-open"/>
|
<use xlink:href="assets/bootstrap-icons.svg#door-open"/>
|
||||||
</svg><ng-container i18n>Logout</ng-container>
|
</svg><ng-container i18n>Logout</ng-container>
|
||||||
</a>
|
</a>
|
||||||
@ -100,7 +100,7 @@
|
|||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item w-100" *ngIf="openDocuments.length >= 1">
|
<li class="nav-item w-100" *ngIf="openDocuments.length >= 1">
|
||||||
<a class="nav-link text-truncate" [routerLink]="" (click)="closeAll()">
|
<a class="nav-link text-truncate" [routerLink]="[]" (click)="closeAll()">
|
||||||
<svg class="sidebaricon" fill="currentColor">
|
<svg class="sidebaricon" fill="currentColor">
|
||||||
<use xlink:href="assets/bootstrap-icons.svg#x"/>
|
<use xlink:href="assets/bootstrap-icons.svg#x"/>
|
||||||
</svg> <ng-container i18n>Close all</ng-container>
|
</svg> <ng-container i18n>Close all</ng-container>
|
||||||
@ -169,13 +169,13 @@
|
|||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<div class="d-flex w-100 flex-wrap">
|
<div class="d-flex w-100 flex-wrap">
|
||||||
<a class="nav-link pr-0 pb-0" target="_blank" rel="noopener noreferrer" href="https://github.com/paperless-ngx/paperless-ngx">
|
<a class="nav-link pe-0 pb-0" target="_blank" rel="noopener noreferrer" href="https://github.com/paperless-ngx/paperless-ngx">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" class="sidebaricon bi bi-github" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" class="sidebaricon bi bi-github" viewBox="0 0 16 16">
|
||||||
<path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.012 8.012 0 0 0 16 8c0-4.42-3.58-8-8-8z"/>
|
<path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.012 8.012 0 0 0 16 8c0-4.42-3.58-8-8-8z"/>
|
||||||
</svg> <ng-container i18n>GitHub</ng-container>
|
</svg> <ng-container i18n>GitHub</ng-container>
|
||||||
</a>
|
</a>
|
||||||
<a class="nav-link-additional small text-muted ml-3" target="_blank" rel="noopener noreferrer" href="https://github.com/paperless-ngx/paperless-ngx/discussions/categories/feature-requests" title="Suggest an idea">
|
<a class="nav-link-additional small text-muted ms-3" target="_blank" rel="noopener noreferrer" href="https://github.com/paperless-ngx/paperless-ngx/discussions/categories/feature-requests" title="Suggest an idea">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="1.3em" height="1.3em" fill="currentColor" class="bi bi-lightbulb pr-1" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="1.3em" height="1.3em" fill="currentColor" class="bi bi-lightbulb pe-1" viewBox="0 0 16 16">
|
||||||
<path d="M2 6a6 6 0 1 1 10.174 4.31c-.203.196-.359.4-.453.619l-.762 1.769A.5.5 0 0 1 10.5 13a.5.5 0 0 1 0 1 .5.5 0 0 1 0 1l-.224.447a1 1 0 0 1-.894.553H6.618a1 1 0 0 1-.894-.553L5.5 15a.5.5 0 0 1 0-1 .5.5 0 0 1 0-1 .5.5 0 0 1-.46-.302l-.761-1.77a1.964 1.964 0 0 0-.453-.618A5.984 5.984 0 0 1 2 6zm6-5a5 5 0 0 0-3.479 8.592c.263.254.514.564.676.941L5.83 12h4.342l.632-1.467c.162-.377.413-.687.676-.941A5 5 0 0 0 8 1z"/>
|
<path d="M2 6a6 6 0 1 1 10.174 4.31c-.203.196-.359.4-.453.619l-.762 1.769A.5.5 0 0 1 10.5 13a.5.5 0 0 1 0 1 .5.5 0 0 1 0 1l-.224.447a1 1 0 0 1-.894.553H6.618a1 1 0 0 1-.894-.553L5.5 15a.5.5 0 0 1 0-1 .5.5 0 0 1 0-1 .5.5 0 0 1-.46-.302l-.761-1.77a1.964 1.964 0 0 0-.453-.618A5.984 5.984 0 0 1 2 6zm6-5a5 5 0 0 0-3.479 8.592c.263.254.514.564.676.941L5.83 12h4.342l.632-1.467c.162-.377.413-.687.676-.941A5 5 0 0 0 8 1z"/>
|
||||||
</svg>
|
</svg>
|
||||||
<ng-container i18n>Suggest an idea</ng-container>
|
<ng-container i18n>Suggest an idea</ng-container>
|
||||||
@ -191,7 +191,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 px-md-4">
|
<main role="main" class="col-md-9 ms-sm-auto col-lg-10 px-md-4">
|
||||||
<router-outlet></router-outlet>
|
<router-outlet></router-outlet>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
@ -139,6 +139,7 @@
|
|||||||
svg {
|
svg {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0.6rem;
|
left: 0.6rem;
|
||||||
|
top: 0.5rem;
|
||||||
color: rgba(255, 255, 255, 0.6);
|
color: rgba(255, 255, 255, 0.6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h4 class="modal-title" id="modal-basic-title">{{title}}</h4>
|
<h4 class="modal-title" id="modal-basic-title">{{title}}</h4>
|
||||||
<button type="button" class="close" aria-label="Close" (click)="cancel()">
|
<button type="button" class="btn-close" aria-label="Close" (click)="cancel()">
|
||||||
<span aria-hidden="true">×</span>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
</button>
|
</button>
|
||||||
<div class="dropdown-menu date-dropdown shadow pt-0" ngbDropdownMenu attr.aria-labelledby="dropdown{{title}}">
|
<div class="dropdown-menu date-dropdown shadow pt-0" ngbDropdownMenu attr.aria-labelledby="dropdown{{title}}">
|
||||||
<div class="list-group list-group-flush">
|
<div class="list-group list-group-flush">
|
||||||
<button *ngFor="let qf of quickFilters" class="list-group-item small list-goup list-group-item-action d-flex p-2 pl-3" role="menuitem" (click)="setDateQuickFilter(qf.id)">
|
<button *ngFor="let qf of quickFilters" class="list-group-item small list-goup list-group-item-action d-flex p-2 ps-3" role="menuitem" (click)="setDateQuickFilter(qf.id)">
|
||||||
{{qf.name}}
|
{{qf.name}}
|
||||||
</button>
|
</button>
|
||||||
<div class="list-group-item d-flex flex-column align-items-start" role="menuitem">
|
<div class="list-group-item d-flex flex-column align-items-start" role="menuitem">
|
||||||
|
@ -5,8 +5,11 @@
|
|||||||
</svg>
|
</svg>
|
||||||
<div class="d-none d-sm-inline"> {{title}}</div>
|
<div class="d-none d-sm-inline"> {{title}}</div>
|
||||||
<ng-container *ngIf="!editing && selectionModel.selectionSize() > 0">
|
<ng-container *ngIf="!editing && selectionModel.selectionSize() > 0">
|
||||||
<div class="badge bg-secondary text-light rounded-pill badge-corner">
|
<div *ngIf="multiple" class="position-absolute top-0 start-100 translate-middle badge bg-secondary border border-light text-light rounded-pill">
|
||||||
{{selectionModel.selectionSize()}}
|
{{selectionModel.selectionSize()}}<span class="visually-hidden">selected</span>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="!multiple" class="position-absolute top-0 start-100 p-2 translate-middle badge bg-secondary border border-light rounded-circle">
|
||||||
|
<span class="visually-hidden">selected</span>
|
||||||
</div>
|
</div>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</button>
|
</button>
|
||||||
@ -15,10 +18,10 @@
|
|||||||
<div *ngIf="!editing && multiple" class="list-group-item d-flex">
|
<div *ngIf="!editing && multiple" class="list-group-item d-flex">
|
||||||
<div class="btn-group btn-group-xs btn-group-toggle flex-fill" ngbRadioGroup [(ngModel)]="selectionModel.logicalOperator" (change)="selectionModel.toggleOperator()" [disabled]="!operatorToggleEnabled">
|
<div class="btn-group btn-group-xs btn-group-toggle flex-fill" ngbRadioGroup [(ngModel)]="selectionModel.logicalOperator" (change)="selectionModel.toggleOperator()" [disabled]="!operatorToggleEnabled">
|
||||||
<label ngbButtonLabel class="btn btn-outline-primary">
|
<label ngbButtonLabel class="btn btn-outline-primary">
|
||||||
<input ngbButton type="radio" name="logicalOperator" value="and"> All
|
<input ngbButton type="radio" class="btn-check" name="logicalOperator" value="and"> All
|
||||||
</label>
|
</label>
|
||||||
<label ngbButtonLabel class="btn btn-outline-primary">
|
<label ngbButtonLabel class="btn btn-outline-primary">
|
||||||
<input ngbButton type="radio" name="logicalOperator" value="or"> Any
|
<input ngbButton type="radio" class="btn-check" name="logicalOperator" value="or"> Any
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -32,8 +35,8 @@
|
|||||||
<app-toggleable-dropdown-button *ngIf="allowSelectNone || item.id" [item]="item" [state]="selectionModel.get(item.id)" (toggle)="selectionModel.toggle(item.id)" (exclude)="excludeClicked(item.id)"></app-toggleable-dropdown-button>
|
<app-toggleable-dropdown-button *ngIf="allowSelectNone || item.id" [item]="item" [state]="selectionModel.get(item.id)" (toggle)="selectionModel.toggle(item.id)" (exclude)="excludeClicked(item.id)"></app-toggleable-dropdown-button>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</div>
|
</div>
|
||||||
<button *ngIf="editing" class="list-group-item list-group-item-action bg-light" (click)="applyClicked()" [disabled]="!selectionModel.isDirty()">
|
<button *ngIf="editing" class="list-group-item list-group-item-action bg-light" (click)="applyClicked()" [disabled]="!modelIsDirty">
|
||||||
<small class="ml-2" [ngClass]="{'font-weight-bold': selectionModel.isDirty()}" i18n>Apply</small>
|
<small class="ms-2" [ngClass]="{'fw-bold': modelIsDirty}" i18n>Apply</small>
|
||||||
<svg width="1.5em" height="1em" viewBox="0 0 16 16" fill="currentColor">
|
<svg width="1.5em" height="1em" viewBox="0 0 16 16" fill="currentColor">
|
||||||
<use xlink:href="assets/bootstrap-icons.svg#arrow-right" />
|
<use xlink:href="assets/bootstrap-icons.svg#arrow-right" />
|
||||||
</svg>
|
</svg>
|
||||||
|
@ -13,6 +13,10 @@
|
|||||||
max-height: 400px;
|
max-height: 400px;
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
button:disabled {
|
||||||
|
opacity: 0.2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-group-xs {
|
.btn-group-xs {
|
||||||
|
@ -275,8 +275,13 @@ export class FilterableDropdownComponent {
|
|||||||
return this.selectionModel.selectionSize() > 1 && this.selectionModel.getExcludedItems().length == 0
|
return this.selectionModel.selectionSize() > 1 && this.selectionModel.getExcludedItems().length == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
modelIsDirty: boolean = false
|
||||||
|
|
||||||
constructor(private filterPipe: FilterPipe) {
|
constructor(private filterPipe: FilterPipe) {
|
||||||
this.selectionModel = new FilterableDropdownSelectionModel()
|
this.selectionModel = new FilterableDropdownSelectionModel()
|
||||||
|
this.selectionModelChange.subscribe(updatedModel => {
|
||||||
|
this.modelIsDirty = updatedModel.isDirty()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
applyClicked() {
|
applyClicked() {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<button class="list-group-item list-group-item-action d-flex align-items-center p-2 border-top-0 border-left-0 border-right-0 border-bottom" role="menuitem" (click)="toggleItem($event)">
|
<button class="list-group-item list-group-item-action d-flex align-items-center p-2 border-top-0 border-start-0 border-end-0 border-bottom" role="menuitem" (click)="toggleItem($event)">
|
||||||
<div class="selected-icon mr-1">
|
<div class="selected-icon me-1">
|
||||||
<ng-container *ngIf="isChecked()">
|
<ng-container *ngIf="isChecked()">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" fill="currentColor" class="bi bi-check" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" fill="currentColor" class="bi bi-check" viewBox="0 0 16 16">
|
||||||
<path d="M10.97 4.97a.75.75 0 0 1 1.07 1.05l-3.99 4.99a.75.75 0 0 1-1.08.02L4.324 8.384a.75.75 0 1 1 1.06-1.06l2.094 2.093 3.473-4.425a.267.267 0 0 1 .02-.022z"/>
|
<path d="M10.97 4.97a.75.75 0 0 1 1.07 1.05l-3.99 4.99a.75.75 0 0 1-1.08.02L4.324 8.384a.75.75 0 1 1 1.06-1.06l2.094 2.093 3.473-4.425a.267.267 0 0 1 .02-.022z"/>
|
||||||
@ -16,9 +16,9 @@
|
|||||||
</svg>
|
</svg>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</div>
|
</div>
|
||||||
<div class="mr-1">
|
<div class="me-1">
|
||||||
<app-tag *ngIf="isTag; else displayName" [tag]="item" [clickable]="false"></app-tag>
|
<app-tag *ngIf="isTag; else displayName" [tag]="item" [clickable]="false"></app-tag>
|
||||||
<ng-template #displayName><small>{{item.name}}</small></ng-template>
|
<ng-template #displayName><small>{{item.name}}</small></ng-template>
|
||||||
</div>
|
</div>
|
||||||
<div class="badge badge-light rounded-pill ml-auto mr-1">{{item.document_count}}</div>
|
<div class="badge badge-light rounded-pill ms-auto me-1">{{item.document_count}}</div>
|
||||||
</button>
|
</button>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<div class="form-group custom-control custom-checkbox">
|
<div class="mb-3 form-check">
|
||||||
<input type="checkbox" class="custom-control-input" [id]="inputId" [(ngModel)]="value" (change)="onChange(value)" (blur)="onTouched()" [disabled]="disabled">
|
<input type="checkbox" class="form-check-input" [id]="inputId" [(ngModel)]="value" (change)="onChange(value)" (blur)="onTouched()" [disabled]="disabled">
|
||||||
<label class="custom-control-label" [for]="inputId">{{title}}</label>
|
<label class="form-check-label" [for]="inputId">{{title}}</label>
|
||||||
<small *ngIf="hint" class="form-text text-muted">{{hint}}</small>
|
<div *ngIf="hint" class="form-text text-muted">{{hint}}</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
<div class="form-group">
|
<div class="mb-3">
|
||||||
<label [for]="inputId">{{title}}</label>
|
<label [for]="inputId">{{title}}</label>
|
||||||
|
|
||||||
<div class="input-group" [class.is-invalid]="error">
|
<div class="input-group" [class.is-invalid]="error">
|
||||||
<div class="input-group-prepend">
|
<span class="input-group-text" [style.background-color]="value"> </span>
|
||||||
<span class="input-group-text" [style.background-color]="value"> </span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<ng-template #popContent>
|
<ng-template #popContent>
|
||||||
<div style="min-width: 200px;" class="pb-3">
|
<div style="min-width: 200px;" class="pb-3">
|
||||||
@ -15,15 +13,12 @@
|
|||||||
|
|
||||||
<input class="form-control" [class.is-invalid]="error" [id]="inputId" [(ngModel)]="value" (change)="onChange(value)" [autoClose]="'outside'" [ngbPopover]="popContent" placement="bottom" popoverClass="shadow">
|
<input class="form-control" [class.is-invalid]="error" [id]="inputId" [(ngModel)]="value" (change)="onChange(value)" [autoClose]="'outside'" [ngbPopover]="popContent" placement="bottom" popoverClass="shadow">
|
||||||
|
|
||||||
<div class="input-group-append">
|
<button class="btn btn-outline-secondary" type="button" (click)="randomize()">
|
||||||
<button class="btn btn-outline-secondary" type="button" (click)="randomize()">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-dice-5" viewBox="0 0 16 16">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-dice-5" viewBox="0 0 16 16">
|
<path d="M13 1a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V3a2 2 0 0 1 2-2h10zM3 0a3 3 0 0 0-3 3v10a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V3a3 3 0 0 0-3-3H3z"/>
|
||||||
<path d="M13 1a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V3a2 2 0 0 1 2-2h10zM3 0a3 3 0 0 0-3 3v10a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V3a3 3 0 0 0-3-3H3z"/>
|
<path d="M5.5 4a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm8 0a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0 8a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm-8 0a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm4-4a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z"/>
|
||||||
<path d="M5.5 4a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm8 0a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0 8a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm-8 0a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm4-4a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z"/>
|
</svg>
|
||||||
</svg>
|
</button>
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<small *ngIf="hint" class="form-text text-muted">{{hint}}</small>
|
<small *ngIf="hint" class="form-text text-muted">{{hint}}</small>
|
||||||
|
@ -1,15 +1,13 @@
|
|||||||
<div class="form-group">
|
<div class="mb-3">
|
||||||
<label [for]="inputId">{{title}}</label>
|
<label class="form-label" [for]="inputId">{{title}}</label>
|
||||||
<div class="input-group" [class.is-invalid]="error">
|
<div class="input-group" [class.is-invalid]="error">
|
||||||
<input class="form-control" [class.is-invalid]="error" [placeholder]="placeholder" [id]="inputId" (dateSelect)="onChange(value)" (change)="onChange(value)"
|
<input class="form-control" [class.is-invalid]="error" [placeholder]="placeholder" [id]="inputId" (dateSelect)="onChange(value)" (change)="onChange(value)"
|
||||||
name="dp" [(ngModel)]="value" ngbDatepicker #datePicker="ngbDatepicker" #datePickerContent="ngModel">
|
name="dp" [(ngModel)]="value" ngbDatepicker #datePicker="ngbDatepicker" #datePickerContent="ngModel">
|
||||||
<div class="input-group-append">
|
<button class="btn btn-outline-secondary calendar" (click)="datePicker.toggle()" type="button">
|
||||||
<button class="btn btn-outline-secondary calendar" (click)="datePicker.toggle()" type="button">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-calendar" viewBox="0 0 16 16">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-calendar" viewBox="0 0 16 16">
|
<path d="M3.5 0a.5.5 0 0 1 .5.5V1h8V.5a.5.5 0 0 1 1 0V1h1a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V3a2 2 0 0 1 2-2h1V.5a.5.5 0 0 1 .5-.5zM1 4v10a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V4H1z"/>
|
||||||
<path d="M3.5 0a.5.5 0 0 1 .5.5V1h8V.5a.5.5 0 0 1 1 0V1h1a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V3a2 2 0 0 1 2-2h1V.5a.5.5 0 0 1 .5-.5zM1 4v10a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V4H1z"/>
|
</svg>
|
||||||
</svg>
|
</button>
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="invalid-feedback" i18n>Invalid date.</div>
|
<div class="invalid-feedback" i18n>Invalid date.</div>
|
||||||
<small *ngIf="hint" class="form-text text-muted">{{hint}}</small>
|
<small *ngIf="hint" class="form-text text-muted">{{hint}}</small>
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
<div class="form-group">
|
<div class="mb-3">
|
||||||
<label [for]="inputId">{{title}}</label>
|
<label class="form-label" [for]="inputId">{{title}}</label>
|
||||||
<div class="input-group" [class.is-invalid]="error">
|
<div class="input-group" [class.is-invalid]="error">
|
||||||
<input type="number" class="form-control" [id]="inputId" [(ngModel)]="value" (change)="onChange(value)" [class.is-invalid]="error">
|
<input type="number" class="form-control" [id]="inputId" [(ngModel)]="value" (change)="onChange(value)" [class.is-invalid]="error">
|
||||||
<div class="input-group-append">
|
<button class="btn btn-outline-secondary" type="button" id="button-addon1" (click)="nextAsn()" [disabled]="value">+1</button>
|
||||||
<button class="btn btn-outline-secondary" type="button" id="button-addon1" (click)="nextAsn()" [disabled]="value">+1</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="invalid-feedback">
|
<div class="invalid-feedback">
|
||||||
{{error}}
|
{{error}}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<div class="form-group paperless-input-select">
|
<div class="mb-3 paperless-input-select">
|
||||||
<label [for]="inputId">{{title}}</label>
|
<label class="form-label" [for]="inputId">{{title}}</label>
|
||||||
<div [class.input-group]="allowCreateNew">
|
<div [class.input-group]="allowCreateNew">
|
||||||
<ng-select name="inputId" [(ngModel)]="value"
|
<ng-select name="inputId" [(ngModel)]="value"
|
||||||
[disabled]="disabled"
|
[disabled]="disabled"
|
||||||
@ -18,19 +18,17 @@
|
|||||||
(clear)="clearLastSearchTerm()"
|
(clear)="clearLastSearchTerm()"
|
||||||
(blur)="onBlur()">
|
(blur)="onBlur()">
|
||||||
</ng-select>
|
</ng-select>
|
||||||
<div *ngIf="allowCreateNew" class="input-group-append">
|
<button *ngIf="allowCreateNew" class="btn btn-outline-secondary" type="button" (click)="addItem()">
|
||||||
<button class="btn btn-outline-secondary" type="button" (click)="addItem()">
|
<svg class="buttonicon" fill="currentColor">
|
||||||
<svg class="buttonicon" fill="currentColor">
|
<use xlink:href="assets/bootstrap-icons.svg#plus" />
|
||||||
<use xlink:href="assets/bootstrap-icons.svg#plus" />
|
</svg>
|
||||||
</svg>
|
</button>
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<small *ngIf="hint" class="form-text text-muted">{{hint}}</small>
|
<small *ngIf="hint" class="form-text text-muted">{{hint}}</small>
|
||||||
<small *ngIf="getSuggestions().length > 0">
|
<small *ngIf="getSuggestions().length > 0">
|
||||||
<span i18n>Suggestions:</span>
|
<span i18n>Suggestions:</span>
|
||||||
<ng-container *ngFor="let s of getSuggestions()">
|
<ng-container *ngFor="let s of getSuggestions()">
|
||||||
<a (click)="value = s.id; onChange(value)" [routerLink]="">{{s.name}}</a>
|
<a (click)="value = s.id; onChange(value)" [routerLink]="[]">{{s.name}}</a>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<div class="form-group paperless-input-select paperless-input-tags">
|
<div class="mb-3 paperless-input-select paperless-input-tags">
|
||||||
<label for="tags" i18n>Tags</label>
|
<label class="form-label" for="tags" i18n>Tags</label>
|
||||||
|
|
||||||
<div class="input-group flex-nowrap">
|
<div class="input-group flex-nowrap">
|
||||||
<ng-select name="tags" [items]="tags" bindLabel="name" bindValue="id" [(ngModel)]="value"
|
<ng-select name="tags" [items]="tags" bindLabel="name" bindValue="id" [(ngModel)]="value"
|
||||||
@ -26,24 +26,22 @@
|
|||||||
</ng-template>
|
</ng-template>
|
||||||
<ng-template ng-option-tmp let-item="item" let-index="index" let-search="searchTerm">
|
<ng-template ng-option-tmp let-item="item" let-index="index" let-search="searchTerm">
|
||||||
<div class="tag-wrap">
|
<div class="tag-wrap">
|
||||||
<app-tag *ngIf="item.id && tags" class="mr-2" [tag]="getTag(item.id)"></app-tag>
|
<app-tag *ngIf="item.id && tags" class="me-2" [tag]="getTag(item.id)"></app-tag>
|
||||||
</div>
|
</div>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</ng-select>
|
</ng-select>
|
||||||
|
|
||||||
<div class="input-group-append">
|
<button class="btn btn-outline-secondary" type="button" (click)="createTag()">
|
||||||
<button class="btn btn-outline-secondary" type="button" (click)="createTag()">
|
<svg class="buttonicon" fill="currentColor">
|
||||||
<svg class="buttonicon" fill="currentColor">
|
<use xlink:href="assets/bootstrap-icons.svg#plus" />
|
||||||
<use xlink:href="assets/bootstrap-icons.svg#plus" />
|
</svg>
|
||||||
</svg>
|
</button>
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<small class="form-text text-muted" *ngIf="hint">{{hint}}</small>
|
<small class="form-text text-muted" *ngIf="hint">{{hint}}</small>
|
||||||
<small *ngIf="getSuggestions().length > 0">
|
<small *ngIf="getSuggestions().length > 0">
|
||||||
<span i18n>Suggestions:</span>
|
<span i18n>Suggestions:</span>
|
||||||
<ng-container *ngFor="let tag of getSuggestions()">
|
<ng-container *ngFor="let tag of getSuggestions()">
|
||||||
<a (click)="addTag(tag.id)" [routerLink]="">{{tag.name}}</a>
|
<a (click)="addTag(tag.id)" [routerLink]="[]">{{tag.name}}</a>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<div class="form-group">
|
<div class="mb-3">
|
||||||
<label [for]="inputId">{{title}}</label>
|
<label class="form-label" [for]="inputId">{{title}}</label>
|
||||||
<input #inputField type="text" class="form-control" [class.is-invalid]="error" [id]="inputId" [(ngModel)]="value" (change)="onChange(value)">
|
<input #inputField type="text" class="form-control" [class.is-invalid]="error" [id]="inputId" [(ngModel)]="value" (change)="onChange(value)">
|
||||||
<small *ngIf="hint" class="form-text text-muted">{{hint}}</small>
|
<small *ngIf="hint" class="form-text text-muted">{{hint}}</small>
|
||||||
<div class="invalid-feedback">
|
<div class="invalid-feedback">
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h4 class="modal-title" id="modal-basic-title">{{title}}</h4>
|
<h4 class="modal-title" id="modal-basic-title">{{title}}</h4>
|
||||||
<button type="button" class="close" aria-label="Close" (click)="cancelClicked()">
|
<button type="button" class="btn-close" aria-label="Close" (click)="cancelClicked()">
|
||||||
<span aria-hidden="true">×</span>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
<span *ngIf="!clickable" class="badge" [style.background]="tag.color" [style.color]="tag.text_color">{{tag.name}}</span>
|
<span *ngIf="!clickable" class="badge" [style.background]="tag.color" [style.color]="tag.text_color">{{tag.name}}</span>
|
||||||
<a [routerLink]="" [title]="linkTitle" *ngIf="clickable" class="badge" [style.background]="tag.color" [style.color]="tag.text_color">{{tag.name}}</a>
|
<a [routerLink]="[]" [title]="linkTitle" *ngIf="clickable" class="badge" [style.background]="tag.color" [style.color]="tag.text_color">{{tag.name}}</a>
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
<app-widget-frame [title]="savedView.name">
|
<app-widget-frame [title]="savedView.name">
|
||||||
|
|
||||||
<a header-buttons [routerLink]="" (click)="showAll()" i18n>Show all</a>
|
<a header-buttons [routerLink]="[]" (click)="showAll()" i18n>Show all</a>
|
||||||
|
|
||||||
|
|
||||||
<table content class="table table-sm table-hover table-borderless">
|
<table content class="table table-sm bg-light table-hover table-borderless mb-0">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th i18n>Created</th>
|
<th i18n>Created</th>
|
||||||
@ -13,7 +13,7 @@
|
|||||||
<tbody>
|
<tbody>
|
||||||
<tr *ngFor="let doc of documents" routerLink="/documents/{{doc.id}}">
|
<tr *ngFor="let doc of documents" routerLink="/documents/{{doc.id}}">
|
||||||
<td>{{doc.created | customDate}}</td>
|
<td>{{doc.created | customDate}}</td>
|
||||||
<td>{{doc.title | documentTitle}}<app-tag [tag]="t" *ngFor="let t of doc.tags$ | async" class="ml-1"></app-tag>
|
<td>{{doc.title | documentTitle}}<app-tag [tag]="t" *ngFor="let t of doc.tags$ | async" class="ms-1"></app-tag></td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
@ -6,3 +6,7 @@ table {
|
|||||||
th:first-child {
|
th:first-child {
|
||||||
width: 25%;
|
width: 25%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tbody tr {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<app-widget-frame title="Upload new documents" i18n-title>
|
<app-widget-frame title="Upload new documents" i18n-title>
|
||||||
<div header-buttons>
|
<div header-buttons>
|
||||||
<a *ngIf="getStatusSuccess().length > 0" (click)="dismissCompleted()" [routerLink]="" >
|
<a *ngIf="getStatusSuccess().length > 0" (click)="dismissCompleted()" [routerLink]="[]" >
|
||||||
<span i18n="This button dismisses all status messages about processed documents on the dashboard (failed and successful)">Dismiss completed</span>
|
<span class="me-1" i18n="This button dismisses all status messages about processed documents on the dashboard (failed and successful)">Dismiss completed</span>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="1rem" height="1rem" fill="currentColor" class="bi bi-check2-all" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="1rem" height="1rem" fill="currentColor" class="bi bi-check2-all" viewBox="0 0 16 16">
|
||||||
<path d="M12.354 4.354a.5.5 0 0 0-.708-.708L5 10.293 1.854 7.146a.5.5 0 1 0-.708.708l3.5 3.5a.5.5 0 0 0 .708 0l7-7zm-4.208 7l-.896-.897.707-.707.543.543 6.646-6.647a.5.5 0 0 1 .708.708l-7 7a.5.5 0 0 1-.708 0z"/>
|
<path d="M12.354 4.354a.5.5 0 0 0-.708-.708L5 10.293 1.854 7.146a.5.5 0 1 0-.708.708l3.5 3.5a.5.5 0 0 0 .708 0l7-7zm-4.208 7l-.896-.897.707-.707.543.543 6.646-6.647a.5.5 0 0 1 .708.708l-7 7a.5.5 0 0 1-.708 0z"/>
|
||||||
<path d="M5.354 7.146l.896.897-.707.707-.897-.896a.5.5 0 1 1 .708-.708z"/>
|
<path d="M5.354 7.146l.896.897-.707.707-.897-.896a.5.5 0 1 1 .708-.708z"/>
|
||||||
@ -13,7 +13,7 @@
|
|||||||
<ngx-file-drop dropZoneLabel="Drop documents here or" browseBtnLabel="Browse files" (onFileDrop)="dropped($event)"
|
<ngx-file-drop dropZoneLabel="Drop documents here or" browseBtnLabel="Browse files" (onFileDrop)="dropped($event)"
|
||||||
(onFileOver)="fileOver($event)" (onFileLeave)="fileLeave($event)" dropZoneClassName="bg-light card"
|
(onFileOver)="fileOver($event)" (onFileLeave)="fileLeave($event)" dropZoneClassName="bg-light card"
|
||||||
multiple="true" contentClassName="justify-content-center d-flex align-items-center py-5 px-2" [showBrowseBtn]=true
|
multiple="true" contentClassName="justify-content-center d-flex align-items-center py-5 px-2" [showBrowseBtn]=true
|
||||||
browseBtnClassName="btn btn-sm btn-outline-primary ml-2" i18n-dropZoneLabel i18n-browseBtnLabel>
|
browseBtnClassName="btn btn-sm btn-outline-primary ms-2" i18n-dropZoneLabel i18n-browseBtnLabel>
|
||||||
</ngx-file-drop>
|
</ngx-file-drop>
|
||||||
</form>
|
</form>
|
||||||
<p class="mt-3" *ngIf="getStatus().length > 0">{{getStatusSummary()}}</p>
|
<p class="mt-3" *ngIf="getStatus().length > 0">{{getStatusSummary()}}</p>
|
||||||
@ -24,7 +24,7 @@
|
|||||||
<p *ngIf="!alertsExpanded" class="mt-3 mb-0 text-center">
|
<p *ngIf="!alertsExpanded" class="mt-3 mb-0 text-center">
|
||||||
<span i18n="This is shown as a summary line when there are more than 5 document in the processing pipeline.">{getStatusHidden().length, plural, =1 {One more document} other {{{getStatusHidden().length}} more documents}}</span>
|
<span i18n="This is shown as a summary line when there are more than 5 document in the processing pipeline.">{getStatusHidden().length, plural, =1 {One more document} other {{{getStatusHidden().length}} more documents}}</span>
|
||||||
•
|
•
|
||||||
<a [routerLink]="" (click)="alertsExpanded = !alertsExpanded" aria-controls="hiddenAlerts" [attr.aria-expanded]="alertsExpanded" i18n>Show all</a>
|
<a [routerLink]="[]" (click)="alertsExpanded = !alertsExpanded" aria-controls="hiddenAlerts" [attr.aria-expanded]="alertsExpanded" i18n>Show all</a>
|
||||||
</p>
|
</p>
|
||||||
<div #hiddenAlerts="ngbCollapse" [(ngbCollapse)]="!alertsExpanded">
|
<div #hiddenAlerts="ngbCollapse" [(ngbCollapse)]="!alertsExpanded">
|
||||||
<div *ngFor="let status of getStatusHidden()">
|
<div *ngFor="let status of getStatusHidden()">
|
||||||
|
@ -1,21 +1,17 @@
|
|||||||
<app-page-header [(title)]="title">
|
<app-page-header [(title)]="title">
|
||||||
<div class="input-group input-group-sm mr-5 d-none d-md-flex" *ngIf="getContentType() == 'application/pdf' && !useNativePdfViewer">
|
<div class="input-group input-group-sm me-5 d-none d-md-flex" *ngIf="getContentType() == 'application/pdf' && !useNativePdfViewer">
|
||||||
<div class="input-group-prepend">
|
<div class="input-group-text" i18n>Page</div>
|
||||||
<div class="input-group-text" i18n>Page</div>
|
|
||||||
</div>
|
|
||||||
<input class="form-control flex-grow-0 w-auto" type="number" min="1" [max]="previewNumPages" [(ngModel)]="previewCurrentPage" />
|
<input class="form-control flex-grow-0 w-auto" type="number" min="1" [max]="previewNumPages" [(ngModel)]="previewCurrentPage" />
|
||||||
<div class="input-group-append">
|
<div class="input-group-text" i18n>of {{previewNumPages}}</div>
|
||||||
<div class="input-group-text" i18n>of {{previewNumPages}}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button type="button" class="btn btn-sm btn-outline-danger mr-2 ml-auto" (click)="delete()">
|
<button type="button" class="btn btn-sm btn-outline-danger me-2 ms-auto" (click)="delete()">
|
||||||
<svg class="buttonicon" fill="currentColor">
|
<svg class="buttonicon" fill="currentColor">
|
||||||
<use xlink:href="assets/bootstrap-icons.svg#trash" />
|
<use xlink:href="assets/bootstrap-icons.svg#trash" />
|
||||||
</svg> <span class="d-none d-lg-inline" i18n>Delete</span>
|
</svg> <span class="d-none d-lg-inline" i18n>Delete</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div class="btn-group mr-2">
|
<div class="btn-group me-2">
|
||||||
|
|
||||||
<a [href]="downloadUrl" class="btn btn-sm btn-outline-primary">
|
<a [href]="downloadUrl" class="btn btn-sm btn-outline-primary">
|
||||||
<svg class="buttonicon" fill="currentColor">
|
<svg class="buttonicon" fill="currentColor">
|
||||||
@ -32,7 +28,7 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button type="button" class="btn btn-sm btn-outline-primary mr-2" (click)="moreLike()">
|
<button type="button" class="btn btn-sm btn-outline-primary me-2" (click)="moreLike()">
|
||||||
<svg class="buttonicon" fill="currentColor">
|
<svg class="buttonicon" fill="currentColor">
|
||||||
<use xlink:href="assets/bootstrap-icons.svg#three-dots" />
|
<use xlink:href="assets/bootstrap-icons.svg#three-dots" />
|
||||||
</svg> <span class="d-none d-lg-inline" i18n>More like this</span>
|
</svg> <span class="d-none d-lg-inline" i18n>More like this</span>
|
||||||
@ -71,7 +67,7 @@
|
|||||||
<li [ngbNavItem]="2">
|
<li [ngbNavItem]="2">
|
||||||
<a ngbNavLink i18n>Content</a>
|
<a ngbNavLink i18n>Content</a>
|
||||||
<ng-template ngbNavContent>
|
<ng-template ngbNavContent>
|
||||||
<div class="form-group">
|
<div class="mb-3">
|
||||||
<textarea class="form-control" id="content" rows="20" formControlName='content'></textarea>
|
<textarea class="form-control" id="content" rows="20" formControlName='content'></textarea>
|
||||||
</div>
|
</div>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
@ -153,7 +149,7 @@
|
|||||||
<div class="col-md-6 col-xl-8 mb-3 d-none d-md-block" #pdfPreview>
|
<div class="col-md-6 col-xl-8 mb-3 d-none d-md-block" #pdfPreview>
|
||||||
<ng-container *ngIf="getContentType() == 'application/pdf'">
|
<ng-container *ngIf="getContentType() == 'application/pdf'">
|
||||||
<div class="preview-sticky pdf-viewer-container" *ngIf="!useNativePdfViewer ; else nativePdfViewer">
|
<div class="preview-sticky pdf-viewer-container" *ngIf="!useNativePdfViewer ; else nativePdfViewer">
|
||||||
<pdf-viewer [src]="previewUrl" [original-size]="false" [show-borders]="true" [show-all]="true" [(page)]="previewCurrentPage" [render-text-mode]="2" (after-load-complete)="pdfPreviewLoaded($event)"></pdf-viewer>
|
<pdf-viewer [src]="previewUrl" [original-size]="false" [show-borders]="false" [show-all]="true" [(page)]="previewCurrentPage" [render-text-mode]="2" (after-load-complete)="pdfPreviewLoaded($event)"></pdf-viewer>
|
||||||
</div>
|
</div>
|
||||||
<ng-template #nativePdfViewer>
|
<ng-template #nativePdfViewer>
|
||||||
<object [data]="previewUrl | safe" class="preview-sticky" width="100%"></object>
|
<object [data]="previewUrl | safe" class="preview-sticky" width="100%"></object>
|
||||||
|
@ -6,4 +6,9 @@
|
|||||||
|
|
||||||
.pdf-viewer-container {
|
.pdf-viewer-container {
|
||||||
background-color: gray;
|
background-color: gray;
|
||||||
|
|
||||||
|
pdf-viewer {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<h6>
|
<h6>
|
||||||
<button type="button" class="btn btn-outline-secondary btn-sm mr-2"
|
<button type="button" class="btn btn-outline-secondary btn-sm me-2"
|
||||||
(click)="expand = !expand">
|
(click)="expand = !expand">
|
||||||
<svg class="buttonicon" fill="currentColor" *ngIf="!expand">
|
<svg class="buttonicon" fill="currentColor" *ngIf="!expand">
|
||||||
<use xlink:href="assets/bootstrap-icons.svg#caret-down" />
|
<use xlink:href="assets/bootstrap-icons.svg#caret-down" />
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
</svg> <ng-container i18n>Cancel</ng-container>
|
</svg> <ng-container i18n>Cancel</ng-container>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-auto mb-2 mb-xl-0 ml-auto ml-md-0" role="group" aria-label="Select">
|
<div class="col-auto mb-2 mb-xl-0 ms-auto ms-md-0" role="group" aria-label="Select">
|
||||||
<label class="mr-2 mb-0" i18n>Select:</label>
|
<label class="me-2 mb-0" i18n>Select:</label>
|
||||||
<div class="btn-group">
|
<div class="btn-group">
|
||||||
<button class="btn btn-sm btn-outline-primary" (click)="list.selectPage()">
|
<button class="btn btn-sm btn-outline-primary" (click)="list.selectPage()">
|
||||||
<svg width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor">
|
<svg width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor">
|
||||||
@ -24,8 +24,8 @@
|
|||||||
<div class="w-100 d-xl-none"></div>
|
<div class="w-100 d-xl-none"></div>
|
||||||
<div class="col-auto mb-2 mb-xl-0">
|
<div class="col-auto mb-2 mb-xl-0">
|
||||||
<div class="d-flex">
|
<div class="d-flex">
|
||||||
<label class="ml-auto mt-1 mb-0 mr-2" i18n>Edit:</label>
|
<label class="ms-auto mt-1 mb-0 me-2" i18n>Edit:</label>
|
||||||
<app-filterable-dropdown class="mr-2 mr-md-3" title="Tags" icon="tag-fill" i18n-title
|
<app-filterable-dropdown class="me-2 me-md-3" title="Tags" icon="tag-fill" i18n-title
|
||||||
filterPlaceholder="Filter tags" i18n-filterPlaceholder
|
filterPlaceholder="Filter tags" i18n-filterPlaceholder
|
||||||
[items]="tags"
|
[items]="tags"
|
||||||
[editing]="true"
|
[editing]="true"
|
||||||
@ -35,7 +35,7 @@
|
|||||||
[(selectionModel)]="tagSelectionModel"
|
[(selectionModel)]="tagSelectionModel"
|
||||||
(apply)="setTags($event)">
|
(apply)="setTags($event)">
|
||||||
</app-filterable-dropdown>
|
</app-filterable-dropdown>
|
||||||
<app-filterable-dropdown class="mr-2 mr-md-3" title="Correspondent" icon="person-fill" i18n-title
|
<app-filterable-dropdown class="me-2 me-md-3" title="Correspondent" icon="person-fill" i18n-title
|
||||||
filterPlaceholder="Filter correspondents" i18n-filterPlaceholder
|
filterPlaceholder="Filter correspondents" i18n-filterPlaceholder
|
||||||
[items]="correspondents"
|
[items]="correspondents"
|
||||||
[editing]="true"
|
[editing]="true"
|
||||||
@ -44,7 +44,7 @@
|
|||||||
[(selectionModel)]="correspondentSelectionModel"
|
[(selectionModel)]="correspondentSelectionModel"
|
||||||
(apply)="setCorrespondents($event)">
|
(apply)="setCorrespondents($event)">
|
||||||
</app-filterable-dropdown>
|
</app-filterable-dropdown>
|
||||||
<app-filterable-dropdown class="mr-2 mr-md-3" title="Document type" icon="file-earmark-fill" i18n-title
|
<app-filterable-dropdown class="me-2 me-md-3" title="Document type" icon="file-earmark-fill" i18n-title
|
||||||
filterPlaceholder="Filter document types" i18n-filterPlaceholder
|
filterPlaceholder="Filter document types" i18n-filterPlaceholder
|
||||||
[items]="documentTypes"
|
[items]="documentTypes"
|
||||||
[editing]="true"
|
[editing]="true"
|
||||||
@ -55,8 +55,8 @@
|
|||||||
</app-filterable-dropdown>
|
</app-filterable-dropdown>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-auto ml-auto mb-2 mb-xl-0 d-flex">
|
<div class="col-auto ms-auto mb-2 mb-xl-0 d-flex">
|
||||||
<div class="btn-group btn-group-sm mr-2">
|
<div class="btn-group btn-group-sm me-2">
|
||||||
<button type="button" class="btn btn-outline-primary btn-sm" (click)="downloadSelected()">
|
<button type="button" class="btn btn-outline-primary btn-sm" (click)="downloadSelected()">
|
||||||
<svg width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor">
|
<svg width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor">
|
||||||
<use xlink:href="assets/bootstrap-icons.svg#download" />
|
<use xlink:href="assets/bootstrap-icons.svg#download" />
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
<div class="card mb-3 shadow-sm" [class.card-selected]="selected" [class.document-card]="selectable" [class.popover-hidden]="popoverHidden" (mouseleave)="mouseLeaveCard()">
|
<div class="card mb-3 shadow-sm" [class.card-selected]="selected" [class.document-card]="selectable" [class.popover-hidden]="popoverHidden" (mouseleave)="mouseLeaveCard()">
|
||||||
<div class="row no-gutters">
|
<div class="row g-0">
|
||||||
<div class="col-md-2 d-none d-lg-block doc-img-background rounded-left" [class.doc-img-background-selected]="selected" (click)="this.toggleSelected.emit($event)">
|
<div class="col-md-2 doc-img-background rounded-start" [class.doc-img-background-selected]="selected" (click)="this.toggleSelected.emit($event)">
|
||||||
<img [src]="getThumbUrl()" class="card-img doc-img border-right rounded-left" [class.inverted]="getIsThumbInverted()">
|
<img [src]="getThumbUrl()" class="card-img doc-img border-end rounded-start" [class.inverted]="getIsThumbInverted()">
|
||||||
|
|
||||||
<div style="top: 0; left: 0" class="position-absolute border-right border-bottom bg-light p-1" [class.document-card-check]="!selected">
|
<div class="border-end border-bottom bg-light document-card-check">
|
||||||
<div class="custom-control custom-checkbox">
|
<div class="form-check">
|
||||||
<input type="checkbox" class="custom-control-input" id="smallCardCheck{{document.id}}" [checked]="selected" (click)="this.toggleSelected.emit($event)">
|
<input type="checkbox" class="form-check-input" id="smallCardCheck{{document.id}}" [checked]="selected" (click)="this.toggleSelected.emit($event)">
|
||||||
<label class="custom-control-label" for="smallCardCheck{{document.id}}"></label>
|
<label class="form-check-label" for="smallCardCheck{{document.id}}"></label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -17,11 +17,11 @@
|
|||||||
<div class="d-flex justify-content-between align-items-center">
|
<div class="d-flex justify-content-between align-items-center">
|
||||||
<h5 class="card-title">
|
<h5 class="card-title">
|
||||||
<ng-container *ngIf="document.correspondent">
|
<ng-container *ngIf="document.correspondent">
|
||||||
<a *ngIf="clickCorrespondent.observers.length ; else nolink" [routerLink]="" title="Filter by correspondent" i18n-title (click)="clickCorrespondent.emit(document.correspondent);$event.stopPropagation()" class="font-weight-bold">{{(document.correspondent$ | async)?.name}}</a>
|
<a *ngIf="clickCorrespondent.observers.length ; else nolink" [routerLink]="[]" title="Filter by correspondent" i18n-title (click)="clickCorrespondent.emit(document.correspondent);$event.stopPropagation()" class="fw-bold">{{(document.correspondent$ | async)?.name}}</a>
|
||||||
<ng-template #nolink>{{(document.correspondent$ | async)?.name}}</ng-template>:
|
<ng-template #nolink>{{(document.correspondent$ | async)?.name}}</ng-template>:
|
||||||
</ng-container>
|
</ng-container>
|
||||||
{{document.title | documentTitle}}
|
{{document.title | documentTitle}}
|
||||||
<app-tag [tag]="t" linkTitle="Filter by tag" i18n-linkTitle *ngFor="let t of document.tags$ | async" class="ml-1" (click)="clickTag.emit(t.id);$event.stopPropagation()" [clickable]="clickTag.observers.length"></app-tag>
|
<app-tag [tag]="t" linkTitle="Filter by tag" i18n-linkTitle *ngFor="let t of document.tags$ | async" class="ms-1" (click)="clickTag.emit(t.id);$event.stopPropagation()" [clickable]="clickTag.observers.length"></app-tag>
|
||||||
</h5>
|
</h5>
|
||||||
</div>
|
</div>
|
||||||
<p class="card-text">
|
<p class="card-text">
|
||||||
@ -61,29 +61,29 @@
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="list-group list-group-horizontal border-0 card-info ml-md-auto mt-2 mt-md-0">
|
<div class="list-group list-group-horizontal border-0 card-info ms-md-auto mt-2 mt-md-0">
|
||||||
<button *ngIf="document.document_type" type="button" class="list-group-item btn btn-sm bg-light text-dark p-1 border-0 mr-2" title="Filter by document type"
|
<button *ngIf="document.document_type" type="button" class="list-group-item btn btn-sm bg-light text-dark p-1 border-0 me-2" title="Filter by document type"
|
||||||
(click)="clickDocumentType.emit(document.document_type);$event.stopPropagation()">
|
(click)="clickDocumentType.emit(document.document_type);$event.stopPropagation()">
|
||||||
<svg class="metadata-icon mr-2 text-muted bi bi-file-earmark" viewBox="0 0 16 16" fill="currentColor">
|
<svg class="metadata-icon me-2 text-muted bi bi-file-earmark" viewBox="0 0 16 16" fill="currentColor">
|
||||||
<path d="M14 4.5V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h5.5L14 4.5zm-3 0A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4.5h-2z"/>
|
<path d="M14 4.5V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h5.5L14 4.5zm-3 0A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4.5h-2z"/>
|
||||||
</svg>
|
</svg>
|
||||||
<small>{{(document.document_type$ | async)?.name}}</small>
|
<small>{{(document.document_type$ | async)?.name}}</small>
|
||||||
</button>
|
</button>
|
||||||
<div *ngIf="document.archive_serial_number" class="list-group-item mr-2 bg-light text-dark p-1 border-0">
|
<div *ngIf="document.archive_serial_number" class="list-group-item me-2 bg-light text-dark p-1 border-0">
|
||||||
<svg class="metadata-icon mr-2 text-muted bi bi-upc-scan" viewBox="0 0 16 16" fill="currentColor">
|
<svg class="metadata-icon me-2 text-muted bi bi-upc-scan" viewBox="0 0 16 16" fill="currentColor">
|
||||||
<path d="M1.5 1a.5.5 0 0 0-.5.5v3a.5.5 0 0 1-1 0v-3A1.5 1.5 0 0 1 1.5 0h3a.5.5 0 0 1 0 1h-3zM11 .5a.5.5 0 0 1 .5-.5h3A1.5 1.5 0 0 1 16 1.5v3a.5.5 0 0 1-1 0v-3a.5.5 0 0 0-.5-.5h-3a.5.5 0 0 1-.5-.5zM.5 11a.5.5 0 0 1 .5.5v3a.5.5 0 0 0 .5.5h3a.5.5 0 0 1 0 1h-3A1.5 1.5 0 0 1 0 14.5v-3a.5.5 0 0 1 .5-.5zm15 0a.5.5 0 0 1 .5.5v3a1.5 1.5 0 0 1-1.5 1.5h-3a.5.5 0 0 1 0-1h3a.5.5 0 0 0 .5-.5v-3a.5.5 0 0 1 .5-.5zM3 4.5a.5.5 0 0 1 1 0v7a.5.5 0 0 1-1 0v-7zm2 0a.5.5 0 0 1 1 0v7a.5.5 0 0 1-1 0v-7zm2 0a.5.5 0 0 1 1 0v7a.5.5 0 0 1-1 0v-7zm2 0a.5.5 0 0 1 .5-.5h1a.5.5 0 0 1 .5.5v7a.5.5 0 0 1-.5.5h-1a.5.5 0 0 1-.5-.5v-7zm3 0a.5.5 0 0 1 1 0v7a.5.5 0 0 1-1 0v-7z"/>
|
<path d="M1.5 1a.5.5 0 0 0-.5.5v3a.5.5 0 0 1-1 0v-3A1.5 1.5 0 0 1 1.5 0h3a.5.5 0 0 1 0 1h-3zM11 .5a.5.5 0 0 1 .5-.5h3A1.5 1.5 0 0 1 16 1.5v3a.5.5 0 0 1-1 0v-3a.5.5 0 0 0-.5-.5h-3a.5.5 0 0 1-.5-.5zM.5 11a.5.5 0 0 1 .5.5v3a.5.5 0 0 0 .5.5h3a.5.5 0 0 1 0 1h-3A1.5 1.5 0 0 1 0 14.5v-3a.5.5 0 0 1 .5-.5zm15 0a.5.5 0 0 1 .5.5v3a1.5 1.5 0 0 1-1.5 1.5h-3a.5.5 0 0 1 0-1h3a.5.5 0 0 0 .5-.5v-3a.5.5 0 0 1 .5-.5zM3 4.5a.5.5 0 0 1 1 0v7a.5.5 0 0 1-1 0v-7zm2 0a.5.5 0 0 1 1 0v7a.5.5 0 0 1-1 0v-7zm2 0a.5.5 0 0 1 1 0v7a.5.5 0 0 1-1 0v-7zm2 0a.5.5 0 0 1 .5-.5h1a.5.5 0 0 1 .5.5v7a.5.5 0 0 1-.5.5h-1a.5.5 0 0 1-.5-.5v-7zm3 0a.5.5 0 0 1 1 0v7a.5.5 0 0 1-1 0v-7z"/>
|
||||||
</svg>
|
</svg>
|
||||||
<small>#{{document.archive_serial_number}}</small>
|
<small>#{{document.archive_serial_number}}</small>
|
||||||
</div>
|
</div>
|
||||||
<div class="list-group-item bg-light text-dark p-1 border-0" ngbTooltip="Added: {{document.added | customDate:'shortDate'}} Created: {{document.created | customDate:'shortDate'}}">
|
<div class="list-group-item bg-light text-dark p-1 border-0" ngbTooltip="Added: {{document.added | customDate:'shortDate'}} Created: {{document.created | customDate:'shortDate'}}">
|
||||||
<svg class="metadata-icon mr-2 text-muted bi bi-calendar-event" viewBox="0 0 16 16" fill="currentColor">
|
<svg class="metadata-icon me-2 text-muted bi bi-calendar-event" viewBox="0 0 16 16" fill="currentColor">
|
||||||
<path d="M11 6.5a.5.5 0 0 1 .5-.5h1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-1a.5.5 0 0 1-.5-.5v-1z"/>
|
<path d="M11 6.5a.5.5 0 0 1 .5-.5h1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-1a.5.5 0 0 1-.5-.5v-1z"/>
|
||||||
<path d="M3.5 0a.5.5 0 0 1 .5.5V1h8V.5a.5.5 0 0 1 1 0V1h1a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V3a2 2 0 0 1 2-2h1V.5a.5.5 0 0 1 .5-.5zM1 4v10a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V4H1z"/>
|
<path d="M3.5 0a.5.5 0 0 1 .5.5V1h8V.5a.5.5 0 0 1 1 0V1h1a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V3a2 2 0 0 1 2-2h1V.5a.5.5 0 0 1 .5-.5zM1 4v10a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V4H1z"/>
|
||||||
</svg>
|
</svg>
|
||||||
<small>{{document.created | customDate:'mediumDate'}}</small>
|
<small>{{document.created | customDate:'mediumDate'}}</small>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div *ngIf="document.__search_hit__?.score" class="list-group-item bg-light text-dark border-0 d-flex p-0 pl-4 search-score">
|
<div *ngIf="document.__search_hit__?.score" class="list-group-item bg-light text-dark border-0 d-flex p-0 ps-4 search-score">
|
||||||
<small class="text-muted" i18n>Score:</small>
|
<small class="text-muted" i18n>Score:</small>
|
||||||
<ngb-progressbar [type]="searchScoreClass" [value]="document.__search_hit__.score" class="search-score-bar mx-2 mt-1" [max]="1"></ngb-progressbar>
|
<ngb-progressbar [type]="searchScoreClass" [value]="document.__search_hit__.score" class="search-score-bar mx-2 mt-1" [max]="1"></ngb-progressbar>
|
||||||
</div>
|
</div>
|
||||||
|
@ -4,6 +4,10 @@
|
|||||||
overflow-wrap: anywhere;
|
overflow-wrap: anywhere;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.doc-img-background {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
.doc-img {
|
.doc-img {
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
object-position: top left;
|
object-position: top left;
|
||||||
@ -23,7 +27,23 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.document-card-check {
|
.document-card-check {
|
||||||
display: none
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
padding: 0.5rem;
|
||||||
|
border-top-left-radius: 0.25rem;
|
||||||
|
border-bottom-right-radius: 0.25rem;
|
||||||
|
|
||||||
|
.form-check {
|
||||||
|
padding: 0;
|
||||||
|
min-height: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
|
||||||
|
.form-check-input {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.document-card:hover .document-card-check {
|
.document-card:hover .document-card-check {
|
||||||
@ -32,6 +52,10 @@
|
|||||||
|
|
||||||
.card-selected {
|
.card-selected {
|
||||||
border-color: $primary;
|
border-color: $primary;
|
||||||
|
|
||||||
|
.document-card-check {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.doc-img-background-selected {
|
.doc-img-background-selected {
|
||||||
|
@ -3,14 +3,14 @@
|
|||||||
<div class="border-bottom doc-img-container" [class.doc-img-background-selected]="selected" (click)="this.toggleSelected.emit($event)">
|
<div class="border-bottom doc-img-container" [class.doc-img-background-selected]="selected" (click)="this.toggleSelected.emit($event)">
|
||||||
<img class="card-img doc-img rounded-top" [class.inverted]="getIsThumbInverted()" [src]="getThumbUrl()">
|
<img class="card-img doc-img rounded-top" [class.inverted]="getIsThumbInverted()" [src]="getThumbUrl()">
|
||||||
|
|
||||||
<div class="border-right border-bottom bg-light p-1 rounded document-card-check">
|
<div class="border-end border-bottom bg-light py-1 px-2 document-card-check">
|
||||||
<div class="custom-control custom-checkbox">
|
<div class="form-check">
|
||||||
<input type="checkbox" class="custom-control-input" id="smallCardCheck{{document.id}}" [checked]="selected" (click)="this.toggleSelected.emit($event)">
|
<input type="checkbox" class="form-check-input" id="smallCardCheck{{document.id}}" [checked]="selected" (click)="this.toggleSelected.emit($event)">
|
||||||
<label class="custom-control-label" for="smallCardCheck{{document.id}}"></label>
|
<label class="form-check-label" for="smallCardCheck{{document.id}}"></label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="top: 0; right: 0; font-size: large" class="text-right position-absolute mr-1">
|
<div style="top: 0; right: 0; font-size: large" class="text-end position-absolute me-1">
|
||||||
<div *ngFor="let t of getTagsLimited$() | async">
|
<div *ngFor="let t of getTagsLimited$() | async">
|
||||||
<app-tag [tag]="t" (click)="clickTag.emit(t.id);$event.stopPropagation()" [clickable]="true" linkTitle="Filter by tag" i18n-linkTitle></app-tag>
|
<app-tag [tag]="t" (click)="clickTag.emit(t.id);$event.stopPropagation()" [clickable]="true" linkTitle="Filter by tag" i18n-linkTitle></app-tag>
|
||||||
</div>
|
</div>
|
||||||
@ -23,16 +23,16 @@
|
|||||||
<div class="card-body p-2">
|
<div class="card-body p-2">
|
||||||
<p class="card-text">
|
<p class="card-text">
|
||||||
<ng-container *ngIf="document.correspondent">
|
<ng-container *ngIf="document.correspondent">
|
||||||
<a [routerLink]="" title="Filter by correspondent" i18n-title (click)="clickCorrespondent.emit(document.correspondent);$event.stopPropagation()" class="font-weight-bold">{{(document.correspondent$ | async)?.name}}</a>:
|
<a [routerLink]="[]" title="Filter by correspondent" i18n-title (click)="clickCorrespondent.emit(document.correspondent);$event.stopPropagation()" class="fw-bold">{{(document.correspondent$ | async)?.name}}</a>:
|
||||||
</ng-container>
|
</ng-container>
|
||||||
{{document.title | documentTitle}}
|
{{document.title | documentTitle}}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-footer pt-0 pb-2 px-2">
|
<div class="card-footer pt-0 pb-2 px-2">
|
||||||
<div class="list-group list-group-flush border-0 pt-1 pb-2 card-info">
|
<div class="list-group list-group-flush border-0 pt-1 pb-2 card-info">
|
||||||
<button *ngIf="document.document_type" type="button" class="list-group-item list-group-item-action bg-transparent pl-0 p-1 border-0" title="Filter by document type"
|
<button *ngIf="document.document_type" type="button" class="list-group-item list-group-item-action bg-transparent ps-0 p-1 border-0" title="Filter by document type"
|
||||||
(click)="clickDocumentType.emit(document.document_type);$event.stopPropagation()">
|
(click)="clickDocumentType.emit(document.document_type);$event.stopPropagation()">
|
||||||
<svg class="metadata-icon mr-2 text-muted bi bi-file-earmark" viewBox="0 0 16 16" fill="currentColor">
|
<svg class="metadata-icon me-2 text-muted bi bi-file-earmark" viewBox="0 0 16 16" fill="currentColor">
|
||||||
<path d="M14 4.5V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h5.5L14 4.5zm-3 0A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4.5h-2z"/>
|
<path d="M14 4.5V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h5.5L14 4.5zm-3 0A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4.5h-2z"/>
|
||||||
</svg>
|
</svg>
|
||||||
<small>{{(document.document_type$ | async)?.name}}</small>
|
<small>{{(document.document_type$ | async)?.name}}</small>
|
||||||
@ -46,15 +46,15 @@
|
|||||||
</div>
|
</div>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
||||||
<div class="pl-0 p-1" placement="top" [ngbTooltip]="dateTooltip">
|
<div class="ps-0 p-1" placement="top" [ngbTooltip]="dateTooltip">
|
||||||
<svg class="metadata-icon mr-2 text-muted bi bi-calendar-event" viewBox="0 0 16 16" fill="currentColor">
|
<svg class="metadata-icon me-2 text-muted bi bi-calendar-event" viewBox="0 0 16 16" fill="currentColor">
|
||||||
<path d="M11 6.5a.5.5 0 0 1 .5-.5h1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-1a.5.5 0 0 1-.5-.5v-1z"/>
|
<path d="M11 6.5a.5.5 0 0 1 .5-.5h1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-1a.5.5 0 0 1-.5-.5v-1z"/>
|
||||||
<path d="M3.5 0a.5.5 0 0 1 .5.5V1h8V.5a.5.5 0 0 1 1 0V1h1a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V3a2 2 0 0 1 2-2h1V.5a.5.5 0 0 1 .5-.5zM1 4v10a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V4H1z"/>
|
<path d="M3.5 0a.5.5 0 0 1 .5.5V1h8V.5a.5.5 0 0 1 1 0V1h1a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V3a2 2 0 0 1 2-2h1V.5a.5.5 0 0 1 .5-.5zM1 4v10a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V4H1z"/>
|
||||||
</svg>
|
</svg>
|
||||||
<small>{{document.created | customDate:'mediumDate'}}</small>
|
<small>{{document.created | customDate:'mediumDate'}}</small>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="document.archive_serial_number" class="pl-0 p-1">
|
<div *ngIf="document.archive_serial_number" class="ps-0 p-1">
|
||||||
<svg class="metadata-icon mr-2 text-muted bi bi-upc-scan" viewBox="0 0 16 16" fill="currentColor">
|
<svg class="metadata-icon me-2 text-muted bi bi-upc-scan" viewBox="0 0 16 16" fill="currentColor">
|
||||||
<path d="M1.5 1a.5.5 0 0 0-.5.5v3a.5.5 0 0 1-1 0v-3A1.5 1.5 0 0 1 1.5 0h3a.5.5 0 0 1 0 1h-3zM11 .5a.5.5 0 0 1 .5-.5h3A1.5 1.5 0 0 1 16 1.5v3a.5.5 0 0 1-1 0v-3a.5.5 0 0 0-.5-.5h-3a.5.5 0 0 1-.5-.5zM.5 11a.5.5 0 0 1 .5.5v3a.5.5 0 0 0 .5.5h3a.5.5 0 0 1 0 1h-3A1.5 1.5 0 0 1 0 14.5v-3a.5.5 0 0 1 .5-.5zm15 0a.5.5 0 0 1 .5.5v3a1.5 1.5 0 0 1-1.5 1.5h-3a.5.5 0 0 1 0-1h3a.5.5 0 0 0 .5-.5v-3a.5.5 0 0 1 .5-.5zM3 4.5a.5.5 0 0 1 1 0v7a.5.5 0 0 1-1 0v-7zm2 0a.5.5 0 0 1 1 0v7a.5.5 0 0 1-1 0v-7zm2 0a.5.5 0 0 1 1 0v7a.5.5 0 0 1-1 0v-7zm2 0a.5.5 0 0 1 .5-.5h1a.5.5 0 0 1 .5.5v7a.5.5 0 0 1-.5.5h-1a.5.5 0 0 1-.5-.5v-7zm3 0a.5.5 0 0 1 1 0v7a.5.5 0 0 1-1 0v-7z"/>
|
<path d="M1.5 1a.5.5 0 0 0-.5.5v3a.5.5 0 0 1-1 0v-3A1.5 1.5 0 0 1 1.5 0h3a.5.5 0 0 1 0 1h-3zM11 .5a.5.5 0 0 1 .5-.5h3A1.5 1.5 0 0 1 16 1.5v3a.5.5 0 0 1-1 0v-3a.5.5 0 0 0-.5-.5h-3a.5.5 0 0 1-.5-.5zM.5 11a.5.5 0 0 1 .5.5v3a.5.5 0 0 0 .5.5h3a.5.5 0 0 1 0 1h-3A1.5 1.5 0 0 1 0 14.5v-3a.5.5 0 0 1 .5-.5zm15 0a.5.5 0 0 1 .5.5v3a1.5 1.5 0 0 1-1.5 1.5h-3a.5.5 0 0 1 0-1h3a.5.5 0 0 0 .5-.5v-3a.5.5 0 0 1 .5-.5zM3 4.5a.5.5 0 0 1 1 0v7a.5.5 0 0 1-1 0v-7zm2 0a.5.5 0 0 1 1 0v7a.5.5 0 0 1-1 0v-7zm2 0a.5.5 0 0 1 1 0v7a.5.5 0 0 1-1 0v-7zm2 0a.5.5 0 0 1 .5-.5h1a.5.5 0 0 1 .5.5v7a.5.5 0 0 1-.5.5h-1a.5.5 0 0 1-.5-.5v-7zm3 0a.5.5 0 0 1 1 0v7a.5.5 0 0 1-1 0v-7z"/>
|
||||||
</svg>
|
</svg>
|
||||||
<small>#{{document.archive_serial_number}}</small>
|
<small>#{{document.archive_serial_number}}</small>
|
||||||
|
@ -16,10 +16,18 @@
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
|
padding: 0.5rem;
|
||||||
|
border-top-left-radius: 0.25rem;
|
||||||
|
border-bottom-right-radius: 0.25rem;
|
||||||
|
|
||||||
.custom-control {
|
.form-check {
|
||||||
margin-left: 4px;
|
padding: 0;
|
||||||
margin-right: -3px;
|
min-height: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
|
||||||
|
.form-check-input {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<app-page-header [title]="getTitle()">
|
<app-page-header [title]="getTitle()">
|
||||||
|
|
||||||
<div ngbDropdown class="mr-2 flex-fill d-flex">
|
<div ngbDropdown class="me-2 flex-fill d-flex">
|
||||||
<button class="btn btn-sm btn-outline-primary flex-fill" id="dropdownSelect" ngbDropdownToggle>
|
<button class="btn btn-sm btn-outline-primary flex-fill" id="dropdownSelect" ngbDropdownToggle>
|
||||||
<svg class="toolbaricon" fill="currentColor">
|
<svg class="toolbaricon" fill="currentColor">
|
||||||
<use xlink:href="assets/bootstrap-icons.svg#text-indent-left" />
|
<use xlink:href="assets/bootstrap-icons.svg#text-indent-left" />
|
||||||
@ -16,37 +16,37 @@
|
|||||||
<div class="btn-group btn-group-toggle flex-fill" ngbRadioGroup [(ngModel)]="displayMode"
|
<div class="btn-group btn-group-toggle flex-fill" ngbRadioGroup [(ngModel)]="displayMode"
|
||||||
(ngModelChange)="saveDisplayMode()">
|
(ngModelChange)="saveDisplayMode()">
|
||||||
<label ngbButtonLabel class="btn-outline-primary btn-sm">
|
<label ngbButtonLabel class="btn-outline-primary btn-sm">
|
||||||
<input ngbButton type="radio" class="btn btn-sm" value="details">
|
<input ngbButton type="radio" class="btn-check btn-sm" value="details">
|
||||||
<svg class="toolbaricon" fill="currentColor">
|
<svg class="toolbaricon" fill="currentColor">
|
||||||
<use xlink:href="assets/bootstrap-icons.svg#list-ul" />
|
<use xlink:href="assets/bootstrap-icons.svg#list-ul" />
|
||||||
</svg>
|
</svg>
|
||||||
</label>
|
</label>
|
||||||
<label ngbButtonLabel class="btn-outline-primary btn-sm">
|
<label ngbButtonLabel class="btn-outline-primary btn-sm">
|
||||||
<input ngbButton type="radio" class="btn btn-sm" value="smallCards">
|
<input ngbButton type="radio" class="btn-check btn-sm" value="smallCards">
|
||||||
<svg class="toolbaricon" fill="currentColor">
|
<svg class="toolbaricon" fill="currentColor">
|
||||||
<use xlink:href="assets/bootstrap-icons.svg#grid" />
|
<use xlink:href="assets/bootstrap-icons.svg#grid" />
|
||||||
</svg>
|
</svg>
|
||||||
</label>
|
</label>
|
||||||
<label ngbButtonLabel class="btn-outline-primary btn-sm">
|
<label ngbButtonLabel class="btn-outline-primary btn-sm">
|
||||||
<input ngbButton type="radio" class="btn btn-sm" value="largeCards">
|
<input ngbButton type="radio" class="btn-check btn-sm" value="largeCards">
|
||||||
<svg class="toolbaricon" fill="currentColor">
|
<svg class="toolbaricon" fill="currentColor">
|
||||||
<use xlink:href="assets/bootstrap-icons.svg#hdd-stack" />
|
<use xlink:href="assets/bootstrap-icons.svg#hdd-stack" />
|
||||||
</svg>
|
</svg>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div ngbDropdown class="btn-group ml-2 flex-fill">
|
<div ngbDropdown class="btn-group ms-2 flex-fill">
|
||||||
<button class="btn btn-outline-primary btn-sm" id="dropdownBasic1" ngbDropdownToggle i18n>Sort</button>
|
<button class="btn btn-outline-primary btn-sm" id="dropdownBasic1" ngbDropdownToggle i18n>Sort</button>
|
||||||
<div ngbDropdownMenu aria-labelledby="dropdownBasic1" class="shadow dropdown-menu-right">
|
<div ngbDropdownMenu aria-labelledby="dropdownBasic1" class="shadow dropdown-menu-right">
|
||||||
<div class="w-100 d-flex btn-group-toggle pb-2 mb-1 border-bottom" ngbRadioGroup [(ngModel)]="list.sortReverse">
|
<div class="w-100 d-flex btn-group-toggle pb-2 mb-1 border-bottom" ngbRadioGroup [(ngModel)]="list.sortReverse">
|
||||||
<label ngbButtonLabel class="btn-outline-primary btn-sm mx-2 flex-fill">
|
<label ngbButtonLabel class="btn-outline-primary btn-sm mx-2 flex-fill">
|
||||||
<input ngbButton type="radio" class="btn btn-sm" [value]="false">
|
<input ngbButton type="radio" class="btn btn-check btn-sm" [value]="false">
|
||||||
<svg class="toolbaricon" fill="currentColor">
|
<svg class="toolbaricon" fill="currentColor">
|
||||||
<use xlink:href="assets/bootstrap-icons.svg#sort-alpha-down" />
|
<use xlink:href="assets/bootstrap-icons.svg#sort-alpha-down" />
|
||||||
</svg>
|
</svg>
|
||||||
</label>
|
</label>
|
||||||
<label ngbButtonLabel class="btn-outline-primary btn-sm mr-2 flex-fill">
|
<label ngbButtonLabel class="btn-outline-primary btn-sm me-2 flex-fill">
|
||||||
<input ngbButton type="radio" class="btn btn-sm" [value]="true">
|
<input ngbButton type="radio" class="btn btn-check btn-sm" [value]="true">
|
||||||
<svg class="toolbaricon" fill="currentColor">
|
<svg class="toolbaricon" fill="currentColor">
|
||||||
<use xlink:href="assets/bootstrap-icons.svg#sort-alpha-up-alt" />
|
<use xlink:href="assets/bootstrap-icons.svg#sort-alpha-up-alt" />
|
||||||
</svg>
|
</svg>
|
||||||
@ -60,7 +60,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="btn-group ml-2 flex-fill" ngbDropdown role="group">
|
<div class="btn-group ms-2 flex-fill" ngbDropdown role="group">
|
||||||
<button class="btn btn-sm btn-outline-primary dropdown-toggle flex-fill" ngbDropdownToggle i18n>Views</button>
|
<button class="btn btn-sm btn-outline-primary dropdown-toggle flex-fill" ngbDropdownToggle i18n>Views</button>
|
||||||
<div class="dropdown-menu shadow dropdown-menu-right" ngbDropdownMenu>
|
<div class="dropdown-menu shadow dropdown-menu-right" ngbDropdownMenu>
|
||||||
<ng-container *ngIf="!list.activeSavedViewId">
|
<ng-container *ngIf="!list.activeSavedViewId">
|
||||||
@ -83,7 +83,7 @@
|
|||||||
<div class="d-flex justify-content-between align-items-center">
|
<div class="d-flex justify-content-between align-items-center">
|
||||||
<p>
|
<p>
|
||||||
<ng-container *ngIf="list.isReloading">
|
<ng-container *ngIf="list.isReloading">
|
||||||
<div class="spinner-border spinner-border-sm mr-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>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<span i18n *ngIf="list.selected.size > 0">{list.collectionSize, plural, =1 {Selected {{list.selected.size}} of one document} other {Selected {{list.selected.size}} of {{list.collectionSize || 0}} documents}}</span>
|
<span i18n *ngIf="list.selected.size > 0">{list.collectionSize, plural, =1 {Selected {{list.selected.size}} of one document} other {Selected {{list.selected.size}} of {{list.collectionSize || 0}} documents}}</span>
|
||||||
@ -106,7 +106,7 @@
|
|||||||
</app-document-card-large>
|
</app-document-card-large>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<table class="table table-sm border shadow-sm" *ngIf="displayMode == 'details'">
|
<table class="table table-sm align-middle border shadow-sm" *ngIf="displayMode == 'details'">
|
||||||
<thead>
|
<thead>
|
||||||
<th></th>
|
<th></th>
|
||||||
<th class="d-none d-lg-table-cell"
|
<th class="d-none d-lg-table-cell"
|
||||||
@ -149,9 +149,9 @@
|
|||||||
<tbody>
|
<tbody>
|
||||||
<tr *ngFor="let d of list.documents; trackBy: trackByDocumentId" (click)="toggleSelected(d, $event)" [ngClass]="list.isSelected(d) ? 'table-row-selected' : ''">
|
<tr *ngFor="let d of list.documents; trackBy: trackByDocumentId" (click)="toggleSelected(d, $event)" [ngClass]="list.isSelected(d) ? 'table-row-selected' : ''">
|
||||||
<td>
|
<td>
|
||||||
<div class="custom-control custom-checkbox">
|
<div class="form-check">
|
||||||
<input type="checkbox" class="custom-control-input" id="docCheck{{d.id}}" [checked]="list.isSelected(d)" (click)="toggleSelected(d, $event)">
|
<input type="checkbox" class="form-check-input" id="docCheck{{d.id}}" [checked]="list.isSelected(d)" (click)="toggleSelected(d, $event)">
|
||||||
<label class="custom-control-label" for="docCheck{{d.id}}"></label>
|
<label class="form-check-label" for="docCheck{{d.id}}"></label>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td class="d-none d-lg-table-cell">
|
<td class="d-none d-lg-table-cell">
|
||||||
@ -159,16 +159,16 @@
|
|||||||
</td>
|
</td>
|
||||||
<td class="d-none d-md-table-cell">
|
<td class="d-none d-md-table-cell">
|
||||||
<ng-container *ngIf="d.correspondent">
|
<ng-container *ngIf="d.correspondent">
|
||||||
<a [routerLink]="" (click)="clickCorrespondent(d.correspondent);$event.stopPropagation()" title="Filter by correspondent">{{(d.correspondent$ | async)?.name}}</a>
|
<a [routerLink]="[]" (click)="clickCorrespondent(d.correspondent);$event.stopPropagation()" title="Filter by correspondent">{{(d.correspondent$ | async)?.name}}</a>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<a routerLink="/documents/{{d.id}}" title="Edit document" style="overflow-wrap: anywhere;">{{d.title | documentTitle}}</a>
|
<a routerLink="/documents/{{d.id}}" title="Edit document" style="overflow-wrap: anywhere;">{{d.title | documentTitle}}</a>
|
||||||
<app-tag [tag]="t" *ngFor="let t of d.tags$ | async" class="ml-1" clickable="true" linkTitle="Filter by tag" (click)="clickTag(t.id);$event.stopPropagation()"></app-tag>
|
<app-tag [tag]="t" *ngFor="let t of d.tags$ | async" class="ms-1" clickable="true" linkTitle="Filter by tag" (click)="clickTag(t.id);$event.stopPropagation()"></app-tag>
|
||||||
</td>
|
</td>
|
||||||
<td class="d-none d-xl-table-cell">
|
<td class="d-none d-xl-table-cell">
|
||||||
<ng-container *ngIf="d.document_type">
|
<ng-container *ngIf="d.document_type">
|
||||||
<a [routerLink]="" (click)="clickDocumentType(d.document_type);$event.stopPropagation()" title="Filter by document type">{{(d.document_type$ | async)?.name}}</a>
|
<a [routerLink]="[]" (click)="clickDocumentType(d.document_type);$event.stopPropagation()" title="Filter by document type">{{(d.document_type$ | async)?.name}}</a>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
@ -182,7 +182,7 @@
|
|||||||
</table>
|
</table>
|
||||||
|
|
||||||
<div class="m-n2 row row-cols-paperless-cards" *ngIf="displayMode == 'smallCards'">
|
<div class="m-n2 row row-cols-paperless-cards" *ngIf="displayMode == 'smallCards'">
|
||||||
<app-document-card-small [selected]="list.isSelected(d)" (toggleSelected)="toggleSelected(d, $event)" [document]="d" *ngFor="let d of list.documents; trackBy: trackByDocumentId" (clickTag)="clickTag($event)" (clickCorrespondent)="clickCorrespondent($event)" (clickDocumentType)="clickDocumentType($event)"></app-document-card-small>
|
<app-document-card-small class="p-0" [selected]="list.isSelected(d)" (toggleSelected)="toggleSelected(d, $event)" [document]="d" *ngFor="let d of list.documents; trackBy: trackByDocumentId" (clickTag)="clickTag($event)" (clickCorrespondent)="clickCorrespondent($event)" (clickDocumentType)="clickDocumentType($event)"></app-document-card-small>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ $paperless-card-breakpoints: (
|
|||||||
@media(min-width: $width) {
|
@media(min-width: $width) {
|
||||||
> * {
|
> * {
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
width: 100% / $n_cols;
|
width: calc(100% / $n-cols);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -43,3 +43,13 @@ $paperless-card-breakpoints: (
|
|||||||
top: 3.5rem; // height of navbar
|
top: 3.5rem; // height of navbar
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.table .form-check {
|
||||||
|
padding: 0.2rem;
|
||||||
|
min-height: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
|
||||||
|
.form-check-input {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
<div class="col mb-2 mb-xl-0">
|
<div class="col mb-2 mb-xl-0">
|
||||||
<div class="form-inline d-flex align-items-center">
|
<div class="form-inline d-flex align-items-center">
|
||||||
<div class="input-group input-group-sm flex-fill w-auto">
|
<div class="input-group input-group-sm flex-fill w-auto">
|
||||||
<div class="input-group-prepend" ngbDropdown>
|
<div ngbDropdown>
|
||||||
<button class="btn btn-outline-primary" ngbDropdownToggle>{{textFilterTargetName}}</button>
|
<button class="btn btn-sm btn-outline-primary" ngbDropdownToggle>{{textFilterTargetName}}</button>
|
||||||
<div class="dropdown-menu shadow" ngbDropdownMenu>
|
<div class="dropdown-menu shadow" ngbDropdownMenu>
|
||||||
<button *ngFor="let t of textFilterTargets" ngbDropdownItem [class.active]="textFilterTarget == t.id" (click)="changeTextFilterTarget(t.id)">{{t.name}}</button>
|
<button *ngFor="let t of textFilterTargets" ngbDropdownItem [class.active]="textFilterTarget == t.id" (click)="changeTextFilterTarget(t.id)">{{t.name}}</button>
|
||||||
</div>
|
</div>
|
||||||
@ -15,7 +15,7 @@
|
|||||||
<div class="w-100 d-xl-none"></div>
|
<div class="w-100 d-xl-none"></div>
|
||||||
<div class="col col-xl-auto mb-2 mb-xl-0">
|
<div class="col col-xl-auto mb-2 mb-xl-0">
|
||||||
<div class="d-flex">
|
<div class="d-flex">
|
||||||
<app-filterable-dropdown class="mr-2 flex-fill" title="Tags" icon="tag-fill" i18n-title
|
<app-filterable-dropdown class="me-2 flex-fill" title="Tags" icon="tag-fill" i18n-title
|
||||||
filterPlaceholder="Filter tags" i18n-filterPlaceholder
|
filterPlaceholder="Filter tags" i18n-filterPlaceholder
|
||||||
[items]="tags"
|
[items]="tags"
|
||||||
[(selectionModel)]="tagSelectionModel"
|
[(selectionModel)]="tagSelectionModel"
|
||||||
@ -23,21 +23,21 @@
|
|||||||
[multiple]="true"
|
[multiple]="true"
|
||||||
(open)="onTagsDropdownOpen()"
|
(open)="onTagsDropdownOpen()"
|
||||||
[allowSelectNone]="true"></app-filterable-dropdown>
|
[allowSelectNone]="true"></app-filterable-dropdown>
|
||||||
<app-filterable-dropdown class="mr-2 flex-fill" title="Correspondent" icon="person-fill" i18n-title
|
<app-filterable-dropdown class="me-2 flex-fill" title="Correspondent" icon="person-fill" i18n-title
|
||||||
filterPlaceholder="Filter correspondents" i18n-filterPlaceholder
|
filterPlaceholder="Filter correspondents" i18n-filterPlaceholder
|
||||||
[items]="correspondents"
|
[items]="correspondents"
|
||||||
[(selectionModel)]="correspondentSelectionModel"
|
[(selectionModel)]="correspondentSelectionModel"
|
||||||
(selectionModelChange)="updateRules()"
|
(selectionModelChange)="updateRules()"
|
||||||
(open)="onCorrespondentDropdownOpen()"
|
(open)="onCorrespondentDropdownOpen()"
|
||||||
[allowSelectNone]="true"></app-filterable-dropdown>
|
[allowSelectNone]="true"></app-filterable-dropdown>
|
||||||
<app-filterable-dropdown class="mr-2 flex-fill" title="Document type" icon="file-earmark-fill" i18n-title
|
<app-filterable-dropdown class="me-2 flex-fill" title="Document type" icon="file-earmark-fill" i18n-title
|
||||||
filterPlaceholder="Filter document types" i18n-filterPlaceholder
|
filterPlaceholder="Filter document types" i18n-filterPlaceholder
|
||||||
[items]="documentTypes"
|
[items]="documentTypes"
|
||||||
[(selectionModel)]="documentTypeSelectionModel"
|
[(selectionModel)]="documentTypeSelectionModel"
|
||||||
(open)="onDocumentTypeDropdownOpen()"
|
(open)="onDocumentTypeDropdownOpen()"
|
||||||
(selectionModelChange)="updateRules()"
|
(selectionModelChange)="updateRules()"
|
||||||
[allowSelectNone]="true"></app-filterable-dropdown>
|
[allowSelectNone]="true"></app-filterable-dropdown>
|
||||||
<app-date-dropdown class="mr-2"
|
<app-date-dropdown class="me-2"
|
||||||
title="Created" i18n-title
|
title="Created" i18n-title
|
||||||
(datesSet)="updateRules()"
|
(datesSet)="updateRules()"
|
||||||
[(dateBefore)]="dateCreatedBefore"
|
[(dateBefore)]="dateCreatedBefore"
|
||||||
@ -51,11 +51,10 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="w-100 d-xl-none"></div>
|
<div class="w-100 d-xl-none"></div>
|
||||||
<div class="col col-xl-auto mb-2 mb-xl-0">
|
<div class="col col-xl-auto mb-2 mb-xl-0">
|
||||||
<button class="btn btn-link btn-sm px-0 mx-0 ml-xl-n4" [disabled]="!rulesModified" (click)="resetSelected()">
|
<button class="btn btn-link btn-sm px-0 mx-0 ms-xl-n3" [disabled]="!rulesModified" (click)="resetSelected()">
|
||||||
<svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-x" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
<svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-x me-1" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path fill-rule="evenodd" d="M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z"/>
|
<path fill-rule="evenodd" d="M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z"/>
|
||||||
</svg> <ng-container i18n>Reset filters</ng-container>
|
</svg><ng-container i18n>Reset filters</ng-container>
|
||||||
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -8,3 +8,12 @@
|
|||||||
min-height: 1em;
|
min-height: 1em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.input-group .dropdown .btn {
|
||||||
|
border-top-right-radius: 0;
|
||||||
|
border-bottom-right-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.me-2 {
|
||||||
|
margin-right: 0.7rem !important; // tweak to make room for badges
|
||||||
|
}
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
<form [formGroup]="saveViewConfigForm" (ngSubmit)="save()">
|
<form [formGroup]="saveViewConfigForm" (ngSubmit)="save()">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h4 class="modal-title" id="modal-basic-title" i18n>Save current view</h4>
|
<h4 class="modal-title" id="modal-basic-title" i18n>Save current view</h4>
|
||||||
<button type="button" [disabled]="!closeEnabled" class="close" aria-label="Close" (click)="cancel()">
|
<button type="button" [disabled]="!closeEnabled" class="btn-close" aria-label="Close" (click)="cancel()">
|
||||||
<span aria-hidden="true">×</span>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
<form [formGroup]="objectForm" (ngSubmit)="save()">
|
<form [formGroup]="objectForm" (ngSubmit)="save()">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h4 class="modal-title" id="modal-basic-title">{{getTitle()}}</h4>
|
<h4 class="modal-title" id="modal-basic-title">{{getTitle()}}</h4>
|
||||||
<button type="button" [disabled]="!closeEnabled" class="close" aria-label="Close" (click)="cancel()">
|
<button type="button" [disabled]="!closeEnabled" class="btn-close" aria-label="Close" (click)="cancel()">
|
||||||
<span aria-hidden="true">×</span>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md mb-2 mb-xl-0">
|
<div class="col-md mb-2 mb-xl-0">
|
||||||
<div class="form-inline d-flex align-items-center">
|
<div class="form-inline d-flex align-items-center">
|
||||||
<label class="text-muted mr-2 mb-0" i18n>Filter by:</label>
|
<label class="text-muted me-2 mb-0" i18n>Filter by:</label>
|
||||||
<input class="form-control form-control-sm flex-fill w-auto" type="text" [(ngModel)]="nameFilter" placeholder="Name" i18n-placeholder>
|
<input class="form-control form-control-sm flex-fill w-auto" type="text" [(ngModel)]="nameFilter" placeholder="Name" i18n-placeholder>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -13,7 +13,7 @@
|
|||||||
<ngb-pagination class="col-auto" [pageSize]="25" [collectionSize]="collectionSize" [(page)]="page" (pageChange)="reloadData()" aria-label="Default pagination"></ngb-pagination>
|
<ngb-pagination class="col-auto" [pageSize]="25" [collectionSize]="collectionSize" [(page)]="page" (pageChange)="reloadData()" aria-label="Default pagination"></ngb-pagination>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<table class="table table-striped border shadow-sm">
|
<table class="table table-striped align-middle border shadow-sm">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="col" sortable="name" [currentSortField]="sortField" [currentSortReverse]="sortReverse" (sort)="onSort($event)" i18n>Name</th>
|
<th scope="col" sortable="name" [currentSortField]="sortField" [currentSortReverse]="sortReverse" (sort)="onSort($event)" i18n>Name</th>
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
<form [formGroup]="objectForm" (ngSubmit)="save()">
|
<form [formGroup]="objectForm" (ngSubmit)="save()">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h4 class="modal-title" id="modal-basic-title">{{getTitle()}}</h4>
|
<h4 class="modal-title" id="modal-basic-title">{{getTitle()}}</h4>
|
||||||
<button type="button" [disabled]="!closeEnabled" class="close" aria-label="Close" (click)="cancel()">
|
<button type="button" [disabled]="!closeEnabled" class="btn-close" aria-label="Close" (click)="cancel()">
|
||||||
<span aria-hidden="true">×</span>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md mb-2 mb-xl-0">
|
<div class="col-md mb-2 mb-xl-0">
|
||||||
<div class="form-inline d-flex align-items-center">
|
<div class="form-inline d-flex align-items-center">
|
||||||
<label class="text-muted mr-2 mb-0" i18n>Filter by:</label>
|
<label class="text-muted me-2 mb-0" i18n>Filter by:</label>
|
||||||
<input class="form-control form-control-sm flex-fill w-auto" type="text" [(ngModel)]="nameFilter" placeholder="Name" i18n-placeholder>
|
<input class="form-control form-control-sm flex-fill w-auto" type="text" [(ngModel)]="nameFilter" placeholder="Name" i18n-placeholder>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -13,7 +13,7 @@
|
|||||||
<ngb-pagination class="col-auto" [pageSize]="25" [collectionSize]="collectionSize" [(page)]="page" (pageChange)="reloadData()" aria-label="Default pagination"></ngb-pagination>
|
<ngb-pagination class="col-auto" [pageSize]="25" [collectionSize]="collectionSize" [(page)]="page" (pageChange)="reloadData()" aria-label="Default pagination"></ngb-pagination>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<table class="table table-striped border shadow-sm">
|
<table class="table table-striped align-middle border shadow-sm">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="col" sortable="name" [currentSortField]="sortField" [currentSortReverse]="sortReverse" (sort)="onSort($event)" i18n>Name</th>
|
<th scope="col" sortable="name" [currentSortField]="sortField" [currentSortReverse]="sortReverse" (sort)="onSort($event)" i18n>Name</th>
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
<div [ngbNavOutlet]="nav" class="mt-2"></div>
|
<div [ngbNavOutlet]="nav" class="mt-2"></div>
|
||||||
|
|
||||||
<div class="bg-dark p-3 text-light text-monospace log-container" #logContainer>
|
<div class="bg-dark p-3 text-light font-monospace log-container" #logContainer>
|
||||||
<p
|
<p
|
||||||
class="m-0 p-0 log-entry-{{getLogLevel(log)}}"
|
class="m-0 p-0 log-entry-{{getLogLevel(log)}}"
|
||||||
*ngFor="let log of logs">{{log}}</p>
|
*ngFor="let log of logs">{{log}}</p>
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
<h4 i18n>Appearance</h4>
|
<h4 i18n>Appearance</h4>
|
||||||
|
|
||||||
<div class="form-row form-group">
|
<div class="row mb-3">
|
||||||
<div class="col-md-3 col-form-label">
|
<div class="col-md-3 col-form-label">
|
||||||
<span i18n>Display language</span>
|
<span i18n>Display language</span>
|
||||||
</div>
|
</div>
|
||||||
@ -27,7 +27,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-row form-group">
|
<div class="row mb-3">
|
||||||
<div class="col-md-3 col-form-label">
|
<div class="col-md-3 col-form-label">
|
||||||
<span i18n>Date display</span>
|
<span i18n>Date display</span>
|
||||||
</div>
|
</div>
|
||||||
@ -40,29 +40,29 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-row form-group">
|
<div class="row mb-3">
|
||||||
<div class="col-md-3 col-form-label">
|
<div class="col-md-3 col-form-label">
|
||||||
<span i18n>Date format</span>
|
<span i18n>Date format</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
|
|
||||||
<div class="custom-control custom-radio">
|
<div class="form-check">
|
||||||
<input type="radio" id="dateFormatShort" name="dateFormat" class="custom-control-input" formControlName="dateFormat" value="shortDate">
|
<input type="radio" id="dateFormatShort" name="dateFormat" class="form-check-input" formControlName="dateFormat" value="shortDate">
|
||||||
<label class="custom-control-label" for="dateFormatShort" i18n>Short: {{today | customDate:'shortDate':null:computedDateLocale}}</label>
|
<label class="form-check-label" for="dateFormatShort" i18n>Short: {{today | customDate:'shortDate':null:computedDateLocale}}</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="custom-control custom-radio">
|
<div class="form-check">
|
||||||
<input type="radio" id="dateFormatMedium" name="dateFormat" class="custom-control-input" formControlName="dateFormat" value="mediumDate">
|
<input type="radio" id="dateFormatMedium" name="dateFormat" class="form-check-input" formControlName="dateFormat" value="mediumDate">
|
||||||
<label class="custom-control-label" for="dateFormatMedium" i18n>Medium: {{today | customDate:'mediumDate':null:computedDateLocale}}</label>
|
<label class="form-check-label" for="dateFormatMedium" i18n>Medium: {{today | customDate:'mediumDate':null:computedDateLocale}}</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="custom-control custom-radio">
|
<div class="form-check">
|
||||||
<input type="radio" id="dateFormatLong" name="dateFormat" class="custom-control-input" formControlName="dateFormat" value="longDate">
|
<input type="radio" id="dateFormatLong" name="dateFormat" class="form-check-input" formControlName="dateFormat" value="longDate">
|
||||||
<label class="custom-control-label" for="dateFormatLong" i18n>Long: {{today | customDate:'longDate':null:computedDateLocale}}</label>
|
<label class="form-check-label" for="dateFormatLong" i18n>Long: {{today | customDate:'longDate':null:computedDateLocale}}</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-row form-group">
|
<div class="row mb-3">
|
||||||
<div class="col-md-3 col-form-label">
|
<div class="col-md-3 col-form-label">
|
||||||
<span i18n>Items per page</span>
|
<span i18n>Items per page</span>
|
||||||
</div>
|
</div>
|
||||||
@ -78,7 +78,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-row form-group">
|
<div class="row mb-3">
|
||||||
<div class="col-md-3 col-form-label">
|
<div class="col-md-3 col-form-label">
|
||||||
<span i18n>Document editor</span>
|
<span i18n>Document editor</span>
|
||||||
</div>
|
</div>
|
||||||
@ -89,7 +89,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-row form-group">
|
<div class="row mb-3">
|
||||||
<div class="col-md-3 col-form-label">
|
<div class="col-md-3 col-form-label">
|
||||||
<span i18n>Dark mode</span>
|
<span i18n>Dark mode</span>
|
||||||
</div>
|
</div>
|
||||||
@ -102,7 +102,7 @@
|
|||||||
|
|
||||||
<h4 class="mt-4" i18n>Bulk editing</h4>
|
<h4 class="mt-4" i18n>Bulk editing</h4>
|
||||||
|
|
||||||
<div class="form-row form-group">
|
<div class="row mb-3">
|
||||||
<div class="offset-md-3 col">
|
<div class="offset-md-3 col">
|
||||||
<app-input-check i18n-title title="Show confirmation dialogs" formControlName="bulkEditConfirmationDialogs" i18n-hint hint="Deleting documents will always ask for confirmation."></app-input-check>
|
<app-input-check i18n-title title="Show confirmation dialogs" formControlName="bulkEditConfirmationDialogs" i18n-hint hint="Deleting documents will always ask for confirmation."></app-input-check>
|
||||||
<app-input-check i18n-title title="Apply on close" formControlName="bulkEditApplyOnClose"></app-input-check>
|
<app-input-check i18n-title title="Apply on close" formControlName="bulkEditApplyOnClose"></app-input-check>
|
||||||
@ -118,7 +118,7 @@
|
|||||||
|
|
||||||
<h4 i18n>Document processing</h4>
|
<h4 i18n>Document processing</h4>
|
||||||
|
|
||||||
<div class="form-row form-group">
|
<div class="row mb-3">
|
||||||
<div class="offset-md-3 col">
|
<div class="offset-md-3 col">
|
||||||
<app-input-check i18n-title title="Show notifications when new documents are detected" formControlName="notificationsConsumerNewDocument"></app-input-check>
|
<app-input-check i18n-title title="Show notifications when new documents are detected" formControlName="notificationsConsumerNewDocument"></app-input-check>
|
||||||
<app-input-check i18n-title title="Show notifications when document processing completes successfully" formControlName="notificationsConsumerSuccess"></app-input-check>
|
<app-input-check i18n-title title="Show notifications when document processing completes successfully" formControlName="notificationsConsumerSuccess"></app-input-check>
|
||||||
@ -136,26 +136,26 @@
|
|||||||
|
|
||||||
<div formGroupName="savedViews">
|
<div formGroupName="savedViews">
|
||||||
|
|
||||||
<div *ngFor="let view of savedViews" [formGroupName]="view.id" class="form-row">
|
<div *ngFor="let view of savedViews" [formGroupName]="view.id" class="row">
|
||||||
<div class="form-group col-4 mr-3">
|
<div class="mb-3 col">
|
||||||
<label for="name_{{view.id}}" i18n>Name</label>
|
<label class="form-label" for="name_{{view.id}}" i18n>Name</label>
|
||||||
<input type="text" class="form-control" formControlName="name" id="name_{{view.id}}">
|
<input type="text" class="form-control" formControlName="name" id="name_{{view.id}}">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group col-auto mr-3">
|
<div class="mb-2 col">
|
||||||
<label for="show_on_dashboard_{{view.id}}" i18n>Appears on</label>
|
<label class="form-label" for="show_on_dashboard_{{view.id}}" i18n>Appears on</label>
|
||||||
<div class="custom-control custom-switch">
|
<div class="form-check form-switch">
|
||||||
<input type="checkbox" class="custom-control-input" id="show_on_dashboard_{{view.id}}" formControlName="show_on_dashboard">
|
<input type="checkbox" class="form-check-input" id="show_on_dashboard_{{view.id}}" formControlName="show_on_dashboard">
|
||||||
<label class="custom-control-label" for="show_on_dashboard_{{view.id}}" i18n>Show on dashboard</label>
|
<label class="form-check-label" for="show_on_dashboard_{{view.id}}" i18n>Show on dashboard</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="custom-control custom-switch">
|
<div class="form-check form-switch">
|
||||||
<input type="checkbox" class="custom-control-input" id="show_in_sidebar_{{view.id}}" formControlName="show_in_sidebar">
|
<input type="checkbox" class="form-check-input" id="show_in_sidebar_{{view.id}}" formControlName="show_in_sidebar">
|
||||||
<label class="custom-control-label" for="show_in_sidebar_{{view.id}}" i18n>Show in sidebar</label>
|
<label class="form-check-label" for="show_in_sidebar_{{view.id}}" i18n>Show in sidebar</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group col-auto">
|
<div class="mb-2 col-auto">
|
||||||
<label for="name_{{view.id}}" i18n>Actions</label>
|
<label class="form-label" for="name_{{view.id}}" i18n>Actions</label>
|
||||||
<button type="button" class="btn btn-sm btn-outline-danger form-control" (click)="deleteSavedView(view)" i18n>Delete</button>
|
<button type="button" class="btn btn-sm btn-outline-danger form-control" (click)="deleteSavedView(view)" i18n>Delete</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -168,7 +168,7 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div [ngbNavOutlet]="nav" class="border-left border-right border-bottom p-3 mb-3 shadow-sm"></div>
|
<div [ngbNavOutlet]="nav" class="border-start border-end border-bottom p-3 mb-3 shadow-sm"></div>
|
||||||
|
|
||||||
<button type="submit" class="btn btn-primary" [disabled]="!(isDirty$ | async)" i18n>Save</button>
|
<button type="submit" class="btn btn-primary" [disabled]="!(isDirty$ | async)" i18n>Save</button>
|
||||||
</form>
|
</form>
|
||||||
|
@ -23,6 +23,7 @@ export class SettingsComponent implements OnInit, OnDestroy, DirtyComponent {
|
|||||||
'documentListItemPerPage': new FormControl(null),
|
'documentListItemPerPage': new FormControl(null),
|
||||||
'darkModeUseSystem': new FormControl(null),
|
'darkModeUseSystem': new FormControl(null),
|
||||||
'darkModeEnabled': new FormControl(null),
|
'darkModeEnabled': new FormControl(null),
|
||||||
|
'darkModeInvertThumbs': new FormControl(null),
|
||||||
'useNativePdfViewer': new FormControl(null),
|
'useNativePdfViewer': new FormControl(null),
|
||||||
'savedViews': this.savedViewGroup,
|
'savedViews': this.savedViewGroup,
|
||||||
'displayLanguage': new FormControl(null),
|
'displayLanguage': new FormControl(null),
|
||||||
@ -61,6 +62,7 @@ export class SettingsComponent implements OnInit, OnDestroy, DirtyComponent {
|
|||||||
'documentListItemPerPage': this.settings.get(SETTINGS_KEYS.DOCUMENT_LIST_SIZE),
|
'documentListItemPerPage': this.settings.get(SETTINGS_KEYS.DOCUMENT_LIST_SIZE),
|
||||||
'darkModeUseSystem': this.settings.get(SETTINGS_KEYS.DARK_MODE_USE_SYSTEM),
|
'darkModeUseSystem': this.settings.get(SETTINGS_KEYS.DARK_MODE_USE_SYSTEM),
|
||||||
'darkModeEnabled': this.settings.get(SETTINGS_KEYS.DARK_MODE_ENABLED),
|
'darkModeEnabled': this.settings.get(SETTINGS_KEYS.DARK_MODE_ENABLED),
|
||||||
|
'darkModeInvertThumbs': this.settings.get(SETTINGS_KEYS.DARK_MODE_THUMB_INVERTED),
|
||||||
'useNativePdfViewer': this.settings.get(SETTINGS_KEYS.USE_NATIVE_PDF_VIEWER),
|
'useNativePdfViewer': this.settings.get(SETTINGS_KEYS.USE_NATIVE_PDF_VIEWER),
|
||||||
'savedViews': {},
|
'savedViews': {},
|
||||||
'displayLanguage': this.settings.getLanguage(),
|
'displayLanguage': this.settings.getLanguage(),
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
<form [formGroup]="objectForm" (ngSubmit)="save()">
|
<form [formGroup]="objectForm" (ngSubmit)="save()">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h4 class="modal-title" id="modal-basic-title">{{getTitle()}}</h4>
|
<h4 class="modal-title" id="modal-basic-title">{{getTitle()}}</h4>
|
||||||
<button type="button" [disabled]="!closeEnabled" class="close" aria-label="Close" (click)="cancel()">
|
<button type="button" [disabled]="!closeEnabled" class="btn-close" aria-label="Close" (click)="cancel()">
|
||||||
<span aria-hidden="true">×</span>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md mb-2 mb-xl-0">
|
<div class="col-md mb-2 mb-xl-0">
|
||||||
<div class="form-inline d-flex align-items-center">
|
<div class="form-inline d-flex align-items-center">
|
||||||
<label class="text-muted mr-2 mb-0" i18n>Filter by:</label>
|
<label class="text-muted me-2 mb-0" i18n>Filter by:</label>
|
||||||
<input class="form-control form-control-sm flex-fill w-auto" type="text" [(ngModel)]="nameFilter" placeholder="Name" i18n-placeholder>
|
<input class="form-control form-control-sm flex-fill w-auto" type="text" [(ngModel)]="nameFilter" placeholder="Name" i18n-placeholder>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -13,7 +13,7 @@
|
|||||||
<ngb-pagination class="col-auto" [pageSize]="25" [collectionSize]="collectionSize" [(page)]="page" (pageChange)="reloadData()" aria-label="Default pagination"></ngb-pagination>
|
<ngb-pagination class="col-auto" [pageSize]="25" [collectionSize]="collectionSize" [(page)]="page" (pageChange)="reloadData()" aria-label="Default pagination"></ngb-pagination>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<table class="table table-striped border shadow-sm">
|
<table class="table table-striped align-middle border shadow-sm">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="col" sortable="name" [currentSortField]="sortField" [currentSortReverse]="sortReverse" (sort)="onSort($event)" i18n>Name</th>
|
<th scope="col" sortable="name" [currentSortField]="sortField" [currentSortReverse]="sortReverse" (sort)="onSort($event)" i18n>Name</th>
|
||||||
|
@ -20,4 +20,4 @@ export const environment = {
|
|||||||
* This import should be commented out in production mode because it will have a negative impact
|
* This import should be commented out in production mode because it will have a negative impact
|
||||||
* on performance if an error is thrown.
|
* on performance if an error is thrown.
|
||||||
*/
|
*/
|
||||||
// import 'zone.js/dist/zone-error'; // Included with Angular CLI.
|
// import 'zone.js/plugins/zone-error'; // Included with Angular CLI.
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -22,16 +22,6 @@ import '@angular/localize/init';
|
|||||||
* BROWSER POLYFILLS
|
* BROWSER POLYFILLS
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** IE10 and IE11 requires the following for NgClass support on SVG elements */
|
|
||||||
// import 'classlist.js'; // Run `npm install --save classlist.js`.
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Web Animations `@angular/platform-browser/animations`
|
|
||||||
* Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
|
|
||||||
* Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
|
|
||||||
*/
|
|
||||||
// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* By default, zone.js will patch all possible macroTask and DomEvents
|
* By default, zone.js will patch all possible macroTask and DomEvents
|
||||||
* user can disable parts of macroTask/DomEvents patch by setting following flags
|
* user can disable parts of macroTask/DomEvents patch by setting following flags
|
||||||
@ -59,7 +49,7 @@ import '@angular/localize/init';
|
|||||||
/***************************************************************************************************
|
/***************************************************************************************************
|
||||||
* Zone JS is required by default for Angular itself.
|
* Zone JS is required by default for Angular itself.
|
||||||
*/
|
*/
|
||||||
import 'zone.js/dist/zone'; // Included with Angular CLI.
|
import 'zone.js'; // Included with Angular CLI.
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************************************
|
/***************************************************************************************************
|
||||||
|
@ -116,3 +116,20 @@ body {
|
|||||||
.ngx-file-drop__drop-zone--over {
|
.ngx-file-drop__drop-zone--over {
|
||||||
background-color: $primaryFaded !important;
|
background-color: $primaryFaded !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Bootstrap 5 tweaks
|
||||||
|
a.badge {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-link {
|
||||||
|
text-decoration: none;
|
||||||
|
&:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-outline-primary:not(:disabled):not(.disabled).active,.btn-outline-primary:not(:disabled):not(.disabled):active,.show>.btn-outline-primary.dropdown-toggle {
|
||||||
|
background-color: $paperless-green;
|
||||||
|
border-color: $paperless-green;
|
||||||
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
|
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
|
||||||
|
|
||||||
import 'zone.js/dist/zone-testing';
|
import 'zone.js/testing';
|
||||||
import { getTestBed } from '@angular/core/testing';
|
import { getTestBed } from '@angular/core/testing';
|
||||||
import {
|
import {
|
||||||
BrowserDynamicTestingModule,
|
BrowserDynamicTestingModule,
|
||||||
@ -17,7 +17,9 @@ declare const require: {
|
|||||||
// First, initialize the Angular testing environment.
|
// First, initialize the Angular testing environment.
|
||||||
getTestBed().initTestEnvironment(
|
getTestBed().initTestEnvironment(
|
||||||
BrowserDynamicTestingModule,
|
BrowserDynamicTestingModule,
|
||||||
platformBrowserDynamicTesting()
|
platformBrowserDynamicTesting(), {
|
||||||
|
teardown: { destroyAfterEach: false }
|
||||||
|
}
|
||||||
);
|
);
|
||||||
// Then we find all the tests.
|
// Then we find all the tests.
|
||||||
const context = require.context('./', true, /\.spec\.ts$/);
|
const context = require.context('./', true, /\.spec\.ts$/);
|
||||||
|
@ -1,10 +1,7 @@
|
|||||||
$paperless-green: #17541f;
|
$paperless-green: #17541f;
|
||||||
$primary: #17541f;
|
$primary: #17541f;
|
||||||
$primaryFaded: #d1ddd2;
|
$primaryFaded: #d1ddd2;
|
||||||
|
$enable-negative-margins: true;
|
||||||
$theme-colors: (
|
|
||||||
"primary": $primary
|
|
||||||
);
|
|
||||||
|
|
||||||
.bg-body {
|
.bg-body {
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
|
@ -49,11 +49,11 @@ $border-color-dark-mode: #47494f;
|
|||||||
border-color: $border-color-dark-mode !important;
|
border-color: $border-color-dark-mode !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.border-right {
|
.border-end {
|
||||||
border-right: 1px solid $border-color-dark-mode !important;
|
border-right: 1px solid $border-color-dark-mode !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.border-left {
|
.border-start {
|
||||||
border-left: 1px solid $border-color-dark-mode !important;
|
border-left: 1px solid $border-color-dark-mode !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,6 +143,10 @@ $border-color-dark-mode: #47494f;
|
|||||||
color: $text-color-dark-mode-accent;
|
color: $text-color-dark-mode-accent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.badge.border-light {
|
||||||
|
border-color: $bg-dark-mode !important;
|
||||||
|
}
|
||||||
|
|
||||||
.doc-img-container {
|
.doc-img-container {
|
||||||
border: none !important;
|
border: none !important;
|
||||||
border-top-left-radius: .25rem;
|
border-top-left-radius: .25rem;
|
||||||
@ -155,7 +159,7 @@ $border-color-dark-mode: #47494f;
|
|||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
border-color: $bg-dark-mode;
|
border-color: $bg-dark-mode;
|
||||||
filter: invert(10%);
|
filter: invert(10%);
|
||||||
&.border-right {
|
&.border-end {
|
||||||
border-right: none !important;
|
border-right: none !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -201,7 +205,7 @@ $border-color-dark-mode: #47494f;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tr:hover {
|
&.table-hover > tbody > tr:hover > * {
|
||||||
background-color: $bg-light-dark-mode;
|
background-color: $bg-light-dark-mode;
|
||||||
color: $text-color-dark-mode-accent;
|
color: $text-color-dark-mode-accent;
|
||||||
}
|
}
|
||||||
@ -216,11 +220,21 @@ $border-color-dark-mode: #47494f;
|
|||||||
background-color: $bg-light-dark-mode;
|
background-color: $bg-light-dark-mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.table-striped > tbody > tr:nth-of-type(odd) > * {
|
||||||
|
color: $text-color-dark-mode-accent;
|
||||||
|
}
|
||||||
|
|
||||||
.close {
|
.close {
|
||||||
color: $text-color-dark-mode;
|
color: $text-color-dark-mode;
|
||||||
text-shadow: 0 1px 0 #666;
|
text-shadow: 0 1px 0 #666;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.modal .btn-close {
|
||||||
|
color: $text-color-dark-mode;
|
||||||
|
text-shadow: 0 1px 0 #666;
|
||||||
|
filter: invert(1) grayscale(100%) brightness(200%);
|
||||||
|
}
|
||||||
|
|
||||||
.btn-outline-primary {
|
.btn-outline-primary {
|
||||||
border-color: $primary-dark-mode;
|
border-color: $primary-dark-mode;
|
||||||
color: $primary-dark-mode;
|
color: $primary-dark-mode;
|
||||||
@ -336,15 +350,6 @@ $border-color-dark-mode: #47494f;
|
|||||||
background-color: $bg-light-dark-mode;
|
background-color: $bg-light-dark-mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
.custom-control-label:before {
|
|
||||||
background-color: $bg-dark-mode;
|
|
||||||
color: $text-color-dark-mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
.custom-control-input:checked ~ .custom-control-label::before {
|
|
||||||
color: $text-color-dark-mode-accent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input-group-text {
|
.input-group-text {
|
||||||
color: $text-color-dark-mode;
|
color: $text-color-dark-mode;
|
||||||
background-color: $bg-light-dark-mode;
|
background-color: $bg-light-dark-mode;
|
||||||
@ -409,13 +414,18 @@ $border-color-dark-mode: #47494f;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$placements: 'top', 'right', 'bottom', 'left';
|
// fix popover carat colors
|
||||||
|
.bs-popover-start > .popover-arrow::after, .bs-popover-auto[data-popper-placement^="left"] {
|
||||||
@each $placement in $placements {
|
border-left-color: $bg-dark-mode-accent;
|
||||||
.bs-popover-#{$placement} > .arrow::after,
|
}
|
||||||
.bs-popover-auto[x-placement^=#{$placement}] > .arrow::after {
|
.bs-popover-end > .popover-arrow::after, .bs-popover-auto[data-popper-placement^="right"] {
|
||||||
border-#{$placement}-color: $bg-dark-mode-accent;
|
border-right-color: $bg-dark-mode-accent;
|
||||||
}
|
}
|
||||||
|
.bs-popover-top > .popover-arrow::after, .bs-popover-auto[data-popper-placement^="top"] {
|
||||||
|
border-top-color: $bg-dark-mode-accent;
|
||||||
|
}
|
||||||
|
.bs-popover-bottom > .popover-arrow::after, .bs-popover-auto[data-popper-placement^="bottom"] {
|
||||||
|
border-bottom-color: $bg-dark-mode-accent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bs-popover-bottom .popover-header::before,
|
.bs-popover-bottom .popover-header::before,
|
||||||
|
@ -16,5 +16,8 @@
|
|||||||
"es2018",
|
"es2018",
|
||||||
"dom"
|
"dom"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"angularCompilerOptions": {
|
||||||
|
"enableI18nLegacyMessageIdFormat": false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -145,7 +145,7 @@ def set_document_type(sender,
|
|||||||
else str(document)
|
else str(document)
|
||||||
) + f" [{document.pk}]"
|
) + f" [{document.pk}]"
|
||||||
)
|
)
|
||||||
print(f"Sugest document type {selected}")
|
print(f"Suggest document type {selected}")
|
||||||
else:
|
else:
|
||||||
logger.info(
|
logger.info(
|
||||||
f"Assigning document type {selected} to {document}",
|
f"Assigning document type {selected} to {document}",
|
||||||
@ -225,6 +225,37 @@ def set_tags(sender,
|
|||||||
@receiver(models.signals.post_delete, sender=Document)
|
@receiver(models.signals.post_delete, sender=Document)
|
||||||
def cleanup_document_deletion(sender, instance, using, **kwargs):
|
def cleanup_document_deletion(sender, instance, using, **kwargs):
|
||||||
with FileLock(settings.MEDIA_LOCK):
|
with FileLock(settings.MEDIA_LOCK):
|
||||||
|
if settings.TRASH_DIR:
|
||||||
|
# Find a non-conflicting filename in case a document with the same
|
||||||
|
# name was moved to trash earlier
|
||||||
|
counter = 0
|
||||||
|
old_filename = os.path.split(instance.source_path)[1]
|
||||||
|
(old_filebase, old_fileext) = os.path.splitext(old_filename)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
new_file_path = os.path.join(
|
||||||
|
settings.TRASH_DIR,
|
||||||
|
old_filebase +
|
||||||
|
(f"_{counter:02}" if counter else "") +
|
||||||
|
old_fileext
|
||||||
|
)
|
||||||
|
|
||||||
|
if os.path.exists(new_file_path):
|
||||||
|
counter += 1
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
|
||||||
|
logger.debug(
|
||||||
|
f"Moving {instance.source_path} to trash at {new_file_path}")
|
||||||
|
try:
|
||||||
|
os.rename(instance.source_path, new_file_path)
|
||||||
|
except OSError as e:
|
||||||
|
logger.error(
|
||||||
|
f"Failed to move {instance.source_path} to trash at "
|
||||||
|
f"{new_file_path}: {e}. Skipping cleanup!"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
for filename in (instance.source_path,
|
for filename in (instance.source_path,
|
||||||
instance.archive_path,
|
instance.archive_path,
|
||||||
instance.thumbnail_path):
|
instance.thumbnail_path):
|
||||||
|
@ -2,6 +2,7 @@ import datetime
|
|||||||
import hashlib
|
import hashlib
|
||||||
import os
|
import os
|
||||||
import random
|
import random
|
||||||
|
import tempfile
|
||||||
import uuid
|
import uuid
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
@ -154,6 +155,40 @@ class TestFileHandling(DirectoriesMixin, TestCase):
|
|||||||
self.assertEqual(os.path.isfile(settings.ORIGINALS_DIR + "/none/none.pdf"), False)
|
self.assertEqual(os.path.isfile(settings.ORIGINALS_DIR + "/none/none.pdf"), False)
|
||||||
self.assertEqual(os.path.isdir(settings.ORIGINALS_DIR + "/none"), False)
|
self.assertEqual(os.path.isdir(settings.ORIGINALS_DIR + "/none"), False)
|
||||||
|
|
||||||
|
@override_settings(PAPERLESS_FILENAME_FORMAT="{correspondent}/{correspondent}", TRASH_DIR=tempfile.mkdtemp())
|
||||||
|
def test_document_delete_trash(self):
|
||||||
|
document = Document()
|
||||||
|
document.mime_type = "application/pdf"
|
||||||
|
document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED
|
||||||
|
document.save()
|
||||||
|
|
||||||
|
# Ensure that filename is properly generated
|
||||||
|
document.filename = generate_filename(document)
|
||||||
|
self.assertEqual(document.filename,
|
||||||
|
"none/none.pdf")
|
||||||
|
|
||||||
|
create_source_path_directory(document.source_path)
|
||||||
|
Path(document.source_path).touch()
|
||||||
|
|
||||||
|
# Ensure file was moved to trash after delete
|
||||||
|
self.assertEqual(os.path.isfile(settings.TRASH_DIR + "/none/none.pdf"), False)
|
||||||
|
document.delete()
|
||||||
|
self.assertEqual(os.path.isfile(settings.ORIGINALS_DIR + "/none/none.pdf"), False)
|
||||||
|
self.assertEqual(os.path.isdir(settings.ORIGINALS_DIR + "/none"), False)
|
||||||
|
self.assertEqual(os.path.isfile(settings.TRASH_DIR + "/none.pdf"), True)
|
||||||
|
self.assertEqual(os.path.isfile(settings.TRASH_DIR + "/none_01.pdf"), False)
|
||||||
|
|
||||||
|
# Create an identical document and ensure it is trashed under a new name
|
||||||
|
document = Document()
|
||||||
|
document.mime_type = "application/pdf"
|
||||||
|
document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED
|
||||||
|
document.save()
|
||||||
|
document.filename = generate_filename(document)
|
||||||
|
create_source_path_directory(document.source_path)
|
||||||
|
Path(document.source_path).touch()
|
||||||
|
document.delete()
|
||||||
|
self.assertEqual(os.path.isfile(settings.TRASH_DIR + "/none_01.pdf"), True)
|
||||||
|
|
||||||
@override_settings(PAPERLESS_FILENAME_FORMAT="{correspondent}/{correspondent}")
|
@override_settings(PAPERLESS_FILENAME_FORMAT="{correspondent}/{correspondent}")
|
||||||
def test_document_delete_nofile(self):
|
def test_document_delete_nofile(self):
|
||||||
document = Document()
|
document = Document()
|
||||||
|
@ -50,6 +50,7 @@ def paths_check(app_configs, **kwargs):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
return path_check("PAPERLESS_DATA_DIR", settings.DATA_DIR) + \
|
return path_check("PAPERLESS_DATA_DIR", settings.DATA_DIR) + \
|
||||||
|
path_check("PAPERLESS_TRASH_DIR", settings.TRASH_DIR) + \
|
||||||
path_check("PAPERLESS_MEDIA_ROOT", settings.MEDIA_ROOT) + \
|
path_check("PAPERLESS_MEDIA_ROOT", settings.MEDIA_ROOT) + \
|
||||||
path_check("PAPERLESS_CONSUMPTION_DIR", settings.CONSUMPTION_DIR)
|
path_check("PAPERLESS_CONSUMPTION_DIR", settings.CONSUMPTION_DIR)
|
||||||
|
|
||||||
|
@ -57,6 +57,8 @@ THUMBNAIL_DIR = os.path.join(MEDIA_ROOT, "documents", "thumbnails")
|
|||||||
|
|
||||||
DATA_DIR = os.getenv('PAPERLESS_DATA_DIR', os.path.join(BASE_DIR, "..", "data"))
|
DATA_DIR = os.getenv('PAPERLESS_DATA_DIR', os.path.join(BASE_DIR, "..", "data"))
|
||||||
|
|
||||||
|
TRASH_DIR = os.getenv('PAPERLESS_TRASH_DIR')
|
||||||
|
|
||||||
# Lock file for synchronizing changes to the MEDIA directory across multiple
|
# Lock file for synchronizing changes to the MEDIA directory across multiple
|
||||||
# threads.
|
# threads.
|
||||||
MEDIA_LOCK = os.path.join(MEDIA_ROOT, "media.lock")
|
MEDIA_LOCK = os.path.join(MEDIA_ROOT, "media.lock")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user