Skip to content

Commit 5964a82

Browse files
committed
Add config for available copy layers
1 parent 76d2d4a commit 5964a82

File tree

10 files changed

+172
-33
lines changed

10 files changed

+172
-33
lines changed

projects/admin-core/assets/locale/messages.admin-core.de.xlf

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@
1010
<source>Single-layer filter</source>
1111
<target>Einzel-Ebenen-Filter</target>
1212
</trans-unit>
13+
<trans-unit id="admin-core.application-metadata.created" datatype="html">
14+
<source>Created by <x id="INTERPOLATION" equiv-text="{{ application.createdBy }}"/> at <x id="INTERPOLATION_1" equiv-text="{{ application.createdDate | date:&apos;medium&apos; }}"/></source>
15+
<target>Erstellt von <x id="INTERPOLATION" equiv-text="{{ application.createdBy }} at {{ application.createdDate | date:&apos;medium&apos; }} | date:&apos;medium&apos; }}"/></target>
16+
</trans-unit>
17+
<trans-unit id="admin-core.application-metadata.updated" datatype="html">
18+
<source>Last updated by <x id="INTERPOLATION" equiv-text="{{ application.lastModifiedBy }}"/> at <x id="INTERPOLATION_1" equiv-text="{{ application.lastModifiedDate | date:&apos;medium&apos; }}"/></source>
19+
<target>Zuletzt aktualisiert von <x id="INTERPOLATION" equiv-text="{{ application.lastModifiedBy }} at {{ application.lastModifiedBy | date:&apos;medium&apos; }}"/></target>
20+
</trans-unit>
1321
<trans-unit id="admin-core.application.add-application" datatype="html">
1422
<source>Add application</source>
1523
<target>Anwendung hinzufügen</target>
@@ -142,6 +150,10 @@
142150
<source>Copy application <x id="INTERPOLATION" equiv-text="{{data.application.title}}"/></source>
143151
<target>Anwendung kopieren <x id="INTERPOLATION" equiv-text="{{data.application.title}}"/></target>
144152
</trans-unit>
153+
<trans-unit id="admin-core.application.copy-layers-info" datatype="html">
154+
<source>Select one or more layers that are available for copying features from. If no layers are selected, all layers will be available. Note that incompatible layer geometry types may prevent successful copying.</source>
155+
<target>Wählen Sie eine oder mehrere Ebenen aus, von denen Features kopiert werden können. Wenn keine Ebenen ausgewählt sind, stehen alle Ebenen zur Verfügung. Beachten Sie, dass inkompatible Geometrietypen der Ebenen ein erfolgreiches Kopieren verhindern können.</target>
156+
</trans-unit>
145157
<trans-unit id="admin-core.application.create-application" datatype="html">
146158
<source>Create application</source>
147159
<target>Anwendung erstellen</target>
@@ -2413,14 +2425,6 @@
24132425
<source>Valid until</source>
24142426
<target>Gültig bis</target>
24152427
</trans-unit>
2416-
<trans-unit id="admin-core.application-metadata.created" datatype="html">
2417-
<source>Created by <x id="INTERPOLATION" equiv-text="{{ application.createdBy }} at {{ application.createdDate | date:&apos;medium&apos; }}"/></source>
2418-
<target>Erstellt von <x id="INTERPOLATION" equiv-text="{{ application.createdBy }} at {{ application.createdDate | date:'medium' }} | date:&apos;medium&apos; }}"/></target>
2419-
</trans-unit>
2420-
<trans-unit id="admin-core.application-metadata.updated" datatype="html">
2421-
<source>Last updated by <x id="INTERPOLATION" equiv-text="{{ application.lastModifiedBy }} at {{ application.lastModifiedBy | date:&apos;medium&apos; }}"/></source>
2422-
<target>Zuletzt aktualisiert von <x id="INTERPOLATION" equiv-text="{{ application.lastModifiedBy }} at {{ application.lastModifiedBy | date:&apos;medium&apos; }}"/></target>
2423-
</trans-unit>
24242428
</body>
24252429
</file>
24262430
</xliff>

