geonetwork-ui 2.9.0-dev.f3376949a → 2.9.0-dev.fc19cbfed
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/geonetwork-ui.mjs +690 -563
- package/fesm2022/geonetwork-ui.mjs.map +1 -1
- package/index.d.ts +253 -162
- package/index.d.ts.map +1 -1
- package/package.json +7 -8
- package/src/libs/api/repository/src/lib/gn4/elasticsearch/elasticsearch.service.ts +11 -2
- package/src/libs/common/domain/src/index.ts +1 -0
- package/src/libs/feature/dataviz/src/lib/chart-view/chart-view.component.html +8 -10
- package/src/libs/feature/dataviz/src/lib/service/data.service.ts +33 -11
- package/src/libs/feature/editor/src/index.ts +8 -7
- package/src/libs/feature/editor/src/lib/+state/editor.actions.ts +6 -1
- package/src/libs/feature/editor/src/lib/+state/editor.facade.ts +5 -1
- package/src/libs/feature/editor/src/lib/+state/editor.reducer.ts +4 -0
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.html +2 -2
- package/src/libs/feature/record/src/lib/external-viewer-button/external-viewer-button.component.ts +2 -0
- package/src/libs/feature/record/src/lib/gpf-api-dl/gpf-api-dl.component.html +4 -4
- package/src/libs/feature/record/src/lib/gpf-api-dl/gpf-api-dl.component.ts +3 -4
- package/src/libs/feature/record/src/lib/map-view/map-view.component.html +10 -18
- package/src/libs/feature/record/src/lib/map-view/map-view.component.ts +96 -9
- package/src/libs/feature/record/src/lib/state/mdview.facade.ts +1 -1
- package/src/libs/feature/router/src/lib/default/router.module.ts +3 -3
- package/src/libs/feature/router/src/lib/default/router.service.ts +2 -2
- package/src/libs/feature/router/src/lib/default/services/router-search.service.ts +12 -3
- package/src/libs/feature/router/src/lib/default/state/router.effects.ts +34 -4
- package/src/libs/feature/search/src/lib/state/reducer.ts +3 -0
- package/src/libs/feature/search/src/lib/utils/service/fields.service.ts +9 -3
- package/src/libs/feature/search/src/lib/utils/service/fields.ts +5 -5
- package/src/libs/ui/elements/src/lib/api-card/api-card.component.html +2 -2
- package/src/libs/ui/elements/src/lib/application-banner/application-banner.component.ts +2 -3
- package/src/libs/ui/elements/src/lib/image-input/image-input.component.html +5 -2
- package/src/libs/ui/elements/src/lib/internal-link-card/internal-link-card.component.html +63 -56
- package/src/libs/ui/elements/src/lib/internal-link-card/internal-link-card.component.scss +5 -5
- package/src/libs/ui/elements/src/lib/metadata-contact/metadata-contact.component.html +11 -8
- package/src/libs/ui/elements/src/lib/metadata-contact/metadata-contact.component.ts +3 -3
- package/src/libs/ui/elements/src/lib/record-api-form/record-api-form.component.html +1 -1
- package/src/libs/ui/elements/src/lib/service-capabilities/service-capabilities.component.html +1 -1
- package/src/libs/ui/inputs/src/lib/autocomplete/autocomplete.component.ts +7 -5
- package/src/libs/ui/map/src/lib/map-utils.ts +1 -1
- package/src/libs/ui/search/src/lib/record-preview-feed/record-preview-feed.component.html +19 -16
- package/src/libs/util/app-config/src/lib/app-config.ts +8 -2
- package/src/libs/util/app-config/src/lib/fixtures.ts +1 -0
- package/src/libs/util/app-config/src/lib/model.ts +1 -0
- package/src/libs/util/shared/src/lib/gn-ui-version.ts +5 -4
- package/src/libs/util/shared/src/lib/links/link-utils.ts +8 -4
- package/src/libs/util/shared/src/lib/services/theme.service.ts +9 -23
- package/tailwind.base.config.js +3 -2
- package/translations/de.json +5 -3
- package/translations/en.json +7 -5
- package/translations/es.json +2 -0
- package/translations/fr.json +7 -5
- package/translations/it.json +7 -5
- package/translations/nl.json +2 -0
- package/translations/pt.json +2 -0
- package/translations/sk.json +3 -1
|
@@ -1,12 +1,13 @@
|
|
|
1
|
+
export * from './lib/+state/editor.actions'
|
|
1
2
|
export * from './lib/+state/editor.facade'
|
|
2
3
|
export * from './lib/+state/editor.models'
|
|
3
|
-
export * from './lib/+state/editor.selectors'
|
|
4
4
|
export * from './lib/+state/editor.reducer'
|
|
5
|
-
export * from './lib/+state/editor.
|
|
6
|
-
export * from './lib/feature-editor.module'
|
|
7
|
-
export * from './lib/services/editor.service'
|
|
5
|
+
export * from './lib/+state/editor.selectors'
|
|
8
6
|
export * from './lib/components/import-record/import-record.component'
|
|
9
|
-
export * from './lib/components/record-form/record-form.component'
|
|
10
|
-
export * from './lib/components/record-form/form-field'
|
|
11
|
-
export * from './lib/components/multilingual-panel/multilingual-panel.component'
|
|
12
7
|
export * from './lib/components/metadata-quality-panel/metadata-quality-panel.component'
|
|
8
|
+
export * from './lib/components/multilingual-panel/multilingual-panel.component'
|
|
9
|
+
export * from './lib/components/record-form/form-field'
|
|
10
|
+
export * from './lib/components/record-form/record-form.component'
|
|
11
|
+
export * from './lib/feature-editor.module'
|
|
12
|
+
export * from './lib/fields.config'
|
|
13
|
+
export * from './lib/services/editor.service'
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
LanguageCode,
|
|
5
5
|
} from '../../../../../../libs/common/domain/src/lib/model/record'
|
|
6
6
|
import { SaveRecordError } from './editor.models'
|
|
7
|
-
import { EditorFieldIdentification } from '../models'
|
|
7
|
+
import { EditorConfig, EditorFieldIdentification } from '../models'
|
|
8
8
|
|
|
9
9
|
export const openRecord = createAction(
|
|
10
10
|
'[Editor] Open record',
|
|
@@ -39,6 +39,11 @@ export const draftSaveSuccess = createAction('[Editor] Draft save success')
|
|
|
39
39
|
|
|
40
40
|
export const undoRecordDraft = createAction('[Editor] Undo record draft')
|
|
41
41
|
|
|
42
|
+
export const setEditorConfiguration = createAction(
|
|
43
|
+
'[Editor] Set editor configuration',
|
|
44
|
+
props<{ configuration: EditorConfig }>()
|
|
45
|
+
)
|
|
46
|
+
|
|
42
47
|
export const setCurrentPage = createAction(
|
|
43
48
|
'[Editor] Set current page',
|
|
44
49
|
props<{ page: number }>()
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
} from '../../../../../../libs/common/domain/src/lib/model/record'
|
|
9
9
|
import { filter } from 'rxjs'
|
|
10
10
|
import { Actions, ofType } from '@ngrx/effects'
|
|
11
|
-
import { EditorFieldIdentification } from '../models'
|
|
11
|
+
import { EditorConfig, EditorFieldIdentification } from '../models'
|
|
12
12
|
|
|
13
13
|
@Injectable()
|
|
14
14
|
export class EditorFacade {
|
|
@@ -69,6 +69,10 @@ export class EditorFacade {
|
|
|
69
69
|
)
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
+
setConfiguration(configuration: EditorConfig) {
|
|
73
|
+
this.store.dispatch(EditorActions.setEditorConfiguration({ configuration }))
|
|
74
|
+
}
|
|
75
|
+
|
|
72
76
|
setCurrentPage(page: number) {
|
|
73
77
|
this.store.dispatch(EditorActions.setCurrentPage({ page }))
|
|
74
78
|
}
|
|
@@ -81,6 +81,10 @@ const reducer = createReducer(
|
|
|
81
81
|
...state,
|
|
82
82
|
changedSinceSave: true,
|
|
83
83
|
})),
|
|
84
|
+
on(EditorActions.setEditorConfiguration, (state, { configuration }) => ({
|
|
85
|
+
...state,
|
|
86
|
+
editorConfig: configuration,
|
|
87
|
+
})),
|
|
84
88
|
on(EditorActions.setCurrentPage, (state, { page }) => ({
|
|
85
89
|
...state,
|
|
86
90
|
currentPage: page,
|
package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.html
CHANGED
|
@@ -31,12 +31,12 @@
|
|
|
31
31
|
cdkAutosizeMinRows="1"
|
|
32
32
|
data-test="recordTitleInput"
|
|
33
33
|
class="grow font-title text-3xl font-normal overflow-hidden text-black/80"
|
|
34
|
+
[value]="valueAsString"
|
|
34
35
|
(change)="valueChange.emit($event.target.value)"
|
|
35
36
|
[placeholder]="
|
|
36
37
|
'editor.record.form.field.title.placeholder' | translate
|
|
37
38
|
"
|
|
38
|
-
|
|
39
|
-
>
|
|
39
|
+
></textarea>
|
|
40
40
|
<div class="flex flex-row justify-between self-start mt-0.5">
|
|
41
41
|
<span
|
|
42
42
|
class="material-symbols-outlined gn-ui-icon-small m-2 cursor-pointer"
|
package/src/libs/feature/record/src/lib/external-viewer-button/external-viewer-button.component.ts
CHANGED
|
@@ -44,6 +44,7 @@ export class ExternalViewerButtonComponent {
|
|
|
44
44
|
private openinNewTab = inject(EXTERNAL_VIEWER_OPEN_NEW_TAB)
|
|
45
45
|
|
|
46
46
|
@Input() link: DatasetOnlineResource
|
|
47
|
+
@Input() mimeType = ''
|
|
47
48
|
@Input() extraClass = ''
|
|
48
49
|
|
|
49
50
|
get externalViewer() {
|
|
@@ -80,6 +81,7 @@ export class ExternalViewerButtonComponent {
|
|
|
80
81
|
`${encodeURIComponent(this.link.url.toString())}`
|
|
81
82
|
)
|
|
82
83
|
.replace('${service_type}', `${this.supportedLinkLayerType}`)
|
|
84
|
+
.replace('${mime_type}', `${encodeURIComponent(this.mimeType)}`)
|
|
83
85
|
window.open(url, this.openinNewTab ? '_blank' : '_self').focus()
|
|
84
86
|
}
|
|
85
87
|
}
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
</h2>
|
|
13
13
|
<button
|
|
14
14
|
(click)="resetUrl()"
|
|
15
|
-
class="bg-primary
|
|
15
|
+
class="bg-primary/50 inline-flex items-center justify-center px-4 py-2 text-white rounded hover:bg-primary transition"
|
|
16
16
|
[attr.title]="'record.metadata.api.form.resetTooltip' | translate"
|
|
17
17
|
[attr.aria-label]="'record.metadata.api.form.resetTooltip' | translate"
|
|
18
18
|
>
|
|
@@ -97,7 +97,7 @@
|
|
|
97
97
|
'px-4 py-2 text-white rounded transition ' +
|
|
98
98
|
((page$ | async) <= 1
|
|
99
99
|
? 'bg-gray-400 cursor-not-allowed '
|
|
100
|
-
: 'bg-primary
|
|
100
|
+
: 'bg-primary/50 hover:bg-primary')
|
|
101
101
|
"
|
|
102
102
|
[attr.title]="'record.metadata.api.form.previousPageTooltip' | translate"
|
|
103
103
|
[attr.aria-label]="
|
|
@@ -117,10 +117,10 @@
|
|
|
117
117
|
<button
|
|
118
118
|
(click)="moreResult()"
|
|
119
119
|
[class]="
|
|
120
|
-
'bg-primary
|
|
120
|
+
'bg-primary/50 px-4 py-2 text-white rounded transition ' +
|
|
121
121
|
((page$ | async) >= (pageMax$ | async)
|
|
122
122
|
? 'bg-gray-400 cursor-not-allowed '
|
|
123
|
-
: 'bg-primary
|
|
123
|
+
: 'bg-primary/50 hover:bg-primary')
|
|
124
124
|
"
|
|
125
125
|
[attr.title]="'record.metadata.api.form.nextPageTooltip' | translate"
|
|
126
126
|
[attr.aria-label]="'record.metadata.api.form.nextPageTooltip' | translate"
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ChangeDetectionStrategy,
|
|
3
3
|
Component,
|
|
4
|
+
inject,
|
|
4
5
|
Input,
|
|
5
6
|
OnInit,
|
|
6
|
-
inject,
|
|
7
7
|
} from '@angular/core'
|
|
8
8
|
import { DatasetServiceDistribution } from '../../../../../../libs/common/domain/src/lib/model/record'
|
|
9
9
|
import { BehaviorSubject, combineLatest, map, mergeMap, Observable } from 'rxjs'
|
|
10
10
|
import { HttpClient } from '@angular/common/http'
|
|
11
11
|
import { Choice, DropdownSelectorComponent } from '../../../../../../libs/ui/inputs/src'
|
|
12
|
-
import axios from 'axios'
|
|
13
12
|
import { CommonModule } from '@angular/common'
|
|
14
13
|
import { TranslateDirective, TranslatePipe } from '@ngx-translate/core'
|
|
15
14
|
import { GpfApiDlListItemComponent } from '../gpf-api-dl-list-item/gpf-api-dl-list-item.component'
|
|
@@ -209,9 +208,9 @@ export class GpfApiDlComponent implements OnInit {
|
|
|
209
208
|
let pageCount = 1
|
|
210
209
|
|
|
211
210
|
while (choicesTest === undefined && pageCount > page) {
|
|
212
|
-
const response = await
|
|
211
|
+
const response = await fetch(
|
|
213
212
|
this.url.concat(`&limit=200&page=${page}`)
|
|
214
|
-
)
|
|
213
|
+
).then((resp) => resp.json())
|
|
215
214
|
|
|
216
215
|
choicesTest = response.data.entry.filter(
|
|
217
216
|
(element) => element['id'] == this.apiBaseUrl
|
|
@@ -13,29 +13,21 @@
|
|
|
13
13
|
></gn-ui-dropdown-selector>
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
} @else {
|
|
26
|
-
<gn-ui-dropdown-selector
|
|
27
|
-
class="w-full md:flex-1 md:min-w-0 text-gray-400"
|
|
28
|
-
extraBtnClass="font-sans font-bold text-gray-400"
|
|
29
|
-
[title]="'map.select.style' | translate"
|
|
30
|
-
[choices]="styleDropdownChoices$ | async"
|
|
31
|
-
[disabled]="true"
|
|
32
|
-
></gn-ui-dropdown-selector>
|
|
33
|
-
}
|
|
16
|
+
<gn-ui-dropdown-selector
|
|
17
|
+
class="w-full md:flex-1 md:min-w-0"
|
|
18
|
+
extraBtnClass="font-sans font-bold"
|
|
19
|
+
[title]="'map.select.style' | translate"
|
|
20
|
+
[choices]="styleDropdownChoices$ | async"
|
|
21
|
+
[selected]="selectedStyleId$ | async"
|
|
22
|
+
[disabled]="(styleDropdownChoices$ | async)?.length <= 1"
|
|
23
|
+
(selectValue)="selectStyleToDisplay($event)"
|
|
24
|
+
></gn-ui-dropdown-selector>
|
|
34
25
|
|
|
35
26
|
<div class="self-end md:ml-2">
|
|
36
27
|
<gn-ui-external-viewer-button
|
|
37
28
|
extraClass="w-[44px] h-[44px]"
|
|
38
29
|
[link]="selectedLink$ | async"
|
|
30
|
+
[mimeType]="wmsMimeType$ | async"
|
|
39
31
|
>
|
|
40
32
|
</gn-ui-external-viewer-button>
|
|
41
33
|
</div>
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
} from '@angular/core'
|
|
12
12
|
import { MapUtilsService } from '../../../../../../libs/feature/map/src'
|
|
13
13
|
import { getLinkId, getLinkLabel } from '../../../../../../libs/util/shared/src'
|
|
14
|
+
import { WmsEndpoint, LayerStyle } from '@camptocamp/ogc-client'
|
|
14
15
|
import {
|
|
15
16
|
BehaviorSubject,
|
|
16
17
|
combineLatest,
|
|
@@ -40,6 +41,7 @@ import {
|
|
|
40
41
|
createViewFromLayer,
|
|
41
42
|
MapContext,
|
|
42
43
|
MapContextLayer,
|
|
44
|
+
MapContextLayerWms,
|
|
43
45
|
SourceLoadErrorEvent,
|
|
44
46
|
} from '@geospatial-sdk/core'
|
|
45
47
|
import {
|
|
@@ -77,6 +79,7 @@ marker('map.dropdown.placeholder')
|
|
|
77
79
|
marker('wfs.feature.limit')
|
|
78
80
|
marker('dataset.error.restrictedAccess')
|
|
79
81
|
marker('map.select.style')
|
|
82
|
+
marker('map.style.default')
|
|
80
83
|
|
|
81
84
|
@Component({
|
|
82
85
|
selector: 'gn-ui-map-view',
|
|
@@ -228,7 +231,16 @@ export class MapViewComponent implements AfterViewInit {
|
|
|
228
231
|
return compatibleLinks[0]
|
|
229
232
|
}
|
|
230
233
|
}
|
|
231
|
-
})
|
|
234
|
+
}),
|
|
235
|
+
shareReplay(1)
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
isWmsStyleMode$ = this.selectedSourceLink$.pipe(
|
|
239
|
+
map(
|
|
240
|
+
(src) => src?.type === 'service' && src?.accessServiceProtocol === 'wms'
|
|
241
|
+
),
|
|
242
|
+
distinctUntilChanged(),
|
|
243
|
+
shareReplay(1)
|
|
232
244
|
)
|
|
233
245
|
|
|
234
246
|
styleLinks$ = this.selectedSourceLink$.pipe(
|
|
@@ -262,6 +274,22 @@ export class MapViewComponent implements AfterViewInit {
|
|
|
262
274
|
})
|
|
263
275
|
)
|
|
264
276
|
}
|
|
277
|
+
if (
|
|
278
|
+
src &&
|
|
279
|
+
src.type === 'service' &&
|
|
280
|
+
src.accessServiceProtocol === 'wms'
|
|
281
|
+
) {
|
|
282
|
+
return from(new WmsEndpoint(src.url.toString()).isReady()).pipe(
|
|
283
|
+
map((endpoint) => {
|
|
284
|
+
const layer = endpoint.getLayerByName(src.name)
|
|
285
|
+
return layer?.styles || []
|
|
286
|
+
}),
|
|
287
|
+
catchError((error) => {
|
|
288
|
+
this.handleError(error)
|
|
289
|
+
return of([])
|
|
290
|
+
})
|
|
291
|
+
)
|
|
292
|
+
}
|
|
265
293
|
return of([])
|
|
266
294
|
}),
|
|
267
295
|
tap((styles) => {
|
|
@@ -274,33 +302,83 @@ export class MapViewComponent implements AfterViewInit {
|
|
|
274
302
|
shareReplay(1)
|
|
275
303
|
)
|
|
276
304
|
|
|
277
|
-
styleDropdownChoices$ =
|
|
278
|
-
|
|
305
|
+
styleDropdownChoices$ = combineLatest([
|
|
306
|
+
this.styleLinks$,
|
|
307
|
+
this.isWmsStyleMode$,
|
|
308
|
+
]).pipe(
|
|
309
|
+
map(([links, isWmsStyleMode]) =>
|
|
279
310
|
links.length
|
|
280
311
|
? links.map((link, index) => ({
|
|
281
|
-
label:
|
|
312
|
+
label: isWmsStyleMode
|
|
313
|
+
? (link as LayerStyle).title || (link as LayerStyle).name
|
|
314
|
+
: getLinkLabel(link as DatasetOnlineResource),
|
|
282
315
|
value: index,
|
|
283
316
|
}))
|
|
284
317
|
: [
|
|
285
318
|
{
|
|
286
|
-
label: '
|
|
319
|
+
label: this.translateService.instant('map.style.default'),
|
|
287
320
|
value: 0,
|
|
288
321
|
},
|
|
289
322
|
]
|
|
290
323
|
)
|
|
291
324
|
)
|
|
292
325
|
|
|
326
|
+
selectedWmsStyleName$ = combineLatest([
|
|
327
|
+
this.styleLinks$,
|
|
328
|
+
this.isWmsStyleMode$,
|
|
329
|
+
this.selectedStyleId$.pipe(distinctUntilChanged()),
|
|
330
|
+
]).pipe(
|
|
331
|
+
map(([styles, isWmsStyleMode, styleIdx]) =>
|
|
332
|
+
isWmsStyleMode && Array.isArray(styles)
|
|
333
|
+
? (styles[styleIdx] as LayerStyle)?.name
|
|
334
|
+
: undefined
|
|
335
|
+
)
|
|
336
|
+
)
|
|
337
|
+
|
|
293
338
|
selectedLink$ = combineLatest([
|
|
294
339
|
this.selectedSourceLink$,
|
|
295
340
|
this.styleLinks$,
|
|
296
341
|
this.selectedStyleId$.pipe(distinctUntilChanged()),
|
|
342
|
+
this.isWmsStyleMode$,
|
|
297
343
|
]).pipe(
|
|
298
|
-
map(([src, styles, styleIdx]) =>
|
|
344
|
+
map(([src, styles, styleIdx, isWmsStyleMode]) =>
|
|
345
|
+
!isWmsStyleMode && styles.length ? styles[styleIdx] : src
|
|
346
|
+
),
|
|
299
347
|
shareReplay(1)
|
|
300
348
|
)
|
|
301
349
|
|
|
302
|
-
|
|
303
|
-
switchMap((
|
|
350
|
+
wmsMimeType$ = this.selectedSourceLink$.pipe(
|
|
351
|
+
switchMap((link) => {
|
|
352
|
+
if (link?.type === 'service' && link?.accessServiceProtocol === 'wms') {
|
|
353
|
+
return from(
|
|
354
|
+
new WmsEndpoint(link.url.toString())
|
|
355
|
+
.isReady()
|
|
356
|
+
.then((endpoint) => {
|
|
357
|
+
return endpoint.describeLayer(link.name).then((description) => {
|
|
358
|
+
if (description) {
|
|
359
|
+
return description.owsType === 'wfs'
|
|
360
|
+
? 'image/png'
|
|
361
|
+
: 'image/jpeg'
|
|
362
|
+
}
|
|
363
|
+
const layer = endpoint.getLayerByName(link.name)
|
|
364
|
+
return layer?.opaque ? 'image/jpeg' : 'image/png'
|
|
365
|
+
})
|
|
366
|
+
})
|
|
367
|
+
.catch(() => 'image/png')
|
|
368
|
+
)
|
|
369
|
+
}
|
|
370
|
+
return of('')
|
|
371
|
+
}),
|
|
372
|
+
shareReplay(1)
|
|
373
|
+
)
|
|
374
|
+
|
|
375
|
+
currentLayers$ = combineLatest([
|
|
376
|
+
this.selectedLink$,
|
|
377
|
+
this.excludeWfs$,
|
|
378
|
+
this.selectedWmsStyleName$,
|
|
379
|
+
this.wmsMimeType$,
|
|
380
|
+
]).pipe(
|
|
381
|
+
switchMap(([link, excludeWfs, wmsStyleName, wmsMimeType]) => {
|
|
304
382
|
if (!link) {
|
|
305
383
|
return of([])
|
|
306
384
|
}
|
|
@@ -315,6 +393,15 @@ export class MapViewComponent implements AfterViewInit {
|
|
|
315
393
|
return of([])
|
|
316
394
|
}
|
|
317
395
|
return this.getLayerFromLink(link).pipe(
|
|
396
|
+
map((layer) =>
|
|
397
|
+
layer.type === 'wms'
|
|
398
|
+
? {
|
|
399
|
+
...layer,
|
|
400
|
+
...(wmsStyleName && { style: wmsStyleName }),
|
|
401
|
+
...(wmsMimeType && { format: wmsMimeType }),
|
|
402
|
+
}
|
|
403
|
+
: layer
|
|
404
|
+
),
|
|
318
405
|
map((layer) => [layer]),
|
|
319
406
|
catchError((e) => {
|
|
320
407
|
this.handleError(e)
|
|
@@ -394,7 +481,7 @@ export class MapViewComponent implements AfterViewInit {
|
|
|
394
481
|
url: link.url.toString(),
|
|
395
482
|
type: 'wms',
|
|
396
483
|
name: link.name,
|
|
397
|
-
})
|
|
484
|
+
} as MapContextLayerWms)
|
|
398
485
|
} else if (
|
|
399
486
|
link.type === 'service' &&
|
|
400
487
|
link.accessServiceProtocol === 'tms'
|
|
@@ -164,7 +164,7 @@ export class MdViewFacade {
|
|
|
164
164
|
link.accessServiceProtocol === 'ogcFeatures'
|
|
165
165
|
) {
|
|
166
166
|
return from(
|
|
167
|
-
this.dataService.getItemsFromOgcApi(link.url.href)
|
|
167
|
+
this.dataService.getItemsFromOgcApi(link.url.href, 1)
|
|
168
168
|
).pipe(
|
|
169
169
|
map((collectionRecords: OgcApiRecord[]) => {
|
|
170
170
|
return collectionRecords &&
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { ModuleWithProviders, NgModule
|
|
1
|
+
import { inject, ModuleWithProviders, NgModule } from '@angular/core'
|
|
2
2
|
import { RouteReuseStrategy } from '@angular/router'
|
|
3
|
-
import { EffectsModule } from '@ngrx/effects'
|
|
4
3
|
import {
|
|
5
4
|
FullRouterStateSerializer,
|
|
6
5
|
routerReducer,
|
|
@@ -11,8 +10,9 @@ import { ROUTER_STATE_KEY } from './constants'
|
|
|
11
10
|
import { RouterService } from './router.service'
|
|
12
11
|
import { SearchRouteReuseStrategy } from './SearchRouteReuseStrategy'
|
|
13
12
|
import { RouterFacade } from './state/router.facade'
|
|
14
|
-
import { RouterEffects } from './state/router.effects'
|
|
15
13
|
import { ROUTER_CONFIG, RouterConfigModel } from './router.config'
|
|
14
|
+
import { RouterEffects } from './state/router.effects'
|
|
15
|
+
import { EffectsModule } from '@ngrx/effects'
|
|
16
16
|
|
|
17
17
|
@NgModule({
|
|
18
18
|
imports: [
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { inject, Injectable } from '@angular/core'
|
|
2
2
|
import {
|
|
3
3
|
ROUTER_ROUTE_DATASET,
|
|
4
4
|
ROUTER_ROUTE_ORGANIZATION,
|
|
5
|
+
ROUTER_ROUTE_REUSE,
|
|
5
6
|
ROUTER_ROUTE_SEARCH,
|
|
6
7
|
ROUTER_ROUTE_SERVICE,
|
|
7
|
-
ROUTER_ROUTE_REUSE,
|
|
8
8
|
} from '.'
|
|
9
9
|
import { Router, Routes } from '@angular/router'
|
|
10
10
|
import { ROUTER_CONFIG, RouterConfigModel } from './router.config'
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { inject, Injectable } from '@angular/core'
|
|
2
2
|
import {
|
|
3
3
|
FieldsService,
|
|
4
4
|
SearchFacade,
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
} from '../../../../../../../libs/feature/search/src'
|
|
7
7
|
import {
|
|
8
8
|
FieldFilters,
|
|
9
|
+
SortByEnum,
|
|
9
10
|
SortByField,
|
|
10
11
|
} from '../../../../../../../libs/common/domain/src/lib/model/search'
|
|
11
12
|
import { ROUTE_PARAMS, SearchRouteParams } from '../constants'
|
|
@@ -31,10 +32,12 @@ export class RouterSearchService implements SearchServiceI {
|
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
async setFilters(newFilters: FieldFilters) {
|
|
34
|
-
|
|
35
|
+
let sortBy = await firstValueFrom(this.searchFacade.sortBy$)
|
|
35
36
|
const fieldSearchParams = await firstValueFrom(
|
|
36
37
|
this.fieldsService.readFieldValuesFromFilters(newFilters)
|
|
37
38
|
)
|
|
39
|
+
// apply relevancy sort if a full text criteria is given
|
|
40
|
+
sortBy = newFilters['any'] ? SortByEnum.RELEVANCY : sortBy
|
|
38
41
|
this.facade.setSearch({
|
|
39
42
|
...fieldSearchParams,
|
|
40
43
|
[ROUTE_PARAMS.SORT]: sortBy ? sortByToString(sortBy) : undefined,
|
|
@@ -46,9 +49,15 @@ export class RouterSearchService implements SearchServiceI {
|
|
|
46
49
|
this.searchFacade.searchFilters$
|
|
47
50
|
)
|
|
48
51
|
const updatedFilters = { ...currentFilters, ...newFilters }
|
|
49
|
-
|
|
52
|
+
let newParams = await firstValueFrom(
|
|
50
53
|
this.fieldsService.readFieldValuesFromFilters(updatedFilters)
|
|
51
54
|
)
|
|
55
|
+
if (newFilters['any']) {
|
|
56
|
+
newParams = {
|
|
57
|
+
...newParams,
|
|
58
|
+
[ROUTE_PARAMS.SORT]: sortByToString(SortByEnum.RELEVANCY),
|
|
59
|
+
}
|
|
60
|
+
}
|
|
52
61
|
this.facade.updateSearch(newParams as SearchRouteParams)
|
|
53
62
|
}
|
|
54
63
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Location } from '@angular/common'
|
|
2
|
-
import {
|
|
2
|
+
import { inject, Injectable } from '@angular/core'
|
|
3
3
|
import { ActivatedRouteSnapshot, Router } from '@angular/router'
|
|
4
4
|
import { MdViewActions } from '../../../../../../../libs/feature/record/src'
|
|
5
5
|
import {
|
|
@@ -9,15 +9,18 @@ import {
|
|
|
9
9
|
SetFilters,
|
|
10
10
|
SetSortBy,
|
|
11
11
|
} from '../../../../../../../libs/feature/search/src'
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
FieldFilters,
|
|
14
|
+
SortByEnum,
|
|
15
|
+
} from '../../../../../../../libs/common/domain/src/lib/model/search'
|
|
13
16
|
import { Actions, createEffect, ofType } from '@ngrx/effects'
|
|
14
17
|
import { navigation } from '@ngrx/router-store/data-persistence'
|
|
15
18
|
import { of, pairwise, startWith } from 'rxjs'
|
|
16
|
-
import { map, mergeMap, tap } from 'rxjs/operators'
|
|
19
|
+
import { map, mergeMap, take, tap } from 'rxjs/operators'
|
|
17
20
|
import * as RouterActions from './router.actions'
|
|
18
21
|
import { RouterFacade } from './router.facade'
|
|
19
22
|
import { ROUTE_PARAMS } from '../constants'
|
|
20
|
-
import { sortByFromString } from '../../../../../../../libs/util/shared/src'
|
|
23
|
+
import { sortByFromString, sortByToString } from '../../../../../../../libs/util/shared/src'
|
|
21
24
|
import { ROUTER_CONFIG, RouterConfigModel } from '../router.config'
|
|
22
25
|
import { RouterService } from '../router.service'
|
|
23
26
|
|
|
@@ -103,6 +106,33 @@ export class RouterEffects {
|
|
|
103
106
|
)
|
|
104
107
|
)
|
|
105
108
|
|
|
109
|
+
/**
|
|
110
|
+
* This effect is needed because on the page load, the search params from the URL are
|
|
111
|
+
* directly applied to the underlying search facade; this means that it doesn't go
|
|
112
|
+
* through the RouterSearchService which makes sure that a relevancy sort is applied
|
|
113
|
+
* whenever there's a full text search criteria set.
|
|
114
|
+
*/
|
|
115
|
+
applyInitialRelevancySort$ = createEffect(
|
|
116
|
+
() =>
|
|
117
|
+
this.facade.searchParams$.pipe(
|
|
118
|
+
take(1),
|
|
119
|
+
tap((filters) => {
|
|
120
|
+
const relevancySort = sortByToString(SortByEnum.RELEVANCY)
|
|
121
|
+
if (
|
|
122
|
+
filters['q'] &&
|
|
123
|
+
(!Array.isArray(filters['q']) || filters['q'].length > 0) &&
|
|
124
|
+
!filters[ROUTE_PARAMS.SORT]
|
|
125
|
+
) {
|
|
126
|
+
this.facade.updateSearch({
|
|
127
|
+
...filters,
|
|
128
|
+
[ROUTE_PARAMS.SORT]: relevancySort,
|
|
129
|
+
})
|
|
130
|
+
}
|
|
131
|
+
})
|
|
132
|
+
),
|
|
133
|
+
{ dispatch: false }
|
|
134
|
+
)
|
|
135
|
+
|
|
106
136
|
/**
|
|
107
137
|
* This effect will load the metadata when a navigation to
|
|
108
138
|
* a metadata record happens
|
|
@@ -111,6 +111,8 @@ export function reducerSearch(
|
|
|
111
111
|
},
|
|
112
112
|
}
|
|
113
113
|
}
|
|
114
|
+
// From router.effects
|
|
115
|
+
// From home - fuzzy-search - search.service
|
|
114
116
|
case fromActions.SET_FILTERS: {
|
|
115
117
|
return {
|
|
116
118
|
...state,
|
|
@@ -132,6 +134,7 @@ export function reducerSearch(
|
|
|
132
134
|
},
|
|
133
135
|
}
|
|
134
136
|
}
|
|
137
|
+
// From results WC
|
|
135
138
|
case fromActions.SET_SEARCH: {
|
|
136
139
|
return {
|
|
137
140
|
...state,
|
|
@@ -138,9 +138,15 @@ export class FieldsService {
|
|
|
138
138
|
)
|
|
139
139
|
})
|
|
140
140
|
return forkJoin(filtersByField$).pipe(
|
|
141
|
-
map((filters) =>
|
|
142
|
-
|
|
143
|
-
|
|
141
|
+
map((filters) => {
|
|
142
|
+
if (typeof filters === 'string') {
|
|
143
|
+
return filters
|
|
144
|
+
}
|
|
145
|
+
return (filters as FieldFilters[]).reduce(
|
|
146
|
+
(prev, curr) => ({ ...prev, ...curr }),
|
|
147
|
+
{}
|
|
148
|
+
)
|
|
149
|
+
})
|
|
144
150
|
)
|
|
145
151
|
}
|
|
146
152
|
|
|
@@ -36,7 +36,7 @@ export abstract class AbstractSearchField {
|
|
|
36
36
|
abstract getAvailableValues(): Observable<FieldAvailableValue[] | DateRange[]>
|
|
37
37
|
abstract getFiltersForValues(
|
|
38
38
|
values: FieldValue[] | DateRange[]
|
|
39
|
-
): Observable<FieldFilters>
|
|
39
|
+
): Observable<FieldFilters | string>
|
|
40
40
|
abstract getValuesForFilter(
|
|
41
41
|
filters: FieldFilters
|
|
42
42
|
): Observable<FieldValue[] | FieldValue | DateRange>
|
|
@@ -89,7 +89,7 @@ export class SimpleSearchField implements AbstractSearchField {
|
|
|
89
89
|
}
|
|
90
90
|
getFiltersForValues(
|
|
91
91
|
values: FieldValue[] | DateRange[]
|
|
92
|
-
): Observable<FieldFilters> {
|
|
92
|
+
): Observable<FieldFilters | string> {
|
|
93
93
|
// FieldValue[]
|
|
94
94
|
if (this.getType() === 'values') {
|
|
95
95
|
return of({
|
|
@@ -538,7 +538,7 @@ export class RecordKindField extends SimpleSearchField {
|
|
|
538
538
|
])
|
|
539
539
|
}
|
|
540
540
|
|
|
541
|
-
getFiltersForValues(values: FieldValue[]): Observable<FieldFilters> {
|
|
541
|
+
getFiltersForValues(values: FieldValue[]): Observable<FieldFilters | string> {
|
|
542
542
|
const filters: FieldFilters = {
|
|
543
543
|
[this.esFieldName]: values.reduce((acc, value) => {
|
|
544
544
|
if (value === '') return { ...acc, [value]: true }
|
|
@@ -552,8 +552,8 @@ export class RecordKindField extends SimpleSearchField {
|
|
|
552
552
|
|
|
553
553
|
const presentationFormFilter = {}
|
|
554
554
|
if (values.includes('reuse') && !values.includes('dataset')) {
|
|
555
|
-
|
|
556
|
-
|
|
555
|
+
filters['gn-ui-crossFieldFilter'] =
|
|
556
|
+
`(resourceType:("dataset" OR "document") AND cl_presentationForm.key:("mapDigital" OR "mapHardcopy")) OR resourceType:("application" OR "interactiveMap" OR "map" OR "map/static" OR "map/interactive" OR "map-interactive" OR "map-static" OR "mapDigital" OR "mapHardcopy" OR "staticMap")`
|
|
557
557
|
} else if (values.includes('dataset') && !values.includes('reuse')) {
|
|
558
558
|
presentationFormFilter['mapDigital'] = false
|
|
559
559
|
presentationFormFilter['mapHardcopy'] = false
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
<div class="flex flex-row gap-2.5 items-center pt-1">
|
|
65
65
|
@if (link.accessServiceProtocol !== 'GPFDL') {
|
|
66
66
|
<span
|
|
67
|
-
class="bg-primary
|
|
67
|
+
class="bg-primary/50 uppercase inline-flex items-center justify-center px-2 py-1 text-13 font-medium leading-none text-white rounded text-primary-lightest group-hover:bg-primary transition-colors"
|
|
68
68
|
[ngClass]="{
|
|
69
69
|
'!bg-primary': currentlyActive,
|
|
70
70
|
}"
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
}
|
|
77
77
|
@if (link.accessServiceProtocol === 'GPFDL') {
|
|
78
78
|
<span
|
|
79
|
-
class="bg-primary
|
|
79
|
+
class="bg-primary/50 uppercase inline-flex items-center justify-center px-2 py-1 text-13 font-medium leading-none text-white rounded text-primary-lightest group-hover:bg-primary transition-colors"
|
|
80
80
|
[ngClass]="{
|
|
81
81
|
'!bg-primary': currentlyActive,
|
|
82
82
|
}"
|
|
@@ -45,13 +45,12 @@ export class ApplicationBannerComponent {
|
|
|
45
45
|
this.icon = 'matWarning'
|
|
46
46
|
break
|
|
47
47
|
case 'light':
|
|
48
|
-
this.msgClass =
|
|
49
|
-
'bg-primary-opacity-10 border-primary-lightest text-black'
|
|
48
|
+
this.msgClass = 'bg-primary/10 border-primary-lightest text-black'
|
|
50
49
|
this.icon = 'matInfoOutline'
|
|
51
50
|
break
|
|
52
51
|
case 'secondary':
|
|
53
52
|
default:
|
|
54
|
-
this.msgClass = 'bg-primary
|
|
53
|
+
this.msgClass = 'bg-primary/50 border-primary-darker text-black'
|
|
55
54
|
this.icon = 'matWarningAmberOutline'
|
|
56
55
|
break
|
|
57
56
|
}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
@if (previewUrl) {
|
|
2
|
-
<div class="w-
|
|
3
|
-
<gn-ui-image-overlay-preview
|
|
2
|
+
<div class="w-[314px] h-full flex flex-col gap-2">
|
|
3
|
+
<gn-ui-image-overlay-preview
|
|
4
|
+
class="w-[314px] h-[314px]"
|
|
5
|
+
[imageUrl]="previewUrl"
|
|
6
|
+
>
|
|
4
7
|
</gn-ui-image-overlay-preview>
|
|
5
8
|
@if (showAltTextInput) {
|
|
6
9
|
<gn-ui-text-input
|