Feature: global search, keyboard shortcuts / hotkey support (#6449)

This commit is contained in:
shamoon
2024-05-02 09:15:56 -07:00
committed by GitHub
parent 40289cd714
commit c6e7d06bb7
51 changed files with 2970 additions and 683 deletions

View File

@@ -6,10 +6,13 @@ import { Subscription } from 'rxjs'
import { TestBed } from '@angular/core/testing'
import { environment } from 'src/environments/environment'
import { SearchService } from './search.service'
import { SettingsService } from '../settings.service'
import { SETTINGS_KEYS } from 'src/app/data/ui-settings'
let httpTestingController: HttpTestingController
let service: SearchService
let subscription: Subscription
let settingsService: SettingsService
const endpoint = 'search/autocomplete'
describe('SearchService', () => {
@@ -20,6 +23,7 @@ describe('SearchService', () => {
})
httpTestingController = TestBed.inject(HttpTestingController)
settingsService = TestBed.inject(SettingsService)
service = TestBed.inject(SearchService)
})
@@ -36,4 +40,18 @@ describe('SearchService', () => {
)
expect(req.request.method).toEqual('GET')
})
it('should call correct api endpoint on globalSearch', () => {
const query = 'apple'
service.globalSearch(query).subscribe()
httpTestingController.expectOne(
`${environment.apiBaseUrl}search/?query=${query}`
)
settingsService.set(SETTINGS_KEYS.SEARCH_DB_ONLY, true)
subscription = service.globalSearch(query).subscribe()
httpTestingController.expectOne(
`${environment.apiBaseUrl}search/?query=${query}&db_only=true`
)
})
})

View File

@@ -1,15 +1,48 @@
import { HttpClient, HttpParams } from '@angular/common/http'
import { Injectable } from '@angular/core'
import { Observable } from 'rxjs'
import { map } from 'rxjs/operators'
import { environment } from 'src/environments/environment'
import { DocumentService } from './document.service'
import { Document } from 'src/app/data/document'
import { DocumentType } from 'src/app/data/document-type'
import { Correspondent } from 'src/app/data/correspondent'
import { CustomField } from 'src/app/data/custom-field'
import { Group } from 'src/app/data/group'
import { MailAccount } from 'src/app/data/mail-account'
import { MailRule } from 'src/app/data/mail-rule'
import { StoragePath } from 'src/app/data/storage-path'
import { Tag } from 'src/app/data/tag'
import { User } from 'src/app/data/user'
import { Workflow } from 'src/app/data/workflow'
import { SettingsService } from '../settings.service'
import { SETTINGS_KEYS } from 'src/app/data/ui-settings'
import { SavedView } from 'src/app/data/saved-view'
export interface GlobalSearchResult {
total: number
documents: Document[]
saved_views: SavedView[]
correspondents: Correspondent[]
document_types: DocumentType[]
storage_paths: StoragePath[]
tags: Tag[]
users: User[]
groups: Group[]
mail_accounts: MailAccount[]
mail_rules: MailRule[]
custom_fields: CustomField[]
workflows: Workflow[]
}
@Injectable({
providedIn: 'root',
})
export class SearchService {
constructor(private http: HttpClient) {}
public readonly searchResultObjectLimit: number = 3 // documents/views.py GlobalSearchView > OBJECT_LIMIT
constructor(
private http: HttpClient,
private settingsService: SettingsService
) {}
autocomplete(term: string): Observable<string[]> {
return this.http.get<string[]>(
@@ -17,4 +50,19 @@ export class SearchService {
{ params: new HttpParams().set('term', term) }
)
}
globalSearch(query: string): Observable<GlobalSearchResult> {
let params = new HttpParams().set('query', query)
if (this.searchDbOnly) {
params = params.set('db_only', true)
}
return this.http.get<GlobalSearchResult>(
`${environment.apiBaseUrl}search/`,
{ params }
)
}
public get searchDbOnly(): boolean {
return this.settingsService.get(SETTINGS_KEYS.SEARCH_DB_ONLY)
}
}