projects/admin-core/assets/locale/messages.admin-core.en.xlf

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@
88
<trans-unit id="admin-core.application-filter-single-layer" datatype="html">
99
<source>Single-layer filter</source>
1010
</trans-unit>
11+
<trans-unit id="admin-core.application-metadata.created" datatype="html">
12+
<source>Created by <x id="INTERPOLATION" equiv-text="{{ application.createdBy }}"/> at <x id="INTERPOLATION_1" equiv-text="{{ application.createdDate | date:&apos;medium&apos; }}"/></source>
13+
</trans-unit>
14+
<trans-unit id="admin-core.application-metadata.updated" datatype="html">
15+
<source>Last updated by <x id="INTERPOLATION" equiv-text="{{ application.lastModifiedBy }}"/> at <x id="INTERPOLATION_1" equiv-text="{{ application.lastModifiedDate | date:&apos;medium&apos; }}"/></source>
16+
</trans-unit>
1117
<trans-unit id="admin-core.application.add-application" datatype="html">
1218
<source>Add application</source>
1319
</trans-unit>
@@ -107,6 +113,9 @@
107113
<trans-unit id="admin-core.application.copy-application" datatype="html">
108114
<source>Copy application <x id="INTERPOLATION" equiv-text="{{data.application.title}}"/></source>
109115
</trans-unit>
116+
<trans-unit id="admin-core.application.copy-layers-info" datatype="html">
117+
<source>Select one or more layers that are available for copying features from. If no layers are selected, all layers will be available. Note that incompatible layer geometry types may prevent successful copying.</source>
118+
</trans-unit>
110119
<trans-unit id="admin-core.application.create-application" datatype="html">
111120
<source>Create application</source>
112121
</trans-unit>
@@ -1775,12 +1784,6 @@
17751784
<trans-unit id="admin-core.users.valid-until" datatype="html">
17761785
<source>Valid until</source>
17771786
</trans-unit>
1778-
<trans-unit id="admin-core.application-metadata.created" datatype="html">
1779-
<source>Created by <x id="INTERPOLATION" equiv-text="{{ application.createdBy }} at {{ application.createdDate | date:&apos;medium&apos; }}"/></source>
1780-
</trans-unit>
1781-
<trans-unit id="admin-core.application-metadata.updated" datatype="html">
1782-
<source>Last updated by <x id="INTERPOLATION" equiv-text="{{ application.lastModifiedBy }} at {{ application.lastModifiedBy | date:&apos;medium&apos; }}"/></source>
1783-
</trans-unit>
17841787
</body>
17851788
</file>
17861789
</xliff>

projects/admin-core/assets/locale/messages.admin-core.nl.xlf

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@
1010
<source>Single-layer filter</source>
1111
<target>Enkele laag filter</target>
1212
</trans-unit>
13+
<trans-unit id="admin-core.application-metadata.created" datatype="html">
14+
<source>Created by <x id="INTERPOLATION" equiv-text="{{ application.createdBy }}"/> at <x id="INTERPOLATION_1" equiv-text="{{ application.createdDate | date:&apos;medium&apos; }}"/></source>
15+
<target>Aangemaakt door <x id="INTERPOLATION" equiv-text="{{ application.createdBy }} at {{ application.createdDate | date:&apos;medium&apos; }}"/></target>
16+
</trans-unit>
17+
<trans-unit id="admin-core.application-metadata.updated" datatype="html">
18+
<source>Last updated by <x id="INTERPOLATION" equiv-text="{{ application.lastModifiedBy }}"/> at <x id="INTERPOLATION_1" equiv-text="{{ application.lastModifiedDate | date:&apos;medium&apos; }}"/></source>
19+
<target>Laatst bijgewerkt door <x id="INTERPOLATION" equiv-text="{{ application.lastModifiedBy }} at {{ application.lastModifiedBy | date:&apos;medium&apos; }}"/></target>
20+
</trans-unit>
1321
<trans-unit id="admin-core.application.add-application" datatype="html">
1422
<source>Add application</source>
1523
<target>Applicatie toevoegen</target>
@@ -142,6 +150,10 @@
142150
<source>Copy application <x id="INTERPOLATION" equiv-text="{{data.application.title}}"/></source>
143151
<target>Kopieer applicatie <x id="INTERPOLATION" equiv-text="{{data.application.title}}"/></target>
144152
</trans-unit>
153+
<trans-unit id="admin-core.application.copy-layers-info" datatype="html">
154+
<source>Select one or more layers that are available for copying features from. If no layers are selected, all layers will be available. Note that incompatible layer geometry types may prevent successful copying.</source>
155+
<target>Selecteer één of meerdere lagen waarvan objecten kunnen worden gekopiëerd. Als geen lagen zijn aangevinkt is dit mogelijk van alle lagen. Let op dat door incompatibele geometrie-types een object mogelijk niet gekopiëerd kan worden.</target>
156+
</trans-unit>
145157
<trans-unit id="admin-core.application.create-application" datatype="html">
146158
<source>Create application</source>
147159
<target>Applicatie aanmaken</target>
@@ -2397,14 +2409,6 @@
23972409
<source>Valid until</source>
23982410
<target>Geldig tot</target>
23992411
</trans-unit>
2400-
<trans-unit id="admin-core.application-metadata.created" datatype="html">
2401-
<source>Created by <x id="INTERPOLATION" equiv-text="{{ application.createdBy }} at {{ application.createdDate | date:&apos;medium&apos; }}"/></source>
2402-
<target>Aangemaakt door <x id="INTERPOLATION" equiv-text="{{ application.createdBy }} at {{ application.createdDate | date:&apos;medium&apos; }}"/></target>
2403-
</trans-unit>
2404-
<trans-unit id="admin-core.application-metadata.updated" datatype="html">
2405-
<source>Last updated by <x id="INTERPOLATION" equiv-text="{{ application.lastModifiedBy }} at {{ application.lastModifiedBy | date:&apos;medium&apos; }}"/></source>
2406-
<target>Laatst bijgewerkt door <x id="INTERPOLATION" equiv-text="{{ application.lastModifiedBy }} at {{ application.lastModifiedBy | date:&apos;medium&apos; }}"/></target>
2407-
</trans-unit>
24082412
</body>
24092413
</file>
24102414
</xliff>

