- @if (searchResults?.total === 0) {
+ @if (searchResults()?.total === 0) {
} @else {
- @if (searchResults?.documents.length) {
+ @if (searchResults()?.documents.length) {
- @for (document of searchResults.documents; track document.id) {
+ @for (document of searchResults().documents; track document.id) {
}
}
- @if (searchResults?.saved_views.length) {
+ @if (searchResults()?.saved_views.length) {
- @for (saved_view of searchResults.saved_views; track saved_view.id) {
+ @for (saved_view of searchResults().saved_views; track saved_view.id) {
}
}
- @if (searchResults?.tags.length) {
+ @if (searchResults()?.tags.length) {
- @for (tag of searchResults.tags; track tag.id) {
+ @for (tag of searchResults().tags; track tag.id) {
}
}
- @if (searchResults?.correspondents.length) {
+ @if (searchResults()?.correspondents.length) {
- @for (correspondent of searchResults.correspondents; track correspondent.id) {
+ @for (correspondent of searchResults().correspondents; track correspondent.id) {
}
}
- @if (searchResults?.document_types.length) {
+ @if (searchResults()?.document_types.length) {
- @for (documentType of searchResults.document_types; track documentType.id) {
+ @for (documentType of searchResults().document_types; track documentType.id) {
}
}
- @if (searchResults?.storage_paths.length) {
+ @if (searchResults()?.storage_paths.length) {
- @for (storagePath of searchResults.storage_paths; track storagePath.id) {
+ @for (storagePath of searchResults().storage_paths; track storagePath.id) {
}
}
- @if (searchResults?.users.length) {
+ @if (searchResults()?.users.length) {
- @for (user of searchResults.users; track user.id) {
+ @for (user of searchResults().users; track user.id) {
}
}
- @if (searchResults?.groups.length) {
+ @if (searchResults()?.groups.length) {
- @for (group of searchResults.groups; track group.id) {
+ @for (group of searchResults().groups; track group.id) {
}
}
- @if (searchResults?.custom_fields.length) {
+ @if (searchResults()?.custom_fields.length) {
- @for (customField of searchResults.custom_fields; track customField.id) {
+ @for (customField of searchResults().custom_fields; track customField.id) {
}
}
- @if (searchResults?.mail_accounts.length) {
+ @if (searchResults()?.mail_accounts.length) {
- @for (mailAccount of searchResults.mail_accounts; track mailAccount.id) {
+ @for (mailAccount of searchResults().mail_accounts; track mailAccount.id) {
}
}
- @if (searchResults?.mail_rules.length) {
+ @if (searchResults()?.mail_rules.length) {
- @for (mailRule of searchResults.mail_rules; track mailRule.id) {
+ @for (mailRule of searchResults().mail_rules; track mailRule.id) {
}
}
- @if (searchResults?.workflows.length) {
+ @if (searchResults()?.workflows.length) {
- @for (workflow of searchResults.workflows; track workflow.id) {
+ @for (workflow of searchResults().workflows; track workflow.id) {
}
}
diff --git a/src-ui/src/app/components/app-frame/global-search/global-search.component.spec.ts b/src-ui/src/app/components/app-frame/global-search/global-search.component.spec.ts
index 1be801478..d605cde89 100644
--- a/src-ui/src/app/components/app-frame/global-search/global-search.component.spec.ts
+++ b/src-ui/src/app/components/app-frame/global-search/global-search.component.spec.ts
@@ -170,7 +170,7 @@ describe('GlobalSearchComponent', () => {
document.dispatchEvent(new KeyboardEvent('keydown', { key: '/' }))
expect(focusSpy).toHaveBeenCalled()
- component.searchResults = searchResults as any
+ component.searchResults.set(searchResults as any)
component.resultsDropdown.open()
fixture.detectChanges()
@@ -238,26 +238,26 @@ describe('GlobalSearchComponent', () => {
)
expect(component['currentItemIndex']).toBe(0)
- component.searchResults = { total: 1 } as any
+ component.searchResults.set({ total: 1 } as any)
const primaryActionSpy = jest.spyOn(component, 'primaryAction')
component.searchInputKeyDown(new KeyboardEvent('keydown', { key: 'Enter' }))
expect(primaryActionSpy).toHaveBeenCalled()
- component.query = 'test'
+ component.query.set('test')
const resetSpy = jest.spyOn(GlobalSearchComponent.prototype as any, 'reset')
component.searchInputKeyDown(
new KeyboardEvent('keydown', { key: 'Escape' })
)
expect(resetSpy).toHaveBeenCalled()
- component.query = ''
+ component.query.set('')
const blurSpy = jest.spyOn(component.searchInput.nativeElement, 'blur')
component.searchInputKeyDown(
new KeyboardEvent('keydown', { key: 'Escape' })
)
expect(blurSpy).toHaveBeenCalled()
- component.searchResults = { total: 1 } as any
+ component.searchResults.set({ total: 1 } as any)
component.resultsDropdown.open()
component.searchInputKeyDown(
@@ -268,9 +268,9 @@ describe('GlobalSearchComponent', () => {
component.dropdownKeyDown(new KeyboardEvent('keydown', { key: 'Escape' }))
expect(closeSpy).toHaveBeenCalled()
- component.searchResults = searchResults as any
+ component.searchResults.set(searchResults as any)
component.resultsDropdown.open()
- component.query = 'test'
+ component.query.set('test')
const advancedSearchSpy = jest.spyOn(component, 'runFullSearch')
component.searchInputKeyDown(new KeyboardEvent('keydown', { key: 'Enter' }))
expect(advancedSearchSpy).toHaveBeenCalled()
@@ -471,7 +471,7 @@ describe('GlobalSearchComponent', () => {
})
it('should support focus current item', () => {
- component.searchResults = searchResults as any
+ component.searchResults.set(searchResults as any)
fixture.detectChanges()
const focusSpy = jest.spyOn(
component.primaryButtons.get(0).nativeElement,
@@ -489,7 +489,7 @@ describe('GlobalSearchComponent', () => {
})
it('should focus button on dropdown item hover', () => {
- component.searchResults = searchResults as any
+ component.searchResults.set(searchResults as any)
fixture.detectChanges()
const item: ElementRef = component.resultItems.first
const focusSpy = jest.spyOn(
@@ -515,7 +515,7 @@ describe('GlobalSearchComponent', () => {
component.primaryAction(DataType.Document, { id: 2 }, event as any)
expect(openSpy).toHaveBeenCalledWith('/documents/2', '_blank')
- component.searchResults = searchResults as any
+ component.searchResults.set(searchResults as any)
component.resultsDropdown.open()
fixture.detectChanges()
@@ -542,7 +542,7 @@ describe('GlobalSearchComponent', () => {
it('should support title content search and advanced search', () => {
const qfSpy = jest.spyOn(documentListViewService, 'quickFilter')
- component.query = 'test'
+ component.query.set('test')
component.runFullSearch()
expect(qfSpy).toHaveBeenCalledWith([
{ rule_type: FILTER_SIMPLE_TEXT, value: 'test' },
@@ -552,7 +552,7 @@ describe('GlobalSearchComponent', () => {
SETTINGS_KEYS.SEARCH_FULL_TYPE,
GlobalSearchType.ADVANCED
)
- component.query = 'test'
+ component.query.set('test')
component.runFullSearch()
expect(qfSpy).toHaveBeenCalledWith([
{ rule_type: FILTER_FULLTEXT_QUERY, value: 'test' },
diff --git a/src-ui/src/app/components/app-frame/global-search/global-search.component.ts b/src-ui/src/app/components/app-frame/global-search/global-search.component.ts
index 50b2cbbbc..ce48c6a47 100644
--- a/src-ui/src/app/components/app-frame/global-search/global-search.component.ts
+++ b/src-ui/src/app/components/app-frame/global-search/global-search.component.ts
@@ -83,36 +83,12 @@ export class GlobalSearchComponent implements OnInit {
private locationStrategy = inject(LocationStrategy)
public DataType = DataType
- private querySignal = signal
(null)
+ readonly query = signal(null)
public queryDebounce: Subject
- private searchResultsSignal = signal(null)
+ readonly searchResults = signal(null)
private currentItemIndex: number = -1
private domIndex: number = -1
- private loadingSignal = signal(false)
-
- public get query(): string {
- return this.querySignal()
- }
-
- public set query(value: string) {
- this.querySignal.set(value)
- }
-
- public get searchResults(): GlobalSearchResult {
- return this.searchResultsSignal()
- }
-
- public set searchResults(value: GlobalSearchResult) {
- this.searchResultsSignal.set(value)
- }
-
- public get loading(): boolean {
- return this.loadingSignal()
- }
-
- public set loading(value: boolean) {
- this.loadingSignal.set(value)
- }
+ readonly loading = signal(false)
@ViewChild('searchInput') searchInput: ElementRef
@ViewChild('resultsDropdown') resultsDropdown: NgbDropdown
@@ -138,7 +114,7 @@ export class GlobalSearchComponent implements OnInit {
distinctUntilChanged()
)
.subscribe((text) => {
- this.query = text
+ this.query.set(text)
if (text) this.search(text)
})
}
@@ -152,10 +128,10 @@ export class GlobalSearchComponent implements OnInit {
}
private search(query: string) {
- this.loading = true
+ this.loading.set(true)
this.searchService.globalSearch(query.trim()).subscribe((results) => {
- this.searchResults = results
- this.loading = false
+ this.searchResults.set(results)
+ this.loading.set(false)
this.resultsDropdown.open()
})
}
@@ -282,8 +258,8 @@ export class GlobalSearchComponent implements OnInit {
private reset(close: boolean = false) {
this.queryDebounce.next(null)
- this.query = null
- this.searchResults = null
+ this.query.set(null)
+ this.searchResults.set(null)
this.currentItemIndex = -1
if (close) {
this.resultsDropdown.close()
@@ -318,7 +294,7 @@ export class GlobalSearchComponent implements OnInit {
public searchInputKeyDown(event: KeyboardEvent) {
if (
event.key === 'ArrowDown' &&
- this.searchResults?.total &&
+ this.searchResults()?.total &&
this.resultsDropdown.isOpen()
) {
event.preventDefault()
@@ -326,22 +302,22 @@ export class GlobalSearchComponent implements OnInit {
this.setCurrentItem()
} else if (
event.key === 'ArrowUp' &&
- this.searchResults?.total &&
+ this.searchResults()?.total &&
this.resultsDropdown.isOpen()
) {
event.preventDefault()
- this.currentItemIndex = this.searchResults.total - 1
+ this.currentItemIndex = this.searchResults()?.total - 1
this.setCurrentItem()
} else if (event.key === 'Enter') {
- if (this.searchResults?.total === 1 && this.resultsDropdown.isOpen()) {
+ if (this.searchResults()?.total === 1 && this.resultsDropdown.isOpen()) {
this.primaryButtons.first.nativeElement.click()
this.searchInput.nativeElement.blur()
- } else if (this.query?.length) {
+ } else if (this.query()?.length) {
this.runFullSearch()
this.reset(true)
}
} else if (event.key === 'Escape' && !this.resultsDropdown.isOpen()) {
- if (this.query?.length) {
+ if (this.query()?.length) {
this.reset(true)
} else {
this.searchInput.nativeElement.blur()
@@ -351,14 +327,14 @@ export class GlobalSearchComponent implements OnInit {
public dropdownKeyDown(event: KeyboardEvent) {
if (
- this.searchResults?.total &&
+ this.searchResults()?.total &&
this.resultsDropdown.isOpen() &&
document.activeElement !== this.searchInput.nativeElement
) {
if (event.key === 'ArrowDown') {
event.preventDefault()
event.stopImmediatePropagation()
- if (this.currentItemIndex < this.searchResults.total - 1) {
+ if (this.currentItemIndex < this.searchResults()?.total - 1) {
this.currentItemIndex++
this.setCurrentItem()
} else {
@@ -438,10 +414,10 @@ export class GlobalSearchComponent implements OnInit {
? FILTER_FULLTEXT_QUERY
: FILTER_SIMPLE_TEXT
this.documentService.searchQuery = this.useAdvancedForFullSearch
- ? this.query
+ ? this.query()
: ''
this.documentListViewService.quickFilter([
- { rule_type: ruleType, value: this.query },
+ { rule_type: ruleType, value: this.query() },
])
this.reset(true)
}
diff --git a/src-ui/src/app/components/common/page-header/page-header.component.html b/src-ui/src/app/components/common/page-header/page-header.component.html
index 6ee0388cd..99e1d426b 100644
--- a/src-ui/src/app/components/common/page-header/page-header.component.html
+++ b/src-ui/src/app/components/common/page-header/page-header.component.html
@@ -2,31 +2,31 @@
{{title}}
- @if (id) {
+ @if (id()) {
- @if (copied) {
+ @if (copied()) {
Copied!
} @else {
- ID: {{id}}
+ ID: {{id()}}
}
}
- @if (subTitle) {
- {{subTitle}}
+ @if (subTitle()) {
+ {{subTitle()}}
}
- @if (info) {
+ @if (info()) {
-
- @if (infoLink) {
- Read more
+
+ @if (infoLink()) {
+ Read more
}
}
- @if (loading) {
+ @if (loading()) {
}
diff --git a/src-ui/src/app/components/common/page-header/page-header.component.ts b/src-ui/src/app/components/common/page-header/page-header.component.ts
index 139ca538d..66cef548f 100644
--- a/src-ui/src/app/components/common/page-header/page-header.component.ts
+++ b/src-ui/src/app/components/common/page-header/page-header.component.ts
@@ -1,5 +1,5 @@
import { Clipboard } from '@angular/cdk/clipboard'
-import { Component, Input, inject, signal } from '@angular/core'
+import { Component, Input, inject, input, signal } from '@angular/core'
import { Title } from '@angular/platform-browser'
import { NgbPopoverModule } from '@ng-bootstrap/ng-bootstrap'
import { NgxBootstrapIconsModule } from 'ngx-bootstrap-icons'
@@ -16,83 +16,31 @@ export class PageHeaderComponent {
private titleService = inject(Title)
private clipboard = inject(Clipboard)
- private titleSignal = signal('')
- private idSignal = signal
(undefined)
- private subTitleSignal = signal('')
- private infoSignal = signal(undefined)
- private infoLinkSignal = signal(undefined)
- private loadingSignal = signal(false)
- private copiedSignal = signal(false)
+ readonly id = input(undefined)
+ readonly subTitle = input('')
+ readonly info = input(undefined)
+ readonly infoLink = input(undefined)
+ readonly loading = input(false)
+ readonly copied = signal(false)
private copyTimeout: any
- public get copied(): boolean {
- return this.copiedSignal()
- }
-
- public set copied(copied: boolean) {
- this.copiedSignal.set(copied)
- }
+ private readonly titleSignal = signal('')
@Input()
set title(title: string) {
this.titleSignal.set(title)
- this.titleService.setTitle(`${this.title} - ${environment.appTitle}`)
+ this.titleService.setTitle(`${title} - ${environment.appTitle}`)
}
get title() {
return this.titleSignal()
}
- @Input()
- get id(): number {
- return this.idSignal()
- }
-
- set id(id: number) {
- this.idSignal.set(id)
- }
-
- @Input()
- get subTitle(): string {
- return this.subTitleSignal()
- }
-
- set subTitle(subTitle: string) {
- this.subTitleSignal.set(subTitle)
- }
-
- @Input()
- get info(): string {
- return this.infoSignal()
- }
-
- set info(info: string) {
- this.infoSignal.set(info)
- }
-
- @Input()
- get infoLink(): string {
- return this.infoLinkSignal()
- }
-
- set infoLink(infoLink: string) {
- this.infoLinkSignal.set(infoLink)
- }
-
- @Input()
- get loading(): boolean {
- return this.loadingSignal()
- }
-
- set loading(loading: boolean) {
- this.loadingSignal.set(loading)
- }
-
public copyID() {
- this.copied = this.clipboard.copy(this.id.toString())
+ this.copied.set(this.clipboard.copy(this.id().toString()))
clearTimeout(this.copyTimeout)
this.copyTimeout = setTimeout(() => {
- this.copied = false
+ this.copied.set(false)
}, 3000)
}
}
diff --git a/src-ui/src/app/components/common/share-links-dialog/share-links-dialog.component.html b/src-ui/src/app/components/common/share-links-dialog/share-links-dialog.component.html
index e41a897a8..f13202cfd 100644
--- a/src-ui/src/app/components/common/share-links-dialog/share-links-dialog.component.html
+++ b/src-ui/src/app/components/common/share-links-dialog/share-links-dialog.component.html
@@ -1,15 +1,15 @@