mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2026-10-26 01:28:55 +00:00
avoid the nasty regex
This commit is contained in:
2 files changed
+47
-37
No files matched your search
+6
-4
@@ -39,10 +39,12 @@
|
||||
</button>
|
||||
@if (relativeDate) {
|
||||
<div class="input-group input-group-sm w-100 order-1 mt-1">
|
||||
<input class="form-control w-25 flex-grow-0" type="number" min="0" aria-label="Amount" i18n-aria-label
|
||||
[ngModel]="relativeDate.amount"
|
||||
(ngModelChange)="updateRelativeDate(atom, { amount: $event })"
|
||||
[ngModelOptions]="{standalone: true}" />
|
||||
@if (relativeDate.unit.includes('{n}')) {
|
||||
<input class="form-control w-25 flex-grow-0" type="number" min="0" aria-label="Amount" i18n-aria-label
|
||||
[ngModel]="relativeDate.amount"
|
||||
(ngModelChange)="updateRelativeDate(atom, { amount: $event })"
|
||||
[ngModelOptions]="{standalone: true}" />
|
||||
}
|
||||
<select class="form-select" aria-label="Unit" i18n-aria-label
|
||||
[ngModel]="relativeDate.unit"
|
||||
(ngModelChange)="updateRelativeDate(atom, { unit: $event })"
|
||||
|
||||
+41
-33
@@ -49,15 +49,26 @@ import { LoadingComponentWithPermissions } from '../../loading-component/loading
|
||||
import { ClearableBadgeComponent } from '../clearable-badge/clearable-badge.component'
|
||||
import { DocumentLinkComponent } from '../input/document-link/document-link.component'
|
||||
|
||||
// Matches the English expressions built by updateRelativeDate, e.g. "30 days ago" / "in 2 weeks"
|
||||
const RELATIVE_DATE_PATTERN =
|
||||
/^(?:(\d+) (days|weeks|months|years) ago|in (\d+) (days|weeks|months|years))$/
|
||||
|
||||
interface RelativeDate {
|
||||
// The expression sent to the API, with {n} standing in for the amount
|
||||
amount: number | null
|
||||
unit: string
|
||||
}
|
||||
|
||||
function parseRelativeDate(
|
||||
value: string,
|
||||
unit: string
|
||||
): RelativeDate | undefined {
|
||||
const [prefix, suffix] = unit.split('{n}')
|
||||
if (suffix === undefined) {
|
||||
return value === unit ? { amount: null, unit } : undefined
|
||||
}
|
||||
if (!value.startsWith(prefix) || !value.endsWith(suffix)) return undefined
|
||||
const amount = value.slice(prefix.length, value.length - suffix.length)
|
||||
if (!amount || !Number.isInteger(+amount) || +amount < 0) return undefined
|
||||
return { amount: +amount, unit }
|
||||
}
|
||||
|
||||
export class CustomFieldQueriesModel {
|
||||
private readonly _queries = signal<CustomFieldQueryElement[]>([])
|
||||
private rootSubscriptions: Subscription[] = []
|
||||
@@ -315,30 +326,27 @@ export class CustomFieldsQueryDropdownComponent extends LoadingComponentWithPerm
|
||||
public readonly today: string = new Date().toLocaleDateString('en-CA')
|
||||
|
||||
public readonly relativeDateUnits = [
|
||||
{ id: 'days ago', label: $localize`days ago` },
|
||||
{ id: 'weeks ago', label: $localize`weeks ago` },
|
||||
{ id: 'months ago', label: $localize`months ago` },
|
||||
{ id: 'years ago', label: $localize`years ago` },
|
||||
{ id: 'days from now', label: $localize`days from now` },
|
||||
{ id: 'weeks from now', label: $localize`weeks from now` },
|
||||
{ id: 'months from now', label: $localize`months from now` },
|
||||
{ id: 'years from now', label: $localize`years from now` },
|
||||
{ id: 'today', label: $localize`Today` },
|
||||
{ id: '{n} days ago', label: $localize`days ago` },
|
||||
{ id: '{n} weeks ago', label: $localize`weeks ago` },
|
||||
{ id: '{n} months ago', label: $localize`months ago` },
|
||||
{ id: '{n} years ago', label: $localize`years ago` },
|
||||
{ id: 'in {n} days', label: $localize`days from now` },
|
||||
{ id: 'in {n} weeks', label: $localize`weeks from now` },
|
||||
{ id: 'in {n} months', label: $localize`months from now` },
|
||||
{ id: 'in {n} years', label: $localize`years from now` },
|
||||
]
|
||||
|
||||
private readonly relativeDates = new Map<string, RelativeDate>()
|
||||
|
||||
getRelativeDate(atom: CustomFieldQueryAtom): RelativeDate | undefined {
|
||||
if (!this.relativeDates.has(atom.id)) {
|
||||
const match =
|
||||
typeof atom.value === 'string' &&
|
||||
atom.value.match(RELATIVE_DATE_PATTERN)
|
||||
if (match) {
|
||||
this.relativeDates.set(
|
||||
atom.id,
|
||||
match[1]
|
||||
? { amount: +match[1], unit: `${match[2]} ago` }
|
||||
: { amount: +match[3], unit: `${match[4]} from now` }
|
||||
)
|
||||
if (!this.relativeDates.has(atom.id) && typeof atom.value === 'string') {
|
||||
for (const { id } of this.relativeDateUnits) {
|
||||
const relativeDate = parseRelativeDate(atom.value, id)
|
||||
if (relativeDate) {
|
||||
this.relativeDates.set(atom.id, relativeDate)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return this.relativeDates.get(atom.id)
|
||||
@@ -349,7 +357,7 @@ export class CustomFieldsQueryDropdownComponent extends LoadingComponentWithPerm
|
||||
this.relativeDates.delete(atom.id)
|
||||
atom.value = null
|
||||
} else {
|
||||
this.relativeDates.set(atom.id, { amount: null, unit: 'days ago' })
|
||||
this.relativeDates.set(atom.id, { amount: null, unit: '{n} days ago' })
|
||||
this.updateRelativeDate(atom, {})
|
||||
}
|
||||
}
|
||||
@@ -358,15 +366,15 @@ export class CustomFieldsQueryDropdownComponent extends LoadingComponentWithPerm
|
||||
atom: CustomFieldQueryAtom,
|
||||
change: Partial<RelativeDate>
|
||||
) {
|
||||
const relativeDate = Object.assign(this.relativeDates.get(atom.id), change)
|
||||
const { amount, unit } = relativeDate
|
||||
const [period, direction] = unit.split(' ', 2)
|
||||
atom.value =
|
||||
amount === null
|
||||
? null
|
||||
: direction === 'ago'
|
||||
? `${amount} ${unit}`
|
||||
: `in ${amount} ${period}`
|
||||
const { amount, unit } = Object.assign(
|
||||
this.relativeDates.get(atom.id),
|
||||
change
|
||||
)
|
||||
if (!unit.includes('{n}')) {
|
||||
atom.value = unit
|
||||
} else {
|
||||
atom.value = amount === null ? null : unit.replace('{n}', `${amount}`)
|
||||
}
|
||||
}
|
||||
|
||||
public customFieldSearchFn = (term: string, field: CustomField): boolean =>
|
||||
|
||||
Reference in new issue
Block a user