From a991ec24a47b81bf406449efb552c4fcea31c143 Mon Sep 17 00:00:00 2001 From: rpulkka Date: Mon, 8 Dec 2025 15:19:53 +0200 Subject: [PATCH 01/15] Added columns to archipelago named place table. --- .../named-place/np-choose/np-list/np-list.component.ts | 10 ++++++++++ projects/laji/src/i18n/fi.json | 2 ++ 2 files changed, 12 insertions(+) diff --git a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-list/np-list.component.ts b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-list/np-list.component.ts index 12a437c9b..21195564a 100644 --- a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-list/np-list.component.ts +++ b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-list/np-list.component.ts @@ -110,6 +110,16 @@ export class NpListComponent implements OnDestroy { '$.locality': { label: 'np.locality' }, + '$.alternativeIDs': { + label: 'np.archipelago.alternativeIDs', + cellTemplate: 'labelIDTpl', + width: 100 + }, + '$.tags': { + label: 'np.archipelago.tags', + cellTemplate: 'labelIDTpl', + width: 100 + }, '$.prepopulatedDocument.gatherings[0].invasiveControlOpen': { label: 'np.invasiveControlOpen', cellTemplate: 'boolToStrTpl' diff --git a/projects/laji/src/i18n/fi.json b/projects/laji/src/i18n/fi.json index 1f5bf30ef..e6b8b212e 100644 --- a/projects/laji/src/i18n/fi.json +++ b/projects/laji/src/i18n/fi.json @@ -1093,6 +1093,8 @@ "notification.markAll": "Merkitse nähdyiksi", "notification.title": "Ilmoitukset", "noYear": "vuosi puuttuu", + "np.archipelago.alternativeIDs": "Reitin nimi", + "np.archipelago.tags": "Saaristotyyppi", "np.biogeographicalProvince": "Eliömaakunta", "np.chooseLabel": "Valitse alla olevasta luettelosta", "np.copyAddress": "Kopioi linkki", From 1628790b1b01bcb001a89072b153c24fc85f36b8 Mon Sep 17 00:00:00 2001 From: rpulkka Date: Wed, 10 Dec 2025 12:26:22 +0200 Subject: [PATCH 02/15] Fix filter iteration for nested objects. --- projects/laji/src/app/shared/service/filter.service.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/projects/laji/src/app/shared/service/filter.service.ts b/projects/laji/src/app/shared/service/filter.service.ts index 121d616d8..8f8dd43bc 100644 --- a/projects/laji/src/app/shared/service/filter.service.ts +++ b/projects/laji/src/app/shared/service/filter.service.ts @@ -70,7 +70,7 @@ export class FilterService { HaystackKey extends string, HaystackValue extends FilterBaseType >( - needle: HaystackValue, haystack: HaystackValue | HaystackObj, properties: HaystackKey[] + needle: HaystackValue, haystack: HaystackValue | HaystackObj, properties?: HaystackKey[] ) { switch (typeof haystack) { case 'string': @@ -93,7 +93,7 @@ export class FilterService { if (typeof obj[i] === 'undefined') { continue; } - if (this.contains(needle, obj[i], properties)) { + if (this.contains(needle, obj[i])) { return true; } } From b4dbf525b1e3c13e769469e1c00a4783b26f229f Mon Sep 17 00:00:00 2001 From: rpulkka Date: Thu, 11 Dec 2025 11:46:39 +0200 Subject: [PATCH 03/15] Added filter and tab -params to named place page. --- .../named-place-wrapper.component.ts | 12 ++++++ .../named-place/named-place.component.html | 8 +++- .../named-place/named-place.component.ts | 40 ++++++++++++++++++- .../np-choose/np-choose.component.html | 4 +- .../np-choose/np-choose.component.ts | 28 +++++++++++++ .../np-choose/np-list/np-list.component.html | 7 ++-- .../np-choose/np-list/np-list.component.ts | 4 +- .../shared/service/project-form.service.ts | 4 ++ 8 files changed, 99 insertions(+), 8 deletions(-) diff --git a/projects/laji/src/app/+project-form/form/named-place/named-place-wrapper/named-place-wrapper.component.ts b/projects/laji/src/app/+project-form/form/named-place/named-place-wrapper/named-place-wrapper.component.ts index 9e43ca99b..8ffeb54b3 100644 --- a/projects/laji/src/app/+project-form/form/named-place/named-place-wrapper/named-place-wrapper.component.ts +++ b/projects/laji/src/app/+project-form/form/named-place/named-place-wrapper/named-place-wrapper.component.ts @@ -10,6 +10,8 @@ import { take } from 'rxjs/operators'; + [activeNP]="data.activeNP?.id" + [filterBy]="data.filterBy" + [tab]="data.tab" + (activePlaceChange)="onActivePlaceChange($event)" + (filterChange)="onFilterChange($event)" + (tabChange)="onTabChange($event)"> (); @Output() tagsChange = new EventEmitter(); @Output() activeIdChange = new EventEmitter(); + @Output() filterChange = new EventEmitter(); + @Output() tabChange = new EventEmitter(); @Output() use = new EventEmitter(); @Output() edit = new EventEmitter(); @Output() create = new EventEmitter(); @@ -89,6 +101,8 @@ export class NamedPlaceComponent implements OnInit, OnDestroy { private updateFromInput!: Subscription; private documentForm$ = new BehaviorSubject(undefined); private activeNP$ = new BehaviorSubject(undefined); + private filterBy$ = new BehaviorSubject(undefined); + private tab$ = new BehaviorSubject(undefined); private municipality$ = new BehaviorSubject(undefined); private birdAssociationArea$ = new BehaviorSubject(undefined); private tags$ = new BehaviorSubject(undefined); @@ -164,7 +178,19 @@ export class NamedPlaceComponent implements OnInit, OnDestroy { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const formRights$ = this.documentForm$.pipe(switchMap(documentForm => this.formPermissionService.getRights(documentForm!))); - this.vm$ = combineLatest(this.documentForm$, placeForm$, this.municipality$, this.birdAssociationArea$, this.tags$, activeNP$, namedPlaces$, user$, formRights$).pipe( + this.vm$ = combineLatest( + this.documentForm$, + placeForm$, + this.municipality$, + this.birdAssociationArea$, + this.tags$, + activeNP$, + this.filterBy$, + this.tab$, + namedPlaces$, + user$, + formRights$ + ).pipe( map(([ documentForm, placeForm, @@ -172,6 +198,8 @@ export class NamedPlaceComponent implements OnInit, OnDestroy { birdAssociationArea, tags, activeNP, + filterBy, + tab, namedPlaces, user, formRights @@ -186,6 +214,8 @@ export class NamedPlaceComponent implements OnInit, OnDestroy { municipality, tags, activeNP, + filterBy, + tab, description: documentForm.options?.namedPlaceOptions?.chooseDescription ?? 'np.defaultDescription', allowEdit: (documentForm?.options?.namedPlaceOptions?.allowAddingPublic || formRights.admin) && !this.readonly, mapOptionsData: NamedPlaceComponent.getMapOptions(documentForm), @@ -271,6 +301,14 @@ export class NamedPlaceComponent implements OnInit, OnDestroy { }); } + onFilterChange(filterBy: string) { + this.filterChange.emit(filterBy); + } + + onTabChange(tab: string) { + this.tabChange.emit(tab); + } + onEdit() { this.activeNP$.pipe(take(1)).subscribe(id => this.edit.emit(id)); } diff --git a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-choose.component.html b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-choose.component.html index afb89e99e..06a87b55b 100644 --- a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-choose.component.html +++ b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-choose.component.html @@ -29,9 +29,11 @@ [placeForm]="placeForm" [listColumnNameMapping]="_documentForm.options?.namedPlaceOptions?.listColumnNameMapping" [activeNP]="findNPIndexById(_activeNP)" + [filterBy]="_filterBy" [formRights]="formRights" [visible]="loadedTabs.getNameFromIdx(activeIndex) === 'list'" - (activePlaceChange)="onActivePlaceChange($event)"> + (activePlaceChange)="onActivePlaceChange($event)" + (filterChange)="onFilterChange($event)"> > diff --git a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-choose.component.ts b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-choose.component.ts index d42e236ac..8d2ccdd5b 100644 --- a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-choose.component.ts +++ b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-choose.component.ts @@ -37,14 +37,17 @@ export class NpChooseComponent implements OnInit, OnChanges { @Input() formRights?: Rights; @Output() activePlaceChange = new EventEmitter(); + @Output() filterChange = new EventEmitter(); @Output() tabChange = new EventEmitter(); sent = this.isSent.bind(this); private seasonStart?: Date; private seasonEnd?: Date; + private queryParamTab?: string; _activeNP?: string; + _filterBy?: string; formOptionToClassName = formOptionToClassName; @@ -59,6 +62,10 @@ export class NpChooseComponent implements OnInit, OnChanges { ngOnChanges(changes: SimpleChanges) { if (changes['documentForm']) { + if (this.queryParamTab !== undefined) { + return; + } + // use named place options if query params do not specify tab if (this._documentForm?.options?.namedPlaceOptions?.startWithMap) { this.activeIndex = this.loadedTabs.getIdxFromName('map'); this.loadedTabs.load(this.activeIndex); @@ -111,6 +118,22 @@ export class NpChooseComponent implements OnInit, OnChanges { this._activeNP = id; } + @Input() set filterBy(id: string|undefined) { + this._filterBy = id; + } + + @Input() set tab(tab: string|undefined) { + this.queryParamTab = tab; + + if (tab) { + const idx = this.loadedTabs.getIdxFromName(tab); + if (idx !== -1) { + this.activeIndex = idx; + this.loadedTabs.load(idx); + } + } + } + private findNPIdByIndex(idx: number) { return this._namedPlaces[idx].id; } @@ -127,6 +150,11 @@ export class NpChooseComponent implements OnInit, OnChanges { this.activePlaceChange.emit(this._activeNP); } + onFilterChange(filterBy: string) { + this.filterBy = filterBy; + this.filterChange.emit(this._filterBy); + } + isSent(np: NamedPlace) { if (this.seasonStart && this.seasonEnd && np?.prepopulatedDocument?.gatheringEvent?.dateBegin) { const dateBegin = new Date(np.prepopulatedDocument.gatheringEvent.dateBegin); diff --git a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-list/np-list.component.html b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-list/np-list.component.html index ae911eb3d..b4da343cb 100644 --- a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-list/np-list.component.html +++ b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-list/np-list.component.html @@ -2,9 +2,10 @@
+ type='text' + placeholder="{{'haseka.submissions.filter' | translate}}" + [value]="filterBy ? filterBy : ''" + (keyup)="updateFilter($event)">
diff --git a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-list/np-list.component.ts b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-list/np-list.component.ts index 21195564a..2ace503e6 100644 --- a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-list/np-list.component.ts +++ b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-list/np-list.component.ts @@ -40,7 +40,6 @@ export class NpListComponent implements OnDestroy { selectionType = SelectionType; showLegendList? = false; multisort? = false; - filterBy?: string; legendList = [ {label: 'Vapaa', color: '#ffffff'}, {label: 'Varattu', color: '#d1c400'}, @@ -61,8 +60,10 @@ export class NpListComponent implements OnDestroy { @ViewChild('dataTable', { static: true }) public datatable!: DatatableComponent; @Output() activePlaceChange = new EventEmitter(); + @Output() filterChange = new EventEmitter(); @Input() activeNP?: number|null; + @Input() filterBy?: string; @Input({ required: true }) height!: string; @Input() listColumnNameMapping?: { [key: string]: string}; @@ -223,6 +224,7 @@ export class NpListComponent implements OnDestroy { updateFilter(event: any) { this.filterBy = event.target.value; + this.filterChange.emit(this.filterBy); } private initData() { diff --git a/projects/laji/src/app/shared/service/project-form.service.ts b/projects/laji/src/app/shared/service/project-form.service.ts index 482299b28..d9c6cc142 100644 --- a/projects/laji/src/app/shared/service/project-form.service.ts +++ b/projects/laji/src/app/shared/service/project-form.service.ts @@ -19,6 +19,8 @@ export interface NamedPlacesQuery { birdAssociationArea?: string; municipality?: string; activeNP?: string; + filterBy?: string; + tab?: string; } export interface NamedPlacesQueryModel { tags?: string[]; @@ -30,6 +32,8 @@ export interface NamedPlacesQueryModel { export interface NamedPlacesRouteData extends NamedPlacesQueryModel { documentForm: Form.SchemaForm; namedPlace?: NamedPlace; + filterBy?: string; + tab?: string; } export interface ExcelFormOptions { From aa3a4e8d8313a10978552681376ddf8b679b7ba5 Mon Sep 17 00:00:00 2001 From: rpulkka Date: Thu, 18 Dec 2025 11:31:36 +0200 Subject: [PATCH 04/15] Apply filter to the np map view + fix scroll to active -logic on datatable. --- .../np-choose/np-choose.component.html | 7 +++-- .../np-choose/np-choose.component.ts | 11 +++++++- .../np-choose/np-list/np-list.component.html | 2 ++ .../np-choose/np-list/np-list.component.ts | 14 ++++++++-- .../np-choose/np-map/np-map.component.ts | 27 ++++++++++-------- .../datatable/datatable.component.ts | 28 +++++++++++++++++-- 6 files changed, 68 insertions(+), 21 deletions(-) diff --git a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-choose.component.html b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-choose.component.html index 06a87b55b..d1a35ef6a 100644 --- a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-choose.component.html +++ b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-choose.component.html @@ -17,12 +17,13 @@ lajiFormOption="options.namedPlaceOptions.reservationUntil" [placeForm]="placeForm" [documentForm]="_documentForm" + [filteredIDs]="filteredIDs" (activePlaceChange)="onActivePlaceChange($event)">
-
+
- > + (filterChange)="onFilterChange($event)" + (filteredIDs)="onFilteredIDsChange($event)">
diff --git a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-choose.component.ts b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-choose.component.ts index 8d2ccdd5b..45a774d36 100644 --- a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-choose.component.ts +++ b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-choose.component.ts @@ -26,6 +26,7 @@ import { formOptionToClassName } from '../../../../shared/directive/project-form export class NpChooseComponent implements OnInit, OnChanges { activeIndex = 0; loadedTabs = new LoadedElementsStore(['list', 'map']); + filteredIDs: string[] = []; height = '600px'; _namedPlaces: ExtendedNamedPlace[] = []; @@ -135,7 +136,11 @@ export class NpChooseComponent implements OnInit, OnChanges { } private findNPIdByIndex(idx: number) { - return this._namedPlaces[idx].id; + if (this.filteredIDs.length === 0) { + return this._namedPlaces[idx]?.id; + } else { + return this.filteredIDs[idx]; + } } findNPIndexById(id?: string) { @@ -155,6 +160,10 @@ export class NpChooseComponent implements OnInit, OnChanges { this.filterChange.emit(this._filterBy); } + onFilteredIDsChange(ids: string[]) { + this.filteredIDs = ids; + } + isSent(np: NamedPlace) { if (this.seasonStart && this.seasonEnd && np?.prepopulatedDocument?.gatheringEvent?.dateBegin) { const dateBegin = new Date(np.prepopulatedDocument.gatheringEvent.dateBegin); diff --git a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-list/np-list.component.html b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-list/np-list.component.html index b4da343cb..8fefc9dbf 100644 --- a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-list/np-list.component.html +++ b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-list/np-list.component.html @@ -16,6 +16,7 @@ #dataTable class="observation-table" (rowSelect)="changeActivePlace($event)" + (filteredIDs)="changeFilteredIDs($event)" [getRowClass]="getRowClass" [virtualScrolling]="true" [clientSideSorting]="true" @@ -31,6 +32,7 @@ [columns]="columns!" [selectionType]="selectionType.single" [preselectedRowIndex]="activeNP!" + [visible]="_visible" >
diff --git a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-list/np-list.component.ts b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-list/np-list.component.ts index 2ace503e6..6514a576b 100644 --- a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-list/np-list.component.ts +++ b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-list/np-list.component.ts @@ -22,6 +22,7 @@ import { DatatableColumn } from '../../../../../shared-modules/datatable/model/d import { DatatableComponent } from '../../../../../shared-modules/datatable/datatable/datatable.component'; import { SelectionType, SortType } from '@achimha/ngx-datatable'; import { NpInfoComponent } from '../../np-info/np-info.component'; +import { DatatableUtil } from '../../../../../shared-modules/datatable/service/datatable-util.service'; @Component({ selector: 'laji-np-list', @@ -47,7 +48,7 @@ export class NpListComponent implements OnDestroy { {label: 'Ilmoitettu', color: '#00aa00'} ]; columnsMetaData: {[columnName: string]: DatatableColumn}; - private _visible?: boolean; + _visible = true; private _visibleTimeout?: Timeout; private _formRights?: Rights; private _documentForm!: Form.SchemaForm; @@ -61,6 +62,7 @@ export class NpListComponent implements OnDestroy { @Output() activePlaceChange = new EventEmitter(); @Output() filterChange = new EventEmitter(); + @Output() filteredIDs = new EventEmitter(); @Input() activeNP?: number|null; @Input() filterBy?: string; @@ -68,7 +70,8 @@ export class NpListComponent implements OnDestroy { @Input() listColumnNameMapping?: { [key: string]: string}; constructor(private cd: ChangeDetectorRef, - private areaNamePipe: AreaNamePipe + private areaNamePipe: AreaNamePipe, + private datatableUtil: DatatableUtil ) { this.columnsMetaData = { '$.alternativeIDs[0]': { @@ -145,6 +148,10 @@ export class NpListComponent implements OnDestroy { this.activePlaceChange.emit(this.data.indexOf(event.row)); } + changeFilteredIDs(event: string[]) { + this.filteredIDs.emit(event); + } + getRowClass(row: any) { const status = row['$._status']; if (status !== 'free') { return status; } @@ -217,7 +224,7 @@ export class NpListComponent implements OnDestroy { this._visibleTimeout = setTimeout(() => { this.datatable.showActiveRow(); this._visibleTimeout = undefined; - }, 10); + }, 100); } this._visible = visibility; } @@ -252,6 +259,7 @@ export class NpListComponent implements OnDestroy { .pipe(take(1))) ).pipe(map(areaLabel => [row, areaLabel]))); } + row['$.id'] = namedPlace.id; results.push(row); } if (municipalities$.length) { diff --git a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-map/np-map.component.ts b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-map/np-map.component.ts index dfe4aa31f..779c8eaac 100644 --- a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-map/np-map.component.ts +++ b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-map/np-map.component.ts @@ -39,7 +39,8 @@ export class NpMapComponent implements OnInit, OnChanges { @Input() reservable?: boolean; @Input() placeForm: any; @Input({ required: true }) documentForm!: Form.SchemaForm; - @Output() activePlaceChange = new EventEmitter(); + @Input() filteredIDs: string[] = []; + @Output() activePlaceChange = new EventEmitter(); visualization?: LajiMapVisualization; listItems: NpInfoRow[] = []; @@ -70,7 +71,7 @@ export class NpMapComponent implements OnInit, OnChanges { } ngOnChanges(changes: SimpleChanges) { - if (changes['namedPlaces']) { + if (changes['namedPlaces'] || changes['filteredIDs']) { this.initMapData(); } if (changes['visible'] && changes['visible'].currentValue === true && this._lastVisibleActiveNP !== this.activeNP) { @@ -192,16 +193,18 @@ export class NpMapComponent implements OnInit, OnChanges { }, featureCollection: { type: 'FeatureCollection', - features: this.namedPlaces.map(np => ({ - type: 'Feature', - geometry: np.geometry, - properties: { - reserved: np._status, - name: np.name, - municipality: np.municipality, - taxon: np.taxonIDs - } - })) + features: this.namedPlaces + .filter(np => this.filteredIDs.length === 0 || this.filteredIDs.includes(np.id)) + .map(np => ({ + type: 'Feature', + geometry: np.geometry, + properties: { + reserved: np._status, + name: np.name, + municipality: np.municipality, + taxon: np.taxonIDs + } + })) }, getPopup: ({featureIdx, feature}: {featureIdx: number; feature: string}, cb: (elem: string | HTMLElement) => void) => { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion diff --git a/projects/laji/src/app/shared-modules/datatable/datatable/datatable.component.ts b/projects/laji/src/app/shared-modules/datatable/datatable/datatable.component.ts index facb9b459..95fe2492a 100644 --- a/projects/laji/src/app/shared-modules/datatable/datatable/datatable.component.ts +++ b/projects/laji/src/app/shared-modules/datatable/datatable/datatable.component.ts @@ -55,12 +55,15 @@ export class DatatableComponent implements AfterViewInit, OnInit, OnChanges, OnD _filterBy?: FilterByType; _height = '100%'; _isFixedHeight = false; + _visible = true; + _pendingScroll = false; @Output() pageChange = new EventEmitter(); @Output() sortChange = new EventEmitter(); @Output() reorder = new EventEmitter(); @Output() datatableSelect = new EventEmitter(); @Output() rowSelect = new EventEmitter(); + @Output() filteredIDs = new EventEmitter(); filterByChange?: Subscription; @@ -201,8 +204,19 @@ export class DatatableComponent implements AfterViewInit, OnInit, OnChanges, OnD if (!this.selected.length) { return; } - if (this.initialized) { + setTimeout(() => { this.showActiveRow(); + }, 100); + } + + @Input() set visible(visible: boolean) { + this._visible = visible; + // If the table becomes visible and there is a pending scroll to active row, do the scroll + if (this._visible && this._pendingScroll) { + this._pendingScroll = false; + setTimeout(() => { + this.showActiveRow(); + }, 100); } } @@ -210,6 +224,11 @@ export class DatatableComponent implements AfterViewInit, OnInit, OnChanges, OnD if (!this.initialized || this._preselectedRowIndex === -1 || !this.datatable || !this.datatable._internalRows) { return; } + // If the table is not visible, postpone scrolling by setting a pending scroll + if (!this._visible) { + this._pendingScroll = true; + return; + } const postSortIndex = (this._rows || []).findIndex((element) => element.preSortIndex === this._preselectedRowIndex); // Calculate relative position of selected row and scroll to it const rowHeight = this.datatable.bodyComponent.rowHeight as number; @@ -239,6 +258,10 @@ export class DatatableComponent implements AfterViewInit, OnInit, OnChanges, OnD this.changeDetectorRef.markForCheck(); }); + if (this._filterBy && this._originalRows) { + this.updateFilteredRows(); + this.changeDetectorRef.markForCheck(); + } } ngAfterViewInit() { @@ -250,7 +273,7 @@ export class DatatableComponent implements AfterViewInit, OnInit, OnChanges, OnD this.initialized = true; // Make sure that preselected row index setter is called after initialization this.showActiveRow(); - }, 10); + }, 100); } } @@ -345,6 +368,7 @@ export class DatatableComponent implements AfterViewInit, OnInit, OnChanges, OnD this._page = 1; this.scrollTo(); this.sortRows(this.sorts); + this.filteredIDs.emit(this._rows?.map(r => r['$.id'])); } private scrollTo(offsetY: number = 0) { From 2a3f5caf06b01d4b8b69938607de81bb2ae9f74d Mon Sep 17 00:00:00 2001 From: rpulkka Date: Thu, 18 Dec 2025 13:50:37 +0200 Subject: [PATCH 05/15] Use visible values on np-list to filter by enum visible names. --- .../np-choose/np-list/np-list.component.ts | 41 +++++++++---------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-list/np-list.component.ts b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-list/np-list.component.ts index 6514a576b..90c5e3072 100644 --- a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-list/np-list.component.ts +++ b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-list/np-list.component.ts @@ -11,7 +11,7 @@ import { import { NamedPlace } from '../../../../../shared/model/NamedPlace'; import { Util } from '../../../../../shared/service/util.service'; import { map, take } from 'rxjs/operators'; -import { forkJoin } from 'rxjs'; +import { forkJoin, Observable } from 'rxjs'; import { AreaNamePipe } from '../../../../../shared/pipe/area-name.pipe'; import { BoolToStringPipe } from '../../../../../shared/pipe/bool-to-string.pipe'; import Timeout = NodeJS.Timeout; @@ -238,35 +238,34 @@ export class NpListComponent implements OnDestroy { if (!this._fields || !this._namedPlaces) { return; } + const results: any[] = []; - const municipalities$ = []; + const observables: Observable[] = []; + for (const namedPlace of this._namedPlaces) { const row: any = {}; + for (const path of this._fields) { - let value = Util.parseJSONPath(namedPlace, path); - if (value && value.length && ( - path === '$.prepopulatedDocument.gatheringEvent.dateBegin' - || path === '$.prepopulatedDocument.gatheringEvent.dateEnd' - )) { - value = value.split('.').reverse().join('-'); - } + const value = Util.parseJSONPath(namedPlace, path); row[path] = value; + const observable = this.datatableUtil.getVisibleValue(value, namedPlace, 'label'); + observables.push( + observable.pipe( + map(visibleValue => { + if (visibleValue && visibleValue.length > 0) { + row[path] = visibleValue; + } + }) + ) + ); } - const municipality = row['$.municipality']; - if (municipality && municipality.length) { - municipalities$.push(forkJoin( - ...municipality.map((_muni: string) => this.areaNamePipe.updateValue(_muni) - .pipe(take(1))) - ).pipe(map(areaLabel => [row, areaLabel]))); - } + row['$.id'] = namedPlace.id; results.push(row); } - if (municipalities$.length) { - forkJoin(...municipalities$).subscribe((municipalityTuples) => { - municipalityTuples.forEach(([row, municipalityLabel]: [any, string[]]) => { - row['$.municipality'] = municipalityLabel.join(', '); - }); + + if (observables.length > 0) { + forkJoin(observables).subscribe(() => { this.data = results; this.cd.markForCheck(); }); From cfde905e1b261ed6c583456b1b5ac6358adadb76 Mon Sep 17 00:00:00 2001 From: rpulkka Date: Thu, 18 Dec 2025 14:26:32 +0200 Subject: [PATCH 06/15] Fix index to id function. --- .../form/named-place/np-choose/np-choose.component.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-choose.component.ts b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-choose.component.ts index 45a774d36..642726141 100644 --- a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-choose.component.ts +++ b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-choose.component.ts @@ -136,11 +136,7 @@ export class NpChooseComponent implements OnInit, OnChanges { } private findNPIdByIndex(idx: number) { - if (this.filteredIDs.length === 0) { - return this._namedPlaces[idx]?.id; - } else { - return this.filteredIDs[idx]; - } + return this._namedPlaces[idx]?.id; } findNPIndexById(id?: string) { From e9afdf0fd5d9905d92cfc3e26cfc559124cde93c Mon Sep 17 00:00:00 2001 From: rpulkka Date: Thu, 18 Dec 2025 15:33:40 +0200 Subject: [PATCH 07/15] Clear active np when it isn't included in filtered places. --- .../form/named-place/np-choose/np-choose.component.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-choose.component.ts b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-choose.component.ts index 642726141..d06a81eb2 100644 --- a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-choose.component.ts +++ b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-choose.component.ts @@ -158,6 +158,10 @@ export class NpChooseComponent implements OnInit, OnChanges { onFilteredIDsChange(ids: string[]) { this.filteredIDs = ids; + if (this._activeNP && !this.filteredIDs.includes(this._activeNP)) { + this._activeNP = undefined; + this.onActivePlaceChange(-1); + } } isSent(np: NamedPlace) { From 70e8f23a7bf82201d6cdf0508704a067c4d8d1d7 Mon Sep 17 00:00:00 2001 From: rpulkka Date: Mon, 22 Dec 2025 10:45:29 +0200 Subject: [PATCH 08/15] Transform selected place's index between all places list and filtered list. --- .../np-choose/np-map/np-map.component.ts | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-map/np-map.component.ts b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-map/np-map.component.ts index 779c8eaac..7397a537a 100644 --- a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-map/np-map.component.ts +++ b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-map/np-map.component.ts @@ -40,7 +40,7 @@ export class NpMapComponent implements OnInit, OnChanges { @Input() placeForm: any; @Input({ required: true }) documentForm!: Form.SchemaForm; @Input() filteredIDs: string[] = []; - @Output() activePlaceChange = new EventEmitter(); + @Output() activePlaceChange = new EventEmitter(); visualization?: LajiMapVisualization; listItems: NpInfoRow[] = []; @@ -81,7 +81,14 @@ export class NpMapComponent implements OnInit, OnChanges { if (this.visible) { this._lastVisibleActiveNP = this.activeNP; } - this.setNewActivePlace(changes['activeNP'].currentValue); + // Transform selected place's index in all places list to index in filtered places list + const fullIdx = changes['activeNP'].currentValue; + if (fullIdx !== undefined && fullIdx !== -1) { + const namedPlace = this.namedPlaces![fullIdx]; + const filteredPlaces = this.namedPlaces!.filter(np => this.filteredIDs.length === 0 || this.filteredIDs.includes(np.id)); + const filteredIdx = filteredPlaces.findIndex(np => np.id === namedPlace.id); + this.setNewActivePlace(filteredIdx); + } } } @@ -185,9 +192,15 @@ export class NpMapComponent implements OnInit, OnChanges { onChange: (events: any) => { events.forEach((e: any) => { if (e.type === 'active') { - this.zone.run(() => { - this.activePlaceChange.emit(e.idx); - }); + // Transform selected place's index in filtered places list to index in all places list before emitting + const filteredPlaces = this.namedPlaces!.filter(np => this.filteredIDs.length === 0 || this.filteredIDs.includes(np.id)); + const selectedPlace = filteredPlaces[e.idx]; + if (selectedPlace) { + const fullIdx = this.namedPlaces!.findIndex(np => np.id === selectedPlace.id); + this.zone.run(() => { + this.activePlaceChange.emit(fullIdx); + }); + } } }); }, From ac0dc2a7eb9343de041d0eb0c40777c099432590 Mon Sep 17 00:00:00 2001 From: rpulkka Date: Mon, 22 Dec 2025 13:15:35 +0200 Subject: [PATCH 09/15] Set active place after map has initialized. --- .../np-choose/np-map/np-map.component.ts | 31 ++++++++++++++----- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-map/np-map.component.ts b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-map/np-map.component.ts index 7397a537a..070f18d5e 100644 --- a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-map/np-map.component.ts +++ b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-map/np-map.component.ts @@ -50,6 +50,7 @@ export class NpMapComponent implements OnInit, OnChanges { private _popupCallback?: (elemOrString: HTMLElement | string) => void; private _zoomOnNextTick = false; private _lastVisibleActiveNP?: number|null; + private _pendingFilteredIdx?: number; private placeColor = '#5294cc'; private placeActiveColor = '#375577'; @@ -73,6 +74,7 @@ export class NpMapComponent implements OnInit, OnChanges { ngOnChanges(changes: SimpleChanges) { if (changes['namedPlaces'] || changes['filteredIDs']) { this.initMapData(); + this.setActivePlaceByFilteredListIndex(this.activeNP ?? undefined); } if (changes['visible'] && changes['visible'].currentValue === true && this._lastVisibleActiveNP !== this.activeNP) { this._zoomOnNextTick = true; @@ -81,14 +83,8 @@ export class NpMapComponent implements OnInit, OnChanges { if (this.visible) { this._lastVisibleActiveNP = this.activeNP; } - // Transform selected place's index in all places list to index in filtered places list const fullIdx = changes['activeNP'].currentValue; - if (fullIdx !== undefined && fullIdx !== -1) { - const namedPlace = this.namedPlaces![fullIdx]; - const filteredPlaces = this.namedPlaces!.filter(np => this.filteredIDs.length === 0 || this.filteredIDs.includes(np.id)); - const filteredIdx = filteredPlaces.findIndex(np => np.id === namedPlace.id); - this.setNewActivePlace(filteredIdx); - } + this.setActivePlaceByFilteredListIndex(fullIdx); } } @@ -97,6 +93,12 @@ export class NpMapComponent implements OnInit, OnChanges { if (popup && this._popupCallback) { this._popupCallback(popup); } + + if (this._pendingFilteredIdx !== undefined) { + this.setNewActivePlace(this._pendingFilteredIdx); + this._pendingFilteredIdx = undefined; + } + if (this._zoomOnNextTick) { this._zoomOnNextTick = false; if (this.activeNP !== undefined && this.activeNP !== -1) { @@ -119,6 +121,21 @@ export class NpMapComponent implements OnInit, OnChanges { } catch (e) {} } + private setActivePlaceByFilteredListIndex(fullIdx?: number | null) { + // Transform selected place's index in all places list to index in filtered places list + if (fullIdx !== undefined && fullIdx !== null && fullIdx !== -1) { + const namedPlace = this.namedPlaces![fullIdx]; + const filteredPlaces = this.namedPlaces!.filter(np => this.filteredIDs.length === 0 || this.filteredIDs.includes(np.id)); + const filteredIdx = filteredPlaces.findIndex(np => np.id === namedPlace.id); + // Apply immediately if map is ready, or store as pending if not + if (this.lajiMap.map) { + this.setNewActivePlace(filteredIdx); + } else { + this._pendingFilteredIdx = filteredIdx; + } + } + } + private initLegend() { if (!this.reservable) { return; From fc1b6bbdc26d4315a14ba7c8354a8fcc570b8acd Mon Sep 17 00:00:00 2001 From: rpulkka Date: Mon, 22 Dec 2025 15:11:58 +0200 Subject: [PATCH 10/15] Do not clear active place if no filters are set. --- .../form/named-place/np-choose/np-choose.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-choose.component.ts b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-choose.component.ts index d06a81eb2..4d8c4ebed 100644 --- a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-choose.component.ts +++ b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-choose.component.ts @@ -158,7 +158,7 @@ export class NpChooseComponent implements OnInit, OnChanges { onFilteredIDsChange(ids: string[]) { this.filteredIDs = ids; - if (this._activeNP && !this.filteredIDs.includes(this._activeNP)) { + if (this._activeNP && this.filteredIDs.length > 0 && !this.filteredIDs.includes(this._activeNP)) { this._activeNP = undefined; this.onActivePlaceChange(-1); } From 5f518a1de7d162ac792aa0ae37c37fd62dc96ae6 Mon Sep 17 00:00:00 2001 From: rpulkka Date: Mon, 5 Jan 2026 13:37:03 +0200 Subject: [PATCH 11/15] Move filter input to np-choose to show it on both tabs (list and map). --- .../named-place/np-choose/np-choose.component.css | 4 ++++ .../named-place/np-choose/np-choose.component.html | 13 ++++++++++++- .../named-place/np-choose/np-choose.component.ts | 4 ++-- .../np-choose/np-list/np-list.component.css | 4 ---- .../np-choose/np-list/np-list.component.html | 11 ----------- .../np-choose/np-list/np-list.component.ts | 6 ------ .../np-choose/np-map/np-map.component.ts | 7 ++++--- 7 files changed, 22 insertions(+), 27 deletions(-) diff --git a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-choose.component.css b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-choose.component.css index d005d92a2..2e6d193e7 100644 --- a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-choose.component.css +++ b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-choose.component.css @@ -20,3 +20,7 @@ .nav a { cursor: pointer; } + +.filterBy { + padding: 15px 0; +} diff --git a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-choose.component.html b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-choose.component.html index d1a35ef6a..b29c05faa 100644 --- a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-choose.component.html +++ b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-choose.component.html @@ -1,4 +1,15 @@
+
+
+
+ +
+
+
@@ -34,7 +46,6 @@ [formRights]="formRights" [visible]="loadedTabs.getNameFromIdx(activeIndex) === 'list'" (activePlaceChange)="onActivePlaceChange($event)" - (filterChange)="onFilterChange($event)" (filteredIDs)="onFilteredIDsChange($event)">
diff --git a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-choose.component.ts b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-choose.component.ts index 4d8c4ebed..219a61cd9 100644 --- a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-choose.component.ts +++ b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-choose.component.ts @@ -151,8 +151,8 @@ export class NpChooseComponent implements OnInit, OnChanges { this.activePlaceChange.emit(this._activeNP); } - onFilterChange(filterBy: string) { - this.filterBy = filterBy; + updateFilter(event: any) { + this._filterBy = event.target.value; this.filterChange.emit(this._filterBy); } diff --git a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-list/np-list.component.css b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-list/np-list.component.css index 440bae8fe..3a610a519 100644 --- a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-list/np-list.component.css +++ b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-list/np-list.component.css @@ -27,7 +27,3 @@ padding: 0; margin: 0; } - -.filterBy { - padding: 15px 0; -} diff --git a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-list/np-list.component.html b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-list/np-list.component.html index 8fefc9dbf..06ad306d7 100644 --- a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-list/np-list.component.html +++ b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-list/np-list.component.html @@ -1,14 +1,3 @@ -
-
-
- -
-
-
diff --git a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-list/np-list.component.ts b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-list/np-list.component.ts index 90c5e3072..23f877305 100644 --- a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-list/np-list.component.ts +++ b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-list/np-list.component.ts @@ -61,7 +61,6 @@ export class NpListComponent implements OnDestroy { @ViewChild('dataTable', { static: true }) public datatable!: DatatableComponent; @Output() activePlaceChange = new EventEmitter(); - @Output() filterChange = new EventEmitter(); @Output() filteredIDs = new EventEmitter(); @Input() activeNP?: number|null; @@ -229,11 +228,6 @@ export class NpListComponent implements OnDestroy { this._visible = visibility; } - updateFilter(event: any) { - this.filterBy = event.target.value; - this.filterChange.emit(this.filterBy); - } - private initData() { if (!this._fields || !this._namedPlaces) { return; diff --git a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-map/np-map.component.ts b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-map/np-map.component.ts index 070f18d5e..b20d0d81c 100644 --- a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-map/np-map.component.ts +++ b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-map/np-map.component.ts @@ -39,6 +39,7 @@ export class NpMapComponent implements OnInit, OnChanges { @Input() reservable?: boolean; @Input() placeForm: any; @Input({ required: true }) documentForm!: Form.SchemaForm; + @Input() filterBy?: string; @Input() filteredIDs: string[] = []; @Output() activePlaceChange = new EventEmitter(); @@ -125,7 +126,7 @@ export class NpMapComponent implements OnInit, OnChanges { // Transform selected place's index in all places list to index in filtered places list if (fullIdx !== undefined && fullIdx !== null && fullIdx !== -1) { const namedPlace = this.namedPlaces![fullIdx]; - const filteredPlaces = this.namedPlaces!.filter(np => this.filteredIDs.length === 0 || this.filteredIDs.includes(np.id)); + const filteredPlaces = this.namedPlaces!.filter(np => !this.filterBy || this.filteredIDs.includes(np.id)); const filteredIdx = filteredPlaces.findIndex(np => np.id === namedPlace.id); // Apply immediately if map is ready, or store as pending if not if (this.lajiMap.map) { @@ -210,7 +211,7 @@ export class NpMapComponent implements OnInit, OnChanges { events.forEach((e: any) => { if (e.type === 'active') { // Transform selected place's index in filtered places list to index in all places list before emitting - const filteredPlaces = this.namedPlaces!.filter(np => this.filteredIDs.length === 0 || this.filteredIDs.includes(np.id)); + const filteredPlaces = this.namedPlaces!.filter(np => !this.filterBy || this.filteredIDs.includes(np.id)); const selectedPlace = filteredPlaces[e.idx]; if (selectedPlace) { const fullIdx = this.namedPlaces!.findIndex(np => np.id === selectedPlace.id); @@ -224,7 +225,7 @@ export class NpMapComponent implements OnInit, OnChanges { featureCollection: { type: 'FeatureCollection', features: this.namedPlaces - .filter(np => this.filteredIDs.length === 0 || this.filteredIDs.includes(np.id)) + .filter(np => !this.filterBy || this.filteredIDs.includes(np.id)) .map(np => ({ type: 'Feature', geometry: np.geometry, From 4eec65ef0eae8a3a2775f8d1551c3171466c739d Mon Sep 17 00:00:00 2001 From: rpulkka Date: Wed, 7 Jan 2026 10:12:35 +0200 Subject: [PATCH 12/15] Use filtered index consistently on np-map. --- .../np-choose/np-map/np-map.component.ts | 38 ++++++++++--------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-map/np-map.component.ts b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-map/np-map.component.ts index b20d0d81c..87e2c5555 100644 --- a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-map/np-map.component.ts +++ b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-map/np-map.component.ts @@ -75,7 +75,6 @@ export class NpMapComponent implements OnInit, OnChanges { ngOnChanges(changes: SimpleChanges) { if (changes['namedPlaces'] || changes['filteredIDs']) { this.initMapData(); - this.setActivePlaceByFilteredListIndex(this.activeNP ?? undefined); } if (changes['visible'] && changes['visible'].currentValue === true && this._lastVisibleActiveNP !== this.activeNP) { this._zoomOnNextTick = true; @@ -85,7 +84,13 @@ export class NpMapComponent implements OnInit, OnChanges { this._lastVisibleActiveNP = this.activeNP; } const fullIdx = changes['activeNP'].currentValue; - this.setActivePlaceByFilteredListIndex(fullIdx); + const filteredIdx = this.getFilteredIdx(fullIdx); + // Apply immediately if map is ready, or store as pending if not + if (this.lajiMap.map) { + this.setNewActivePlace(filteredIdx); + } else { + this._pendingFilteredIdx = filteredIdx; + } } } @@ -114,29 +119,26 @@ export class NpMapComponent implements OnInit, OnChanges { } } - private setNewActivePlace(newActive: number) { - if (!this.lajiMap.map) { return; } - - try { - this.lajiMap.map.setActive(this.lajiMap.map.getLayerByIdxTuple([0, newActive])); - } catch (e) {} - } - - private setActivePlaceByFilteredListIndex(fullIdx?: number | null) { + private getFilteredIdx(fullIdx: any): number { // Transform selected place's index in all places list to index in filtered places list if (fullIdx !== undefined && fullIdx !== null && fullIdx !== -1) { const namedPlace = this.namedPlaces![fullIdx]; const filteredPlaces = this.namedPlaces!.filter(np => !this.filterBy || this.filteredIDs.includes(np.id)); const filteredIdx = filteredPlaces.findIndex(np => np.id === namedPlace.id); - // Apply immediately if map is ready, or store as pending if not - if (this.lajiMap.map) { - this.setNewActivePlace(filteredIdx); - } else { - this._pendingFilteredIdx = filteredIdx; - } + return filteredIdx; + } else { + return -1; } } + private setNewActivePlace(newActive: number) { + if (!this.lajiMap.map) { return; } + + try { + this.lajiMap.map.setActive(this.lajiMap.map.getLayerByIdxTuple([0, newActive])); + } catch (e) {} + } + private initLegend() { if (!this.reservable) { return; @@ -243,7 +245,7 @@ export class NpMapComponent implements OnInit, OnChanges { this._popupCallback = cb; this.cdr.markForCheck(); }, - activeIdx: this.activeNP, + activeIdx: this.getFilteredIdx(this.activeNP), cluster: mapCluster }; } catch (e) { } From be731701b43571529a203eb1b7c5688e3214efe2 Mon Sep 17 00:00:00 2001 From: rpulkka Date: Wed, 7 Jan 2026 10:22:59 +0200 Subject: [PATCH 13/15] Clear active named place when it doesn't match the filter. --- .../form/named-place/np-choose/np-choose.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-choose.component.ts b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-choose.component.ts index 219a61cd9..f49694d1b 100644 --- a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-choose.component.ts +++ b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-choose.component.ts @@ -158,7 +158,7 @@ export class NpChooseComponent implements OnInit, OnChanges { onFilteredIDsChange(ids: string[]) { this.filteredIDs = ids; - if (this._activeNP && this.filteredIDs.length > 0 && !this.filteredIDs.includes(this._activeNP)) { + if (this._activeNP && !this.filteredIDs.includes(this._activeNP)) { this._activeNP = undefined; this.onActivePlaceChange(-1); } From 74e2651c3f587cdac081d95da94321dab856f72e Mon Sep 17 00:00:00 2001 From: rpulkka Date: Wed, 7 Jan 2026 12:15:59 +0200 Subject: [PATCH 14/15] Increased np-choose map height. --- .../form/named-place/np-choose/np-choose.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-choose.component.ts b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-choose.component.ts index f49694d1b..d1b0318fc 100644 --- a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-choose.component.ts +++ b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-choose.component.ts @@ -105,7 +105,7 @@ export class NpChooseComponent implements OnInit, OnChanges { updateHeight() { if (this.platformService.isBrowser) { - this.height = Math.min(window.innerHeight - 70, 490) + 'px'; + this.height = Math.min(window.innerHeight - 70, 600) + 'px'; } } From 2e739693f582e12a582898f5c4719809fec26c69 Mon Sep 17 00:00:00 2001 From: rpulkka Date: Tue, 13 Jan 2026 14:17:14 +0200 Subject: [PATCH 15/15] Use tap instead of map for transforming visible values. --- .../form/named-place/np-choose/np-list/np-list.component.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-list/np-list.component.ts b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-list/np-list.component.ts index 23f877305..782f76814 100644 --- a/projects/laji/src/app/+project-form/form/named-place/np-choose/np-list/np-list.component.ts +++ b/projects/laji/src/app/+project-form/form/named-place/np-choose/np-list/np-list.component.ts @@ -10,7 +10,7 @@ import { } from '@angular/core'; import { NamedPlace } from '../../../../../shared/model/NamedPlace'; import { Util } from '../../../../../shared/service/util.service'; -import { map, take } from 'rxjs/operators'; +import { tap } from 'rxjs/operators'; import { forkJoin, Observable } from 'rxjs'; import { AreaNamePipe } from '../../../../../shared/pipe/area-name.pipe'; import { BoolToStringPipe } from '../../../../../shared/pipe/bool-to-string.pipe'; @@ -245,7 +245,7 @@ export class NpListComponent implements OnDestroy { const observable = this.datatableUtil.getVisibleValue(value, namedPlace, 'label'); observables.push( observable.pipe( - map(visibleValue => { + tap(visibleValue => { if (visibleValue && visibleValue.length > 0) { row[path] = visibleValue; }