Merge branch 'dev' into celery-tasks

This commit is contained in:
Jonas Winkler
2020-11-22 22:49:37 +01:00
146 changed files with 1762 additions and 1390 deletions

View File

@@ -1,126 +1,130 @@
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"paperless-ui": {
"projectType": "application",
"schematics": {},
"root": "",
"sourceRoot": "src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/paperless-ui",
"outputHashing": "none",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.app.json",
"aot": true,
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"node_modules/bootstrap/dist/css/bootstrap.min.css",
"src/styles.css"
],
"scripts": []
},
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"optimization": true,
"outputHashing": "none",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"budgets": [
{
"type": "initial",
"maximumWarning": "2mb",
"maximumError": "5mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "6kb",
"maximumError": "10kb"
}
]
}
}
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "paperless-ui:build"
},
"configurations": {
"production": {
"browserTarget": "paperless-ui:build:production"
}
}
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "paperless-ui:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "src/test.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.spec.json",
"karmaConfig": "karma.conf.js",
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"src/styles.css"
],
"scripts": []
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"tsconfig.app.json",
"tsconfig.spec.json",
"e2e/tsconfig.json"
],
"exclude": [
"**/node_modules/**"
]
}
},
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"options": {
"protractorConfig": "e2e/protractor.conf.js",
"devServerTarget": "paperless-ui:serve"
},
"configurations": {
"production": {
"devServerTarget": "paperless-ui:serve:production"
}
}
}
}
}},
"defaultProject": "paperless-ui"
}
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"paperless-ui": {
"projectType": "application",
"schematics": {
"@schematics/angular:component": {
"style": "scss"
}
},
"root": "",
"sourceRoot": "src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/paperless-ui",
"outputHashing": "none",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.app.json",
"aot": true,
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"src/styles.scss"
],
"scripts": []
},
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"optimization": true,
"outputHashing": "none",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"budgets": [
{
"type": "initial",
"maximumWarning": "2mb",
"maximumError": "5mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "6kb",
"maximumError": "10kb"
}
]
}
}
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "paperless-ui:build"
},
"configurations": {
"production": {
"browserTarget": "paperless-ui:build:production"
}
}
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "paperless-ui:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "src/test.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.spec.json",
"karmaConfig": "karma.conf.js",
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"src/styles.scss"
],
"scripts": []
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"tsconfig.app.json",
"tsconfig.spec.json",
"e2e/tsconfig.json"
],
"exclude": [
"**/node_modules/**"
]
}
},
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"options": {
"protractorConfig": "e2e/protractor.conf.js",
"devServerTarget": "paperless-ui:serve"
},
"configurations": {
"production": {
"devServerTarget": "paperless-ui:serve:production"
}
}
}
}
}
},
"defaultProject": "paperless-ui"
}

View File

@@ -7,7 +7,7 @@ import { Toast, ToastService } from './services/toast.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit, OnDestroy {

View File

