Merge branch 'dev' into celery-tasks

This commit is contained in:
Jonas Winkler
2020-11-19 22:10:57 +01:00
145 changed files with 5228 additions and 11538 deletions

View File

@@ -39,6 +39,8 @@ import { InfiniteScrollModule } from 'ngx-infinite-scroll';
import { DateTimeComponent } from './components/common/input/date-time/date-time.component';
import { TagsComponent } from './components/common/input/tags/tags.component';
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';
@@ -93,7 +95,12 @@ import { FileUploadWidgetComponent } from './components/dashboard/widgets/file-u
InfiniteScrollModule
],
providers: [
DatePipe
DatePipe,
CookieService, {
provide: HTTP_INTERCEPTORS,
useClass: CsrfInterceptor,
multi: true
}
],
bootstrap: [AppComponent]
})

View File

@@ -1,5 +1,5 @@
<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</span>
<span class="navbar-brand col-md-3 col-lg-2 mr-0 px-3" href="#">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">
<span class="navbar-toggler-icon"></span>
@@ -69,6 +69,14 @@
{{d.title}}
</a>
</li>
<li class="nav-item w-100" *ngIf="openDocuments.length > 1">
<a class="nav-link text-truncate" [routerLink]="" (click)="closeAll()">
<svg class="sidebaricon" fill="currentColor">
<use xlink:href="assets/bootstrap-icons.svg#x"/>
</svg>
Close all
</a>
</li>
</ul>
<h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted">
@@ -124,6 +132,28 @@
</a>
</li>
</ul>
<h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted">
<span>Misc</span>
</h6>
<ul class="nav flex-column mb-2">
<li class="nav-item">
<a class="nav-link" href="https://paperless-ng.readthedocs.io/en/latest/">
<svg class="sidebaricon" fill="currentColor">
<use xlink:href="assets/bootstrap-icons.svg#question-circle"/>
</svg>
Documentation
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="https://github.com/jonaswinkler/paperless-ng">
<svg class="sidebaricon" fill="currentColor">
<use xlink:href="assets/bootstrap-icons.svg#link"/>
</svg>
Github
</a>
</li>
</ul>
</div>
</nav>

View File

