use created_date

This commit is contained in:
Michael Shamoon 2022-05-15 21:09:42 -07:00
parent bb15b744c8
commit 2ca691d3b8
9 changed files with 43 additions and 48 deletions

View File

@ -12,7 +12,7 @@
</thead> </thead>
<tbody> <tbody>
<tr *ngFor="let doc of documents" (click)="openDocumentsService.openDocument(doc)"> <tr *ngFor="let doc of documents" (click)="openDocumentsService.openDocument(doc)">
<td>{{doc.created | customDate}}</td> <td>{{doc.created_date | customDate}}</td>
<td>{{doc.title | documentTitle}}<app-tag [tag]="t" *ngFor="let t of doc.tags$ | async" class="ms-1" (click)="clickTag(t); $event.stopPropagation();"></app-tag></td> <td>{{doc.title | documentTitle}}<app-tag [tag]="t" *ngFor="let t of doc.tags$ | async" class="ms-1" (click)="clickTag(t); $event.stopPropagation();"></app-tag></td>
</tr> </tr>
</tbody> </tbody>

View File

@ -68,7 +68,7 @@
<app-input-text #inputTitle i18n-title title="Title" formControlName="title" (keyup)="titleKeyUp($event)" [error]="error?.title"></app-input-text> <app-input-text #inputTitle i18n-title title="Title" formControlName="title" (keyup)="titleKeyUp($event)" [error]="error?.title"></app-input-text>
<app-input-number i18n-title title="Archive serial number" [error]="error?.archive_serial_number" formControlName='archive_serial_number'></app-input-number> <app-input-number i18n-title title="Archive serial number" [error]="error?.archive_serial_number" formControlName='archive_serial_number'></app-input-number>
<app-input-date i18n-title title="Date created" formControlName="created" [error]="error?.created"></app-input-date> <app-input-date i18n-title title="Date created" formControlName="created_date" [error]="error?.created"></app-input-date>
<app-input-select [items]="correspondents" i18n-title title="Correspondent" formControlName="correspondent" [allowNull]="true" <app-input-select [items]="correspondents" i18n-title title="Correspondent" formControlName="correspondent" [allowNull]="true"
(createNew)="createCorrespondent($event)" [suggestions]="suggestions?.correspondents"></app-input-select> (createNew)="createCorrespondent($event)" [suggestions]="suggestions?.correspondents"></app-input-select>
<app-input-select [items]="documentTypes" i18n-title title="Document type" formControlName="document_type" [allowNull]="true" <app-input-select [items]="documentTypes" i18n-title title="Document type" formControlName="document_type" [allowNull]="true"

View File

