geonetwork-ui 2.10.0-dev.f143bfdfa → 2.10.0-dev.f1c00d5fe
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 +1331 -6228
- package/fesm2022/geonetwork-ui.mjs.map +1 -1
- package/index.d.ts +186 -170
- package/index.d.ts.map +1 -1
- package/package.json +23 -33
- package/src/libs/api/metadata-converter/src/lib/dcat-ap/dcat-ap.converter.ts +11 -0
- package/src/libs/api/metadata-converter/src/lib/fixtures/eu.dcat-ap.records.ts +2 -0
- package/src/libs/api/metadata-converter/src/lib/fixtures/generic.records.ts +22 -0
- package/src/libs/api/metadata-converter/src/lib/fixtures/geo2france.records.reuse+ongules.ts +1 -0
- package/src/libs/api/metadata-converter/src/lib/fixtures/geo2france.records.reuse+roilaye.ts +1 -0
- package/src/libs/api/metadata-converter/src/lib/fixtures/geo2france.records.ts +1 -0
- package/src/libs/api/metadata-converter/src/lib/fixtures/geocat-ch.records.ts +1 -0
- package/src/libs/api/metadata-converter/src/lib/fixtures/georhena.records.ts +1 -0
- package/src/libs/api/metadata-converter/src/lib/fixtures/metadata-for-i18n.records.ts +2 -0
- package/src/libs/api/metadata-converter/src/lib/fixtures/metawal.records.ts +22 -0
- package/src/libs/api/metadata-converter/src/lib/fixtures/opendataswiss.records.ts +1 -0
- package/src/libs/api/metadata-converter/src/lib/fixtures/sextant.records.ts +2 -0
- package/src/libs/api/metadata-converter/src/lib/fixtures/vlaanderen.dcat-ap.records.ts +1 -0
- package/src/libs/api/metadata-converter/src/lib/fixtures/wallonie.records.reuse.ts +1 -0
- package/src/libs/api/metadata-converter/src/lib/gn4/atomic-operations.ts +48 -7
- package/src/libs/api/metadata-converter/src/lib/gn4/gn4.converter.ts +1 -0
- package/src/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.ts +6 -5
- package/src/libs/api/metadata-converter/src/lib/gn4/metadata-url.service.ts +2 -2
- package/src/libs/api/metadata-converter/src/lib/gn4/types/metadata.model.ts +1 -0
- package/src/libs/api/metadata-converter/src/lib/iso19115-3/iso19115-3.converter.ts +4 -0
- package/src/libs/api/metadata-converter/src/lib/iso19115-3/read-parts.ts +13 -0
- package/src/libs/api/metadata-converter/src/lib/iso19115-3/write-parts.ts +45 -1
- package/src/libs/api/metadata-converter/src/lib/iso19139/iso19139.converter.ts +13 -1
- package/src/libs/api/metadata-converter/src/lib/iso19139/read-parts.ts +40 -0
- package/src/libs/api/metadata-converter/src/lib/iso19139/write-parts.ts +47 -1
- package/src/libs/api/repository/src/lib/gn4/auth/auth.service.ts +4 -4
- package/src/libs/api/repository/src/lib/gn4/elasticsearch/elasticsearch.service.ts +2 -2
- package/src/libs/api/repository/src/lib/gn4/gn4-repository.ts +12 -8
- package/src/libs/api/repository/src/lib/gn4/organizations/organizations-from-groups.service.ts +1 -1
- package/src/libs/api/repository/src/lib/gn4/organizations/organizations-from-metadata.service.ts +1 -1
- package/src/libs/api/repository/src/lib/gn4/platform/gn4-platform.service.ts +11 -22
- package/src/libs/common/domain/src/lib/model/record/metadata.model.ts +12 -5
- package/src/libs/common/domain/src/lib/model/thesaurus/thesaurus.model.ts +2 -1
- package/src/libs/common/domain/src/lib/repository/records-repository.interface.ts +2 -1
- package/src/libs/common/fixtures/src/lib/records.fixtures.ts +57 -0
- package/src/libs/feature/catalog/src/lib/sources/sources.service.ts +5 -2
- package/src/libs/feature/editor/src/index.ts +1 -0
- package/src/libs/feature/editor/src/lib/+state/editor.actions.ts +4 -1
- package/src/libs/feature/editor/src/lib/+state/editor.effects.ts +26 -19
- package/src/libs/feature/editor/src/lib/+state/editor.facade.ts +5 -1
- package/src/libs/feature/editor/src/lib/components/constraint-card/constraint-card.component.ts +0 -2
- package/src/libs/feature/editor/src/lib/components/contact-details/contact-details-form.component.html +7 -6
- package/src/libs/feature/editor/src/lib/components/contact-details/contact-details-form.component.ts +10 -8
- package/src/libs/feature/editor/src/lib/components/generic-keywords/generic-keywords.component.html +5 -14
- package/src/libs/feature/editor/src/lib/components/generic-keywords/generic-keywords.component.ts +3 -28
- package/src/libs/feature/editor/src/lib/components/online-service-resource-input/online-service-resource-input.component.html +5 -5
- package/src/libs/feature/editor/src/lib/components/online-service-resource-input/online-service-resource-input.component.ts +2 -1
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/field-focus.directive.ts +4 -1
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-constraints-shortcuts/form-field-constraints-shortcuts.component.ts +7 -7
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-resources/form-field-online-resources.component.ts +1 -1
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-overviews/form-field-overviews.component.ts +12 -5
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-rich/form-field-rich.component.html +4 -4
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-rich/form-field-rich.component.ts +7 -0
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-topics/form-field-topics.component.ts +2 -2
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-update-frequency/form-field-update-frequency.component.html +6 -2
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-update-frequency/form-field-update-frequency.component.ts +3 -1
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.css +0 -34
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.html +27 -16
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.ts +11 -0
- package/src/libs/feature/editor/src/lib/components/record-form/record-form.component.css +35 -0
- package/src/libs/feature/editor/src/lib/components/record-form/record-form.component.html +18 -5
- package/src/libs/feature/editor/src/lib/components/record-form/record-form.component.ts +76 -19
- package/src/libs/feature/editor/src/lib/expressions.ts +380 -8
- package/src/libs/feature/editor/src/lib/fields.config.ts +354 -337
- package/src/libs/feature/editor/src/lib/models/editor-config.model.ts +6 -3
- package/src/libs/feature/editor/src/lib/services/editor.service.ts +8 -12
- package/src/libs/feature/map/src/lib/utils/map-utils.service.ts +33 -0
- package/src/libs/feature/notify-reuse/src/index.ts +1 -0
- package/src/libs/feature/notify-reuse/src/lib/edit-delete-reuse-buttons/edit-delete-reuse-buttons.component.css +0 -0
- package/src/libs/feature/notify-reuse/src/lib/edit-delete-reuse-buttons/edit-delete-reuse-buttons.component.html +23 -0
- package/src/libs/feature/notify-reuse/src/lib/edit-delete-reuse-buttons/edit-delete-reuse-buttons.component.ts +114 -0
- package/src/libs/feature/notify-reuse/src/lib/notify-reuse-form/notify-reuse-form.component.html +111 -1
- package/src/libs/feature/notify-reuse/src/lib/notify-reuse-form/notify-reuse-form.component.ts +221 -8
- package/src/libs/feature/notify-reuse/src/lib/utils/url.ts +16 -0
- package/src/libs/feature/record/src/lib/map-view/map-view.component.ts +9 -1
- package/src/libs/feature/search/src/lib/results-table/results-table-container.component.ts +10 -5
- package/src/libs/ui/catalog/src/lib/language-switcher/language-switcher.component.ts +2 -2
- package/src/libs/ui/dataviz/src/index.ts +0 -1
- package/src/libs/ui/elements/src/index.ts +1 -0
- package/src/libs/ui/elements/src/lib/contact-details/contact-details.component.html +48 -56
- package/src/libs/ui/elements/src/lib/external-link-card/external-link-card.component.html +2 -1
- package/src/libs/ui/elements/src/lib/external-link-card/external-link-card.component.ts +2 -2
- package/src/libs/ui/elements/src/lib/image-overlay-preview/image-overlay-preview.component.css +13 -0
- package/src/libs/ui/elements/src/lib/image-overlay-preview/image-overlay-preview.component.html +13 -3
- package/src/libs/ui/elements/src/lib/image-overlay-preview/image-overlay-preview.component.ts +43 -6
- package/src/libs/ui/elements/src/lib/keyword-badge/keyword-badge.component.html +14 -0
- package/src/libs/ui/elements/src/lib/keyword-badge/keyword-badge.component.ts +85 -0
- package/src/libs/ui/elements/src/lib/markdown-parser/markdown-parser.component.ts +2 -2
- package/src/libs/ui/elements/src/lib/metadata-info/metadata-info.component.css +5 -0
- package/src/libs/ui/elements/src/lib/metadata-info/metadata-info.component.html +4 -7
- package/src/libs/ui/elements/src/lib/metadata-info/metadata-info.component.ts +2 -2
- package/src/libs/ui/elements/src/lib/record-api-form/record-api-form.component.html +4 -5
- package/src/libs/ui/elements/src/lib/record-api-form/record-api-form.component.ts +4 -0
- package/src/libs/ui/inputs/src/lib/badge/badge.component.html +33 -26
- package/src/libs/ui/inputs/src/lib/badge/badge.component.ts +9 -0
- package/src/libs/ui/inputs/src/lib/date-picker/date-picker.component.ts +2 -2
- package/src/libs/ui/inputs/src/lib/dropdown-multiselect/dropdown-multiselect.component.html +1 -1
- package/src/libs/ui/inputs/src/lib/dropdown-multiselect/dropdown-multiselect.component.ts +3 -3
- package/src/libs/ui/inputs/src/lib/text-input/text-input.component.css +0 -3
- package/src/libs/ui/inputs/src/lib/text-input/text-input.component.html +11 -7
- package/src/libs/ui/inputs/src/lib/text-input/text-input.component.ts +56 -30
- package/src/libs/ui/layout/src/lib/form-field-wrapper/form-field-wrapper.component.html +5 -5
- package/src/libs/ui/layout/src/lib/form-field-wrapper/form-field-wrapper.component.ts +9 -1
- package/src/libs/ui/layout/src/lib/interactive-table/interactive-table.component.html +1 -1
- package/src/libs/ui/layout/src/lib/interactive-table/interactive-table.component.ts +3 -8
- package/src/libs/ui/layout/src/lib/sortable-list/sortable-list.component.html +7 -7
- package/src/libs/ui/layout/src/lib/sortable-list/sortable-list.component.ts +14 -1
- package/src/libs/ui/map/src/lib/components/spatial-extent/spatial-extent.component.ts +4 -54
- package/src/libs/ui/map/src/lib/map-utils.ts +48 -0
- package/src/libs/ui/search/src/lib/record-preview-feed/record-preview-feed.component.ts +1 -1
- package/src/libs/ui/search/src/lib/results-table/action-menu/action-menu.component.html +12 -8
- package/src/libs/ui/search/src/lib/results-table/action-menu/action-menu.component.ts +3 -1
- package/src/libs/ui/search/src/lib/results-table/results-table.component.html +1 -0
- package/src/libs/ui/widgets/src/lib/popover/popover.component.ts +7 -1
- package/src/libs/ui/widgets/src/lib/spinning-loader/spinning-loader.component.html +1 -1
- package/src/libs/util/app-config/src/lib/app-config.ts +21 -9
- package/src/libs/util/data-fetcher/src/lib/readers/base-file.ts +1 -2
- package/src/libs/util/data-fetcher/src/lib/readers/wfs.ts +6 -3
- package/src/libs/util/i18n/src/index.ts +0 -1
- package/src/libs/util/i18n/src/lib/i18n.constants.ts +17 -11
- package/src/libs/util/i18n/src/lib/i18n.interceptor.ts +2 -2
- package/src/libs/util/i18n/src/lib/i18n.providers.ts +14 -17
- package/src/libs/util/i18n/src/lib/test.translate.loader.ts +48 -0
- package/src/libs/util/shared/src/lib/links/link-utils.ts +22 -0
- package/src/libs/util/shared/src/lib/services/date.service.ts +3 -3
- package/src/libs/util/shared/src/lib/utils/geojson.ts +58 -1
- package/style.css +0 -1
- package/tailwind.base.css +9 -0
- package/translations/de.json +102 -49
- package/translations/en.json +112 -59
- package/translations/es.json +76 -23
- package/translations/fr.json +109 -56
- package/translations/it.json +103 -50
- package/translations/nl.json +75 -22
- package/translations/pt.json +76 -23
- package/translations/sk.json +76 -23
- package/src/libs/feature/editor/src/lib/components/generic-keywords/generic-keywords.component.css +0 -3
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
HttpErrorResponse,
|
|
4
4
|
HttpHeaders,
|
|
5
5
|
} from '@angular/common/http'
|
|
6
|
-
import { Injectable, InjectionToken
|
|
6
|
+
import { inject, Injectable, InjectionToken } from '@angular/core'
|
|
7
7
|
import {
|
|
8
8
|
assertValidXml,
|
|
9
9
|
BaseConverter,
|
|
@@ -327,8 +327,10 @@ export class Gn4Repository implements RecordsRepositoryInterface {
|
|
|
327
327
|
return this.settingsService.allowEditHarvested$.pipe(
|
|
328
328
|
map((allowEditHarvested) => {
|
|
329
329
|
return (
|
|
330
|
-
|
|
331
|
-
|
|
330
|
+
(this.platformService.supportsAuthentication() &&
|
|
331
|
+
record.extras?.['edit'] &&
|
|
332
|
+
(!record.extras?.['isHarvested'] || allowEditHarvested)) ??
|
|
333
|
+
false
|
|
332
334
|
)
|
|
333
335
|
})
|
|
334
336
|
)
|
|
@@ -336,10 +338,10 @@ export class Gn4Repository implements RecordsRepositoryInterface {
|
|
|
336
338
|
|
|
337
339
|
private canEdit(record: CatalogRecord, allowEditHarvested: boolean): boolean {
|
|
338
340
|
return (
|
|
339
|
-
this.platformService.supportsAuthentication() &&
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
341
|
+
(this.platformService.supportsAuthentication() &&
|
|
342
|
+
record.extras?.['edit'] &&
|
|
343
|
+
(!record.extras?.['isHarvested'] || allowEditHarvested)) ??
|
|
344
|
+
false
|
|
343
345
|
)
|
|
344
346
|
}
|
|
345
347
|
|
|
@@ -361,8 +363,10 @@ export class Gn4Repository implements RecordsRepositoryInterface {
|
|
|
361
363
|
}
|
|
362
364
|
|
|
363
365
|
openRecordForEdition(
|
|
364
|
-
uniqueIdentifier: string
|
|
366
|
+
uniqueIdentifier: string,
|
|
367
|
+
disableDraft?: boolean
|
|
365
368
|
): Observable<[CatalogRecord, string, boolean] | null> {
|
|
369
|
+
this.disableDraft = disableDraft ?? this.disableDraft
|
|
366
370
|
const draft$ = this.disableDraft
|
|
367
371
|
? of(null)
|
|
368
372
|
: of(this.getRecordFromLocalStorage(uniqueIdentifier))
|
package/src/libs/api/repository/src/lib/gn4/organizations/organizations-from-groups.service.ts
CHANGED
|
@@ -52,7 +52,7 @@ export class OrganizationsFromGroupsService
|
|
|
52
52
|
organisationsCount$ = this.organisations$.pipe(map((orgs) => orgs.length))
|
|
53
53
|
|
|
54
54
|
private get lang3() {
|
|
55
|
-
return toLang3(this.translateService.
|
|
55
|
+
return toLang3(this.translateService.getCurrentLang())
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
constructor(
|
package/src/libs/api/repository/src/lib/gn4/organizations/organizations-from-metadata.service.ts
CHANGED
|
@@ -128,7 +128,7 @@ export class OrganizationsFromMetadataService
|
|
|
128
128
|
) {}
|
|
129
129
|
|
|
130
130
|
private get langIndex() {
|
|
131
|
-
return `lang${toLang3(this.translateService.
|
|
131
|
+
return `lang${toLang3(this.translateService.getCurrentLang())}`
|
|
132
132
|
}
|
|
133
133
|
|
|
134
134
|
equalsNormalizedStrings(
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { HttpClient, HttpEventType } from '@angular/common/http'
|
|
2
|
-
import { Injectable, InjectionToken
|
|
2
|
+
import { inject, Injectable, InjectionToken } from '@angular/core'
|
|
3
3
|
import {
|
|
4
4
|
KeywordApiResponse,
|
|
5
5
|
ThesaurusApiResponse,
|
|
@@ -100,7 +100,7 @@ export class Gn4PlatformService implements PlatformServiceInterface {
|
|
|
100
100
|
private keywordsByThesauri: Record<string, Observable<Keyword[]>> = {}
|
|
101
101
|
|
|
102
102
|
private get lang3() {
|
|
103
|
-
return toLang3(this.translateService.
|
|
103
|
+
return toLang3(this.translateService.getCurrentLang())
|
|
104
104
|
}
|
|
105
105
|
|
|
106
106
|
constructor() {
|
|
@@ -177,26 +177,15 @@ export class Gn4PlatformService implements PlatformServiceInterface {
|
|
|
177
177
|
const editorIds = meResponse.groupsWithEditor ?? []
|
|
178
178
|
const memberIds = meResponse.groupsWithRegisteredUser ?? []
|
|
179
179
|
const adminIds = meResponse.groupsWithUserAdmin ?? []
|
|
180
|
-
|
|
181
|
-
return
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
.map((id) => {
|
|
190
|
-
const group = groupsById.get(id)
|
|
191
|
-
return {
|
|
192
|
-
groupId: group.id,
|
|
193
|
-
groupName: group.name,
|
|
194
|
-
isMember: memberIds.includes(id),
|
|
195
|
-
canEdit: editorIds.includes(id),
|
|
196
|
-
canApprove: reviewerIds.includes(id),
|
|
197
|
-
canAdministrate: adminIds.includes(id),
|
|
198
|
-
}
|
|
199
|
-
})
|
|
180
|
+
|
|
181
|
+
return groups.map((group) => ({
|
|
182
|
+
groupId: group.id,
|
|
183
|
+
groupName: group.name,
|
|
184
|
+
isMember: memberIds.includes(group.id),
|
|
185
|
+
canEdit: editorIds.includes(group.id),
|
|
186
|
+
canApprove: reviewerIds.includes(group.id),
|
|
187
|
+
canAdministrate: adminIds.includes(group.id),
|
|
188
|
+
}))
|
|
200
189
|
})
|
|
201
190
|
)
|
|
202
191
|
}
|
|
@@ -104,15 +104,12 @@ export interface Keyword {
|
|
|
104
104
|
type: KeywordType
|
|
105
105
|
thesaurus?: ThesaurusModel
|
|
106
106
|
bbox?: [number, number, number, number]
|
|
107
|
+
// thesaurus hierarchy path incl. the keyword as last element; unset for root-level keywords
|
|
108
|
+
hierarchyPath?: string[]
|
|
107
109
|
|
|
108
110
|
translations?: KeywordTranslations
|
|
109
111
|
}
|
|
110
112
|
|
|
111
|
-
export interface INSPIRE_topic {
|
|
112
|
-
value: string
|
|
113
|
-
label: string
|
|
114
|
-
}
|
|
115
|
-
|
|
116
113
|
export interface ResourceIdentifier {
|
|
117
114
|
code: string
|
|
118
115
|
codeSpace?: string
|
|
@@ -263,11 +260,20 @@ export interface SourceRecord {
|
|
|
263
260
|
href?: string
|
|
264
261
|
}
|
|
265
262
|
|
|
263
|
+
/**
|
|
264
|
+
* Represents another record associated with this one (e.g. a parent/sibling dataset).
|
|
265
|
+
*/
|
|
266
|
+
export interface AssociatedRecord {
|
|
267
|
+
uuid: string
|
|
268
|
+
associationType: string
|
|
269
|
+
}
|
|
270
|
+
|
|
266
271
|
export interface DatasetRecord extends BaseRecord {
|
|
267
272
|
kind: 'dataset'
|
|
268
273
|
status: RecordStatus
|
|
269
274
|
lineage: string // Explanation of the origin of this record (e.g: how, why)"
|
|
270
275
|
sourceRecords: Array<SourceRecord>
|
|
276
|
+
associatedRecords: Array<AssociatedRecord>
|
|
271
277
|
onlineResources: Array<DatasetOnlineResource>
|
|
272
278
|
spatialExtents: Array<DatasetSpatialExtent>
|
|
273
279
|
temporalExtents: Array<DatasetTemporalExtent>
|
|
@@ -296,6 +302,7 @@ export interface ReuseRecord extends BaseRecord {
|
|
|
296
302
|
kind: 'reuse'
|
|
297
303
|
lineage: string // Explanation of the origin of this record (e.g: how, why)"
|
|
298
304
|
sourceRecords: Array<SourceRecord>
|
|
305
|
+
associatedRecords: Array<AssociatedRecord>
|
|
299
306
|
onlineResources: Array<DatasetOnlineResource>
|
|
300
307
|
reuseType: ReuseType
|
|
301
308
|
spatialExtents: Array<DatasetSpatialExtent>
|
|
@@ -39,7 +39,8 @@ export abstract class RecordsRepositoryInterface {
|
|
|
39
39
|
* @returns Observable<[CatalogRecord, string, boolean] | null>
|
|
40
40
|
*/
|
|
41
41
|
abstract openRecordForEdition(
|
|
42
|
-
uniqueIdentifier: string
|
|
42
|
+
uniqueIdentifier: string,
|
|
43
|
+
disableDraft?: boolean
|
|
43
44
|
): Observable<[CatalogRecord, string, boolean] | null>
|
|
44
45
|
|
|
45
46
|
/**
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
DatasetRecord,
|
|
4
4
|
DatasetSpatialExtent,
|
|
5
5
|
Keyword,
|
|
6
|
+
ReuseRecord,
|
|
6
7
|
ServiceRecord,
|
|
7
8
|
} from '../../../../../libs/common/domain/src/lib/model/record'
|
|
8
9
|
|
|
@@ -135,6 +136,7 @@ Cette section contient des *caractères internationaux* (ainsi que des "caractè
|
|
|
135
136
|
|
|
136
137
|
As such, **it is not very interesting at all.**`,
|
|
137
138
|
sourceRecords: [],
|
|
139
|
+
associatedRecords: [],
|
|
138
140
|
licenses: [
|
|
139
141
|
{
|
|
140
142
|
text: 'Licence ODbL mai 2013 (basée sur ODbL 1.0)',
|
|
@@ -312,6 +314,7 @@ Malgré l'attention portée à la création de ces données, il est rappelé que
|
|
|
312
314
|
lineage: `Document d’urbanisme numérisé conformément aux prescriptions nationales du CNIG par le Service d'Information Géographique de l'Agglomération de la Région de Compiègne.
|
|
313
315
|
Ce lot de données produit en 2019, a été numérisé à partir du PCI Vecteur de 2019 et contrôlé par le Service d'Information Géographique de l'Agglomération de la Région de Compiègne.`,
|
|
314
316
|
sourceRecords: [],
|
|
317
|
+
associatedRecords: [],
|
|
315
318
|
legalConstraints: [],
|
|
316
319
|
securityConstraints: [],
|
|
317
320
|
otherConstraints: [],
|
|
@@ -364,6 +367,7 @@ export const simpleDatasetRecordFixture = (): DatasetRecord => ({
|
|
|
364
367
|
spatialExtents: [],
|
|
365
368
|
temporalExtents: [],
|
|
366
369
|
sourceRecords: [],
|
|
370
|
+
associatedRecords: [],
|
|
367
371
|
onlineResources: [
|
|
368
372
|
{
|
|
369
373
|
type: 'download',
|
|
@@ -417,6 +421,7 @@ export const simpleDatasetRecordWithFcatsFixture = (): DatasetRecord => ({
|
|
|
417
421
|
spatialExtents: [],
|
|
418
422
|
temporalExtents: [],
|
|
419
423
|
sourceRecords: [],
|
|
424
|
+
associatedRecords: [],
|
|
420
425
|
onlineResources: [],
|
|
421
426
|
updateFrequency: { per: 'month', updatedTimes: 3 },
|
|
422
427
|
translations: {},
|
|
@@ -983,6 +988,7 @@ export const multilingualDatasetFixture: () => DatasetRecord = () => ({
|
|
|
983
988
|
abstract: 'English Abstract',
|
|
984
989
|
lineage: 'English Lineage',
|
|
985
990
|
sourceRecords: [],
|
|
991
|
+
associatedRecords: [],
|
|
986
992
|
translations: {
|
|
987
993
|
title: { fr: 'Titre Français', de: 'Titel DE' },
|
|
988
994
|
abstract: { fr: 'Résumé Français', de: 'Beschreibung DE' },
|
|
@@ -1027,3 +1033,54 @@ export const multilingualDatasetFixture: () => DatasetRecord = () => ({
|
|
|
1027
1033
|
topics: [],
|
|
1028
1034
|
recordUpdated: null,
|
|
1029
1035
|
})
|
|
1036
|
+
|
|
1037
|
+
export const simpleReuseRecordFixture = (): ReuseRecord => ({
|
|
1038
|
+
abstract: `Sample reuse record`,
|
|
1039
|
+
kind: 'reuse',
|
|
1040
|
+
reuseType: 'application',
|
|
1041
|
+
recordUpdated: new Date('2023-03-17T07:38:08.875Z'),
|
|
1042
|
+
recordPublished: null,
|
|
1043
|
+
ownerOrganization: null,
|
|
1044
|
+
licenses: [],
|
|
1045
|
+
legalConstraints: [],
|
|
1046
|
+
securityConstraints: [],
|
|
1047
|
+
otherConstraints: [],
|
|
1048
|
+
contacts: [],
|
|
1049
|
+
contactsForResource: [],
|
|
1050
|
+
keywords: [],
|
|
1051
|
+
topics: [],
|
|
1052
|
+
spatialExtents: [],
|
|
1053
|
+
temporalExtents: [],
|
|
1054
|
+
lineage: 'bla',
|
|
1055
|
+
sourceRecords: [],
|
|
1056
|
+
associatedRecords: [],
|
|
1057
|
+
overviews: [],
|
|
1058
|
+
defaultLanguage: null,
|
|
1059
|
+
otherLanguages: [],
|
|
1060
|
+
title: 'Sites de gestion des déchets miniers - Service de visualisation WMS',
|
|
1061
|
+
onlineResources: [
|
|
1062
|
+
{
|
|
1063
|
+
name: 'Rapport de disponibilité du service WMS',
|
|
1064
|
+
description:
|
|
1065
|
+
'Ce service de visualisation WMS permet de consulter la série de couches de données "Sites de gestion des déchets miniers - Série".',
|
|
1066
|
+
mimeType: 'text/html',
|
|
1067
|
+
type: 'link',
|
|
1068
|
+
url: new URL(
|
|
1069
|
+
'https://geoservices.wallonie.be/rapportDisponibilite/wms/sites_de_gestion_des_dechets_miniers_srie.html'
|
|
1070
|
+
),
|
|
1071
|
+
accessRestricted: false,
|
|
1072
|
+
},
|
|
1073
|
+
],
|
|
1074
|
+
uniqueIdentifier: '00b22798-ec8e-4500-89e8-90eeeda45919',
|
|
1075
|
+
landingPage: new URL(
|
|
1076
|
+
'http://localhost:4200/geonetwork/srv/fre/catalog.search#/metadata/00b22798-ec8e-4500-89e8-90eeeda45919'
|
|
1077
|
+
),
|
|
1078
|
+
extras: {
|
|
1079
|
+
isPublishedToAll: true,
|
|
1080
|
+
id: '723',
|
|
1081
|
+
isHarvested: true,
|
|
1082
|
+
ownerInfo: 'admin|admin|admin|Administrator',
|
|
1083
|
+
edit: true,
|
|
1084
|
+
},
|
|
1085
|
+
recordCreated: new Date('2023-03-17T07:38:08.875Z'),
|
|
1086
|
+
})
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { inject, Injectable } from '@angular/core'
|
|
2
2
|
import { SourcesApiService } from '../../../../../../libs/data-access/gn4/src'
|
|
3
3
|
import { Observable } from 'rxjs'
|
|
4
4
|
import { filter, map, shareReplay } from 'rxjs/operators'
|
|
@@ -21,7 +21,10 @@ export class SourcesService {
|
|
|
21
21
|
return this.sources$.pipe(
|
|
22
22
|
map((sources) => sources.filter((source) => source.uuid === uuid)[0]),
|
|
23
23
|
filter((source) => !!source),
|
|
24
|
-
map(
|
|
24
|
+
map(
|
|
25
|
+
(source) =>
|
|
26
|
+
source.label[toLang3(this.translateService.getCurrentLang())]
|
|
27
|
+
)
|
|
25
28
|
)
|
|
26
29
|
}
|
|
27
30
|
}
|
|
@@ -3,6 +3,7 @@ export * from './lib/+state/editor.facade'
|
|
|
3
3
|
export * from './lib/+state/editor.models'
|
|
4
4
|
export * from './lib/+state/editor.reducer'
|
|
5
5
|
export * from './lib/+state/editor.selectors'
|
|
6
|
+
export * from './lib/components/contact-details/contact-details-form.component'
|
|
6
7
|
export * from './lib/components/import-record/import-record.component'
|
|
7
8
|
export * from './lib/components/metadata-quality-panel/metadata-quality-panel.component'
|
|
8
9
|
export * from './lib/components/multilingual-panel/multilingual-panel.component'
|
|
@@ -29,7 +29,10 @@ export const markRecordAsChanged = createAction(
|
|
|
29
29
|
'[Editor] Mark record as changed'
|
|
30
30
|
)
|
|
31
31
|
|
|
32
|
-
export const saveRecord = createAction(
|
|
32
|
+
export const saveRecord = createAction(
|
|
33
|
+
'[Editor] Save record',
|
|
34
|
+
props<{ publish: boolean }>()
|
|
35
|
+
)
|
|
33
36
|
export const saveRecordSuccess = createAction('[Editor] Save record success')
|
|
34
37
|
export const saveRecordFailure = createAction(
|
|
35
38
|
'[Editor] Save record failure',
|
|
@@ -28,30 +28,37 @@ export class EditorEffects {
|
|
|
28
28
|
this.store.select(selectRecordSource),
|
|
29
29
|
this.store.select(selectEditorConfig)
|
|
30
30
|
),
|
|
31
|
-
switchMap(([, record, recordSource, fieldsConfig]) =>
|
|
32
|
-
this.editorService
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
switchMap(([{ publish }, record, recordSource, fieldsConfig]) =>
|
|
32
|
+
this.editorService
|
|
33
|
+
.saveRecord(record, recordSource, fieldsConfig, publish)
|
|
34
|
+
.pipe(
|
|
35
|
+
switchMap(([savedRecord, savedRecordSource]) => {
|
|
36
|
+
const actions: Action[] = [EditorActions.saveRecordSuccess()]
|
|
37
|
+
|
|
38
|
+
if (publish) {
|
|
39
|
+
// saving without publishing doesn't unpublish
|
|
40
|
+
actions.push(EditorActions.isPublished({ isPublished: true }))
|
|
41
|
+
}
|
|
35
42
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
43
|
+
if (!record?.uniqueIdentifier) {
|
|
44
|
+
actions.push(
|
|
45
|
+
EditorActions.openRecord({
|
|
46
|
+
record: savedRecord,
|
|
47
|
+
recordSource: savedRecordSource,
|
|
48
|
+
})
|
|
49
|
+
)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return of(...actions)
|
|
53
|
+
}),
|
|
54
|
+
catchError((error) =>
|
|
55
|
+
of(
|
|
56
|
+
EditorActions.saveRecordFailure({
|
|
57
|
+
error,
|
|
41
58
|
})
|
|
42
59
|
)
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
return of(...actions)
|
|
46
|
-
}),
|
|
47
|
-
catchError((error) =>
|
|
48
|
-
of(
|
|
49
|
-
EditorActions.saveRecordFailure({
|
|
50
|
-
error,
|
|
51
|
-
})
|
|
52
60
|
)
|
|
53
61
|
)
|
|
54
|
-
)
|
|
55
62
|
)
|
|
56
63
|
)
|
|
57
64
|
)
|
|
@@ -54,7 +54,11 @@ export class EditorFacade {
|
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
saveRecord() {
|
|
57
|
-
this.store.dispatch(EditorActions.saveRecord())
|
|
57
|
+
this.store.dispatch(EditorActions.saveRecord({ publish: false }))
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
saveAndPublishRecord() {
|
|
61
|
+
this.store.dispatch(EditorActions.saveRecord({ publish: true }))
|
|
58
62
|
}
|
|
59
63
|
|
|
60
64
|
undoRecordDraft() {
|
package/src/libs/feature/editor/src/lib/components/constraint-card/constraint-card.component.ts
CHANGED
|
@@ -8,7 +8,6 @@ import {
|
|
|
8
8
|
|
|
9
9
|
import { FormFieldRichComponent } from '../record-form/form-field/form-field-rich/form-field-rich.component'
|
|
10
10
|
import { ButtonComponent, UrlInputComponent } from '../../../../../../../libs/ui/inputs/src'
|
|
11
|
-
import { MatIconModule } from '@angular/material/icon'
|
|
12
11
|
import { TranslateDirective, TranslatePipe } from '@ngx-translate/core'
|
|
13
12
|
import { Constraint } from '../../../../../../../libs/common/domain/src/lib/model/record'
|
|
14
13
|
import {
|
|
@@ -26,7 +25,6 @@ import { marker } from '@biesbjerg/ngx-translate-extract-marker'
|
|
|
26
25
|
FormFieldRichComponent,
|
|
27
26
|
UrlInputComponent,
|
|
28
27
|
ButtonComponent,
|
|
29
|
-
MatIconModule,
|
|
30
28
|
TranslateDirective,
|
|
31
29
|
TranslatePipe,
|
|
32
30
|
NgIconComponent,
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
<gn-ui-text-input
|
|
8
8
|
class="block w-full"
|
|
9
9
|
extraClass="w-full"
|
|
10
|
-
[
|
|
11
|
-
(valueChange)="
|
|
10
|
+
[value]="contact.lastName ?? ''"
|
|
11
|
+
(valueChange)="handleChange({ lastName: $event })"
|
|
12
12
|
[placeholder]="
|
|
13
13
|
'editor.record.form.field.contactDetails.lastName.placeholder'
|
|
14
14
|
| translate
|
|
@@ -23,8 +23,8 @@
|
|
|
23
23
|
<gn-ui-text-input
|
|
24
24
|
class="block w-full"
|
|
25
25
|
extraClass="w-full"
|
|
26
|
-
[
|
|
27
|
-
(valueChange)="
|
|
26
|
+
[value]="contact.firstName ?? ''"
|
|
27
|
+
(valueChange)="handleChange({ firstName: $event })"
|
|
28
28
|
[placeholder]="
|
|
29
29
|
'editor.record.form.field.contactDetails.firstName.placeholder'
|
|
30
30
|
| translate
|
|
@@ -40,8 +40,9 @@
|
|
|
40
40
|
<gn-ui-text-input
|
|
41
41
|
class="block w-full"
|
|
42
42
|
extraClass="w-full"
|
|
43
|
-
[
|
|
44
|
-
|
|
43
|
+
[type]="'email'"
|
|
44
|
+
[value]="contact.email ?? ''"
|
|
45
|
+
(valueChange)="handleChange({ email: $event })"
|
|
45
46
|
[placeholder]="
|
|
46
47
|
'editor.record.form.field.contactDetails.email.placeholder' | translate
|
|
47
48
|
"
|
package/src/libs/feature/editor/src/lib/components/contact-details/contact-details-form.component.ts
CHANGED
|
@@ -24,16 +24,18 @@ export class ContactDetailsFormComponent {
|
|
|
24
24
|
@Input() contact: Individual
|
|
25
25
|
@Output() contactChange = new EventEmitter<Individual>()
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
// emit a fresh contact on each change; never mutate the @Input
|
|
28
|
+
handleChange(change: Partial<Individual>) {
|
|
29
|
+
this.contactChange.emit({ ...this.contact, ...change })
|
|
29
30
|
}
|
|
30
31
|
|
|
31
32
|
handleOrganizationChange(change: Partial<Organization>) {
|
|
32
|
-
this.
|
|
33
|
-
...
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
33
|
+
this.contactChange.emit({
|
|
34
|
+
...this.contact,
|
|
35
|
+
organization: {
|
|
36
|
+
...(this.contact.organization ?? ({} as Organization)),
|
|
37
|
+
...change,
|
|
38
|
+
} as Organization,
|
|
39
|
+
})
|
|
38
40
|
}
|
|
39
41
|
}
|
package/src/libs/feature/editor/src/lib/components/generic-keywords/generic-keywords.component.html
CHANGED
|
@@ -11,20 +11,11 @@
|
|
|
11
11
|
></gn-ui-autocomplete>
|
|
12
12
|
<div class="flex gap-2 flex-wrap">
|
|
13
13
|
@for (keyword of keywords; track keyword) {
|
|
14
|
-
<gn-ui-badge
|
|
15
|
-
[
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
<ng-icon
|
|
20
|
-
[title]="
|
|
21
|
-
'editor.record.form.keywords.place.withoutExtent' | translate
|
|
22
|
-
"
|
|
23
|
-
class="badge-warning"
|
|
24
|
-
name="matWarningAmberOutline"
|
|
25
|
-
></ng-icon>
|
|
26
|
-
}
|
|
27
|
-
</gn-ui-badge>
|
|
14
|
+
<gn-ui-keyword-badge
|
|
15
|
+
[keyword]="keyword"
|
|
16
|
+
[editable]="true"
|
|
17
|
+
(keywordRemove)="removeKeyword($event)"
|
|
18
|
+
></gn-ui-keyword-badge>
|
|
28
19
|
}
|
|
29
20
|
</div>
|
|
30
21
|
</div>
|
package/src/libs/feature/editor/src/lib/components/generic-keywords/generic-keywords.component.ts
CHANGED
|
@@ -7,40 +7,20 @@ import {
|
|
|
7
7
|
inject,
|
|
8
8
|
} from '@angular/core'
|
|
9
9
|
import { PlatformServiceInterface } from '../../../../../../../libs/common/domain/src/lib/platform.service.interface'
|
|
10
|
-
import { AutocompleteComponent
|
|
10
|
+
import { AutocompleteComponent } from '../../../../../../../libs/ui/inputs/src'
|
|
11
|
+
import { KeywordBadgeComponent } from '../../../../../../../libs/ui/elements/src'
|
|
11
12
|
import { map } from 'rxjs'
|
|
12
13
|
import { Keyword } from '../../../../../../../libs/common/domain/src/lib/model/record'
|
|
13
14
|
import { KeywordType } from '../../../../../../../libs/common/domain/src/lib/model/thesaurus'
|
|
14
|
-
import { TranslatePipe } from '@ngx-translate/core'
|
|
15
|
-
import {
|
|
16
|
-
NgIconComponent,
|
|
17
|
-
provideIcons,
|
|
18
|
-
provideNgIconsConfig,
|
|
19
|
-
} from '@ng-icons/core'
|
|
20
|
-
import { matWarningAmberOutline } from '@ng-icons/material-icons/outline'
|
|
21
15
|
|
|
22
16
|
type AutocompleteItem = { title: string; value: Keyword }
|
|
23
17
|
|
|
24
18
|
@Component({
|
|
25
19
|
selector: 'gn-ui-generic-keywords',
|
|
26
20
|
templateUrl: './generic-keywords.component.html',
|
|
27
|
-
styleUrls: ['./generic-keywords.component.css'],
|
|
28
21
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
29
22
|
standalone: true,
|
|
30
|
-
imports: [
|
|
31
|
-
AutocompleteComponent,
|
|
32
|
-
NgIconComponent,
|
|
33
|
-
BadgeComponent,
|
|
34
|
-
TranslatePipe,
|
|
35
|
-
],
|
|
36
|
-
providers: [
|
|
37
|
-
provideIcons({
|
|
38
|
-
matWarningAmberOutline,
|
|
39
|
-
}),
|
|
40
|
-
provideNgIconsConfig({
|
|
41
|
-
size: '1.5em',
|
|
42
|
-
}),
|
|
43
|
-
],
|
|
23
|
+
imports: [AutocompleteComponent, KeywordBadgeComponent],
|
|
44
24
|
})
|
|
45
25
|
export class GenericKeywordsComponent {
|
|
46
26
|
private platformService = inject(PlatformServiceInterface)
|
|
@@ -87,9 +67,4 @@ export class GenericKeywordsComponent {
|
|
|
87
67
|
this.changedKeywords.emit(this.keywords)
|
|
88
68
|
this.deletedKeyword.emit(keyword)
|
|
89
69
|
}
|
|
90
|
-
|
|
91
|
-
isPlaceWithoutExtent(keyword: Keyword): boolean {
|
|
92
|
-
if (keyword.type !== 'place') return false
|
|
93
|
-
return !keyword.bbox
|
|
94
|
-
}
|
|
95
70
|
}
|
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
editor.record.form.field.onlineResource.edit.protocol
|
|
4
4
|
</h3>
|
|
5
5
|
@if (protocolHint) {
|
|
6
|
-
<
|
|
7
|
-
|
|
6
|
+
<ng-icon
|
|
7
|
+
name="matHelpOutline"
|
|
8
|
+
size="16"
|
|
9
|
+
class="m-2"
|
|
8
10
|
[matTooltip]="protocolHint"
|
|
9
11
|
matTooltipPosition="above"
|
|
10
|
-
>
|
|
11
|
-
help
|
|
12
|
-
</span>
|
|
12
|
+
></ng-icon>
|
|
13
13
|
}
|
|
14
14
|
</div>
|
|
15
15
|
<div class="flex flex-row items-center gap-4 h-[48px]">
|
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
provideNgIconsConfig,
|
|
31
31
|
} from '@ng-icons/core'
|
|
32
32
|
import { iconoirRefresh } from '@ng-icons/iconoir'
|
|
33
|
+
import { matHelpOutline } from '@ng-icons/material-icons/outline'
|
|
33
34
|
import { TranslateDirective, TranslatePipe } from '@ngx-translate/core'
|
|
34
35
|
import {
|
|
35
36
|
BehaviorSubject,
|
|
@@ -65,7 +66,7 @@ marker(
|
|
|
65
66
|
UrlInputComponent,
|
|
66
67
|
],
|
|
67
68
|
providers: [
|
|
68
|
-
provideIcons({ iconoirRefresh }),
|
|
69
|
+
provideIcons({ iconoirRefresh, matHelpOutline }),
|
|
69
70
|
provideNgIconsConfig({
|
|
70
71
|
size: '1.5em',
|
|
71
72
|
}),
|
package/src/libs/feature/editor/src/lib/components/record-form/form-field/field-focus.directive.ts
CHANGED
|
@@ -10,7 +10,7 @@ export class FieldFocusDirective {
|
|
|
10
10
|
|
|
11
11
|
private el = inject(ElementRef)
|
|
12
12
|
|
|
13
|
-
public focusField() {
|
|
13
|
+
public focusField(focusInnerTarget = true) {
|
|
14
14
|
setTimeout(() => {
|
|
15
15
|
const host = this.el.nativeElement as HTMLElement
|
|
16
16
|
const glowClass = this.gnUiFieldFocusGlowClass
|
|
@@ -25,6 +25,9 @@ export class FieldFocusDirective {
|
|
|
25
25
|
)
|
|
26
26
|
|
|
27
27
|
host.scrollIntoView({ behavior: 'smooth', block: 'start' })
|
|
28
|
+
if (!focusInnerTarget) {
|
|
29
|
+
return
|
|
30
|
+
}
|
|
28
31
|
const target =
|
|
29
32
|
host.querySelector<HTMLElement>(
|
|
30
33
|
'input, textarea, select, [contenteditable="true"]'
|
|
@@ -131,14 +131,14 @@ export class FormFieldConstraintsShortcutsComponent implements OnDestroy {
|
|
|
131
131
|
map((c) => c.length > 0),
|
|
132
132
|
distinctUntilChanged()
|
|
133
133
|
)
|
|
134
|
-
combineLatest([
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
})
|
|
134
|
+
combineLatest([isConstraintNotEmpty$, this.anyToggleActivated$])
|
|
135
|
+
.pipe(takeUntil(this.onDestroy$))
|
|
136
|
+
.subscribe(([isNotEmpty, anyToggleActivated]) => {
|
|
137
|
+
const visible = isNotEmpty && !anyToggleActivated
|
|
138
|
+
this.editorFacade.setFieldVisibility({ model }, visible)
|
|
139
|
+
})
|
|
141
140
|
}
|
|
141
|
+
hideEmptyConstraints(this.legalConstraints$, 'legalConstraints')
|
|
142
142
|
hideEmptyConstraints(this.securityConstraints$, 'securityConstraints')
|
|
143
143
|
hideEmptyConstraints(this.otherConstraints$, 'otherConstraints')
|
|
144
144
|
})
|
|
@@ -3,11 +3,11 @@ import {
|
|
|
3
3
|
ChangeDetectorRef,
|
|
4
4
|
Component,
|
|
5
5
|
EventEmitter,
|
|
6
|
+
inject,
|
|
6
7
|
Input,
|
|
7
8
|
Output,
|
|
8
9
|
TemplateRef,
|
|
9
10
|
ViewChild,
|
|
10
|
-
inject,
|
|
11
11
|
} from '@angular/core'
|
|
12
12
|
import { MatDialog } from '@angular/material/dialog'
|
|
13
13
|
import { marker } from '@biesbjerg/ngx-translate-extract-marker'
|