@@ -42,9 +42,9 @@ import { SortableDirective } from './directives/sortable.directive';
import { CookieService } from 'ngx-cookie-service';
import { CsrfInterceptor } from './interceptors/csrf.interceptor';
import { SavedViewWidgetComponent } from './components/dashboard/widgets/saved-view-widget/saved-view-widget.component';
import { ConsumerStatusWidgetComponent } from './components/dashboard/widgets/consumer-status-widget/consumer-status-widget.component';
import { StatisticsWidgetComponent } from './components/dashboard/widgets/statistics-widget/statistics-widget.component';
import { FileUploadWidgetComponent } from './components/dashboard/widgets/file-upload-widget/file-upload-widget.component';
import { UploadFileWidgetComponent } from './components/dashboard/widgets/upload-file-widget/upload-file-widget.component';
import { WidgetFrameComponent } from './components/dashboard/widgets/widget-frame/widget-frame.component';
@NgModule({
declarations: [
@@ -79,10 +79,10 @@ import { FileUploadWidgetComponent } from './components/dashboard/widgets/file-u
DateTimeComponent,
TagsComponent,
SortableDirective,
ConsumerStatusWidgetComponent,
SavedViewWidgetComponent,
StatisticsWidgetComponent,
FileUploadWidgetComponent
UploadFileWidgetComponent,
WidgetFrameComponent
],
imports: [
BrowserModule,

View File

@@ -1,32 +1,26 @@
<nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0 shadow">
<span class="navbar-brand col-md-3 col-lg-2 mr-0 px-3" href="#">Paperless-ng</span>
<nav class="navbar navbar-dark sticky-top bg-primary flex-md-nowrap p-0 shadow">
<span class="navbar-brand col-md-3 col-lg-2 mr-0 px-3" href="#">
<img src="assets/logo-dark-notext.svg" height="18px" class="mr-2">
Paperless-ng
</span>
<button class="navbar-toggler position-absolute d-md-none collapsed" type="button" data-toggle="collapse"
data-target="#sidebarMenu" aria-controls="sidebarMenu" aria-expanded="false" aria-label="Toggle navigation">
data-target="#sidebarMenu" aria-controls="sidebarMenu" aria-expanded="false" aria-label="Toggle navigation"
(click)="isMenuCollapsed = !isMenuCollapsed">
<span class="navbar-toggler-icon"></span>
</button>
<form (ngSubmit)="search()" class="w-100">
<form (ngSubmit)="search()" class="w-100 m-1">
<input class="form-control form-control-dark" type="text" placeholder="Search" aria-label="Search"
[formControl]="searchField" [ngbTypeahead]="searchAutoComplete" (selectItem)="itemSelected($event)">
</form>
<ul class="navbar-nav px-3">
<li class="nav-item text-nowrap">
<a class="nav-link" href="accounts/logout/">
<svg class="buttonicon" fill="currentColor">
<use xlink:href="assets/bootstrap-icons.svg#door-closed"/>
</svg>
Logout
</a>
</li>
</ul>
</nav>
<div class="container-fluid">
<div class="row">
<nav id="sidebarMenu" class="col-md-3 col-lg-2 d-md-block bg-light sidebar collapse">
<nav id="sidebarMenu" class="col-md-3 col-lg-2 d-md-block bg-light sidebar collapse" [ngbCollapse]="isMenuCollapsed">
<div class="sidebar-sticky pt-3">
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link" routerLink="dashboard" routerLinkActive="active">
<a class="nav-link" routerLink="dashboard" routerLinkActive="active" (click)="closeMenu()">
<svg class="sidebaricon" fill="currentColor">
<use xlink:href="assets/bootstrap-icons.svg#house"/>
</svg>
@@ -34,7 +28,7 @@
</a>
</li>
<li class="nav-item">
<a class="nav-link" routerLink="documents" routerLinkActive="active" [routerLinkActiveOptions]="{exact: true}">
<a class="nav-link" routerLink="documents" routerLinkActive="active" [routerLinkActiveOptions]="{exact: true}" (click)="closeMenu()">
<svg class="sidebaricon" fill="currentColor">
<use xlink:href="assets/bootstrap-icons.svg#files"/>
</svg>
@@ -48,7 +42,7 @@
</h6>
<ul class="nav flex-column mb-2">
<li class="nav-item w-100" *ngFor='let config of viewConfigService.getSideBarConfigs()'>
<a class="nav-link text-truncate" routerLink="view/{{config.id}}" routerLinkActive="active">
<a class="nav-link text-truncate" routerLink="view/{{config.id}}" routerLinkActive="active" (click)="closeMenu()">
<svg class="sidebaricon" fill="currentColor">
<use xlink:href="assets/bootstrap-icons.svg#funnel"/>
</svg>
@@ -62,7 +56,7 @@
</h6>
<ul class="nav flex-column mb-2">
<li class="nav-item w-100" *ngFor='let d of openDocuments'>
<a class="nav-link text-truncate" routerLink="documents/{{d.id}}" routerLinkActive="active">
<a class="nav-link text-truncate" routerLink="documents/{{d.id}}" routerLinkActive="active" (click)="closeMenu()">
<svg class="sidebaricon" fill="currentColor">
<use xlink:href="assets/bootstrap-icons.svg#file-text"/>
</svg>
@@ -84,7 +78,7 @@
</h6>
<ul class="nav flex-column mb-2">
<li class="nav-item">
<a class="nav-link" routerLink="correspondents" routerLinkActive="active">
<a class="nav-link" routerLink="correspondents" routerLinkActive="active" (click)="closeMenu()">
<svg class="sidebaricon" fill="currentColor">
<use xlink:href="assets/bootstrap-icons.svg#person"/>
</svg>
@@ -92,7 +86,7 @@
</a>
</li>
<li class="nav-item">
<a class="nav-link" routerLink="tags" routerLinkActive="active">
<a class="nav-link" routerLink="tags" routerLinkActive="active" (click)="closeMenu()">
<svg class="sidebaricon" fill="currentColor">
<use xlink:href="assets/bootstrap-icons.svg#tags"/>
</svg>
@@ -100,7 +94,7 @@
</a>
</li>
<li class="nav-item">
<a class="nav-link" routerLink="documenttypes" routerLinkActive="active">
<a class="nav-link" routerLink="documenttypes" routerLinkActive="active" (click)="closeMenu()">
<svg class="sidebaricon" fill="currentColor">
<use xlink:href="assets/bootstrap-icons.svg#hash"/>
</svg>
@@ -108,7 +102,7 @@
</a>
</li>
<li class="nav-item">
<a class="nav-link" routerLink="logs" routerLinkActive="active">
<a class="nav-link" routerLink="logs" routerLinkActive="active" (click)="closeMenu()">
<svg class="sidebaricon" fill="currentColor">
<use xlink:href="assets/bootstrap-icons.svg#text-left"/>
</svg>
@@ -116,7 +110,7 @@
</a>
</li>
<li class="nav-item">
<a class="nav-link" routerLink="settings" routerLinkActive="active">
<a class="nav-link" routerLink="settings" routerLinkActive="active" (click)="closeMenu()">
<svg class="sidebaricon" fill="currentColor">
<use xlink:href="assets/bootstrap-icons.svg#gear"/>
</svg>
@@ -150,7 +144,15 @@
<svg class="sidebaricon" fill="currentColor">
<use xlink:href="assets/bootstrap-icons.svg#link"/>
</svg>
Github
GitHub
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="accounts/logout/">
<svg class="sidebaricon" fill="currentColor">
<use xlink:href="assets/bootstrap-icons.svg#door-open"/>
</svg>
Logout
</a>
</li>
</ul>
@@ -161,4 +163,4 @@
<router-outlet></router-outlet>
</main>
</div>
</div>
</div>

View File

@@ -1,4 +1,6 @@
@import "/src/theme";
/*
* Sidebar
*/
@@ -15,14 +17,15 @@
@media (max-width: 767.98px) {
.sidebar {
top: 5rem;
top: 3rem;
}
}
.sidebar-sticky {
position: relative;
top: 0;
height: calc(100vh - 48px);
/* height: calc(100vh - 48px); */
height: 100%;
padding-top: .5rem;
overflow-x: hidden;
overflow-y: auto; /* Scrollable contents if viewport is shorter than content. */
@@ -46,7 +49,7 @@
}
.sidebar .nav-link.active {
color: #007bff;
color: $primary;
}
.sidebar .nav-link:hover .sidebaricon,

View File

@@ -12,7 +12,7 @@ import { DocumentDetailComponent } from '../document-detail/document-detail.comp
@Component({
selector: 'app-app-frame',
templateUrl: './app-frame.component.html',
styleUrls: ['./app-frame.component.css']
styleUrls: ['./app-frame.component.scss']
})
export class AppFrameComponent implements OnInit, OnDestroy {
@@ -25,6 +25,12 @@ export class AppFrameComponent implements OnInit, OnDestroy {
) {
}
isMenuCollapsed: boolean = true
closeMenu() {
this.isMenuCollapsed = true
}
searchField = new FormControl('')
openDocuments: PaperlessDocument[] = []
@@ -61,10 +67,12 @@ export class AppFrameComponent implements OnInit, OnDestroy {
}
search() {
this.closeMenu()
this.router.navigate(['search'], {queryParams: {query: this.searchField.value}})
}
closeAll() {
this.closeMenu()
this.openDocumentsService.closeAll()
// TODO: is there a better way to do this?

View File

@@ -4,7 +4,7 @@ import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
@Component({
selector: 'app-delete-dialog',
templateUrl: './delete-dialog.component.html',
styleUrls: ['./delete-dialog.component.css']
styleUrls: ['./delete-dialog.component.scss']
})
export class DeleteDialogComponent implements OnInit {

View File

@@ -1,5 +1,5 @@
<div class="form-group form-check">
<input type="checkbox" class="form-check-input" [id]="inputId" [(ngModel)]="value" (change)="onChange(value)" (blur)="onTouched()" [disabled]="disabled">
<label class="form-check-label" [for]="inputId">{{title}}</label>
<div class="form-group custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" [id]="inputId" [(ngModel)]="value" (change)="onChange(value)" (blur)="onTouched()" [disabled]="disabled">
<label class="custom-control-label" [for]="inputId">{{title}}</label>
<small *ngIf="hint" class="form-text text-muted">{{hint}}</small>
</div>

View File

@@ -11,7 +11,7 @@ import { AbstractInputComponent } from '../abstract-input';
}],
selector: 'app-input-check',
templateUrl: './check.component.html',
styleUrls: ['./check.component.css']
styleUrls: ['./check.component.scss']
})
export class CheckComponent extends AbstractInputComponent<boolean> {

View File

@@ -11,7 +11,7 @@ import { AbstractInputComponent } from '../abstract-input';
}],
selector: 'app-input-date-time',
templateUrl: './date-time.component.html',
styleUrls: ['./date-time.component.css']
styleUrls: ['./date-time.component.scss']
})
export class DateTimeComponent implements OnInit,ControlValueAccessor {

View File

@@ -10,7 +10,7 @@ import { AbstractInputComponent } from '../abstract-input';
}],
selector: 'app-input-select',
templateUrl: './select.component.html',
styleUrls: ['./select.component.css']
styleUrls: ['./select.component.scss']
})
export class SelectComponent extends AbstractInputComponent<number> {

View File

@@ -15,7 +15,7 @@ import { TagService } from 'src/app/services/rest/tag.service';
}],
selector: 'app-input-tags',
templateUrl: './tags.component.html',
styleUrls: ['./tags.component.css']
styleUrls: ['./tags.component.scss']
})
export class TagsComponent implements OnInit, ControlValueAccessor {

View File

@@ -11,7 +11,7 @@ import { AbstractInputComponent } from '../abstract-input';
}],
selector: 'app-input-text',
templateUrl: './text.component.html',
styleUrls: ['./text.component.css']
styleUrls: ['./text.component.scss']
})
export class TextComponent extends AbstractInputComponent<string> {

View File

@@ -1,6 +1,7 @@
<div class="row pt-3 pb-1 mb-3 border-bottom align-items-center" >
<div class="col text-truncate">
<h1 class="h2 text-truncate" style="line-height: 1.4">{{title}}</h1>
<div class="col-md text-truncate">
<p class="h2 text-truncate" style="line-height: 1.4">{{title}}</p>
<p *ngIf="subTitle" class="h5 text-truncate" style="line-height: 1.4">{{subTitle}}</p>
</div>
<div class="btn-toolbar col-auto">
<ng-content></ng-content>

View File

@@ -3,7 +3,7 @@ import { Component, Input, OnInit } from '@angular/core';
@Component({
selector: 'app-page-header',
templateUrl: './page-header.component.html',
styleUrls: ['./page-header.component.css']
styleUrls: ['./page-header.component.scss']
})
export class PageHeaderComponent implements OnInit {
@@ -12,6 +12,9 @@ export class PageHeaderComponent implements OnInit {
@Input()
title: string = ""
@Input()
subTitle: string = ""
ngOnInit(): void {
}

View File

@@ -4,7 +4,7 @@ import { TAG_COLOURS, PaperlessTag } from 'src/app/data/paperless-tag';
@Component({
selector: 'app-tag',
templateUrl: './tag.component.html',
styleUrls: ['./tag.component.css']
styleUrls: ['./tag.component.scss']
})
export class TagComponent implements OnInit {

View File

@@ -5,7 +5,7 @@ import { Toast, ToastService } from 'src/app/services/toast.service';
@Component({
selector: 'app-toasts',
templateUrl: './toasts.component.html',
styleUrls: ['./toasts.component.css']
styleUrls: ['./toasts.component.scss']
})
export class ToastsComponent implements OnInit, OnDestroy {

View File

@@ -1,16 +1,27 @@
<app-page-header title="Dashboard">
<app-page-header title="Dashboard" subTitle="Welcome to paperless-ng!">
<img src="assets/logo.svg" height="80" class="m-2 d-none d-md-block">
</app-page-header>
<p>Welcome to paperless-ng!</p>
<div class='row'>
<div class="col-lg">
<app-saved-view-widget [viewConfig]="conf" *ngFor="let conf of savedViewConfigService.getDashboardConfigs()"></app-saved-view-widget>
<app-widget-frame title="Saved views" *ngIf="savedViews.length == 0">
<p class="card-text">This space is reserved to display your saved views. Go to your documents and save a view
to have it displayed
here!</p>
</app-widget-frame>
<ng-container *ngFor="let v of savedViews">
<app-saved-view-widget [savedView]="v"></app-saved-view-widget>
</ng-container>
</div>
<div class="col-lg">
<app-statistics-widget></app-statistics-widget>
<app-file-upload-widget></app-file-upload-widget>
<app-upload-file-widget></app-upload-file-widget>
<app-consumer-status-widget></app-consumer-status-widget>
</div>
</div>

View File

@@ -1,22 +1,22 @@
import { HttpClient } from '@angular/common/http';
import { Component, OnInit } from '@angular/core';
import { FileSystemFileEntry, NgxFileDropEntry } from 'ngx-file-drop';
import { Observable } from 'rxjs';
import { DocumentService } from 'src/app/services/rest/document.service';
import { SavedViewConfigService } from 'src/app/services/saved-view-config.service';
import { ToastService } from 'src/app/services/toast.service';
import { environment } from 'src/environments/environment';
@Component({
selector: 'app-dashboard',
templateUrl: './dashboard.component.html',
styleUrls: ['./dashboard.component.css']
styleUrls: ['./dashboard.component.scss']
})
export class DashboardComponent implements OnInit {
constructor(public savedViewConfigService: SavedViewConfigService) { }
constructor(
public savedViewConfigService: SavedViewConfigService) { }
savedViews = []
ngOnInit(): void {
this.savedViews = this.savedViewConfigService.getDashboardConfigs()
}
}

View File

@@ -1,16 +1,18 @@
<h4>{{viewConfig.title}}</h4>
<app-widget-frame [title]="savedView.title">
<table class="table table-sm table-hover table-borderless">
<thead>
<tr>
<th>Date created</th>
<th scope="col">Document</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let doc of documents" routerLink="/documents/{{doc.id}}">
<td>{{doc.created | date}}</td>
<td>{{doc.title}}<app-tag [tag]="t" *ngFor="let t of doc.tags" class="ml-1"></app-tag>
</tr>
</tbody>
</table>
<table class="table table-sm table-hover table-borderless">
<thead>
<tr>
<th>Created</th>
<th scope="col">Title</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let doc of documents" routerLink="/documents/{{doc.id}}">
<td>{{doc.created | date}}</td>
<td>{{doc.title}}<app-tag [tag]="t" *ngFor="let t of doc.tags" class="ml-1"></app-tag>
</tr>
</tbody>
</table>
</app-widget-frame>

View File

@@ -8,16 +8,16 @@ import { DocumentService } from 'src/app/services/rest/document.service';
@Component({
selector: 'app-saved-view-widget',
templateUrl: './saved-view-widget.component.html',
styleUrls: ['./saved-view-widget.component.css']
styleUrls: ['./saved-view-widget.component.scss']
})
export class SavedViewWidgetComponent implements OnInit, OnDestroy {
export class SavedViewWidgetComponent implements OnInit {
constructor(private documentService: DocumentService, private consumerStatusService: ConsumerStatusService) { }
@Input()
viewConfig: SavedViewConfig
savedView: SavedViewConfig
documents: PaperlessDocument[]
documents: PaperlessDocument[] = []
subscription: Subscription
@@ -33,7 +33,7 @@ export class SavedViewWidgetComponent implements OnInit, OnDestroy {
}
reload() {
this.documentService.list(1,10,this.viewConfig.sortField,this.viewConfig.sortDirection,this.viewConfig.filterRules).subscribe(result => {
this.documentService.list(1,10,this.savedView.sortField,this.savedView.sortDirection,this.savedView.filterRules).subscribe(result => {
this.documents = result.results
})
}

View File

@@ -1,3 +1,4 @@
<h4>Statistics</h4>
<p>Documents in inbox: {{statistics.documents_inbox}}</p>
<p>Total documents: {{statistics.documents_total}}</p>
<app-widget-frame title="Statistics">
<p class="card-text">Documents in inbox: {{statistics.documents_inbox}}</p>
<p class="card-text">Total documents: {{statistics.documents_total}}</p>
</app-widget-frame>

View File

@@ -8,10 +8,11 @@ export interface Statistics {
documents_inbox?: number
}
@Component({
selector: 'app-statistics-widget',
templateUrl: './statistics-widget.component.html',
styleUrls: ['./statistics-widget.component.css']
styleUrls: ['./statistics-widget.component.scss']
})
export class StatisticsWidgetComponent implements OnInit {
@@ -19,14 +20,14 @@ export class StatisticsWidgetComponent implements OnInit {
statistics: Statistics = {}
getStatistics(): Observable<Statistics> {
return this.http.get(`${environment.apiBaseUrl}statistics/`)
}
ngOnInit(): void {
this.getStatistics().subscribe(statistics => {
this.statistics = statistics
})
}
getStatistics(): Observable<Statistics> {
return this.http.get(`${environment.apiBaseUrl}statistics/`)
}
}

View File

@@ -0,0 +1,15 @@
<app-widget-frame title="Upload new documents">
<form>
<ngx-file-drop
dropZoneLabel="Drop documents here or" (onFileDrop)="dropped($event)"
(onFileOver)="fileOver($event)" (onFileLeave)="fileLeave($event)"
dropZoneClassName="bg-light card"
multiple="true"
contentClassName="justify-content-center d-flex align-items-center p-5"
[showBrowseBtn]=true
browseBtnClassName="btn btn-sm btn-outline-primary ml-2">
</ngx-file-drop>
</form>
</app-widget-frame>

View File

@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { UploadFileWidgetComponent } from './upload-file-widget.component';
describe('UploadFileWidgetComponent', () => {
let component: UploadFileWidgetComponent;
let fixture: ComponentFixture<UploadFileWidgetComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ UploadFileWidgetComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(UploadFileWidgetComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,44 @@
import { Component, OnInit } from '@angular/core';
import { FileSystemFileEntry, NgxFileDropEntry } from 'ngx-file-drop';
import { DocumentService } from 'src/app/services/rest/document.service';
import { Toast, ToastService } from 'src/app/services/toast.service';
@Component({
selector: 'app-upload-file-widget',
templateUrl: './upload-file-widget.component.html',
styleUrls: ['./upload-file-widget.component.scss']
})
export class UploadFileWidgetComponent implements OnInit {
constructor(private documentService: DocumentService, private toastService: ToastService) { }
ngOnInit(): void {
}
public fileOver(event){
console.log(event);
}
public fileLeave(event){
console.log(event);
}
public dropped(files: NgxFileDropEntry[]) {
for (const droppedFile of files) {
if (droppedFile.fileEntry.isFile) {
const fileEntry = droppedFile.fileEntry as FileSystemFileEntry;
console.log(fileEntry)
fileEntry.file((file: File) => {
console.log(file)
const formData = new FormData()
formData.append('document', file, file.name)
this.documentService.uploadDocument(formData).subscribe(result => {
this.toastService.showToast(Toast.make("Information", "The document has been uploaded and will be processed by the consumer shortly."))
}, error => {
this.toastService.showToast(Toast.makeError("An error has occured while uploading the document. Sorry!"))
})
});
}
}
}
}

View File

@@ -0,0 +1,8 @@
<div class="card mb-3 shadow">
<div class="card-header">
<h5 class="card-title mb-0">{{title}}</h5>
</div>
<div class="card-body text-dark">
<ng-content></ng-content>
</div>
</div>

View File

@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { WidgetFrameComponent } from './widget-frame.component';
describe('WidgetFrameComponent', () => {
let component: WidgetFrameComponent;
let fixture: ComponentFixture<WidgetFrameComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ WidgetFrameComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(WidgetFrameComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,18 @@
import { Component, Input, OnInit } from '@angular/core';
@Component({
selector: 'app-widget-frame',
templateUrl: './widget-frame.component.html',
styleUrls: ['./widget-frame.component.scss']
})
export class WidgetFrameComponent implements OnInit {
constructor() { }
@Input()
title: string
ngOnInit(): void {
}
}

View File

@@ -3,19 +3,19 @@
<svg class="buttonicon" fill="currentColor">
<use xlink:href="assets/bootstrap-icons.svg#trash" />
</svg>
<span class="d-none d-lg-inline">Delete</span>
<span class="d-none d-lg-inline"> Delete</span>
</button>
<a [href]="downloadUrl" class="btn btn-sm btn-outline-secondary mr-2">
<a [href]="downloadUrl" class="btn btn-sm btn-outline-primary mr-2">
<svg class="buttonicon" fill="currentColor">
<use xlink:href="assets/bootstrap-icons.svg#download" />
</svg>
<span class="d-none d-lg-inline">Download</span>
<span class="d-none d-lg-inline"> Download</span>
</a>
<button type="button" class="btn btn-sm btn-outline-secondary" (click)="close()">
<button type="button" class="btn btn-sm btn-outline-primary" (click)="close()">
<svg class="buttonicon" fill="currentColor">
<use xlink:href="assets/bootstrap-icons.svg#x" />
</svg>
<span class="d-none d-lg-inline">Close</span>
<span class="d-none d-lg-inline"> Close</span>
</button>
</app-page-header>
@@ -23,17 +23,17 @@
<div class="row">
<div class="col-xl">
<form [formGroup]='documentForm' (ngSubmit)="save()">
<app-input-text title="Title" formControlName="title"></app-input-text>
<div class="form-group">
<label for="archive_serial_number">Archive Serial Number</label>
<input type="number" class="form-control" id="archive_serial_number"
formControlName='archive_serial_number'>
</div>
<app-input-date-time title="Date created" titleTime="Time created" formControlName="created"></app-input-date-time>
<div class="form-group">
<label for="content">Content</label>
<textarea class="form-control" id="content" rows="5" formControlName='content'></textarea>
@@ -58,4 +58,4 @@
</object>
</div>
</div>
</div>

View File

@@ -21,7 +21,7 @@ import { TagEditDialogComponent } from '../manage/tag-list/tag-edit-dialog/tag-e
@Component({
selector: 'app-document-detail',
templateUrl: './document-detail.component.html',
styleUrls: ['./document-detail.component.css']
styleUrls: ['./document-detail.component.scss']
})
export class DocumentDetailComponent implements OnInit {

View File

@@ -1,7 +1,7 @@
<div class="card mb-3 bg-light">
<div class="card mb-3 bg-light shadow-sm">
<div class="row no-gutters">
<div class="col-md-2 d-none d-lg-block">
<img [src]="getThumbUrl()" class="card-img doc-img">
<img [src]="getThumbUrl()" class="card-img doc-img border-right">
</div>
<div class="col">
<div class="card-body">

View File

@@ -6,7 +6,7 @@ import { DocumentService } from 'src/app/services/rest/document.service';
@Component({
selector: 'app-document-card-large',
templateUrl: './document-card-large.component.html',
styleUrls: ['./document-card-large.component.css']
styleUrls: ['./document-card-large.component.scss']
})
export class DocumentCardLargeComponent implements OnInit {

View File

@@ -1,5 +0,0 @@
.doc-img {
object-fit: cover;
object-position: top;
}

View File

@@ -1,11 +1,20 @@
<div class="col-auto mb-3">
<div class="card h-100 bg-light" style="width: 14rem">
<div style="height: 10rem; overflow: hidden;">
<img [src]="getThumbUrl()" class="card-img doc-img"/>
<div class="col p-2 h-100" style="width: 16rem;">
<div class="card h-100 shadow-sm">
<div class=" border-bottom doc-img pr-1" [ngStyle]="{'background-image': 'url(' + getThumbUrl() + ')'}">
<div class="row" *ngFor="let t of document.tags">
<app-tag [tag]="t" class="col text-right"></app-tag>
</div>
</div>
<div class="card-body">
<p class="card-title">{{document.correspondent ? document.correspondent.name + ': ' : ''}}{{document.title}} <app-tag [tag]="t" *ngFor="let t of document.tags" class="ml-1"></app-tag></p>
<div class="d-flex justify-content-between align-items-center">
<div class="card-body p-2">
<p class="card-text">
<span class="font-weight-bold">{{document.correspondent? document.correspondent.name + ': ' : ''}}</span> {{document.title}}
</p>
</div>
<div class="card-footer">
<div class="d-flex justify-content-between align-items-center ml-n2">
<div class="btn-group">
<a routerLink="/documents/{{document.id}}" class="btn btn-sm btn-outline-secondary">
<svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-pencil" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
@@ -21,6 +30,7 @@
</div>
<small class="text-muted">{{document.created | date}}</small>
</div>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,5 @@
.doc-img {
background-size: cover;
background-position: top;
height: 200px;
}

View File

@@ -5,7 +5,7 @@ import { DocumentService } from 'src/app/services/rest/document.service';
@Component({
selector: 'app-document-card-small',
templateUrl: './document-card-small.component.html',
styleUrls: ['./document-card-small.component.css']
styleUrls: ['./document-card-small.component.scss']
})
export class DocumentCardSmallComponent implements OnInit {

View File

@@ -1,51 +1,51 @@
<app-page-header [title]="getTitle()">
<div class="btn-group btn-group-toggle mr-2" ngbRadioGroup [(ngModel)]="displayMode"
<div class="btn-group btn-group-toggle" ngbRadioGroup [(ngModel)]="displayMode"
(ngModelChange)="saveDisplayMode()">
<label ngbButtonLabel class="btn-outline-secondary btn-sm">
<label ngbButtonLabel class="btn-outline-primary btn-sm">
<input ngbButton type="radio" class="btn btn-sm" value="details">
<svg class="toolbaricon" fill="currentColor">
<use xlink:href="assets/bootstrap-icons.svg#list-ul" />
</svg>
</label>
<label ngbButtonLabel class="btn-outline-secondary btn-sm">
<label ngbButtonLabel class="btn-outline-primary btn-sm">
<input ngbButton type="radio" class="btn btn-sm" value="smallCards">
<svg class="toolbaricon" fill="currentColor">
<use xlink:href="assets/bootstrap-icons.svg#grid" />
</svg>
</label>
<label ngbButtonLabel class="btn-outline-secondary btn-sm">
<label ngbButtonLabel class="btn-outline-primary btn-sm">
<input ngbButton type="radio" class="btn btn-sm" value="largeCards">
<svg class="toolbaricon" fill="currentColor">
<use xlink:href="assets/bootstrap-icons.svg#hdd-stack" />
</svg>
</label>
</div>
<div class="btn-group btn-group-toggle mr-2" ngbRadioGroup [(ngModel)]="docs.sortDirection"
<div class="btn-group btn-group-toggle ml-2" ngbRadioGroup [(ngModel)]="docs.sortDirection"
*ngIf="!docs.viewId">
<div ngbDropdown class="btn-group">
<button class="btn btn-outline-secondary btn-sm" id="dropdownBasic1" ngbDropdownToggle>Sort by</button>
<button class="btn btn-outline-primary btn-sm" id="dropdownBasic1" ngbDropdownToggle>Sort by</button>
<div ngbDropdownMenu aria-labelledby="dropdownBasic1">
<button *ngFor="let f of getSortFields()" ngbDropdownItem (click)="setSort(f.field)"
[class.active]="docs.sortField == f.field">{{f.name}}</button>
</div>
</div>
<label ngbButtonLabel class="btn-outline-secondary btn-sm">
<label ngbButtonLabel class="btn-outline-primary btn-sm">
<input ngbButton type="radio" class="btn btn-sm" value="asc">
<svg class="toolbaricon" fill="currentColor">
<use xlink:href="assets/bootstrap-icons.svg#sort-alpha-down" />
</svg>
</label>
<label ngbButtonLabel class="btn-outline-secondary btn-sm">
<label ngbButtonLabel class="btn-outline-primary btn-sm">
<input ngbButton type="radio" class="btn btn-sm" value="des">
<svg class="toolbaricon" fill="currentColor">
<use xlink:href="assets/bootstrap-icons.svg#sort-alpha-up-alt" />
</svg>
</label>
</div>
<div class="btn-group" *ngIf="!docs.viewId">
<div class="btn-group ml-2" *ngIf="!docs.viewId">
<button type="button" class="btn btn-sm btn-outline-secondary" (click)="showFilter=!showFilter">
<button type="button" class="btn btn-sm btn-outline-primary" (click)="showFilter=!showFilter">
<svg class="toolbaricon" fill="currentColor">
<use xlink:href="assets/bootstrap-icons.svg#funnel" />
</svg>
@@ -53,7 +53,7 @@
</button>
<div class="btn-group" ngbDropdown role="group">
<button class="btn btn-sm btn-outline-secondary dropdown-toggle-split" ngbDropdownToggle></button>
<button class="btn btn-sm btn-outline-primary dropdown-toggle-split" ngbDropdownToggle></button>
<div class="dropdown-menu" ngbDropdownMenu>
<button ngbDropdownItem *ngFor="let config of savedViewConfigService.getConfigs()" (click)="loadViewConfig(config)">{{config.title}}</button>
<div class="dropdown-divider" *ngIf="savedViewConfigService.getConfigs().length > 0"></div>
@@ -71,38 +71,40 @@
</div>
</div>
<ngb-pagination [pageSize]="docs.currentPageSize" [collectionSize]="docs.collectionSize" [(page)]="docs.currentPage" [maxSize]="5"
[rotate]="true" [boundaryLinks]="true" (pageChange)="reload()" aria-label="Default pagination"></ngb-pagination>
<div class="row m-0 justify-content-end">
<ngb-pagination [pageSize]="docs.currentPageSize" [collectionSize]="docs.collectionSize" [(page)]="docs.currentPage" [maxSize]="5"
[rotate]="true" (pageChange)="reload()" aria-label="Default pagination"></ngb-pagination>
</div>
<div *ngIf="displayMode == 'largeCards'">
<app-document-card-large *ngFor="let d of docs.documents" [document]="d" [details]="d.content">
</app-document-card-large>
</div>
<table class="table table-hover table-sm" *ngIf="displayMode == 'details'">
<table class="table table-hover table-sm border shadow" *ngIf="displayMode == 'details'">
<thead>
<th>ASN</th>
<th>Correspondent</th>
<th class="d-none d-lg-table-cell">ASN</th>
<th class="d-none d-md-table-cell">Correspondent</th>
<th>Title</th>
<th>Document type</th>
<th class="d-none d-xl-table-cell">Document type</th>
<th>Created</th>
<th>Added</th>
<th class="d-none d-xl-table-cell">Added</th>
</thead>
<tbody>
<tr *ngFor="let d of docs.documents" routerLink="/documents/{{d.id}}">
<td>{{d.archive_serial_number}}</td>
<td>{{d.correspondent ? d.correspondent.name : ''}}</td>
<td>{{d.title}}<app-tag [tag]="t" *ngFor="let t of d.tags" class="ml-1"></app-tag>
</td>
<td>{{d.document_type ? d.document_type.name : ''}}</td>
<td class="d-none d-lg-table-cell">{{d.archive_serial_number}}</td>
<td class="d-none d-md-table-cell">{{d.correspondent ? d.correspondent.name : ''}}</td>
<td>{{d.title}}<app-tag [tag]="t" *ngFor="let t of d.tags" class="ml-1"></app-tag></td>
<td class="d-none d-xl-table-cell">{{d.document_type ? d.document_type.name : ''}}</td>
<td>{{d.created | date}}</td>
<td>{{d.added | date}}</td>
<td class="d-none d-xl-table-cell">{{d.added | date}}</td>
</tr>
</tbody>
</table>
<div class="row justify-content-left" *ngIf="displayMode == 'smallCards'">
<app-document-card-small [document]="d" *ngFor="let d of docs.documents"></app-document-card-small>
<div class=" m-n2 row" *ngIf="displayMode == 'smallCards'">
<app-document-card-small [document]="d" *ngFor="let d of docs.documents"></app-document-card-small>
</div>
<p *ngIf="docs.documents.length == 0" class="mx-auto">No results</p>

View File

@@ -11,7 +11,7 @@ import { SaveViewConfigDialogComponent } from './save-view-config-dialog/save-vi
@Component({
selector: 'app-document-list',
templateUrl: './document-list.component.html',
styleUrls: ['./document-list.component.css']
styleUrls: ['./document-list.component.scss']
})
export class DocumentListComponent implements OnInit {

View File

@@ -5,7 +5,7 @@ import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
@Component({
selector: 'app-save-view-config-dialog',
templateUrl: './save-view-config-dialog.component.html',
styleUrls: ['./save-view-config-dialog.component.css']
styleUrls: ['./save-view-config-dialog.component.scss']
})
export class SaveViewConfigDialogComponent implements OnInit {

View File

@@ -12,7 +12,7 @@ import { TagService } from 'src/app/services/rest/tag.service';
@Component({
selector: 'app-filter-editor',
templateUrl: './filter-editor.component.html',
styleUrls: ['./filter-editor.component.css']
styleUrls: ['./filter-editor.component.scss']
})
export class FilterEditorComponent implements OnInit {

View File

@@ -9,7 +9,7 @@ import { ToastService } from 'src/app/services/toast.service';
@Component({
selector: 'app-correspondent-edit-dialog',
templateUrl: './correspondent-edit-dialog.component.html',
styleUrls: ['./correspondent-edit-dialog.component.css']
styleUrls: ['./correspondent-edit-dialog.component.scss']
})
export class CorrespondentEditDialogComponent extends EditDialogComponent<PaperlessCorrespondent> {

View File

@@ -1,12 +1,14 @@
<app-page-header title="Correspondents">
<button type="button" class="btn btn-sm btn-outline-secondary" (click)="openCreateDialog()">
<button type="button" class="btn btn-sm btn-outline-primary" (click)="openCreateDialog()">
Create
</button>
</app-page-header>
<ngb-pagination [pageSize]="25" [collectionSize]="collectionSize" [(page)]="page" (pageChange)="reloadData()" aria-label="Default pagination"></ngb-pagination>
<div class="row m-0 justify-content-end">
<ngb-pagination [pageSize]="25" [collectionSize]="collectionSize" [(page)]="page" (pageChange)="reloadData()" aria-label="Default pagination"></ngb-pagination>
</div>
<table class="table table-striped">
<table class="table table-striped border shadow">
<thead>
<tr>
<th scope="col" sortable="name" (sort)="onSort($event)">Name</th>

View File

@@ -8,7 +8,7 @@ import { CorrespondentEditDialogComponent } from './correspondent-edit-dialog/co
@Component({
selector: 'app-correspondent-list',
templateUrl: './correspondent-list.component.html',
styleUrls: ['./correspondent-list.component.css']
styleUrls: ['./correspondent-list.component.scss']
})
export class CorrespondentListComponent extends GenericListComponent<PaperlessCorrespondent> {

View File

@@ -9,7 +9,7 @@ import { ToastService } from 'src/app/services/toast.service';
@Component({
selector: 'app-document-type-edit-dialog',
templateUrl: './document-type-edit-dialog.component.html',
styleUrls: ['./document-type-edit-dialog.component.css']
styleUrls: ['./document-type-edit-dialog.component.scss']
})
export class DocumentTypeEditDialogComponent extends EditDialogComponent<PaperlessDocumentType> {

View File

@@ -1,13 +1,15 @@
<app-page-header title="Document types">
<button type="button" class="btn btn-sm btn-outline-secondary" (click)="openCreateDialog()">
<button type="button" class="btn btn-sm btn-outline-primary" (click)="openCreateDialog()">
Create
</button>
</app-page-header>
<ngb-pagination [pageSize]="25" [collectionSize]="collectionSize" [(page)]="page" (pageChange)="reloadData()"
<div class="row m-0 justify-content-end">
<ngb-pagination [pageSize]="25" [collectionSize]="collectionSize" [(page)]="page" (pageChange)="reloadData()"
aria-label="Default pagination"></ngb-pagination>
</div>
<table class="table table-striped">
<table class="table table-striped border shadow">
<thead>
<tr>
<th scope="col" sortable="name" (sort)="onSort($event)">Name</th>

View File

@@ -8,7 +8,7 @@ import { DocumentTypeEditDialogComponent } from './document-type-edit-dialog/doc
@Component({
selector: 'app-document-type-list',
templateUrl: './document-type-list.component.html',
styleUrls: ['./document-type-list.component.css']
styleUrls: ['./document-type-list.component.scss']
})
export class DocumentTypeListComponent extends GenericListComponent<PaperlessDocumentType> {

View File

@@ -1,7 +1,7 @@
<app-page-header title="Logs">
<div ngbDropdown class="btn-group">
<button class="btn btn-outline-secondary btn-sm" id="dropdownBasic1" ngbDropdownToggle>
<button class="btn btn-outline-primary btn-sm" id="dropdownBasic1" ngbDropdownToggle>
<svg class="toolbaricon" fill="currentColor">
<use xlink:href="assets/bootstrap-icons.svg#funnel" />
</svg>

View File

@@ -6,7 +6,7 @@ import { LogService } from 'src/app/services/rest/log.service';
@Component({
selector: 'app-logs',
templateUrl: './logs.component.html',
styleUrls: ['./logs.component.css']
styleUrls: ['./logs.component.scss']
})
export class LogsComponent implements OnInit {

View File

@@ -57,7 +57,7 @@
</li>
</ul>
<div [ngbNavOutlet]="nav" class="border-left border-right border-bottom p-3 mb-3"></div>
<div [ngbNavOutlet]="nav" class="border-left border-right border-bottom p-3 mb-3 shadow"></div>
<button type="submit" class="btn btn-primary">Save</button>
</form>

View File

@@ -8,7 +8,7 @@ import { SavedViewConfigService } from 'src/app/services/saved-view-config.servi
@Component({
selector: 'app-settings',
templateUrl: './settings.component.html',
styleUrls: ['./settings.component.css']
styleUrls: ['./settings.component.scss']
})
export class SettingsComponent implements OnInit {

View File

@@ -9,7 +9,7 @@ import { ToastService } from 'src/app/services/toast.service';
@Component({
selector: 'app-tag-edit-dialog',
templateUrl: './tag-edit-dialog.component.html',
styleUrls: ['./tag-edit-dialog.component.css']
styleUrls: ['./tag-edit-dialog.component.scss']
})
export class TagEditDialogComponent extends EditDialogComponent<PaperlessTag> {

View File

@@ -1,34 +1,37 @@
<app-page-header title="Tags">
<button type="button" class="btn btn-sm btn-outline-secondary" (click)="openCreateDialog()">
<button type="button" class="btn btn-sm btn-outline-primary" (click)="openCreateDialog()">
Create
</button>
</app-page-header>
<ngb-pagination [pageSize]="25" [collectionSize]="collectionSize" [(page)]="page" (pageChange)="reloadData()" aria-label="Default pagination"></ngb-pagination>
<table class="table table-striped">
<thead>
<tr>
<th scope="col" sortable="name" (sort)="onSort($event)">Name</th>
<th scope="col">Colour</th>
<th scope="col" sortable="matching_algorithm" (sort)="onSort($event)">Matching</th>
<th scope="col" sortable="document_count" (sort)="onSort($event)">Document count</th>
<th scope="col">Actions</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let tag of data">
<td scope="row">{{ tag.name }}</td>
<td scope="row"><span class="badge" [style.color]="getColor(tag.colour).textColor" [style.background-color]="getColor(tag.colour).value">{{ getColor(tag.colour).name }}</span></td>
<td scope="row">{{ getMatching(tag) }}</td>
<td scope="row">{{ tag.document_count }}</td>
<td scope="row">
<div class="btn-group">
<button class="btn btn-sm btn-outline-secondary" (click)="openEditDialog(tag)">Edit</button>
<button class="btn btn-sm btn-outline-danger" (click)="openDeleteDialog(tag)">Delete</button>
</div>
</td>
</tr>
</tbody>
</table>
<div class="row m-0 justify-content-end">
<ngb-pagination [pageSize]="25" [collectionSize]="collectionSize" [(page)]="page" (pageChange)="reloadData()"
aria-label="Default pagination"></ngb-pagination>
</div>
<table class="table table-striped border shadow">
<thead>
<tr>
<th scope="col" sortable="name" (sort)="onSort($event)">Name</th>
<th scope="col">Colour</th>
<th scope="col" sortable="matching_algorithm" (sort)="onSort($event)">Matching</th>
<th scope="col" sortable="document_count" (sort)="onSort($event)">Document count</th>
<th scope="col">Actions</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let tag of data">
<td scope="row">{{ tag.name }}</td>
<td scope="row"><span class="badge" [style.color]="getColor(tag.colour).textColor"
[style.background-color]="getColor(tag.colour).value">{{ getColor(tag.colour).name }}</span></td>
<td scope="row">{{ getMatching(tag) }}</td>
<td scope="row">{{ tag.document_count }}</td>
<td scope="row">
<div class="btn-group">
<button class="btn btn-sm btn-outline-secondary" (click)="openEditDialog(tag)">Edit</button>
<button class="btn btn-sm btn-outline-danger" (click)="openDeleteDialog(tag)">Delete</button>
</div>
</td>
</tr>
</tbody>
</table>

View File

@@ -9,7 +9,7 @@ import { TagEditDialogComponent } from './tag-edit-dialog/tag-edit-dialog.compon
@Component({
selector: 'app-tag-list',
templateUrl: './tag-list.component.html',
styleUrls: ['./tag-list.component.css']
styleUrls: ['./tag-list.component.scss']
})
export class TagListComponent extends GenericListComponent<PaperlessTag> {

View File

@@ -3,7 +3,7 @@ import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-not-found',
templateUrl: './not-found.component.html',
styleUrls: ['./not-found.component.css']
styleUrls: ['./not-found.component.scss']
})
export class NotFoundComponent implements OnInit {

View File

@@ -4,7 +4,7 @@ import { SearchHitHighlight } from 'src/app/data/search-result';
@Component({
selector: 'app-result-hightlight',
templateUrl: './result-hightlight.component.html',
styleUrls: ['./result-hightlight.component.css']
styleUrls: ['./result-hightlight.component.scss']
})
export class ResultHightlightComponent implements OnInit {

View File

@@ -6,7 +6,7 @@ import { SearchService } from 'src/app/services/rest/search.service';
@Component({
selector: 'app-search',
templateUrl: './search.component.html',
styleUrls: ['./search.component.css']
styleUrls: ['./search.component.scss']
})
export class SearchComponent implements OnInit {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 948 B

After

Width:  |  Height:  |  Size: 108 KiB

View File

@@ -2,9 +2,9 @@
<html lang="en">
<head>
<meta charset="utf-8">
<title>PaperlessUi</title>
<title>Paperless-ng</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>

View File

@@ -1,3 +1,7 @@
@import "theme";
@import "node_modules/bootstrap/scss/bootstrap";
.toolbaricon {
width: 1.2em;
@@ -25,12 +29,15 @@ body {
border-color: rgba(255, 255, 255, .1);
}
.form-control-dark::placeholder {
color: #fff;
}
.form-control-dark:focus {
border-color: transparent;
box-shadow: 0 0 0 3px rgba(255, 255, 255, .25);
}
.asc {
background-color: #f8f9fa!important;
}

6
src-ui/src/theme.scss Normal file
View File

@@ -0,0 +1,6 @@
$paperless-green: #17541f;
$primary: #17541f;
$theme-colors: (
"primary": $primary
);