@ -34,7 +34,6 @@ import {
} from 'rxjs/operators' } from 'rxjs/operators'
import { PaperlessDocumentSuggestions } from 'src/app/data/paperless-document-suggestions' import { PaperlessDocumentSuggestions } from 'src/app/data/paperless-document-suggestions'
import { FILTER_FULLTEXT_MORELIKE } from 'src/app/data/filter-rule-type' import { FILTER_FULLTEXT_MORELIKE } from 'src/app/data/filter-rule-type'
import { normalizeDateStr } from 'src/app/utils/date'
import { QueryParamsService } from 'src/app/services/query-params.service' import { QueryParamsService } from 'src/app/services/query-params.service'
@Component({ @Component({
@ -72,7 +71,7 @@ export class DocumentDetailComponent
documentForm: FormGroup = new FormGroup({ documentForm: FormGroup = new FormGroup({
title: new FormControl(''), title: new FormControl(''),
content: new FormControl(''), content: new FormControl(''),
created: new FormControl(), created_date: new FormControl(),
correspondent: new FormControl(), correspondent: new FormControl(),
document_type: new FormControl(), document_type: new FormControl(),
archive_serial_number: new FormControl(), archive_serial_number: new FormControl(),
@ -137,27 +136,8 @@ export class DocumentDetailComponent
ngOnInit(): void { ngOnInit(): void {
this.documentForm.valueChanges this.documentForm.valueChanges
.pipe(takeUntil(this.unsubscribeNotifier)) .pipe(takeUntil(this.unsubscribeNotifier))
.subscribe((changes) => { .subscribe(() => {
this.error = null this.error = null
if (this.ogDate) {
try {
let newDate = new Date(normalizeDateStr(changes['created']))
newDate.setHours(
this.ogDate.getHours(),
this.ogDate.getMinutes(),
this.ogDate.getSeconds(),
this.ogDate.getMilliseconds()
)
this.documentForm.patchValue(
{ created: newDate.toISOString() },
{ emitEvent: false }
)
} catch (e) {
// catch this before we try to save and simulate an api error
this.error = { created: e.message }
}
}
Object.assign(this.document, this.documentForm.value) Object.assign(this.document, this.documentForm.value)
}) })
@ -223,25 +203,17 @@ export class DocumentDetailComponent
}, },
}) })
this.ogDate = new Date(normalizeDateStr(doc.created.toString()))
// Initialize dirtyCheck // Initialize dirtyCheck
this.store = new BehaviorSubject({ this.store = new BehaviorSubject({
title: doc.title, title: doc.title,
content: doc.content, content: doc.content,
created: this.ogDate.toISOString(), created_date: doc.created_date,
correspondent: doc.correspondent, correspondent: doc.correspondent,
document_type: doc.document_type, document_type: doc.document_type,
archive_serial_number: doc.archive_serial_number, archive_serial_number: doc.archive_serial_number,
tags: [...doc.tags], tags: [...doc.tags],
}) })
// start with ISO8601 string
this.documentForm.patchValue(
{ created: this.ogDate.toISOString() },
{ emitEvent: false }
)
this.isDirty$ = dirtyCheck( this.isDirty$ = dirtyCheck(
this.documentForm, this.documentForm,
this.store.asObservable() this.store.asObservable()

View File

@ -32,8 +32,12 @@ export interface PaperlessDocument extends ObjectWithId {
checksum?: string checksum?: string
// UTC
created?: Date created?: Date
// localized date
created_date?: Date
modified?: Date modified?: Date
added?: Date added?: Date

View File

@ -1,7 +1,6 @@
import { DatePipe } from '@angular/common' import { DatePipe } from '@angular/common'
import { Inject, LOCALE_ID, Pipe, PipeTransform } from '@angular/core' import { Inject, LOCALE_ID, Pipe, PipeTransform } from '@angular/core'
import { SettingsService, SETTINGS_KEYS } from '../services/settings.service' import { SettingsService, SETTINGS_KEYS } from '../services/settings.service'
import { normalizeDateStr } from '../utils/date'
const FORMAT_TO_ISO_FORMAT = { const FORMAT_TO_ISO_FORMAT = {
longDate: 'y-MM-dd', longDate: 'y-MM-dd',
@ -34,7 +33,6 @@ export class CustomDatePipe implements PipeTransform {
this.settings.get(SETTINGS_KEYS.DATE_LOCALE) || this.settings.get(SETTINGS_KEYS.DATE_LOCALE) ||
this.defaultLocale this.defaultLocale
let f = format || this.settings.get(SETTINGS_KEYS.DATE_FORMAT) let f = format || this.settings.get(SETTINGS_KEYS.DATE_FORMAT)
if (typeof value == 'string') value = normalizeDateStr(value)
if (l == 'iso-8601') { if (l == 'iso-8601') {
return this.datePipe.transform(value, FORMAT_TO_ISO_FORMAT[f], timezone) return this.datePipe.transform(value, FORMAT_TO_ISO_FORMAT[f], timezone)
} else { } else {

View File

@ -1,5 +0,0 @@
// see https://github.com/dateutil/dateutil/issues/878 , JS Date does not
// seem to accept these strings as valid dates so we must normalize offset
export function normalizeDateStr(dateStr: string): string {
return dateStr.replace(/[\+-](\d\d):\d\d:\d\d/gm, `-$1:00`)
}

View File

@ -5,20 +5,27 @@ import { NgbDateAdapter, NgbDateStruct } from '@ng-bootstrap/ng-bootstrap'
export class ISODateTimeAdapter extends NgbDateAdapter<string> { export class ISODateTimeAdapter extends NgbDateAdapter<string> {
fromModel(value: string | null): NgbDateStruct | null { fromModel(value: string | null): NgbDateStruct | null {
if (value) { if (value) {
if (value.match(/\d\d\d\d\-\d\d\-\d\d/g)) {
const segs = value.split('-')
return {
year: parseInt(segs[0]),
month: parseInt(segs[1]),
day: parseInt(segs[2]),
}
} else {
let date = new Date(value) let date = new Date(value)
return { return {
day: date.getDate(), day: date.getDate(),
month: date.getMonth() + 1, month: date.getMonth() + 1,
year: date.getFullYear(), year: date.getFullYear(),
} }
}
} else { } else {
return null return null
} }
} }
toModel(date: NgbDateStruct | null): string | null { toModel(date: NgbDateStruct | null): string | null {
return date return date ? [date.year, date.month, date.day].join('-') : null
? new Date(date.year, date.month - 1, date.day).toISOString()
: null
} }
} }

View File

@ -279,6 +279,10 @@ class Document(models.Model):
def thumbnail_file(self): def thumbnail_file(self):
return open(self.thumbnail_path, "rb") return open(self.thumbnail_path, "rb")
@property
def created_date(self):
return timezone.localdate(self.created)
class Log(models.Model): class Log(models.Model):

View File

@ -1,7 +1,10 @@
import datetime
import math import math
import re import re
import magic import magic
from dateutil import tz
from django.conf import settings
from django.utils.text import slugify from django.utils.text import slugify
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from rest_framework import serializers from rest_framework import serializers
@ -206,6 +209,7 @@ class DocumentSerializer(DynamicFieldsModelSerializer):
original_file_name = SerializerMethodField() original_file_name = SerializerMethodField()
archived_file_name = SerializerMethodField() archived_file_name = SerializerMethodField()
created_date = serializers.DateField()
def get_original_file_name(self, obj): def get_original_file_name(self, obj):
return obj.get_public_filename() return obj.get_public_filename()
@ -216,6 +220,16 @@ class DocumentSerializer(DynamicFieldsModelSerializer):
else: else:
return None return None
def update(self, instance, validated_data):
if "created_date" in validated_data and "created" not in validated_data:
new_datetime = datetime.datetime.combine(
validated_data.get("created_date"),
datetime.time(0, 0, 0, 0, tz.gettz(settings.TIME_ZONE)),
)
instance.created = new_datetime
instance.save()
return instance
class Meta: class Meta:
model = Document model = Document
depth = 1 depth = 1
@ -227,6 +241,7 @@ class DocumentSerializer(DynamicFieldsModelSerializer):
"content", "content",
"tags", "tags",
"created", "created",
"created_date",
"modified", "modified",
"added", "added",
"archive_serial_number", "archive_serial_number",