projects/admin-core/src/lib/application/components/components.module.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { EditComponentConfigComponent } from './edit-config/edit-component-confi
1616
import { GeolocationConfigComponent } from './geolocation-config/geolocation-config.component';
1717
import { InfoConfigComponent } from './info-config/info-config.component';
1818
import { DrawingConfigComponent } from './drawing-config/drawing-config.component';
19+
import { SharedAdminComponentsModule } from '../../shared/components';
1920

2021
@NgModule({
2122
declarations: [
@@ -31,13 +32,14 @@ import { DrawingConfigComponent } from './drawing-config/drawing-config.componen
3132
InfoConfigComponent,
3233
DrawingConfigComponent,
3334
],
34-
imports: [
35-
CommonModule,
36-
SharedModule,
37-
BaseComponentConfigComponent,
38-
SelectUploadModule,
39-
MarkdownEditorComponent,
40-
],
35+
imports: [
36+
CommonModule,
37+
SharedModule,
38+
BaseComponentConfigComponent,
39+
SelectUploadModule,
40+
MarkdownEditorComponent,
41+
SharedAdminComponentsModule,
42+
],
4143
exports: [
4244
ComponentsListComponent,
4345
ComponentConfigRendererComponent,
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
div {
2+
margin-bottom: 8px;
3+
}
4+
5+
.copy-layers {
6+
max-width: 500px;
7+
}

projects/admin-core/src/lib/application/components/edit-config/edit-component-config.component.html

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,22 @@
66
<div [formGroup]="formGroup">
77
<mat-checkbox formControlName="closeAfterAddFeature"
88
i18n="@@admin-core.components.edit-close-after-add-feature">Close window after adding new feature</mat-checkbox>
9+
10+
<div class="copy-layers">
11+
<div class="copy-layers-info">
12+
<span i18n="@@admin-core.application.copy-layers-info">Select one or more layers that are available for copying features from. If no layers are selected, all layers will be available. Note that incompatible layer geometry types may prevent successful copying.</span>
13+
</div>
14+
<tm-admin-list-filter [formControl]="copyLayerFilter"
15+
[filterTerm]="copyLayerFilterSignal()"
16+
i18n-label="@@admin-core.application.filter-tree"
17+
label="Filter application layers"></tm-admin-list-filter>
18+
<mat-selection-list (selectionChange)="onCopyLayerSelectionChange($event)">
19+
@for (layer of filteredLayerList(); track layer.id) {
20+
<mat-list-option [value]="layer.id" [selected]="layer.selected">
21+
<div class="layer-label">{{ layer.label }}</div>
22+
</mat-list-option>
23+
}
24+
</mat-selection-list>
25+
</div>
926
</div>
1027
</tm-admin-base-component-config>

projects/admin-core/src/lib/application/components/edit-config/edit-component-config.component.ts

Lines changed: 62 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
1-
import { ChangeDetectionStrategy, Component, DestroyRef, Input, inject } from '@angular/core';
1+
import { ChangeDetectionStrategy, Component, DestroyRef, Input, inject, signal, OnInit, computed, effect } from '@angular/core';
22
import {
33
BaseComponentTypeEnum, EditConfigModel,
44
} from '@tailormap-viewer/api';
55
import { FormControl, FormGroup } from '@angular/forms';
66
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
77
import { ComponentConfigurationService } from '../../services/component-configuration.service';
88
import { ConfigurationComponentModel } from '../configuration-component.model';
9-
import { debounceTime } from 'rxjs';
9+
import { debounceTime, take } from 'rxjs';
10+
import { MatSelectionListChange } from '@angular/material/list';
11+
import { selectExtendedAppLayerNodesForSelectedApplication } from '../../state/application.selectors';
12+
import { Store } from '@ngrx/store';
13+
import { FilterHelper, LoadingStateEnum } from '@tailormap-viewer/shared';
14+
import { selectCatalogLoadStatus } from '../../../catalog/state/catalog.selectors';
15+
import { loadCatalog } from '../../../catalog/state/catalog.actions';
1016

1117
@Component({
1218
selector: 'tm-admin-edit-component-config',
@@ -15,10 +21,10 @@ import { debounceTime } from 'rxjs';
1521
changeDetection: ChangeDetectionStrategy.OnPush,
1622
standalone: false,
1723
})
18-
export class EditComponentConfigComponent implements ConfigurationComponentModel<EditConfigModel> {
24+
export class EditComponentConfigComponent implements ConfigurationComponentModel<EditConfigModel>, OnInit {
1925
private componentConfigService = inject(ComponentConfigurationService);
2026
private destroyRef = inject(DestroyRef);
21-
27+
private store$ = inject(Store);
2228

2329
@Input()
2430
public type: BaseComponentTypeEnum | undefined;
@@ -39,8 +45,36 @@ export class EditComponentConfigComponent implements ConfigurationComponentModel
3945
public formGroup = new FormGroup({
4046
closeAfterAddFeature: new FormControl<boolean>(false),
4147
});
48+
public selectedCopyLayers = signal<string[]>([]);
49+
50+
// Not in formGroup for config properties, used for layer filter control
51+
public copyLayerFilter = new FormControl<string>('');
52+
public copyLayerFilterSignal = signal<string>('');
53+
public allLayers = this.store$.selectSignal(selectExtendedAppLayerNodesForSelectedApplication);
54+
55+
public filteredLayerList = computed(() => {
56+
const allLayers = this.allLayers();
57+
const selectedLayerIds = this.selectedCopyLayers();
58+
const filterTerm = this.copyLayerFilterSignal();
59+
const layersWithSelected = allLayers.map(layer => ({
60+
...layer,
61+
selected: selectedLayerIds.includes(layer.id),
62+
}));
63+
if (filterTerm) {
64+
return FilterHelper.filterByTerm(layersWithSelected, filterTerm, l => l.label);
65+
}
66+
return layersWithSelected;
67+
});
4268

4369
constructor() {
70+
this.store$.select(selectCatalogLoadStatus)
71+
.pipe(take(1))
72+
.subscribe(loadStatus => {
73+
if (loadStatus === LoadingStateEnum.INITIAL || loadStatus === LoadingStateEnum.FAILED) {
74+
this.store$.dispatch(loadCatalog());
75+
}
76+
});
77+
4478
this.formGroup.valueChanges
4579
.pipe(takeUntilDestroyed(this.destroyRef), debounceTime(250))
4680
.subscribe(() => {
@@ -49,14 +83,38 @@ export class EditComponentConfigComponent implements ConfigurationComponentModel
4983
}
5084
this.saveConfig();
5185
});
86+
87+
effect(() => {
88+
this.componentConfigService.updateConfigForKey<EditConfigModel>(this.type, 'copyLayerIds', this.selectedCopyLayers());
89+
});
90+
}
91+
92+
public ngOnInit(): void {
93+
this.copyLayerFilter.valueChanges
94+
.pipe(takeUntilDestroyed(this.destroyRef))
95+
.subscribe(filterTerm => {
96+
this.copyLayerFilterSignal.set(filterTerm || '');
97+
});
5298
}
5399

54100
public initForm(config: EditConfigModel | undefined) {
55101
this.formGroup.patchValue({ closeAfterAddFeature: config?.closeAfterAddFeature ?? false }, { emitEvent: false });
102+
this.selectedCopyLayers.set(config?.copyLayerIds ?? []);
56103
}
57104

58105
private saveConfig() {
59106
this.componentConfigService.updateConfigForKey<EditConfigModel>(this.type, 'closeAfterAddFeature', this.formGroup.value.closeAfterAddFeature);
60107
}
61108

109+
public onCopyLayerSelectionChange($event: MatSelectionListChange) {
110+
const selectedLayers = [...this.selectedCopyLayers()];
111+
$event.options.forEach(option => {
112+
if (option.selected) {
113+
selectedLayers.push(option.value);
114+
} else {
115+
selectedLayers.splice(selectedLayers.indexOf(option.value), 1);
116+
}
117+
});
118+
this.selectedCopyLayers.set(selectedLayers);
119+
}
62120
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { ExtendedGeoServiceModel } from '../../catalog/models/extended-geo-service.model';
2+
import { ExtendedFeatureTypeModel } from '../../catalog/models/extended-feature-type.model';
3+
import { ExtendedGeoServiceLayerModel } from '../../catalog/models/extended-geo-service-layer.model';
4+
import { AppLayerSettingsModel, AppTreeLayerNodeModel } from '@tailormap-admin/admin-api';
5+
6+
export interface ExtendedAppTreeLayerNodeModel extends AppTreeLayerNodeModel {
7+
label: string;
8+
appLayerSettings: AppLayerSettingsModel;
9+
geoService: ExtendedGeoServiceModel | undefined;
10+
geoServiceLayer: ExtendedGeoServiceLayerModel | undefined;
11+
featureType: ExtendedFeatureTypeModel | undefined;
12+
}

projects/admin-core/src/lib/application/state/application.selectors.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { ApplicationModelHelper } from '../helpers/application-model.helper';
1111
import { GeoServiceLayerInApplicationModel } from '../models/geo-service-layer-in-application.model';
1212
import { ExtendedGeoServiceLayerModel } from '../../catalog/models/extended-geo-service-layer.model';
1313
import { ExtendedFilterGroupModel } from '../models/extended-filter-group.model';
14+
import { ExtendedAppTreeLayerNodeModel } from '../models/extended-app-tree-layer-node.model';
1415

1516
const selectApplicationState = createFeatureSelector<ApplicationState>(applicationStateKey);
1617

@@ -205,6 +206,36 @@ export const selectStylingConfig = createSelector(selectDraftApplication, applic
205206

206207
export const selectFilterGroups = createSelector(selectDraftApplication, application => application?.settings?.filterGroups || []);
207208

209+
export const selectExtendedAppLayerNodesForSelectedApplication = createSelector(
210+
selectAppLayerNodesForSelectedApplication,
211+
selectGeoServices,
212+
selectGeoServiceLayers,
213+
selectSelectedApplicationLayerSettings,
214+
selectFeatureTypes,
215+
(appLayerTreeNodes, geoServices, geoServiceLayers, layerSettings, featureTypes) => {
216+
const geoServiceLayerMap = ApplicationTreeHelper.getLayerMap(geoServiceLayers);
217+
return appLayerTreeNodes
218+
.filter(node => ApplicationModelHelper.isLayerTreeNode(node))
219+
.map((appLayerNode): ExtendedAppTreeLayerNodeModel => {
220+
const geoServiceLayer = geoServiceLayerMap.get(ApplicationTreeHelper.getLayerMapKey(appLayerNode.layerName, appLayerNode.serviceId));
221+
const geoService = geoServices.find(service => service.id === geoServiceLayer?.serviceId);
222+
const appLayerSettings = layerSettings[appLayerNode.id];
223+
const featureType = featureTypes.find(ft => {
224+
return ft.featureSourceId === geoServiceLayer?.layerSettings?.featureType?.featureSourceId.toString()
225+
&& ft.name === geoServiceLayer.layerSettings?.featureType?.featureTypeName;
226+
});
227+
return {
228+
...appLayerNode,
229+
label: ApplicationTreeHelper.getTreeModelLabel(appLayerNode, geoServiceLayerMap, layerSettings, 'layer'),
230+
appLayerSettings,
231+
geoService,
232+
geoServiceLayer,
233+
featureType,
234+
};
235+
});
236+
},
237+
);
238+
208239
export const selectFilterableLayersForApplication = createSelector(
209240
selectAppLayerNodesForSelectedApplication,
210241
selectGeoServiceLayers,

projects/api/src/lib/models/component-config/edit-config.model.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ import { ComponentBaseConfigModel } from '../component-base-config.model';
22

33
export interface EditConfigModel extends ComponentBaseConfigModel {
44
closeAfterAddFeature: boolean;
5+
copyLayerIds?: string[];
56
}

0 commit comments

Comments
 (0)