mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-07-28 18:24:38 -05:00
added paperless ui
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title" id="modal-basic-title">{{title}}</h4>
|
||||
<button type="button" class="close" aria-label="Close" (click)="cancelClicked()">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p><b>{{message}}</b></p>
|
||||
<p *ngIf="message2">{{message2}}</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-outline-dark" (click)="cancelClicked()">Cancel</button>
|
||||
<button type="button" class="btn btn-danger" (click)="deleteClicked.emit()">Delete</button>
|
||||
</div>
|
@@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { DeleteDialogComponent } from './delete-dialog.component';
|
||||
|
||||
describe('DeleteDialogComponent', () => {
|
||||
let component: DeleteDialogComponent;
|
||||
let fixture: ComponentFixture<DeleteDialogComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ DeleteDialogComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(DeleteDialogComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
@@ -0,0 +1,31 @@
|
||||
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
|
||||
@Component({
|
||||
selector: 'app-delete-dialog',
|
||||
templateUrl: './delete-dialog.component.html',
|
||||
styleUrls: ['./delete-dialog.component.css']
|
||||
})
|
||||
export class DeleteDialogComponent implements OnInit {
|
||||
|
||||
constructor(public activeModal: NgbActiveModal) { }
|
||||
|
||||
@Output()
|
||||
public deleteClicked = new EventEmitter()
|
||||
|
||||
@Input()
|
||||
title = "Delete confirmation"
|
||||
|
||||
@Input()
|
||||
message = "Do you really want to delete this?"
|
||||
|
||||
@Input()
|
||||
message2
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
cancelClicked() {
|
||||
this.activeModal.close()
|
||||
}
|
||||
}
|
@@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { EditDialogComponent } from './edit-dialog.component';
|
||||
|
||||
describe('EditDialogComponent', () => {
|
||||
let component: EditDialogComponent;
|
||||
let fixture: ComponentFixture<EditDialogComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ EditDialogComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(EditDialogComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
@@ -0,0 +1,71 @@
|
||||
import { Directive, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||
import { Form, FormGroup } from '@angular/forms';
|
||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { Observable } from 'rxjs';
|
||||
import { ObjectWithId } from 'src/app/data/object-with-id';
|
||||
import { AbstractPaperlessService } from 'src/app/services/rest/abstract-paperless-service';
|
||||
import { Toast, ToastService } from 'src/app/services/toast.service';
|
||||
|
||||
@Directive()
|
||||
export abstract class EditDialogComponent<T extends ObjectWithId> implements OnInit {
|
||||
|
||||
constructor(
|
||||
private service: AbstractPaperlessService<T>,
|
||||
private activeModal: NgbActiveModal,
|
||||
private toastService: ToastService,
|
||||
private entityName: string) { }
|
||||
|
||||
@Input()
|
||||
dialogMode: string = 'create'
|
||||
|
||||
@Input()
|
||||
object: T
|
||||
|
||||
@Output()
|
||||
success = new EventEmitter()
|
||||
|
||||
abstract getForm(): FormGroup
|
||||
|
||||
objectForm: FormGroup = this.getForm()
|
||||
|
||||
ngOnInit(): void {
|
||||
if (this.object != null) {
|
||||
this.objectForm.patchValue(this.object)
|
||||
}
|
||||
}
|
||||
|
||||
getTitle() {
|
||||
switch (this.dialogMode) {
|
||||
case 'create':
|
||||
return "Create new " + this.entityName
|
||||
case 'edit':
|
||||
return "Edit " + this.entityName
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
save() {
|
||||
var newObject = Object.assign(Object.assign({}, this.object), this.objectForm.value)
|
||||
var serverResponse: Observable<T>
|
||||
switch (this.dialogMode) {
|
||||
case 'create':
|
||||
serverResponse = this.service.create(newObject)
|
||||
break;
|
||||
case 'edit':
|
||||
serverResponse = this.service.update(newObject)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
serverResponse.subscribe(result => {
|
||||
this.activeModal.close()
|
||||
this.success.emit(result)
|
||||
}, error => {
|
||||
this.toastService.showToast(Toast.make("Error", `Could not save ${this.entityName}: ${error.error.name}`))
|
||||
})
|
||||
}
|
||||
|
||||
cancel() {
|
||||
this.activeModal.close()
|
||||
}
|
||||
}
|
@@ -0,0 +1,6 @@
|
||||
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
|
||||
<h1 class="h2">{{title}}</h1>
|
||||
<div class="btn-toolbar mb-2 mb-md-0">
|
||||
<ng-content></ng-content>
|
||||
</div>
|
||||
</div>
|
@@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { PageHeaderComponent } from './page-header.component';
|
||||
|
||||
describe('PageHeaderComponent', () => {
|
||||
let component: PageHeaderComponent;
|
||||
let fixture: ComponentFixture<PageHeaderComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ PageHeaderComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(PageHeaderComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
@@ -0,0 +1,18 @@
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-page-header',
|
||||
templateUrl: './page-header.component.html',
|
||||
styleUrls: ['./page-header.component.css']
|
||||
})
|
||||
export class PageHeaderComponent implements OnInit {
|
||||
|
||||
constructor() { }
|
||||
|
||||
@Input()
|
||||
title: string = ""
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
}
|
2
src-ui/src/app/components/common/tag/tag.component.html
Normal file
2
src-ui/src/app/components/common/tag/tag.component.html
Normal file
@@ -0,0 +1,2 @@
|
||||
<span *ngIf="!clickable" class="badge" [style.background]="getColour().value" [style.color]="getColour().textColor">{{tag.name}}</span>
|
||||
<a [routerLink]="" *ngIf="clickable" class="badge" [style.background]="getColour().value" [style.color]="getColour().textColor">{{tag.name}}</a>
|
25
src-ui/src/app/components/common/tag/tag.component.spec.ts
Normal file
25
src-ui/src/app/components/common/tag/tag.component.spec.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { TagComponent } from './tag.component';
|
||||
|
||||
describe('TagComponent', () => {
|
||||
let component: TagComponent;
|
||||
let fixture: ComponentFixture<TagComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ TagComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(TagComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
29
src-ui/src/app/components/common/tag/tag.component.ts
Normal file
29
src-ui/src/app/components/common/tag/tag.component.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||
import { PaperlessTag } from 'src/app/data/paperless-tag';
|
||||
|
||||
@Component({
|
||||
selector: 'app-tag',
|
||||
templateUrl: './tag.component.html',
|
||||
styleUrls: ['./tag.component.css']
|
||||
})
|
||||
export class TagComponent implements OnInit {
|
||||
|
||||
constructor() { }
|
||||
|
||||
@Input()
|
||||
tag: PaperlessTag
|
||||
|
||||
@Input()
|
||||
clickable: boolean = false
|
||||
|
||||
@Output()
|
||||
click = new EventEmitter()
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
getColour() {
|
||||
return PaperlessTag.COLOURS.find(c => c.id == this.tag.colour)
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
:host {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
margin: 0.5em;
|
||||
z-index: 1200;
|
||||
}
|
@@ -0,0 +1,6 @@
|
||||
<ngb-toast
|
||||
*ngFor="let toast of toasts"
|
||||
[header]="toast.title" [autohide]="true" [delay]="toast.delay"
|
||||
(hide)="toastService.closeToast(toast)">
|
||||
{{toast.content}}
|
||||
</ngb-toast>
|
@@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ToastsComponent } from './toasts.component';
|
||||
|
||||
describe('ToastsComponent', () => {
|
||||
let component: ToastsComponent;
|
||||
let fixture: ComponentFixture<ToastsComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ ToastsComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ToastsComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
26
src-ui/src/app/components/common/toasts/toasts.component.ts
Normal file
26
src-ui/src/app/components/common/toasts/toasts.component.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { Component, OnDestroy, OnInit } from '@angular/core';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { Toast, ToastService } from 'src/app/services/toast.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-toasts',
|
||||
templateUrl: './toasts.component.html',
|
||||
styleUrls: ['./toasts.component.css']
|
||||
})
|
||||
export class ToastsComponent implements OnInit, OnDestroy {
|
||||
|
||||
constructor(private toastService: ToastService) { }
|
||||
|
||||
subscription: Subscription
|
||||
|
||||
toasts: Toast[] = []
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.subscription.unsubscribe()
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.subscription = this.toastService.getToasts().subscribe(toasts => this.toasts = toasts)
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user