diff --git a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/components/dossier-details-stats/dossier-details-stats.component.ts b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/components/dossier-details-stats/dossier-details-stats.component.ts
index d52811feb..c09b132df 100644
--- a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/components/dossier-details-stats/dossier-details-stats.component.ts
+++ b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/components/dossier-details-stats/dossier-details-stats.component.ts
@@ -4,7 +4,7 @@ import { Dossier, DossierAttributeWithValue, DossierTemplate } from '@red/domain
import { DossiersDialogService } from '../../../../services/dossiers-dialog.service';
import { DossiersService } from '@services/entity-services/dossiers.service';
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
-import { FilesService } from '../../../../../../services/entity-services/files.service';
+import { FilesService } from '@services/entity-services/files.service';
import { Observable } from 'rxjs';
import { distinctUntilChanged, map, switchMap } from 'rxjs/operators';
diff --git a/apps/red-ui/src/app/modules/dossier/screens/search-screen/search-screen.component.html b/apps/red-ui/src/app/modules/dossier/screens/search-screen/search-screen.component.html
index a6be19bf0..768955d41 100644
--- a/apps/red-ui/src/app/modules/dossier/screens/search-screen/search-screen.component.html
+++ b/apps/red-ui/src/app/modules/dossier/screens/search-screen/search-screen.component.html
@@ -47,9 +47,7 @@
{{ 'search-screen.missing' | translate }}: {{ term }}. {{ 'search-screen.must-contain' | translate }}:
- {{ term }}
diff --git a/apps/red-ui/src/app/modules/dossier/screens/search-screen/search-screen.component.ts b/apps/red-ui/src/app/modules/dossier/screens/search-screen/search-screen.component.ts
index 7f63f7a04..c409a94dc 100644
--- a/apps/red-ui/src/app/modules/dossier/screens/search-screen/search-screen.component.ts
+++ b/apps/red-ui/src/app/modules/dossier/screens/search-screen/search-screen.component.ts
@@ -1,7 +1,6 @@
-import { Component, forwardRef, Injector, OnDestroy } from '@angular/core';
+import { ChangeDetectionStrategy, Component, forwardRef, Injector, OnDestroy } from '@angular/core';
import {
DefaultListingServices,
- IListable,
keyChecker,
List,
ListingComponent,
@@ -10,8 +9,8 @@ import {
SearchPositions,
TableColumnConfig,
} from '@iqser/common-ui';
-import { BehaviorSubject, Observable } from 'rxjs';
-import { debounceTime, map, skip, switchMap, tap } from 'rxjs/operators';
+import { merge, Observable } from 'rxjs';
+import { debounceTime, map, startWith, switchMap, tap } from 'rxjs/operators';
import { ActivatedRoute, Router } from '@angular/router';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { fileStatusTranslations } from '../../translations/file-status-translations';
@@ -19,44 +18,38 @@ import { TranslateService } from '@ngx-translate/core';
import { RouterHistoryService } from '@services/router-history.service';
import { DossiersService } from '@services/entity-services/dossiers.service';
import { PlatformSearchService } from '../../shared/services/platform-search.service';
-import { IMatchedDocument, ISearchResponse } from '@red/domain';
+import { IMatchedDocument, ISearchInput, ISearchListItem, ISearchResponse } from '@red/domain';
-interface ListItem extends IListable {
- readonly dossierId: string;
- readonly filename: string;
- readonly unmatched: List | null;
- readonly highlights: Record;
- readonly routerLink: string;
- readonly status: string;
- readonly dossierName: string;
- readonly numberOfPages: number;
-}
-
-interface SearchInput {
- readonly query: string;
- readonly dossierIds?: List;
+function toSearchInput(query: string, dossierIds: List | string): ISearchInput {
+ return {
+ query,
+ dossierIds: dossierIds ? (typeof dossierIds === 'string' ? [dossierIds] : dossierIds) : [],
+ };
}
@Component({
templateUrl: './search-screen.component.html',
styleUrls: ['./search-screen.component.scss'],
providers: [...DefaultListingServices, { provide: ListingComponent, useExisting: forwardRef(() => SearchScreenComponent) }],
+ changeDetection: ChangeDetectionStrategy.OnPush,
})
-export class SearchScreenComponent extends ListingComponent implements OnDestroy {
+export class SearchScreenComponent extends ListingComponent implements OnDestroy {
readonly fileStatusTranslations = fileStatusTranslations;
readonly searchPositions = SearchPositions;
readonly tableHeaderLabel = _('search-screen.table-header');
- readonly tableColumnConfigs: TableColumnConfig[] = [
+ readonly tableColumnConfigs: TableColumnConfig[] = [
{ label: _('search-screen.cols.document'), width: '2fr' },
{ label: _('search-screen.cols.status') },
{ label: _('search-screen.cols.dossier') },
{ label: _('search-screen.cols.pages'), width: 'auto' },
];
- readonly search$ = new BehaviorSubject(null);
- readonly searchResults$: Observable = this.search$.asObservable().pipe(
+
+ readonly searchResults$ = merge(this._searchChanged$, this._filtersChanged$).pipe(
+ startWith(this._routeQuery),
tap(() => this._loadingService.start()),
- switchMap(query => this._search(query)),
+ tap(value => this.updateNavigation(value.query)),
+ switchMap(query => this._platformSearchService.search(query)),
map(searchResult => this._toMatchedDocuments(searchResult)),
map(docs => this._toListItems(docs)),
tap(result => this.entitiesService.setEntities(result)),
@@ -76,6 +69,7 @@ export class SearchScreenComponent extends ListingComponent implements
super(_injector);
this.searchService.skip = true;
+ const dossierId = _activatedRoute.snapshot.queryParamMap.get('dossierId');
this.filterService.addFilterGroups([
{
slug: 'dossiers',
@@ -87,57 +81,53 @@ export class SearchScreenComponent extends ListingComponent implements
new NestedFilter({
id: dossier.id,
label: dossier.dossierName,
+ checked: dossier.id === dossierId,
}),
),
checker: keyChecker('dossierId'),
},
]);
-
- this.addSubscription = _activatedRoute.queryParamMap
- .pipe(map(value => ({ query: value.get('query'), dossierId: value.get('dossierId') })))
- .subscribe(mappedValue => this._updateValues(mappedValue));
-
- this.addSubscription = this.searchService.valueChanges$.pipe(debounceTime(300)).subscribe(value => this.updateNavigation(value));
-
- this.addSubscription = this.filterService.filterGroups$.pipe(skip(1)).subscribe(group => {
- const dossierIds = group[0].filters.filter(v => v.checked).map(v => v.id);
- this.search$.next({ query: this.searchService.searchValue, dossierIds: dossierIds });
- });
}
- updateNavigation(query: string, mustContain?: string): void {
- const newQuery = query?.replace(mustContain, `"${mustContain}"`);
- const queryParams = newQuery && newQuery !== '' ? { query: newQuery } : {};
- this._router.navigate([], { queryParams }).then();
+ private get _searchChanged$(): Observable {
+ return this.searchService.valueChanges$.pipe(
+ debounceTime(300),
+ map(value => ({ query: value, dossierIds: [] })),
+ );
}
- private _search(searchInput: SearchInput): Observable {
- return this._platformSearchService.search({
- dossierIds: [...searchInput.dossierIds],
- queryString: searchInput.query ?? '',
- page: 1,
- returnSections: false,
- pageSize: 300,
- });
+ private get _filtersChanged$() {
+ return this.filterService.filterGroups$.pipe(
+ map(groups => groups[0].filters.filter(v => v.checked).map(v => v.id)),
+ map(dossierIds => toSearchInput(this.searchService.searchValue, dossierIds)),
+ );
}
- private _updateValues({ query, dossierId }: { readonly query: string; readonly dossierId: string }) {
- if (dossierId) {
- this.filterService.toggleFilter('dossiers', dossierId);
- }
+ private get _routeQuery(): ISearchInput {
+ const query = this._activatedRoute.snapshot.queryParamMap.get('query');
+ const dossierId = this._activatedRoute.snapshot.queryParamMap.get('dossierId');
this.searchService.searchValue = query;
- this.search$.next({ query, dossierIds: dossierId ? [dossierId] : [] });
+ return { query, dossierIds: dossierId ? [dossierId] : [] };
+ }
+
+ updateNavigation(query: string) {
+ return this._router.navigate([], { queryParams: { query } });
+ }
+
+ mustContain(value: string) {
+ const newQuery = this.searchService.searchValue.replace(value, `"${value}"`);
+ this.searchService.searchValue = newQuery ?? '';
}
private _toMatchedDocuments({ matchedDocuments }: ISearchResponse): IMatchedDocument[] {
return matchedDocuments.filter(doc => doc.score > 0 && doc.matchedTerms.length > 0);
}
- private _toListItems(matchedDocuments: IMatchedDocument[]): ListItem[] {
+ private _toListItems(matchedDocuments: IMatchedDocument[]): ISearchListItem[] {
return matchedDocuments.map(document => this._toListItem(document)).filter(value => value);
}
- private _toListItem({ dossierId, fileId, unmatchedTerms, highlights }: IMatchedDocument): ListItem {
+ private _toListItem({ dossierId, fileId, unmatchedTerms, highlights, score }: IMatchedDocument): ISearchListItem {
const file = this._dossiersService.find(dossierId, fileId);
if (!file) {
return undefined;
@@ -152,7 +142,7 @@ export class SearchScreenComponent extends ListingComponent implements
numberOfPages: file.numberOfPages,
dossierName: this._dossiersService.find(dossierId).dossierName,
filename: file.filename,
- searchKey: file.filename,
+ searchKey: score.toString(),
routerLink: `/main/dossiers/${dossierId}/file/${fileId}`,
};
}
diff --git a/apps/red-ui/src/app/modules/dossier/shared/services/platform-search.service.ts b/apps/red-ui/src/app/modules/dossier/shared/services/platform-search.service.ts
index 1eb744b27..19c11d681 100644
--- a/apps/red-ui/src/app/modules/dossier/shared/services/platform-search.service.ts
+++ b/apps/red-ui/src/app/modules/dossier/shared/services/platform-search.service.ts
@@ -1,6 +1,6 @@
import { Injectable, Injector } from '@angular/core';
import { GenericService } from '@iqser/common-ui';
-import { ISearchRequest, ISearchResponse } from '@red/domain';
+import { ISearchInput, ISearchRequest, ISearchResponse } from '@red/domain';
@Injectable()
export class PlatformSearchService extends GenericService {
@@ -8,7 +8,13 @@ export class PlatformSearchService extends GenericService {
super(_injector, 'search');
}
- search(body: ISearchRequest) {
- return this._post(body);
+ search({ dossierIds, query }: ISearchInput) {
+ return this._post({
+ dossierIds,
+ queryString: query ?? '',
+ page: 1,
+ returnSections: false,
+ pageSize: 300,
+ } as ISearchRequest);
}
}
diff --git a/libs/red-domain/src/lib/search/index.ts b/libs/red-domain/src/lib/search/index.ts
index 78ecaf160..536d4fccf 100644
--- a/libs/red-domain/src/lib/search/index.ts
+++ b/libs/red-domain/src/lib/search/index.ts
@@ -2,3 +2,5 @@ export * from './matched-document';
export * from './matched-section';
export * from './search.request';
export * from './search.response';
+export * from './search-list-item';
+export * from './search-input';
diff --git a/libs/red-domain/src/lib/search/search-input.ts b/libs/red-domain/src/lib/search/search-input.ts
new file mode 100644
index 000000000..597b6391f
--- /dev/null
+++ b/libs/red-domain/src/lib/search/search-input.ts
@@ -0,0 +1,6 @@
+import { List } from '@iqser/common-ui';
+
+export interface ISearchInput {
+ readonly query: string;
+ readonly dossierIds?: List;
+}
diff --git a/libs/red-domain/src/lib/search/search-list-item.ts b/libs/red-domain/src/lib/search/search-list-item.ts
new file mode 100644
index 000000000..c1b2b700b
--- /dev/null
+++ b/libs/red-domain/src/lib/search/search-list-item.ts
@@ -0,0 +1,12 @@
+import { IListable, List } from '@iqser/common-ui';
+
+export interface ISearchListItem extends IListable {
+ readonly dossierId: string;
+ readonly filename: string;
+ readonly unmatched: List | null;
+ readonly highlights: Record;
+ readonly routerLink: string;
+ readonly status: string;
+ readonly dossierName: string;
+ readonly numberOfPages: number;
+}