@@ -1,12 +1,13 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { FormControl } from '@angular/forms';
import { Router } from '@angular/router';
import { ActivatedRoute, Router } from '@angular/router';
import { from, Observable, Subscription } from 'rxjs';
import { debounceTime, distinctUntilChanged, map, switchMap } from 'rxjs/operators';
import { PaperlessDocument } from 'src/app/data/paperless-document';
import { OpenDocumentsService } from 'src/app/services/open-documents.service';
import { SearchService } from 'src/app/services/rest/search.service';
import { SavedViewConfigService } from 'src/app/services/saved-view-config.service';
import { DocumentDetailComponent } from '../document-detail/document-detail.component';
@Component({
selector: 'app-app-frame',
@@ -17,6 +18,7 @@ export class AppFrameComponent implements OnInit, OnDestroy {
constructor (
public router: Router,
private activatedRoute: ActivatedRoute,
private openDocumentsService: OpenDocumentsService,
private searchService: SearchService,
public viewConfigService: SavedViewConfigService
@@ -62,6 +64,19 @@ export class AppFrameComponent implements OnInit, OnDestroy {
this.router.navigate(['search'], {queryParams: {query: this.searchField.value}})
}
closeAll() {
this.openDocumentsService.closeAll()
// TODO: is there a better way to do this?
let route = this.activatedRoute
while (route.firstChild) {
route = route.firstChild
}
if (route.component == DocumentDetailComponent) {
this.router.navigate([""])
}
}
ngOnInit() {
this.openDocuments = this.openDocumentsService.getOpenDocuments()
}

View File

@@ -86,7 +86,7 @@ export class TagsComponent implements OnInit, ControlValueAccessor {
var modal = this.modalService.open(TagEditDialogComponent, {backdrop: 'static'})
modal.componentInstance.dialogMode = 'create'
modal.componentInstance.success.subscribe(newTag => {
this.tagService.list().subscribe(tags => {
this.tagService.listAll().subscribe(tags => {
this.tags = tags.results
this.addTag(newTag.id)
})

View File

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

View File

@@ -2,7 +2,7 @@
<app-page-header title="Dashboard">
</app-page-header>
<p>Welcome to paperless!</p>
<p>Welcome to paperless-ng!</p>
<div class='row'>
<div class="col-lg">

View File

@@ -49,7 +49,6 @@ export class DocumentDetailComponent implements OnInit {
private route: ActivatedRoute,
private correspondentService: CorrespondentService,
private documentTypeService: DocumentTypeService,
private datePipe: DatePipe,
private router: Router,
private modalService: NgbModal,
private openDocumentService: OpenDocumentsService,
@@ -89,7 +88,7 @@ export class DocumentDetailComponent implements OnInit {
var modal = this.modalService.open(DocumentTypeEditDialogComponent, {backdrop: 'static'})
modal.componentInstance.dialogMode = 'create'
modal.componentInstance.success.subscribe(newDocumentType => {
this.documentTypeService.list().subscribe(documentTypes => {
this.documentTypeService.listAll().subscribe(documentTypes => {
this.documentTypes = documentTypes.results
this.documentForm.get('document_type_id').setValue(newDocumentType.id)
})
@@ -100,7 +99,7 @@ export class DocumentDetailComponent implements OnInit {
var modal = this.modalService.open(CorrespondentEditDialogComponent, {backdrop: 'static'})
modal.componentInstance.dialogMode = 'create'
modal.componentInstance.success.subscribe(newCorrespondent => {
this.correspondentService.list().subscribe(correspondents => {
this.correspondentService.listAll().subscribe(correspondents => {
this.correspondents = correspondents.results
this.documentForm.get('correspondent_id').setValue(newCorrespondent.id)
})

View File

@@ -85,8 +85,8 @@
<th>Correspondent</th>
<th>Title</th>
<th>Document type</th>
<th>Date created</th>
<th>Date added</th>
<th>Created</th>
<th>Added</th>
</thead>
<tbody>
<tr *ngFor="let d of docs.documents" routerLink="/documents/{{d.id}}">

View File

@@ -1,3 +1,7 @@
.log-entry-10 {
color: lightslategray !important;
}
.log-entry-30 {
color: yellow !important;
}

View File

@@ -30,7 +30,7 @@ export class LogsComponent implements OnInit {
onScroll() {
let lastCreated = null
if (this.logs.length > 0) {
lastCreated = this.logs[this.logs.length-1].created
lastCreated = new Date(this.logs[this.logs.length-1].created).toISOString()
}
this.logService.list(1, 25, 'created', 'des', {'created__lt': lastCreated, 'level__gte': this.level}).subscribe(result => {
this.logs.push(...result.results)

View File

@@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';
import { CsrfInterceptor } from './csrf.interceptor';
describe('CsrfInterceptor', () => {
beforeEach(() => TestBed.configureTestingModule({
providers: [
CsrfInterceptor
]
}));
it('should be created', () => {
const interceptor: CsrfInterceptor = TestBed.inject(CsrfInterceptor);
expect(interceptor).toBeTruthy();
});
});

View File

@@ -0,0 +1,30 @@
import { Injectable } from '@angular/core';
import {
HttpRequest,
HttpHandler,
HttpEvent,
HttpInterceptor
} from '@angular/common/http';
import { Observable } from 'rxjs';
import { CookieService } from 'ngx-cookie-service';
@Injectable()
export class CsrfInterceptor implements HttpInterceptor {
constructor(private cookieService: CookieService) {
}
intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
let csrfToken = this.cookieService.get('csrftoken')
if (csrfToken) {
request = request.clone({
setHeaders: {
'X-CSRFToken': csrfToken
}
})
}
return next.handle(request);
}
}

View File

@@ -1,5 +1,4 @@
import { Injectable } from '@angular/core';
import { Observable, Subject } from 'rxjs';
import { PaperlessDocument } from '../data/paperless-document';
import { OPEN_DOCUMENT_SERVICE } from '../data/storage-keys';
@@ -8,6 +7,8 @@ import { OPEN_DOCUMENT_SERVICE } from '../data/storage-keys';
})
export class OpenDocumentsService {
private MAX_OPEN_DOCUMENTS = 5
constructor() {
if (sessionStorage.getItem(OPEN_DOCUMENT_SERVICE.DOCUMENTS)) {
try {
@@ -31,7 +32,10 @@ export class OpenDocumentsService {
openDocument(doc: PaperlessDocument) {
if (this.openDocuments.find(d => d.id == doc.id) == null) {
this.openDocuments.push(doc)
this.openDocuments.unshift(doc)
if (this.openDocuments.length > this.MAX_OPEN_DOCUMENTS) {
this.openDocuments.pop()
}
this.save()
}
}
@@ -44,6 +48,11 @@ export class OpenDocumentsService {
}
}
closeAll() {
this.openDocuments.splice(0, this.openDocuments.length)
this.save()
}
save() {
sessionStorage.setItem(OPEN_DOCUMENT_SERVICE.DOCUMENTS, JSON.stringify(this.openDocuments))
}

View File

@@ -0,0 +1,69 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="69.999977mm"
height="84.283669mm"
viewBox="0 0 69.999977 84.283669"
version="1.1"
id="svg4812"
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)"
sodipodi:docname="logo-dark-notext.svg">
<defs
id="defs4806" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.98994949"
inkscape:cx="328.04904"
inkscape:cy="330.33332"
inkscape:document-units="mm"
inkscape:current-layer="SvgjsG1020"
inkscape:document-rotation="0"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="1016"
inkscape:window-x="1280"
inkscape:window-y="27"
inkscape:window-maximized="1" />
<metadata
id="metadata4809">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-9.9999792,-10.000082)">
<g
id="SvgjsG1020"
featureKey="symbol1"
fill="#ffffff"
transform="matrix(0.10341565,0,0,0.10341565,1.2287665,8.3453496)">
<path
id="path57"
style="fill:#ffffff;stroke-width:1.10017"
d="M 752.4375,82.365234 C 638.02019,348.60552 87.938206,381.6089 263.96484,810.67383 c 2.20034,5.50083 -40.70621,63.80947 -69.31054,112.21679 -6.601,-24.20366 -14.30329,-50.6063 -13.20313,-52.80664 C 324.47281,700.65835 79.135592,604.94324 65.933594,466.32227 4.3242706,576.33891 -17.678136,768.86756 168.25,879.98438 c 1.10017,-10e-6 9.90207,41.80777 14.30273,62.71093 -4.40066,8.80133 -8.80162,17.60213 -11.00195,24.20313 -4.40066,11.00166 28.60352,9.90123 28.60352,12.10156 3.3005,-1.10017 81.41295,-138.62054 83.61328,-139.7207 C 726.0345,738.06398 804.14532,339.80419 752.4375,82.365234 Z M 526.9043,362.90625 C 320.073,547.73422 284.86775,685.25508 291.46875,752.36523 222.15826,588.44043 425.68898,408.01308 526.9043,362.90625 Z M 127.54297,626.94727 c 39.60599,36.30549 105.6163,147.4222 49.50781,212.33203 13.202,-29.7045 17.60234,-96.81455 -49.50781,-212.33203 z"
transform="matrix(0.90895334,0,0,0.90895334,65.06894,-58.865357)" />
<defs
id="defs14302" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB