Skip to content

Commit 53e2aa6

Browse files
committed
in progress(plan)
Signed-off-by: Johnny Mariéthoz <Johnny.Mariethoz@rero.ch>
1 parent 20599f6 commit 53e2aa6

20 files changed

+1507
-977
lines changed

projects/rero/ng-core/src/lib/model/record.interface.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ export interface Aggregation {
137137
bucketSize: any;
138138
value: { buckets: any[] };
139139
expanded: boolean;
140+
included?: boolean;
140141
loaded?: boolean;
141142
doc_count: number;
142143
type?: string;

projects/rero/ng-core/src/lib/record/component/search/record-search-page.component.spec.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -224,8 +224,7 @@ describe('RecordSearchPageComponent', () => {
224224

225225
fixture.detectChanges();
226226
tick(100);
227-
const updatedParams = component.store.searchParams();
228-
expect(updatedParams.q).toBe('new search');
227+
expect(component.store.q()).toBe('new search');
229228
}));
230229

231230

@@ -371,7 +370,7 @@ describe('RecordSearchPageComponent', () => {
371370
tick(200);
372371
fixture.detectChanges();
373372
// Store should still have valid state
374-
expect(component.store.searchParams()).toBeDefined();
373+
expect(component.store.q()).toBeDefined();
375374
expect(component.store.currentType()).toBeDefined();
376375
}));
377376

@@ -386,7 +385,7 @@ describe('RecordSearchPageComponent', () => {
386385
tick(200);
387386
fixture.detectChanges();
388387
// Should handle gracefully - the paramMapToSearchParams function should handle this
389-
expect(component.store.searchParams()).toBeDefined();
388+
expect(component.store.q()).toBeDefined();
390389
}));
391390
});
392391
});

projects/rero/ng-core/src/lib/record/component/search/record-search-page.component.ts

Lines changed: 34 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,14 @@
1515
* along with this program. If not, see <http://www.gnu.org/licenses/>.
1616
*/
1717
import { Component, inject, effect, untracked } from '@angular/core';
18+
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
1819
import { ActivatedRoute, Router } from '@angular/router';
19-
import { combineLatest, map } from 'rxjs';
20+
import { map } from 'rxjs';
2021
import { paramMapToSearchParams, searchParamsToUrlParams, shallowEqual } from '../../record-search-utils';
2122
import { RecordSearchStore } from './store/record-search.store';
2223
import { RecordUiService } from '../../service/record-ui/record-ui.service';
23-
import { DEFAULT_SEARCH_PARAMS } from './store/features/with-search-params.feature';
2424
import { RecordSearchComponent } from './record-search/record-search.component';
25+
import { SearchParams } from '../../model';
2526

