geonetwork-ui 2.2.0-dev.cbcafed5 → 2.2.0-dev.da2c1f8f
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/esm2022/libs/api/metadata-converter/src/lib/gn4/atomic-operations.mjs +27 -1
- package/esm2022/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.mjs +64 -61
- package/esm2022/libs/api/metadata-converter/src/lib/gn4/gn4.metadata.mapper.mjs +7 -4
- package/esm2022/libs/api/metadata-converter/src/lib/gn4/types/metadata.model.mjs +1 -1
- package/esm2022/libs/api/metadata-converter/src/lib/iso19139/codelists/keyword.mapper.mjs +14 -0
- package/esm2022/libs/api/metadata-converter/src/lib/iso19139/converter.mjs +25 -17
- package/esm2022/libs/api/metadata-converter/src/lib/iso19139/read-parts.mjs +55 -23
- package/esm2022/libs/api/metadata-converter/src/lib/iso19139/write-parts.mjs +52 -32
- package/esm2022/libs/api/repository/src/lib/gn4/elasticsearch/elasticsearch.service.mjs +2 -2
- package/esm2022/libs/api/repository/src/lib/gn4/organizations/organizations-from-metadata.service.mjs +10 -3
- package/esm2022/libs/api/repository/src/lib/gn4/platform/gn4-platform.mapper.mjs +14 -5
- package/esm2022/libs/api/repository/src/lib/gn4/platform/gn4-platform.service.mjs +33 -8
- package/esm2022/libs/common/domain/src/lib/model/record/metadata.model.mjs +1 -1
- package/esm2022/libs/common/domain/src/lib/model/thesaurus/thesaurus.model.mjs +1 -1
- package/esm2022/libs/common/domain/src/lib/platform.service.interface.mjs +1 -1
- package/esm2022/libs/feature/editor/src/index.mjs +6 -1
- package/esm2022/libs/feature/editor/src/lib/+state/editor.actions.mjs +8 -0
- package/esm2022/libs/feature/editor/src/lib/+state/editor.effects.mjs +26 -0
- package/esm2022/libs/feature/editor/src/lib/+state/editor.facade.mjs +30 -0
- package/esm2022/libs/feature/editor/src/lib/+state/editor.models.mjs +2 -0
- package/esm2022/libs/feature/editor/src/lib/+state/editor.reducer.mjs +42 -0
- package/esm2022/libs/feature/editor/src/lib/+state/editor.selectors.mjs +13 -0
- package/esm2022/libs/feature/editor/src/lib/expressions.mjs +13 -0
- package/esm2022/libs/feature/editor/src/lib/feature-editor.module.mjs +16 -4
- package/esm2022/libs/feature/editor/src/lib/fields.config.mjs +34 -0
- package/esm2022/libs/feature/editor/src/lib/models/fields.model.mjs +2 -0
- package/esm2022/libs/feature/editor/src/lib/record-form/record-form.component.mjs +15 -11
- package/esm2022/libs/feature/editor/src/lib/services/editor.service.mjs +22 -44
- package/esm2022/libs/feature/map/src/lib/map-context/map-context.service.mjs +9 -1
- package/esm2022/libs/feature/record/src/lib/data-view-permalink/data-view-permalink.component.mjs +13 -13
- package/esm2022/libs/feature/search/src/lib/favorites/favorite-star/favorite-star.component.mjs +3 -3
- package/esm2022/libs/feature/search/src/lib/utils/service/fields.mjs +41 -26
- package/esm2022/libs/feature/search/src/lib/utils/service/fields.service.mjs +11 -9
- package/esm2022/libs/ui/catalog/src/lib/language-switcher/language-switcher.component.mjs +3 -3
- package/esm2022/libs/ui/elements/src/lib/markdown-parser/markdown-parser.component.mjs +3 -3
- package/esm2022/libs/ui/elements/src/lib/max-lines/max-lines.component.mjs +5 -3
- package/esm2022/libs/ui/elements/src/lib/metadata-contact/metadata-contact.component.mjs +3 -3
- package/esm2022/libs/ui/elements/src/lib/metadata-info/metadata-info.component.mjs +47 -22
- package/esm2022/libs/ui/elements/src/lib/metadata-quality/metadata-quality.component.mjs +3 -4
- package/esm2022/libs/ui/elements/src/lib/thumbnail/thumbnail.component.mjs +3 -3
- package/esm2022/libs/ui/elements/src/lib/ui-elements.module.mjs +4 -4
- package/esm2022/libs/ui/inputs/src/lib/button/button.component.mjs +9 -9
- package/esm2022/libs/ui/inputs/src/lib/dropdown-multiselect/dropdown-multiselect.component.mjs +3 -3
- package/esm2022/libs/ui/inputs/src/lib/dropdown-selector/dropdown-selector.component.mjs +3 -3
- package/esm2022/libs/ui/inputs/src/lib/form-field/form-field.component.mjs +4 -2
- package/esm2022/libs/ui/inputs/src/lib/form-field/form-field.model.mjs +1 -1
- package/esm2022/libs/ui/inputs/src/lib/navigation-button/navigation-button.component.mjs +3 -3
- package/esm2022/libs/ui/inputs/src/lib/text-area/text-area.component.mjs +3 -3
- package/esm2022/libs/ui/inputs/src/lib/ui-inputs.module.mjs +6 -6
- package/esm2022/libs/ui/layout/src/lib/carousel/carousel.component.mjs +3 -3
- package/esm2022/libs/ui/widgets/src/lib/badge/badge.component.mjs +3 -3
- package/esm2022/libs/util/i18n/src/lib/i18n.constants.mjs +18 -1
- package/esm2022/libs/util/shared/src/lib/utils/index.mjs +2 -1
- package/esm2022/libs/util/shared/src/lib/utils/temporal-extent-union.mjs +32 -0
- package/esm2022/translations/de.json +37 -27
- package/esm2022/translations/en.json +32 -22
- package/esm2022/translations/es.json +27 -17
- package/esm2022/translations/fr.json +50 -40
- package/esm2022/translations/it.json +44 -34
- package/esm2022/translations/nl.json +28 -18
- package/esm2022/translations/pt.json +27 -17
- package/fesm2022/geonetwork-ui.mjs +972 -527
- package/fesm2022/geonetwork-ui.mjs.map +1 -1
- package/libs/api/metadata-converter/src/lib/gn4/atomic-operations.d.ts +2 -0
- package/libs/api/metadata-converter/src/lib/gn4/atomic-operations.d.ts.map +1 -1
- package/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.d.ts +0 -1
- package/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.d.ts.map +1 -1
- package/libs/api/metadata-converter/src/lib/gn4/gn4.metadata.mapper.d.ts.map +1 -1
- package/libs/api/metadata-converter/src/lib/gn4/types/metadata.model.d.ts +4 -5
- package/libs/api/metadata-converter/src/lib/gn4/types/metadata.model.d.ts.map +1 -1
- package/libs/api/metadata-converter/src/lib/iso19139/codelists/keyword.mapper.d.ts +3 -0
- package/libs/api/metadata-converter/src/lib/iso19139/codelists/keyword.mapper.d.ts.map +1 -0
- package/libs/api/metadata-converter/src/lib/iso19139/converter.d.ts.map +1 -1
- package/libs/api/metadata-converter/src/lib/iso19139/read-parts.d.ts +7 -6
- package/libs/api/metadata-converter/src/lib/iso19139/read-parts.d.ts.map +1 -1
- package/libs/api/metadata-converter/src/lib/iso19139/write-parts.d.ts +4 -3
- package/libs/api/metadata-converter/src/lib/iso19139/write-parts.d.ts.map +1 -1
- package/libs/api/repository/src/lib/gn4/elasticsearch/elasticsearch.service.d.ts.map +1 -1
- package/libs/api/repository/src/lib/gn4/organizations/organizations-from-metadata.service.d.ts.map +1 -1
- package/libs/api/repository/src/lib/gn4/platform/gn4-platform.mapper.d.ts +1 -1
- package/libs/api/repository/src/lib/gn4/platform/gn4-platform.mapper.d.ts.map +1 -1
- package/libs/api/repository/src/lib/gn4/platform/gn4-platform.service.d.ts +9 -2
- package/libs/api/repository/src/lib/gn4/platform/gn4-platform.service.d.ts.map +1 -1
- package/libs/common/domain/src/lib/model/record/metadata.model.d.ts +21 -12
- package/libs/common/domain/src/lib/model/record/metadata.model.d.ts.map +1 -1
- package/libs/common/domain/src/lib/model/thesaurus/thesaurus.model.d.ts +1 -0
- package/libs/common/domain/src/lib/model/thesaurus/thesaurus.model.d.ts.map +1 -1
- package/libs/common/domain/src/lib/platform.service.interface.d.ts +1 -1
- package/libs/common/domain/src/lib/platform.service.interface.d.ts.map +1 -1
- package/libs/feature/editor/src/index.d.ts +5 -0
- package/libs/feature/editor/src/index.d.ts.map +1 -1
- package/libs/feature/editor/src/lib/+state/editor.actions.d.ts +23 -0
- package/libs/feature/editor/src/lib/+state/editor.actions.d.ts.map +1 -0
- package/libs/feature/editor/src/lib/+state/editor.effects.d.ts +15 -0
- package/libs/feature/editor/src/lib/+state/editor.effects.d.ts.map +1 -0
- package/libs/feature/editor/src/lib/+state/editor.facade.d.ts +19 -0
- package/libs/feature/editor/src/lib/+state/editor.facade.d.ts.map +1 -0
- package/libs/feature/editor/src/lib/+state/editor.models.d.ts +2 -0
- package/libs/feature/editor/src/lib/+state/editor.models.d.ts.map +1 -0
- package/libs/feature/editor/src/lib/+state/editor.reducer.d.ts +18 -0
- package/libs/feature/editor/src/lib/+state/editor.reducer.d.ts.map +1 -0
- package/libs/feature/editor/src/lib/+state/editor.selectors.d.ts +15 -0
- package/libs/feature/editor/src/lib/+state/editor.selectors.d.ts.map +1 -0
- package/libs/feature/editor/src/lib/expressions.d.ts +4 -0
- package/libs/feature/editor/src/lib/expressions.d.ts.map +1 -0
- package/libs/feature/editor/src/lib/feature-editor.module.d.ts +3 -1
- package/libs/feature/editor/src/lib/feature-editor.module.d.ts.map +1 -1
- package/libs/feature/editor/src/lib/fields.config.d.ts +3 -0
- package/libs/feature/editor/src/lib/fields.config.d.ts.map +1 -0
- package/libs/feature/editor/src/lib/models/fields.model.d.ts +15 -0
- package/libs/feature/editor/src/lib/models/fields.model.d.ts.map +1 -0
- package/libs/feature/editor/src/lib/record-form/record-form.component.d.ts +10 -5
- package/libs/feature/editor/src/lib/record-form/record-form.component.d.ts.map +1 -1
- package/libs/feature/editor/src/lib/services/editor.service.d.ts +3 -13
- package/libs/feature/editor/src/lib/services/editor.service.d.ts.map +1 -1
- package/libs/feature/map/src/lib/map-context/map-context.service.d.ts +1 -0
- package/libs/feature/map/src/lib/map-context/map-context.service.d.ts.map +1 -1
- package/libs/feature/search/src/lib/utils/service/fields.d.ts +21 -8
- package/libs/feature/search/src/lib/utils/service/fields.d.ts.map +1 -1
- package/libs/feature/search/src/lib/utils/service/fields.service.d.ts.map +1 -1
- package/libs/ui/elements/src/lib/markdown-parser/markdown-parser.component.d.ts +1 -1
- package/libs/ui/elements/src/lib/markdown-parser/markdown-parser.component.d.ts.map +1 -1
- package/libs/ui/elements/src/lib/max-lines/max-lines.component.d.ts.map +1 -1
- package/libs/ui/elements/src/lib/metadata-info/metadata-info.component.d.ts +16 -6
- package/libs/ui/elements/src/lib/metadata-info/metadata-info.component.d.ts.map +1 -1
- package/libs/ui/elements/src/lib/metadata-quality/metadata-quality.component.d.ts.map +1 -1
- package/libs/ui/elements/src/lib/ui-elements.module.d.ts +13 -13
- package/libs/ui/inputs/src/lib/button/button.component.d.ts +1 -1
- package/libs/ui/inputs/src/lib/button/button.component.d.ts.map +1 -1
- package/libs/ui/inputs/src/lib/form-field/form-field.component.d.ts.map +1 -1
- package/libs/ui/inputs/src/lib/form-field/form-field.model.d.ts +0 -1
- package/libs/ui/inputs/src/lib/form-field/form-field.model.d.ts.map +1 -1
- package/libs/ui/inputs/src/lib/text-area/text-area.component.d.ts +1 -1
- package/libs/ui/inputs/src/lib/text-area/text-area.component.d.ts.map +1 -1
- package/libs/ui/inputs/src/lib/ui-inputs.module.d.ts +40 -40
- package/libs/ui/layout/src/lib/interactive-table/interactive-table-column/interactive-table-column.component.d.ts +1 -1
- package/libs/util/i18n/src/lib/i18n.constants.d.ts +17 -0
- package/libs/util/i18n/src/lib/i18n.constants.d.ts.map +1 -1
- package/libs/util/shared/src/lib/utils/index.d.ts +1 -0
- package/libs/util/shared/src/lib/utils/index.d.ts.map +1 -1
- package/libs/util/shared/src/lib/utils/temporal-extent-union.d.ts +5 -0
- package/libs/util/shared/src/lib/utils/temporal-extent-union.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/libs/api/metadata-converter/src/lib/fixtures/generic.records.ts +63 -8
- package/src/libs/api/metadata-converter/src/lib/fixtures/geo2france.records.ts +57 -9
- package/src/libs/api/metadata-converter/src/lib/fixtures/geocat-ch.records.ts +229 -24
- package/src/libs/api/metadata-converter/src/lib/gn4/atomic-operations.ts +29 -0
- package/src/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.ts +99 -76
- package/src/libs/api/metadata-converter/src/lib/gn4/gn4.metadata.mapper.ts +6 -3
- package/src/libs/api/metadata-converter/src/lib/gn4/types/metadata.model.ts +4 -5
- package/src/libs/api/metadata-converter/src/lib/iso19139/codelists/keyword.mapper.ts +16 -0
- package/src/libs/api/metadata-converter/src/lib/iso19139/converter.ts +30 -21
- package/src/libs/api/metadata-converter/src/lib/iso19139/read-parts.ts +120 -63
- package/src/libs/api/metadata-converter/src/lib/iso19139/write-parts.ts +177 -97
- package/src/libs/api/repository/src/lib/gn4/elasticsearch/elasticsearch.service.ts +1 -1
- package/src/libs/api/repository/src/lib/gn4/organizations/organizations-from-metadata.service.ts +22 -2
- package/src/libs/api/repository/src/lib/gn4/platform/gn4-platform.mapper.ts +15 -4
- package/src/libs/api/repository/src/lib/gn4/platform/gn4-platform.service.ts +47 -8
- package/src/libs/common/domain/src/lib/model/record/metadata.model.ts +25 -14
- package/src/libs/common/domain/src/lib/model/thesaurus/thesaurus.model.ts +1 -0
- package/src/libs/common/domain/src/lib/platform.service.interface.ts +1 -4
- package/src/libs/common/fixtures/src/lib/elasticsearch/full-response.ts +1 -1
- package/src/libs/common/fixtures/src/lib/gn4/groups.fixtures.ts +1 -1
- package/src/libs/common/fixtures/src/lib/records.fixtures.ts +52 -10
- package/src/libs/feature/editor/src/index.ts +5 -0
- package/src/libs/feature/editor/src/lib/+state/editor.actions.ts +24 -0
- package/src/libs/feature/editor/src/lib/+state/editor.effects.ts +49 -0
- package/src/libs/feature/editor/src/lib/+state/editor.facade.ts +30 -0
- package/src/libs/feature/editor/src/lib/+state/editor.models.ts +1 -0
- package/src/libs/feature/editor/src/lib/+state/editor.reducer.ts +68 -0
- package/src/libs/feature/editor/src/lib/+state/editor.selectors.ts +39 -0
- package/src/libs/feature/editor/src/lib/expressions.ts +16 -0
- package/src/libs/feature/editor/src/lib/feature-editor.module.ts +11 -0
- package/src/libs/feature/editor/src/lib/fields.config.ts +35 -0
- package/src/libs/feature/editor/src/lib/models/fields.model.ts +29 -0
- package/src/libs/feature/editor/src/lib/record-form/record-form.component.html +9 -7
- package/src/libs/feature/editor/src/lib/record-form/record-form.component.ts +11 -5
- package/src/libs/feature/editor/src/lib/services/editor.service.ts +34 -73
- package/src/libs/feature/map/src/lib/map-context/map-context.service.ts +10 -0
- package/src/libs/feature/record/src/lib/data-view-permalink/data-view-permalink.component.ts +12 -12
- package/src/libs/feature/search/src/lib/favorites/favorite-star/favorite-star.component.html +3 -4
- package/src/libs/feature/search/src/lib/utils/service/fields.service.ts +21 -16
- package/src/libs/feature/search/src/lib/utils/service/fields.ts +43 -34
- package/src/libs/ui/catalog/src/lib/language-switcher/language-switcher.component.html +1 -1
- package/src/libs/ui/elements/src/lib/markdown-editor/markdown-editor.component.css +5 -0
- package/src/libs/ui/elements/src/lib/markdown-editor/markdown-editor.component.html +39 -0
- package/src/libs/ui/elements/src/lib/markdown-editor/markdown-editor.component.ts +58 -0
- package/src/libs/ui/elements/src/lib/markdown-parser/markdown-parser.component.css +2 -2
- package/src/libs/ui/elements/src/lib/markdown-parser/markdown-parser.component.ts +1 -0
- package/src/libs/ui/elements/src/lib/max-lines/max-lines.component.html +5 -1
- package/src/libs/ui/elements/src/lib/max-lines/max-lines.component.ts +1 -0
- package/src/libs/ui/elements/src/lib/metadata-contact/metadata-contact.component.html +1 -1
- package/src/libs/ui/elements/src/lib/metadata-info/metadata-info.component.html +169 -52
- package/src/libs/ui/elements/src/lib/metadata-info/metadata-info.component.ts +51 -15
- package/src/libs/ui/elements/src/lib/metadata-quality/metadata-quality.component.ts +2 -3
- package/src/libs/ui/elements/src/lib/thumbnail/thumbnail.component.html +2 -2
- package/src/libs/ui/elements/src/lib/ui-elements.module.ts +1 -1
- package/src/libs/ui/inputs/src/lib/button/button.component.css +0 -5
- package/src/libs/ui/inputs/src/lib/button/button.component.html +0 -1
- package/src/libs/ui/inputs/src/lib/button/button.component.ts +7 -6
- package/src/libs/ui/inputs/src/lib/dropdown-multiselect/dropdown-multiselect.component.html +1 -1
- package/src/libs/ui/inputs/src/lib/dropdown-selector/dropdown-selector.component.html +3 -1
- package/src/libs/ui/inputs/src/lib/form-field/form-field.component.ts +3 -1
- package/src/libs/ui/inputs/src/lib/form-field/form-field.model.ts +0 -1
- package/src/libs/ui/inputs/src/lib/navigation-button/navigation-button.component.css +3 -0
- package/src/libs/ui/inputs/src/lib/navigation-button/navigation-button.component.html +1 -1
- package/src/libs/ui/inputs/src/lib/text-area/text-area.component.ts +1 -0
- package/src/libs/ui/inputs/src/lib/ui-inputs.module.ts +2 -2
- package/src/libs/ui/layout/src/lib/carousel/carousel.component.html +1 -0
- package/src/libs/ui/widgets/src/lib/badge/badge.component.html +3 -1
- package/src/libs/util/i18n/src/lib/i18n.constants.ts +18 -0
- package/src/libs/util/shared/src/lib/utils/index.ts +1 -0
- package/src/libs/util/shared/src/lib/utils/temporal-extent-union.ts +32 -0
- package/tailwind.base.css +44 -15
- package/translations/de.json +37 -27
- package/translations/en.json +32 -22
- package/translations/es.json +27 -17
- package/translations/fr.json +50 -40
- package/translations/it.json +44 -34
- package/translations/nl.json +28 -18
- package/translations/pt.json +27 -17
- package/translations/sk.json +118 -108
package/src/libs/api/repository/src/lib/gn4/organizations/organizations-from-metadata.service.ts
CHANGED
|
@@ -25,7 +25,14 @@ import {
|
|
|
25
25
|
SourceWithUnknownProps,
|
|
26
26
|
} from '../../../../../../../libs/api/metadata-converter/src'
|
|
27
27
|
import { combineLatest, Observable, of, switchMap, takeLast } from 'rxjs'
|
|
28
|
-
import {
|
|
28
|
+
import {
|
|
29
|
+
filter,
|
|
30
|
+
map,
|
|
31
|
+
shareReplay,
|
|
32
|
+
startWith,
|
|
33
|
+
tap,
|
|
34
|
+
withLatestFrom,
|
|
35
|
+
} from 'rxjs/operators'
|
|
29
36
|
import { LangService } from '../../../../../../../libs/util/i18n/src'
|
|
30
37
|
import { PlatformServiceInterface } from '../../../../../../../libs/common/domain/src/lib/platform.service.interface'
|
|
31
38
|
import { coerce, satisfies, valid } from 'semver'
|
|
@@ -296,15 +303,28 @@ export class OrganizationsFromMetadataService
|
|
|
296
303
|
|
|
297
304
|
const ownerOrganization = allContactOrgs[0]
|
|
298
305
|
|
|
306
|
+
// read the owner group as well to have a fallback logo
|
|
307
|
+
const groupId = selectField(source, 'groupOwner')
|
|
308
|
+
const group$ = this.groups$.pipe(
|
|
309
|
+
map((groups) =>
|
|
310
|
+
groups.find((group) => {
|
|
311
|
+
return group.id === Number(groupId)
|
|
312
|
+
})
|
|
313
|
+
)
|
|
314
|
+
)
|
|
315
|
+
|
|
299
316
|
return this.organisations$.pipe(
|
|
300
317
|
takeLast(1),
|
|
301
|
-
|
|
318
|
+
withLatestFrom(group$),
|
|
319
|
+
map(([organisations, group]: [Organization[], GroupApiModel]) => {
|
|
302
320
|
const recordOrganisation = organisations.filter(
|
|
303
321
|
(org) => org.name === ownerOrganization.name
|
|
304
322
|
)[0]
|
|
323
|
+
const logoUrl = group?.logo && getAsUrl(`${IMAGE_URL}${group.logo}`)
|
|
305
324
|
return {
|
|
306
325
|
...record,
|
|
307
326
|
ownerOrganization: {
|
|
327
|
+
logoUrl,
|
|
308
328
|
...ownerOrganization,
|
|
309
329
|
...recordOrganisation,
|
|
310
330
|
},
|
|
@@ -45,12 +45,23 @@ export class Gn4PlatformMapper {
|
|
|
45
45
|
return { ...apiUser, id: id.toString() } as UserModel
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
thesaurusFromApi(thesaurus: any[]): ThesaurusModel {
|
|
48
|
+
thesaurusFromApi(thesaurus: any[], lang3?: string): ThesaurusModel {
|
|
49
49
|
return thesaurus.map((keyword) => {
|
|
50
|
-
|
|
50
|
+
let key = keyword.uri
|
|
51
|
+
// sometines GN can prefix an URI with an "all thesaurus" URI; only keep the last one
|
|
52
|
+
if (key.indexOf('@@@') > -1) {
|
|
53
|
+
key = key.split('@@@')[1]
|
|
54
|
+
}
|
|
55
|
+
const label =
|
|
56
|
+
lang3 && lang3 in keyword.values ? keyword.values[lang3] : keyword.value
|
|
57
|
+
const description =
|
|
58
|
+
lang3 && lang3 in keyword.definitions
|
|
59
|
+
? keyword.definitions[lang3]
|
|
60
|
+
: keyword.definition
|
|
51
61
|
return {
|
|
52
|
-
key
|
|
53
|
-
label
|
|
62
|
+
key,
|
|
63
|
+
label,
|
|
64
|
+
description,
|
|
54
65
|
}
|
|
55
66
|
})
|
|
56
67
|
}
|
|
@@ -14,8 +14,10 @@ import { Organization } from '../../../../../../../libs/common/domain/src/lib/mo
|
|
|
14
14
|
import { Gn4PlatformMapper } from './gn4-platform.mapper'
|
|
15
15
|
import { ltr } from 'semver'
|
|
16
16
|
import { ThesaurusModel } from '../../../../../../../libs/common/domain/src/lib/model/thesaurus/thesaurus.model'
|
|
17
|
+
import { LangService } from '../../../../../../../libs/util/i18n/src'
|
|
17
18
|
|
|
18
19
|
const minApiVersion = '4.2.2'
|
|
20
|
+
|
|
19
21
|
@Injectable()
|
|
20
22
|
export class Gn4PlatformService implements PlatformServiceInterface {
|
|
21
23
|
private readonly type = 'GeoNetwork'
|
|
@@ -50,13 +52,20 @@ export class Gn4PlatformService implements PlatformServiceInterface {
|
|
|
50
52
|
shareReplay(1)
|
|
51
53
|
)
|
|
52
54
|
|
|
55
|
+
/**
|
|
56
|
+
* A map of already loaded thesauri (groups of keywords); the key is a URI
|
|
57
|
+
* @private
|
|
58
|
+
*/
|
|
59
|
+
private thesauri: Record<string, Observable<ThesaurusModel>> = {}
|
|
60
|
+
|
|
53
61
|
constructor(
|
|
54
62
|
private siteApiService: SiteApiService,
|
|
55
63
|
private meApi: MeApiService,
|
|
56
64
|
private usersApi: UsersApiService,
|
|
57
65
|
private mapper: Gn4PlatformMapper,
|
|
58
66
|
private toolsApiService: ToolsApiService,
|
|
59
|
-
private registriesApiService: RegistriesApiService
|
|
67
|
+
private registriesApiService: RegistriesApiService,
|
|
68
|
+
private langService: LangService
|
|
60
69
|
) {
|
|
61
70
|
this.me$ = this.meApi.getMe().pipe(
|
|
62
71
|
switchMap((apiUser) => this.mapper.userFromMeApi(apiUser)),
|
|
@@ -98,17 +107,47 @@ export class Gn4PlatformService implements PlatformServiceInterface {
|
|
|
98
107
|
}
|
|
99
108
|
|
|
100
109
|
translateKey(key: string): Observable<string> {
|
|
110
|
+
// if the key is a URI, use the registries API to look for the translation
|
|
111
|
+
if (key.match(/^https?:\/\//)) {
|
|
112
|
+
// the thesaurus URI is inferred by removing a part of the keyword URI
|
|
113
|
+
// this is not exact science but it's OK, we'll still end up loading a bunch of keywords at once anyway
|
|
114
|
+
const thesaurusUri = key.replace(/\/([^/]+)$/, '/')
|
|
115
|
+
return this.getThesaurusByUri(thesaurusUri).pipe(
|
|
116
|
+
map((thesaurus) => {
|
|
117
|
+
for (const item of thesaurus) {
|
|
118
|
+
if (item.key === key) return item.label
|
|
119
|
+
}
|
|
120
|
+
return key
|
|
121
|
+
})
|
|
122
|
+
)
|
|
123
|
+
}
|
|
101
124
|
return this.keyTranslations$.pipe(map((translations) => translations[key]))
|
|
102
125
|
}
|
|
103
126
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
.searchKeywords(
|
|
127
|
+
getThesaurusByUri(uri: string): Observable<ThesaurusModel> {
|
|
128
|
+
if (this.thesauri[uri]) {
|
|
129
|
+
return this.thesauri[uri]
|
|
130
|
+
}
|
|
131
|
+
this.thesauri[uri] = this.registriesApiService
|
|
132
|
+
.searchKeywords(
|
|
133
|
+
null,
|
|
134
|
+
this.langService.iso3,
|
|
135
|
+
1000,
|
|
136
|
+
0,
|
|
137
|
+
null,
|
|
138
|
+
null,
|
|
139
|
+
null,
|
|
140
|
+
`${uri}*`
|
|
141
|
+
)
|
|
110
142
|
.pipe(
|
|
111
|
-
map((thesaurus) =>
|
|
143
|
+
map((thesaurus) =>
|
|
144
|
+
this.mapper.thesaurusFromApi(
|
|
145
|
+
thesaurus as any[],
|
|
146
|
+
this.langService.iso3
|
|
147
|
+
)
|
|
148
|
+
),
|
|
149
|
+
shareReplay(1)
|
|
112
150
|
)
|
|
151
|
+
return this.thesauri[uri]
|
|
113
152
|
}
|
|
114
153
|
}
|
|
@@ -48,13 +48,7 @@ export const RecordStatusValues = [
|
|
|
48
48
|
]
|
|
49
49
|
export type RecordStatus = typeof RecordStatusValues[number]
|
|
50
50
|
|
|
51
|
-
export type
|
|
52
|
-
export interface AccessConstraint {
|
|
53
|
-
text: string
|
|
54
|
-
type: AccessConstraintType
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export type License = {
|
|
51
|
+
export type Constraint = {
|
|
58
52
|
text: string
|
|
59
53
|
url?: URL
|
|
60
54
|
}
|
|
@@ -66,6 +60,22 @@ export type SpatialRepresentationType =
|
|
|
66
60
|
| 'table'
|
|
67
61
|
| 'point'
|
|
68
62
|
|
|
63
|
+
export type KeywordType = 'place' | 'temporal' | 'theme' | 'other'
|
|
64
|
+
|
|
65
|
+
export type KeywordThesaurus = {
|
|
66
|
+
id: string
|
|
67
|
+
name?: string
|
|
68
|
+
url?: URL
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export interface Keyword {
|
|
72
|
+
label: string
|
|
73
|
+
type: KeywordType
|
|
74
|
+
thesaurus?: KeywordThesaurus
|
|
75
|
+
}
|
|
76
|
+
// languages should be expressed using two-letters ISO 639-1 codes
|
|
77
|
+
export type LanguageCode = string
|
|
78
|
+
|
|
69
79
|
export interface BaseRecord {
|
|
70
80
|
uniqueIdentifier: Uuid
|
|
71
81
|
ownerOrganization: Organization
|
|
@@ -74,19 +84,20 @@ export interface BaseRecord {
|
|
|
74
84
|
abstract: string
|
|
75
85
|
recordCreated?: Date
|
|
76
86
|
recordUpdated: Date
|
|
87
|
+
recordPublished?: Date
|
|
88
|
+
languages: Array<LanguageCode>
|
|
77
89
|
kind: RecordKind
|
|
78
|
-
|
|
79
|
-
keywords: Array<
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
90
|
+
topics: Array<string> // TODO: handle codelists
|
|
91
|
+
keywords: Array<Keyword>
|
|
92
|
+
licenses: Array<Constraint>
|
|
93
|
+
legalConstraints: Array<Constraint>
|
|
94
|
+
securityConstraints: Array<Constraint>
|
|
95
|
+
otherConstraints: Array<Constraint>
|
|
84
96
|
overviews: Array<GraphicOverview>
|
|
85
97
|
extras?: Record<string, unknown>
|
|
86
98
|
landingPage?: URL
|
|
87
99
|
updateFrequency?: UpdateFrequency
|
|
88
100
|
|
|
89
|
-
// to add: iso19139.topicCategory
|
|
90
101
|
// to add: canonical url
|
|
91
102
|
// to add: source catalog (??)
|
|
92
103
|
// to add: is open data ?
|
|
@@ -15,8 +15,5 @@ export abstract class PlatformServiceInterface {
|
|
|
15
15
|
): Observable<UserModel[]>
|
|
16
16
|
abstract getOrganizations(): Observable<Organization[]>
|
|
17
17
|
abstract translateKey(key: string): Observable<string>
|
|
18
|
-
abstract
|
|
19
|
-
thesaurusName: string,
|
|
20
|
-
lang: string
|
|
21
|
-
): Observable<ThesaurusModel>
|
|
18
|
+
abstract getThesaurusByUri(uri: string): Observable<ThesaurusModel>
|
|
22
19
|
}
|
|
@@ -131,7 +131,7 @@ export const ES_FIXTURE_FULL_RESPONSE = deepFreeze({
|
|
|
131
131
|
creationDateForResource: ['2012-01-01T00:00:00.000Z'],
|
|
132
132
|
creationYearForResource: '2012',
|
|
133
133
|
creationMonthForResource: '2012-01',
|
|
134
|
-
publicationDateForResource:
|
|
134
|
+
publicationDateForResource: '2021-04-01T00:00:00.000Z',
|
|
135
135
|
publicationYearForResource: '2021',
|
|
136
136
|
publicationMonthForResource: '2021-04',
|
|
137
137
|
resourceDate: [
|
|
@@ -64,7 +64,7 @@ export const GROUPS_FIXTURE = deepFreeze([
|
|
|
64
64
|
defaultCategory: null,
|
|
65
65
|
allowedCategories: [],
|
|
66
66
|
enableAllowedCategories: false,
|
|
67
|
-
id:
|
|
67
|
+
id: 2,
|
|
68
68
|
email: 'ifremer.ifremer@ifremer.admin.fr',
|
|
69
69
|
referrer: null,
|
|
70
70
|
description: "Institut français de recherche pour l'exploitation de la mer",
|
|
@@ -69,8 +69,24 @@ Cette section contient des *caractères internationaux* (ainsi que des "caractè
|
|
|
69
69
|
url: new URL('http://my-org.net/two.png'),
|
|
70
70
|
},
|
|
71
71
|
],
|
|
72
|
-
keywords: [
|
|
73
|
-
|
|
72
|
+
keywords: [
|
|
73
|
+
{
|
|
74
|
+
thesaurus: { id: 'geonetwork.thesaurus.local' },
|
|
75
|
+
type: 'other',
|
|
76
|
+
label: 'international',
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
thesaurus: { id: 'geonetwork.thesaurus.local' },
|
|
80
|
+
type: 'other',
|
|
81
|
+
label: 'test',
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
thesaurus: { id: 'geonetwork.thesaurus.local' },
|
|
85
|
+
type: 'other',
|
|
86
|
+
label: '_another_keyword_',
|
|
87
|
+
},
|
|
88
|
+
],
|
|
89
|
+
topics: ['testData', 'exampleData'],
|
|
74
90
|
spatialRepresentation: 'grid',
|
|
75
91
|
distributions: [
|
|
76
92
|
{
|
|
@@ -115,7 +131,7 @@ As such, **it is not very interesting at all.**`,
|
|
|
115
131
|
url: new URL('https://data.rennesmetropole.fr/pages/licence/'),
|
|
116
132
|
},
|
|
117
133
|
],
|
|
118
|
-
|
|
134
|
+
legalConstraints: [
|
|
119
135
|
{
|
|
120
136
|
text: "Dataset access isn't possible since it does not really exist",
|
|
121
137
|
type: 'other',
|
|
@@ -125,12 +141,15 @@ As such, **it is not very interesting at all.**`,
|
|
|
125
141
|
type: 'security',
|
|
126
142
|
},
|
|
127
143
|
],
|
|
144
|
+
securityConstraints: [],
|
|
145
|
+
otherConstraints: [],
|
|
128
146
|
spatialExtents: [],
|
|
129
147
|
temporalExtents: [],
|
|
130
148
|
updateFrequency: {
|
|
131
149
|
updatedTimes: 3,
|
|
132
150
|
per: 'month',
|
|
133
151
|
},
|
|
152
|
+
languages: ['en'],
|
|
134
153
|
},
|
|
135
154
|
{
|
|
136
155
|
uniqueIdentifier: '7d002c4c-92ef-4b9f-a568-d732f740b99e',
|
|
@@ -168,13 +187,33 @@ Malgré l'attention portée à la création de ces données, il est rappelé que
|
|
|
168
187
|
},
|
|
169
188
|
],
|
|
170
189
|
keywords: [
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
190
|
+
{
|
|
191
|
+
thesaurus: { id: 'geonetwork.thesaurus.local' },
|
|
192
|
+
type: 'other',
|
|
193
|
+
label: 'planification',
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
thesaurus: { id: 'geonetwork.thesaurus.local' },
|
|
197
|
+
type: 'other',
|
|
198
|
+
label: 'PLU',
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
thesaurus: { id: 'geonetwork.thesaurus.local' },
|
|
202
|
+
type: 'other',
|
|
203
|
+
label: "Plan local d'urbanisme",
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
thesaurus: { id: 'geonetwork.thesaurus.local' },
|
|
207
|
+
type: 'other',
|
|
208
|
+
label: 'données ouvertes',
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
thesaurus: { id: 'geonetwork.thesaurus.local' },
|
|
212
|
+
type: 'other',
|
|
213
|
+
label: 'Avrigny*60036',
|
|
214
|
+
},
|
|
176
215
|
],
|
|
177
|
-
|
|
216
|
+
topics: ['Usage des sols', "document d'urbanisme"],
|
|
178
217
|
spatialRepresentation: 'vector',
|
|
179
218
|
distributions: [
|
|
180
219
|
{
|
|
@@ -189,7 +228,9 @@ Malgré l'attention portée à la création de ces données, il est rappelé que
|
|
|
189
228
|
],
|
|
190
229
|
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.
|
|
191
230
|
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.`,
|
|
192
|
-
|
|
231
|
+
legalConstraints: [],
|
|
232
|
+
securityConstraints: [],
|
|
233
|
+
otherConstraints: [],
|
|
193
234
|
useLimitations: ["Aucune condition ne s'applique", 'Licence Ouverte 2.0'],
|
|
194
235
|
licenses: [
|
|
195
236
|
{
|
|
@@ -200,5 +241,6 @@ Ce lot de données produit en 2019, a été numérisé à partir du PCI Vecteur
|
|
|
200
241
|
temporalExtents: [],
|
|
201
242
|
status: 'completed',
|
|
202
243
|
updateFrequency: 'unknown',
|
|
244
|
+
languages: ['fr', 'de'],
|
|
203
245
|
},
|
|
204
246
|
])
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
export * from './lib/+state/editor.facade'
|
|
2
|
+
export * from './lib/+state/editor.models'
|
|
3
|
+
export * from './lib/+state/editor.selectors'
|
|
4
|
+
export * from './lib/+state/editor.reducer'
|
|
5
|
+
export * from './lib/+state/editor.actions'
|
|
1
6
|
export * from './lib/feature-editor.module'
|
|
2
7
|
export * from './lib/services/editor.service'
|
|
3
8
|
export * from './lib/record-form/record-form.component'
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { createAction, props } from '@ngrx/store'
|
|
2
|
+
import { CatalogRecord } from '../../../../../../libs/common/domain/src/lib/model/record'
|
|
3
|
+
import { SaveRecordError } from './editor.models'
|
|
4
|
+
|
|
5
|
+
export const openRecord = createAction(
|
|
6
|
+
'[Editor] Open record',
|
|
7
|
+
props<{ record: CatalogRecord }>()
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
export const updateRecordField = createAction(
|
|
11
|
+
'[Editor] Update record field',
|
|
12
|
+
props<{ field: string; value: unknown }>()
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
export const markRecordAsChanged = createAction(
|
|
16
|
+
'[Editor] Mark record as changed'
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
export const saveRecord = createAction('[Editor] Save record')
|
|
20
|
+
export const saveRecordSuccess = createAction('[Editor] Save record success')
|
|
21
|
+
export const saveRecordFailure = createAction(
|
|
22
|
+
'[Editor] Save record failure',
|
|
23
|
+
props<{ error: SaveRecordError }>()
|
|
24
|
+
)
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { inject, Injectable } from '@angular/core'
|
|
2
|
+
import { Actions, createEffect, ofType } from '@ngrx/effects'
|
|
3
|
+
import { of, withLatestFrom } from 'rxjs'
|
|
4
|
+
import { catchError, map, switchMap } from 'rxjs/operators'
|
|
5
|
+
import * as EditorActions from './editor.actions'
|
|
6
|
+
import { EditorService } from '../services/editor.service'
|
|
7
|
+
import { Store } from '@ngrx/store'
|
|
8
|
+
import { selectRecord, selectRecordFieldsConfig } from './editor.selectors'
|
|
9
|
+
|
|
10
|
+
@Injectable()
|
|
11
|
+
export class EditorEffects {
|
|
12
|
+
private actions$ = inject(Actions)
|
|
13
|
+
private editorService = inject(EditorService)
|
|
14
|
+
private store = inject(Store)
|
|
15
|
+
|
|
16
|
+
saveRecord$ = createEffect(() =>
|
|
17
|
+
this.actions$.pipe(
|
|
18
|
+
ofType(EditorActions.saveRecord),
|
|
19
|
+
withLatestFrom(
|
|
20
|
+
this.store.select(selectRecord),
|
|
21
|
+
this.store.select(selectRecordFieldsConfig)
|
|
22
|
+
),
|
|
23
|
+
switchMap(([, record, fieldsConfig]) =>
|
|
24
|
+
this.editorService.saveRecord(record, fieldsConfig).pipe(
|
|
25
|
+
switchMap((newRecord) =>
|
|
26
|
+
of(
|
|
27
|
+
EditorActions.saveRecordSuccess(),
|
|
28
|
+
EditorActions.openRecord({ record: newRecord })
|
|
29
|
+
)
|
|
30
|
+
),
|
|
31
|
+
catchError((error) =>
|
|
32
|
+
of(
|
|
33
|
+
EditorActions.saveRecordFailure({
|
|
34
|
+
error: error.message,
|
|
35
|
+
})
|
|
36
|
+
)
|
|
37
|
+
)
|
|
38
|
+
)
|
|
39
|
+
)
|
|
40
|
+
)
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
markAsChanged$ = createEffect(() =>
|
|
44
|
+
this.actions$.pipe(
|
|
45
|
+
ofType(EditorActions.updateRecordField),
|
|
46
|
+
map(() => EditorActions.markRecordAsChanged())
|
|
47
|
+
)
|
|
48
|
+
)
|
|
49
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { inject, Injectable } from '@angular/core'
|
|
2
|
+
import { select, Store } from '@ngrx/store'
|
|
3
|
+
import * as EditorActions from './editor.actions'
|
|
4
|
+
import * as EditorSelectors from './editor.selectors'
|
|
5
|
+
import { CatalogRecord } from '../../../../../../libs/common/domain/src/lib/model/record'
|
|
6
|
+
|
|
7
|
+
@Injectable()
|
|
8
|
+
export class EditorFacade {
|
|
9
|
+
private readonly store = inject(Store)
|
|
10
|
+
|
|
11
|
+
record$ = this.store.pipe(select(EditorSelectors.selectRecord))
|
|
12
|
+
saving$ = this.store.pipe(select(EditorSelectors.selectRecordSaving))
|
|
13
|
+
saveError$ = this.store.pipe(select(EditorSelectors.selectRecordSaveError))
|
|
14
|
+
changedSinceSave$ = this.store.pipe(
|
|
15
|
+
select(EditorSelectors.selectRecordChangedSinceSave)
|
|
16
|
+
)
|
|
17
|
+
recordFields$ = this.store.pipe(select(EditorSelectors.selectRecordFields))
|
|
18
|
+
|
|
19
|
+
openRecord(record: CatalogRecord) {
|
|
20
|
+
this.store.dispatch(EditorActions.openRecord({ record }))
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
saveRecord() {
|
|
24
|
+
this.store.dispatch(EditorActions.saveRecord())
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
updateRecordField(field: string, value: unknown) {
|
|
28
|
+
this.store.dispatch(EditorActions.updateRecordField({ field, value }))
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type SaveRecordError = string
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { Action, createReducer, on } from '@ngrx/store'
|
|
2
|
+
import * as EditorActions from './editor.actions'
|
|
3
|
+
import { CatalogRecord } from '../../../../../../libs/common/domain/src/lib/model/record'
|
|
4
|
+
import { SaveRecordError } from './editor.models'
|
|
5
|
+
import { EditorFieldsConfig } from '../models/fields.model'
|
|
6
|
+
import { DEFAULT_FIELDS } from '../fields.config'
|
|
7
|
+
|
|
8
|
+
export const EDITOR_FEATURE_KEY = 'editor'
|
|
9
|
+
|
|
10
|
+
export interface EditorState {
|
|
11
|
+
record: CatalogRecord | null
|
|
12
|
+
saving: boolean
|
|
13
|
+
saveError: SaveRecordError | null
|
|
14
|
+
changedSinceSave: boolean
|
|
15
|
+
fieldsConfig: EditorFieldsConfig
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface EditorPartialState {
|
|
19
|
+
readonly [EDITOR_FEATURE_KEY]: EditorState
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const initialEditorState: EditorState = {
|
|
23
|
+
record: null,
|
|
24
|
+
saving: false,
|
|
25
|
+
saveError: null,
|
|
26
|
+
changedSinceSave: false,
|
|
27
|
+
fieldsConfig: DEFAULT_FIELDS,
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const reducer = createReducer(
|
|
31
|
+
initialEditorState,
|
|
32
|
+
on(EditorActions.openRecord, (state, { record }) => ({
|
|
33
|
+
...state,
|
|
34
|
+
changedSinceSave: false,
|
|
35
|
+
record,
|
|
36
|
+
})),
|
|
37
|
+
on(EditorActions.saveRecord, (state) => ({
|
|
38
|
+
...state,
|
|
39
|
+
saving: true,
|
|
40
|
+
saveError: null,
|
|
41
|
+
})),
|
|
42
|
+
on(EditorActions.saveRecordSuccess, (state) => ({
|
|
43
|
+
...state,
|
|
44
|
+
saving: false,
|
|
45
|
+
saveError: null,
|
|
46
|
+
changedSinceSave: false,
|
|
47
|
+
})),
|
|
48
|
+
on(EditorActions.saveRecordFailure, (state, { error }) => ({
|
|
49
|
+
...state,
|
|
50
|
+
saving: false,
|
|
51
|
+
saveError: error,
|
|
52
|
+
})),
|
|
53
|
+
on(EditorActions.updateRecordField, (state, { field, value }) => ({
|
|
54
|
+
...state,
|
|
55
|
+
record: {
|
|
56
|
+
...state.record,
|
|
57
|
+
[field]: value,
|
|
58
|
+
},
|
|
59
|
+
})),
|
|
60
|
+
on(EditorActions.markRecordAsChanged, (state) => ({
|
|
61
|
+
...state,
|
|
62
|
+
changedSinceSave: true,
|
|
63
|
+
}))
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
export function editorReducer(state: EditorState | undefined, action: Action) {
|
|
67
|
+
return reducer(state, action)
|
|
68
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { createFeatureSelector, createSelector } from '@ngrx/store'
|
|
2
|
+
import { EDITOR_FEATURE_KEY, EditorState } from './editor.reducer'
|
|
3
|
+
|
|
4
|
+
export const selectEditorState =
|
|
5
|
+
createFeatureSelector<EditorState>(EDITOR_FEATURE_KEY)
|
|
6
|
+
|
|
7
|
+
export const selectRecord = createSelector(
|
|
8
|
+
selectEditorState,
|
|
9
|
+
(state: EditorState) => state.record
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
export const selectRecordSaving = createSelector(
|
|
13
|
+
selectEditorState,
|
|
14
|
+
(state: EditorState) => state.saving
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
export const selectRecordSaveError = createSelector(
|
|
18
|
+
selectEditorState,
|
|
19
|
+
(state: EditorState) => state.saveError
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
export const selectRecordChangedSinceSave = createSelector(
|
|
23
|
+
selectEditorState,
|
|
24
|
+
(state: EditorState) => state.changedSinceSave
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
export const selectRecordFieldsConfig = createSelector(
|
|
28
|
+
selectEditorState,
|
|
29
|
+
(state: EditorState) => state.fieldsConfig
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
export const selectRecordFields = createSelector(
|
|
33
|
+
selectEditorState,
|
|
34
|
+
(state: EditorState) =>
|
|
35
|
+
state.fieldsConfig.map((fieldConfig) => ({
|
|
36
|
+
config: fieldConfig,
|
|
37
|
+
value: state.record?.[fieldConfig.model] || null,
|
|
38
|
+
}))
|
|
39
|
+
)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { EditorFieldState, EditorFieldValue } from './models/fields.model'
|
|
2
|
+
|
|
3
|
+
export type ExpressionEvaluator = (field: EditorFieldState) => EditorFieldValue
|
|
4
|
+
|
|
5
|
+
export function evaluate(expression: string): ExpressionEvaluator {
|
|
6
|
+
if (expression.match(/^\${.*}$/)) {
|
|
7
|
+
return evaluate(expression.slice(2, -1))
|
|
8
|
+
}
|
|
9
|
+
const operator = expression.split('(')[0]
|
|
10
|
+
switch (operator) {
|
|
11
|
+
case 'dateNow':
|
|
12
|
+
return () => new Date()
|
|
13
|
+
default:
|
|
14
|
+
throw new Error(`Unknown operator: ${operator}`)
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -10,6 +10,11 @@ import { TranslateModule } from '@ngx-translate/core'
|
|
|
10
10
|
import { WizardSummarizeComponent } from './components/wizard-summarize/wizard-summarize.component'
|
|
11
11
|
import { CommonModule } from '@angular/common'
|
|
12
12
|
import { HttpClientModule, HttpClientXsrfModule } from '@angular/common/http'
|
|
13
|
+
import { StoreModule } from '@ngrx/store'
|
|
14
|
+
import { EffectsModule } from '@ngrx/effects'
|
|
15
|
+
import * as fromEditor from './+state/editor.reducer'
|
|
16
|
+
import { EditorEffects } from './+state/editor.effects'
|
|
17
|
+
import { EditorFacade } from './+state/editor.facade'
|
|
13
18
|
|
|
14
19
|
@NgModule({
|
|
15
20
|
declarations: [
|
|
@@ -27,8 +32,14 @@ import { HttpClientModule, HttpClientXsrfModule } from '@angular/common/http'
|
|
|
27
32
|
MatFormFieldModule,
|
|
28
33
|
HttpClientModule,
|
|
29
34
|
HttpClientXsrfModule,
|
|
35
|
+
StoreModule.forFeature(
|
|
36
|
+
fromEditor.EDITOR_FEATURE_KEY,
|
|
37
|
+
fromEditor.editorReducer
|
|
38
|
+
),
|
|
39
|
+
EffectsModule.forFeature([EditorEffects]),
|
|
30
40
|
],
|
|
31
41
|
exports: [WizardComponent, WizardSummarizeComponent],
|
|
42
|
+
providers: [EditorFacade],
|
|
32
43
|
})
|
|
33
44
|
export class FeatureEditorModule {}
|
|
34
45
|
export * from './services/wizard.service'
|