Saving work, basic frontend getting & display

This commit is contained in:
shamoon 2023-10-20 23:51:14 -07:00
parent d9526ea32f
commit 6f62da077a
11 changed files with 263 additions and 139 deletions

View File

@ -41,6 +41,9 @@ export class AbstractInputComponent<T> implements OnInit, ControlValueAccessor {
@Input()
error: string
@Input()
horizontal: boolean = false
value: T
ngOnInit(): void {

View File

@ -1,5 +1,9 @@
<div class="mb-3">
<label class="form-label" [for]="inputId">{{title}}</label>
<div class="row">
<div class="d-flex align-items-center" [class.col-md-3]="horizontal">
<label class="form-label mb-md-0" [for]="inputId">{{title}}</label>
</div>
<div [class.col-md-9]="horizontal">
<div class="input-group" [class.is-invalid]="error">
<input #inputField class="form-control" [class.is-invalid]="error" [placeholder]="placeholder" [id]="inputId" maxlength="10"
(dateSelect)="onChange(value)" (change)="onChange(value)" (keypress)="onKeyPress($event)" (paste)="onPaste($event)"
@ -23,4 +27,6 @@
<a (click)="onSuggestionClick(s)" [routerLink]="[]">{{s}}</a>&nbsp;
</ng-container>
</small>
</div>
</div>
</div>

View File

@ -1,5 +1,9 @@
<div class="mb-3">
<div class="row">
<div [class.col-md-3]="horizontal">
<label class="form-label" [for]="inputId">{{title}}</label>
</div>
<div [class.col-md-9]="horizontal">
<div class="input-group" [class.is-invalid]="error">
<input #inputField type="number" class="form-control" [id]="inputId" [(ngModel)]="value" (change)="onChange(value)" [class.is-invalid]="error" [disabled]="disabled">
<button *ngIf="showAdd" class="btn btn-outline-secondary" type="button" id="button-addon1" (click)="nextAsn()" [disabled]="disabled">+1</button>
@ -8,5 +12,6 @@
{{error}}
</div>
<small *ngIf="hint" class="form-text text-muted">{{hint}}</small>
</div>
</div>
</div>

View File

@ -1,5 +1,9 @@
<div class="mb-3 paperless-input-select" [class.disabled]="disabled">
<label *ngIf="title" class="form-label" [for]="inputId">{{title}}</label>
<div class="row">
<div class="d-flex align-items-center" [class.col-md-3]="horizontal">
<label *ngIf="title" class="form-label mb-md-0" [for]="inputId">{{title}}</label>
</div>
<div [class.col-md-9]="horizontal">
<div [class.input-group]="allowCreateNew || showFilter">
<ng-select name="inputId" [(ngModel)]="value"
[disabled]="disabled"
@ -38,7 +42,7 @@
<ng-container *ngFor="let s of getSuggestions()">
<a (click)="value = s.id; onChange(value)" [routerLink]="[]">{{s.name}}</a>&nbsp;
</ng-container>
</small>
</div>
</div>
</div>

View File

@ -1,6 +1,9 @@
<div class="mb-3 paperless-input-select paperless-input-tags" [class.disabled]="disabled">
<label class="form-label" for="tags" i18n>{{title}}</label>
<div class="row">
<div class="d-flex align-items-center" [class.col-md-3]="horizontal">
<label class="form-label mb-md-0" for="tags" i18n>{{title}}</label>
</div>
<div [class.col-md-9]="horizontal">
<div class="input-group flex-nowrap">
<ng-select #tagSelect name="tags" [items]="tags" bindLabel="name" bindValue="id" [(ngModel)]="value"
[disabled]="disabled"
@ -44,8 +47,7 @@
<ng-container *ngFor="let tag of getSuggestions()">
<a (click)="addTag(tag.id)" [routerLink]="[]">{{tag.name}}</a>&nbsp;
</ng-container>
</small>
</div>
</div>
</div>

View File

@ -77,6 +77,9 @@ export class TagsComponent implements OnInit, ControlValueAccessor {
@Input()
showFilter: boolean = false
@Input()
horizontal: boolean = false
@Output()
filterDocuments = new EventEmitter<PaperlessTag[]>()

View File

@ -1,8 +1,14 @@
<div class="mb-3">
<label class="form-label" [for]="inputId">{{title}}</label>
<div class="row">
<div class="d-flex align-items-center" [class.col-md-3]="horizontal">
<label class="form-label mb-md-0" [for]="inputId">{{title}}</label>
</div>
<div [class.col-md-9]="horizontal">
<input #inputField type="text" class="form-control" [class.is-invalid]="error" [id]="inputId" [(ngModel)]="value" (change)="onChange(value)" [disabled]="disabled">
<small *ngIf="hint" class="form-text text-muted" [innerHTML]="hint | safeHtml"></small>
<div class="invalid-feedback">
{{error}}
</div>
</div>
</div>
</div>

View File

@ -81,19 +81,23 @@
<li [ngbNavItem]="DocumentDetailNavIDs.Details">
<a ngbNavLink i18n>Details</a>
<ng-template ngbNavContent>
<pngx-input-text #inputTitle i18n-title title="Title" formControlName="title" (keyup)="titleKeyUp($event)" [error]="error?.title"></pngx-input-text>
<pngx-input-number i18n-title title="Archive serial number" [error]="error?.archive_serial_number" formControlName='archive_serial_number'></pngx-input-number>
<pngx-input-date i18n-title title="Date created" formControlName="created_date" [suggestions]="suggestions?.dates" [showFilter]="true" (filterDocuments)="filterDocuments($event)"
<div class="my-3">
<pngx-input-text #inputTitle i18n-title title="Title" formControlName="title" [horizontal]="true" (keyup)="titleKeyUp($event)" [error]="error?.title"></pngx-input-text>
<pngx-input-number i18n-title title="Archive serial number" [error]="error?.archive_serial_number" [horizontal]="true" formControlName='archive_serial_number'></pngx-input-number>
<pngx-input-date i18n-title title="Date created" formControlName="created_date" [suggestions]="suggestions?.dates" [showFilter]="true" [horizontal]="true" (filterDocuments)="filterDocuments($event)"
[error]="error?.created_date"></pngx-input-date>
<pngx-input-select [items]="correspondents" i18n-title title="Correspondent" formControlName="correspondent" [allowNull]="true" [showFilter]="true" (filterDocuments)="filterDocuments($event)"
<pngx-input-select [items]="correspondents" i18n-title title="Correspondent" formControlName="correspondent" [allowNull]="true" [showFilter]="true" [horizontal]="true" (filterDocuments)="filterDocuments($event)"
(createNew)="createCorrespondent($event)" [suggestions]="suggestions?.correspondents" *pngxIfPermissions="{ action: PermissionAction.View, type: PermissionType.Correspondent }"></pngx-input-select>
<pngx-input-select [items]="documentTypes" i18n-title title="Document type" formControlName="document_type" [allowNull]="true" [showFilter]="true" (filterDocuments)="filterDocuments($event)"
<pngx-input-select [items]="documentTypes" i18n-title title="Document type" formControlName="document_type" [allowNull]="true" [showFilter]="true" [horizontal]="true" (filterDocuments)="filterDocuments($event)"
(createNew)="createDocumentType($event)" [suggestions]="suggestions?.document_types" *pngxIfPermissions="{ action: PermissionAction.View, type: PermissionType.DocumentType }"></pngx-input-select>
<pngx-input-select [items]="storagePaths" i18n-title title="Storage path" formControlName="storage_path" [allowNull]="true" [showFilter]="true" (filterDocuments)="filterDocuments($event)"
<pngx-input-select [items]="storagePaths" i18n-title title="Storage path" formControlName="storage_path" [allowNull]="true" [showFilter]="true" [horizontal]="true" (filterDocuments)="filterDocuments($event)"
(createNew)="createStoragePath($event)" [suggestions]="suggestions?.storage_paths" i18n-placeholder placeholder="Default" *pngxIfPermissions="{ action: PermissionAction.View, type: PermissionType.StoragePath }"></pngx-input-select>
<pngx-input-tags formControlName="tags" [suggestions]="suggestions?.tags" [showFilter]="true" (filterDocuments)="filterDocuments($event)" *pngxIfPermissions="{ action: PermissionAction.View, type: PermissionType.Tag }"></pngx-input-tags>
<pngx-input-tags formControlName="tags" [suggestions]="suggestions?.tags" [showFilter]="true" [horizontal]="true" (filterDocuments)="filterDocuments($event)" *pngxIfPermissions="{ action: PermissionAction.View, type: PermissionType.Tag }"></pngx-input-tags>
<ng-container *ngFor="let field of customFields">
<pngx-input-text [formControlName]="'custom-field-' + field.id" *ngIf="field.type === PaperlessCustomFieldDataType.String" [title]="field.name" [horizontal]="true"></pngx-input-text>
<pngx-input-date [formControlName]="'custom-field-' + field.id" *ngIf="field.type === PaperlessCustomFieldDataType.Date" [title]="field.name" [horizontal]="true"></pngx-input-date>
</ng-container>
</div>
</ng-template>
</li>

View File

@ -63,7 +63,11 @@ import { EditDialogMode } from '../common/edit-dialog/edit-dialog.component'
import { ObjectWithId } from 'src/app/data/object-with-id'
import { FilterRule } from 'src/app/data/filter-rule'
import { ISODateAdapter } from 'src/app/utils/ngb-iso-date-adapter'
import { ShareLinksDropdownComponent } from '../common/share-links-dropdown/share-links-dropdown.component'
import { CustomFieldsService } from 'src/app/services/rest/custom-fields.service'
import {
PaperlessCustomField,
PaperlessCustomFieldDataType,
} from 'src/app/data/paperless-custom-field'
enum DocumentDetailNavIDs {
Details = 1,
@ -135,6 +139,9 @@ export class DocumentDetailComponent
ogDate: Date
public readonly PaperlessCustomFieldDataType = PaperlessCustomFieldDataType
customFields: PaperlessCustomField[]
@ViewChild('nav') nav: NgbNav
@ViewChild('pdfPreview') set pdfPreview(element) {
// this gets called when compontent added or removed from DOM
@ -166,7 +173,8 @@ export class DocumentDetailComponent
private storagePathService: StoragePathService,
private permissionsService: PermissionsService,
private userService: UserService,
private http: HttpClient
private http: HttpClient,
private customFieldsService: CustomFieldsService
) {
super()
}
@ -385,6 +393,28 @@ export class DocumentDetailComponent
updateComponent(doc: PaperlessDocument) {
this.document = doc
this.requiresPassword = false
this.customFieldsService
.getFields(doc.id)
.pipe(first())
.subscribe({
next: (fields) => {
this.customFields = fields
this.customFields.forEach((field) => {
this.documentForm.addControl(
`custom-field-${field.id}`,
new FormControl(field.data)
)
})
this.store.next(this.documentForm.value)
console.log(fields)
},
error: (error) => {
this.toastService.showError(
$localize`Error retrieving custom fields`,
error
)
},
})
this.documentsService
.getMetadata(doc.id)
.pipe(first())
@ -511,6 +541,11 @@ export class DocumentDetailComponent
}
this.title = doc.title
this.documentForm.patchValue(doc)
this.customFields.forEach((field) => {
this.documentForm
.get(`custom-field-${field.id}`)
.patchValue(field.data)
})
this.openDocumentService.setDirty(doc, false)
},
error: () => {

View File

@ -0,0 +1,16 @@
import { ObjectWithId } from './object-with-id'
export enum PaperlessCustomFieldDataType {
String = 'string',
Url = 'url',
Date = 'date',
}
export interface PaperlessCustomField extends ObjectWithId {
type: PaperlessCustomFieldDataType
name: string
data: any
document: number // PaperlessDocument
created?: Date
user: number // PaperlessUser
}

View File

@ -0,0 +1,40 @@
import { Injectable } from '@angular/core'
import { HttpClient, HttpParams } from '@angular/common/http'
import { AbstractPaperlessService } from './abstract-paperless-service'
import { Observable } from 'rxjs'
import { PaperlessCustomField } from 'src/app/data/paperless-custom-field'
@Injectable({
providedIn: 'root',
})
export class CustomFieldsService extends AbstractPaperlessService<PaperlessCustomField> {
constructor(http: HttpClient) {
super(http, 'documents')
}
getFields(documentId: number): Observable<PaperlessCustomField[]> {
return this.http.get<PaperlessCustomField[]>(
this.getResourceUrl(documentId, 'custom_metadata')
)
}
addField(
documentId: number,
field: PaperlessCustomField
): Observable<PaperlessCustomField[]> {
return this.http.post<PaperlessCustomField[]>(
this.getResourceUrl(documentId, 'custom_metadata'),
field
)
}
// deleteField(
// documentId: number,
// fieldId: number
// ): Observable<PaperlessCustomField[]> {
// return this.http.delete<PaperlessCustomField[]>(
// this.getResourceUrl(documentId, 'custom_metadata'),
// { params: new HttpParams({ fromString: `id=${fieldId}` }) }
// )
// }
}