2627
@Component({
2728
selector: 'ng-core-record-search-page',
@@ -37,27 +38,26 @@ export class RecordSearchPageComponent {
3738

3839
readonly store = inject(RecordSearchStore);
3940

40-
/**
41-
* 1. Source Stream: The URL (Observable).
42-
* Combines Query Params and Path Params into a single SearchParams object.
43-
*/
44-
private readonly searchParamsFromUrl$ = combineLatest([
45-
this.route.queryParamMap,
46-
this.route.paramMap.pipe(map(p => p.get('type')))
47-
]).pipe(
48-
map(([paramMap, currentType]) => ({
49-
currentType: currentType || DEFAULT_SEARCH_PARAMS.currentType,
50-
...paramMapToSearchParams(paramMap)
51-
}))
52-
);
53-
5441
constructor() {
5542
/**
56-
* A. Sync URL -> Store
57-
* We "pipe" the URL observable into the store's rxMethod.
58-
* No manual subscribe or DestroyRef management needed here.
43+
* A1. Sync URL path param :type -> currentType (via updateCurrentType)
44+
*/
45+
this.route.paramMap.pipe(
46+
map(p => p.get('type') || ''),
47+
takeUntilDestroyed(),
48+
).subscribe(type => {
49+
if (type) {
50+
this.store.updateCurrentType(type);
51+
}
52+
});
53+
/**
54+
* A2. Sync URL query params -> searchParams (via syncUrlParams rxMethod)
5955
*/
60-
this.store.syncUrlParams(this.searchParamsFromUrl$);
56+
this.store.syncUrlParams(
57+
this.route.queryParamMap.pipe(
58+
map(paramMap => paramMapToSearchParams(paramMap))
59+
)
60+
);
6161

6262
/**
6363
* B. Sync Route Data (Static or Resolved data)
@@ -74,20 +74,26 @@ export class RecordSearchPageComponent {
7474
* Reacts whenever the store state changes to update the browser URL.
7575
*/
7676
effect(() => {
77-
const storeParams = this.store.searchParams();
77+
const currentType = this.store.currentType();
78+
// Read individual signals so the effect tracks only the URL-relevant fields
79+
const storeParams: Partial<SearchParams> = {
80+
q: this.store.q(),
81+
page: this.store.page(),
82+
size: this.store.size(),
83+
sort: this.store.sort(),
84+
};
7885

7986
// We use untracked to read current route state without creating dependencies,
8087
// preventing recursive effect triggers.
8188
untracked(() => {
8289
const urlParams = paramMapToSearchParams(this.route.snapshot.queryParamMap);
8390
const currentTypeInUrl = this.route.snapshot.paramMap.get('type');
8491

85-
// Final guard: check if the URL already matches the Store state
86-
const isAlreadyInSync =
87-
shallowEqual(storeParams, { ...urlParams, currentType: currentTypeInUrl });
92+
const paramsInSync = shallowEqual(storeParams, urlParams);
93+
const typeInSync = currentType === currentTypeInUrl;
8894

89-
if (!isAlreadyInSync) {
90-
this.navigate(storeParams);
95+
if (!paramsInSync || !typeInSync) {
96+
this.navigate(currentType, storeParams as SearchParams);
9197
}
9298
});
9399
});
@@ -96,9 +102,9 @@ export class RecordSearchPageComponent {
96102
/**
97103
* Helper method to perform the actual router navigation
98104
*/
99-
private navigate(params: any) {
105+
private navigate(currentType: string, params: SearchParams) {
100106
this.router.navigate(
101-
['..', params.currentType],
107+
['..', currentType],
102108
{
103109
relativeTo: this.route,
104110
queryParams: searchParamsToUrlParams(params, this.store.aggregationsFilters()),

projects/rero/ng-core/src/lib/record/component/search/record-search/record-search.component.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ <h5>{{ availableTypes()[0].label | translate }}</h5>
5252
} @else {
5353
<div class="core:flex core:items-stretch core:w-full">
5454
<div class="core:flex core:items-center core:w-full">
55-
<strong>{{ store.resultsText() | async }}</strong>
55+
<strong>{{ store.resultsText() | translate:{ total: store.total() } }}</strong>
5656
</div>
5757
<div class="core:flex core:items-center core:justify-end core:w-full">
5858
@if (adminMode().can && addStatus().can) {
@@ -67,7 +67,7 @@ <h5>{{ availableTypes()[0].label | translate }}</h5>
6767
@if (config().sortOptions.length) {
6868
<ng-core-menu-sort
6969
class="core:ml-1"
70-
[selectedValue]="store.sort()"
70+
[selectedValue]="store.activeSort()"
7171
[config]="sortMenuItems()"
7272
(valueChange)="changeSorting($event)"
7373
/>

projects/rero/ng-core/src/lib/record/component/search/record-search/record-search.component.spec.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,6 @@ describe('RecordSearchComponent', () => {
9393
}
9494
];
9595

96-
const tabViewChangeEventMock = jasmine.createSpyObj('TabViewChangeEvent', ['']);
97-
9896
const route = {
9997
snapshot: {
10098
data: {

projects/rero/ng-core/src/lib/record/component/search/record-search/record-search.component.ts

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ export class RecordSearchComponent {
184184
// // Build aggregations to used.
185185
// // This is a combination of `defaultSearchInputFilters` and persistent aggregation filters.
186186
// const aggregations = new Set(this._extractPersistentAggregationsFilters());
187-
// this.store.aggregationsFilters().forEach((aggregation) => aggregations.add(aggregation));
187+
// this.store.aggregationsFilters.forEach((aggregation) => aggregations.add(aggregation));
188188
// this.store.updateAggregationsFilters(Array.from(aggregations));
189189
}
190190

@@ -209,7 +209,18 @@ export class RecordSearchComponent {
209209
tap(() => {
210210
this.store.updatePage(1);
211211
// Force reload of results after deletion
212-
this.store.fetchRecords({params: this.store.searchParams(), type: this.store.currentType()});
212+
// TODO: force reload event if no params has changed
213+
this.store.fetchRecords({
214+
index: this.store.currentIndex(),
215+
query: this.store.q(),
216+
page: this.store.page(),
217+
itemsPerPage: this.store.size(),
218+
aggregationsFilters: this.store.aggregationsFilters(),
219+
preFilters: this.store.config().preFilters,
220+
sort: this.store.activeSort(),
221+
facets: this.store.facetsParameter(),
222+
headers: this.store.config()?.listHeaders,
223+
});
213224
}),
214225
)
215226
.subscribe();
@@ -236,7 +247,7 @@ export class RecordSearchComponent {
236247
* @param format - export format object
237248
* @return formatted url for an export format.
238249
*/
239-
getExportFormatUrl(format: ExportFormat) {
250+
getExportFormatUrl(format: ExportFormat): string {
240251
const queryParams = Object.keys(this.activatedRoute.snapshot.queryParams);
241252
// TODO: maybe we can use URLSerializer to build query string
242253
const baseUrl = format.endpoint ? format.endpoint : this.apiService.getEndpointByType(this.store.currentIndex());
@@ -300,7 +311,7 @@ export class RecordSearchComponent {
300311
// return item;
301312
// }));
302313
// // If query string is specified, search is processed.
303-
// const q = this.store.q();
314+
// const q = this.store.q;
304315
// if (q) {
305316
// this.searchByQuery(q);
306317
// }

0 commit comments

Comments
 (0)