geonetwork-ui 2.4.1-dev.9ee0df3df → 2.4.1-dev.a28bdabc1

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.
Files changed (121) hide show
  1. package/esm2022/libs/api/metadata-converter/src/lib/gn4/gn4.converter.mjs +4 -3
  2. package/esm2022/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.mjs +5 -2
  3. package/esm2022/libs/api/metadata-converter/src/lib/gn4/types/metadata.model.mjs +1 -1
  4. package/esm2022/libs/api/repository/src/lib/gn4/gn4-repository.mjs +27 -16
  5. package/esm2022/libs/common/domain/src/lib/repository/records-repository.interface.mjs +1 -1
  6. package/esm2022/libs/data-access/gn4/src/openapi/api/records.api.service.mjs +7 -1
  7. package/esm2022/libs/feature/editor/src/lib/+state/editor.actions.mjs +3 -1
  8. package/esm2022/libs/feature/editor/src/lib/+state/editor.effects.mjs +18 -14
  9. package/esm2022/libs/feature/editor/src/lib/+state/editor.facade.mjs +15 -5
  10. package/esm2022/libs/feature/editor/src/lib/+state/editor.reducer.mjs +10 -4
  11. package/esm2022/libs/feature/editor/src/lib/+state/editor.selectors.mjs +6 -5
  12. package/esm2022/libs/feature/editor/src/lib/components/online-service-resource-input/online-service-resource-input.component.mjs +57 -10
  13. package/esm2022/libs/feature/editor/src/lib/components/record-form/form-field/form-field-license/form-field-license.component.mjs +36 -23
  14. package/esm2022/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-link-resources/form-field-online-link-resources.component.mjs +7 -12
  15. package/esm2022/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-resources/form-field-online-resources.component.mjs +8 -12
  16. package/esm2022/libs/feature/editor/src/lib/components/record-form/form-field/form-field-overviews/form-field-overviews.component.mjs +6 -12
  17. package/esm2022/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.mjs +3 -3
  18. package/esm2022/libs/feature/editor/src/lib/services/editor.service.mjs +9 -5
  19. package/esm2022/libs/feature/search/src/lib/results-table/results-table-container.component.mjs +3 -4
  20. package/esm2022/libs/ui/dataviz/src/lib/figure/figure.component.mjs +3 -3
  21. package/esm2022/libs/ui/inputs/src/lib/file-input/file-input.component.mjs +4 -4
  22. package/esm2022/libs/ui/layout/src/lib/interactive-table/interactive-table.component.mjs +9 -4
  23. package/esm2022/libs/ui/search/src/lib/results-table/results-table.component.mjs +10 -10
  24. package/esm2022/libs/util/shared/src/lib/links/link-utils.mjs +40 -1
  25. package/esm2022/translations/de.json +29 -6
  26. package/esm2022/translations/en.json +13 -9
  27. package/esm2022/translations/es.json +27 -4
  28. package/esm2022/translations/fr.json +13 -9
  29. package/esm2022/translations/it.json +243 -218
  30. package/esm2022/translations/nl.json +27 -4
  31. package/esm2022/translations/pt.json +27 -4
  32. package/fesm2022/geonetwork-ui.mjs +883 -616
  33. package/fesm2022/geonetwork-ui.mjs.map +1 -1
  34. package/libs/api/metadata-converter/src/lib/gn4/gn4.converter.d.ts.map +1 -1
  35. package/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.d.ts.map +1 -1
  36. package/libs/api/metadata-converter/src/lib/gn4/types/metadata.model.d.ts +1 -0
  37. package/libs/api/metadata-converter/src/lib/gn4/types/metadata.model.d.ts.map +1 -1
  38. package/libs/api/repository/src/lib/gn4/gn4-repository.d.ts +4 -3
  39. package/libs/api/repository/src/lib/gn4/gn4-repository.d.ts.map +1 -1
  40. package/libs/common/domain/src/lib/repository/records-repository.interface.d.ts +4 -3
  41. package/libs/common/domain/src/lib/repository/records-repository.interface.d.ts.map +1 -1
  42. package/libs/data-access/gn4/src/openapi/api/records.api.service.d.ts +3 -0
  43. package/libs/data-access/gn4/src/openapi/api/records.api.service.d.ts.map +1 -1
  44. package/libs/feature/editor/src/lib/+state/editor.actions.d.ts +10 -2
  45. package/libs/feature/editor/src/lib/+state/editor.actions.d.ts.map +1 -1
  46. package/libs/feature/editor/src/lib/+state/editor.effects.d.ts +6 -2
  47. package/libs/feature/editor/src/lib/+state/editor.effects.d.ts.map +1 -1
  48. package/libs/feature/editor/src/lib/+state/editor.facade.d.ts +5 -2
  49. package/libs/feature/editor/src/lib/+state/editor.facade.d.ts.map +1 -1
  50. package/libs/feature/editor/src/lib/+state/editor.reducer.d.ts +2 -1
  51. package/libs/feature/editor/src/lib/+state/editor.reducer.d.ts.map +1 -1
  52. package/libs/feature/editor/src/lib/+state/editor.selectors.d.ts +2 -1
  53. package/libs/feature/editor/src/lib/+state/editor.selectors.d.ts.map +1 -1
  54. package/libs/feature/editor/src/lib/components/online-service-resource-input/online-service-resource-input.component.d.ts +16 -5
  55. package/libs/feature/editor/src/lib/components/online-service-resource-input/online-service-resource-input.component.d.ts.map +1 -1
  56. package/libs/feature/editor/src/lib/components/record-form/form-field/form-field-license/form-field-license.component.d.ts +4 -4
  57. package/libs/feature/editor/src/lib/components/record-form/form-field/form-field-license/form-field-license.component.d.ts.map +1 -1
  58. package/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-link-resources/form-field-online-link-resources.component.d.ts +1 -4
  59. package/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-link-resources/form-field-online-link-resources.component.d.ts.map +1 -1
  60. package/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-resources/form-field-online-resources.component.d.ts +2 -5
  61. package/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-resources/form-field-online-resources.component.d.ts.map +1 -1
  62. package/libs/feature/editor/src/lib/components/record-form/form-field/form-field-overviews/form-field-overviews.component.d.ts +1 -4
  63. package/libs/feature/editor/src/lib/components/record-form/form-field/form-field-overviews/form-field-overviews.component.d.ts.map +1 -1
  64. package/libs/feature/editor/src/lib/services/editor.service.d.ts +1 -1
  65. package/libs/feature/editor/src/lib/services/editor.service.d.ts.map +1 -1
  66. package/libs/feature/search/src/lib/results-table/results-table-container.component.d.ts +0 -1
  67. package/libs/feature/search/src/lib/results-table/results-table-container.component.d.ts.map +1 -1
  68. package/libs/ui/elements/src/lib/record-api-form/record-api-form.component.d.ts +1 -1
  69. package/libs/ui/inputs/src/lib/file-input/file-input.component.d.ts +1 -1
  70. package/libs/ui/inputs/src/lib/file-input/file-input.component.d.ts.map +1 -1
  71. package/libs/ui/layout/src/lib/interactive-table/interactive-table.component.d.ts +2 -1
  72. package/libs/ui/layout/src/lib/interactive-table/interactive-table.component.d.ts.map +1 -1
  73. package/libs/ui/search/src/lib/results-table/results-table.component.d.ts +3 -3
  74. package/libs/ui/search/src/lib/results-table/results-table.component.d.ts.map +1 -1
  75. package/libs/util/shared/src/lib/links/link-utils.d.ts +2 -1
  76. package/libs/util/shared/src/lib/links/link-utils.d.ts.map +1 -1
  77. package/package.json +1 -1
  78. package/src/libs/api/metadata-converter/src/lib/gn4/gn4.converter.ts +4 -3
  79. package/src/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.ts +8 -1
  80. package/src/libs/api/metadata-converter/src/lib/gn4/types/metadata.model.ts +1 -0
  81. package/src/libs/api/repository/src/lib/gn4/gn4-repository.ts +53 -27
  82. package/src/libs/common/domain/src/lib/repository/records-repository.interface.ts +5 -4
  83. package/src/libs/common/fixtures/src/lib/elasticsearch/full-response.fixtures.ts +2 -2
  84. package/src/libs/common/fixtures/src/lib/elasticsearch/search-responses.fixtures.ts +16 -16
  85. package/src/libs/common/fixtures/src/lib/records.fixtures.ts +163 -0
  86. package/src/libs/data-access/gn4/src/openapi/api/records.api.service.ts +24 -4
  87. package/src/libs/feature/editor/src/lib/+state/editor.actions.ts +10 -1
  88. package/src/libs/feature/editor/src/lib/+state/editor.effects.ts +57 -31
  89. package/src/libs/feature/editor/src/lib/+state/editor.facade.ts +15 -9
  90. package/src/libs/feature/editor/src/lib/+state/editor.reducer.ts +18 -12
  91. package/src/libs/feature/editor/src/lib/+state/editor.selectors.ts +13 -8
  92. package/src/libs/feature/editor/src/lib/components/online-service-resource-input/online-service-resource-input.component.html +38 -7
  93. package/src/libs/feature/editor/src/lib/components/online-service-resource-input/online-service-resource-input.component.ts +62 -3
  94. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-license/form-field-license.component.html +1 -1
  95. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-license/form-field-license.component.ts +31 -19
  96. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-link-resources/form-field-online-link-resources.component.html +1 -10
  97. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-link-resources/form-field-online-link-resources.component.ts +1 -7
  98. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-resources/form-field-online-resources.component.html +11 -20
  99. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-resources/form-field-online-resources.component.ts +5 -10
  100. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-overviews/form-field-overviews.component.html +0 -9
  101. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-overviews/form-field-overviews.component.ts +2 -8
  102. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.html +2 -2
  103. package/src/libs/feature/editor/src/lib/services/editor.service.ts +18 -16
  104. package/src/libs/feature/search/src/lib/results-table/results-table-container.component.html +0 -1
  105. package/src/libs/feature/search/src/lib/results-table/results-table-container.component.ts +0 -3
  106. package/src/libs/ui/dataviz/src/lib/figure/figure.component.html +1 -0
  107. package/src/libs/ui/inputs/src/lib/file-input/file-input.component.ts +1 -1
  108. package/src/libs/ui/layout/src/lib/interactive-table/interactive-table.component.html +12 -1
  109. package/src/libs/ui/layout/src/lib/interactive-table/interactive-table.component.ts +4 -6
  110. package/src/libs/ui/search/src/lib/results-table/results-table.component.html +23 -6
  111. package/src/libs/ui/search/src/lib/results-table/results-table.component.ts +6 -6
  112. package/src/libs/util/shared/src/lib/links/link-utils.ts +51 -1
  113. package/tailwind.base.config.js +2 -0
  114. package/translations/de.json +29 -6
  115. package/translations/en.json +13 -9
  116. package/translations/es.json +27 -4
  117. package/translations/fr.json +13 -9
  118. package/translations/it.json +243 -218
  119. package/translations/nl.json +27 -4
  120. package/translations/pt.json +27 -4
  121. package/translations/sk.json +27 -4
@@ -8,7 +8,6 @@ import { Store } from '@ngrx/store'
8
8
  import {
9
9
  selectEditorConfig,
10
10
  selectRecord,
11
- selectRecordAlreadySavedOnce,
12
11
  selectRecordSource,
13
12
  } from './editor.selectors'
14
13
  import { RecordsRepositoryInterface } from '../../../../../../libs/common/domain/src/lib/repository/records-repository.interface'
@@ -28,31 +27,27 @@ export class EditorEffects {
28
27
  withLatestFrom(
29
28
  this.store.select(selectRecord),
30
29
  this.store.select(selectRecordSource),
31
- this.store.select(selectEditorConfig),
32
- this.store.select(selectRecordAlreadySavedOnce)
30
+ this.store.select(selectEditorConfig)
33
31
  ),
34
- switchMap(([, record, recordSource, fieldsConfig, alreadySavedOnce]) =>
35
- this.editorService
36
- .saveRecord(record, recordSource, fieldsConfig, !alreadySavedOnce)
37
- .pipe(
38
- switchMap(([record, recordSource]) =>
39
- of(
40
- EditorActions.saveRecordSuccess(),
41
- EditorActions.openRecord({
42
- record,
43
- alreadySavedOnce: true,
44
- recordSource,
45
- })
46
- )
47
- ),
48
- catchError((error) =>
49
- of(
50
- EditorActions.saveRecordFailure({
51
- error,
52
- })
53
- )
32
+ switchMap(([, record, recordSource, fieldsConfig]) =>
33
+ this.editorService.saveRecord(record, recordSource, fieldsConfig).pipe(
34
+ switchMap(([record, recordSource]) =>
35
+ of(
36
+ EditorActions.saveRecordSuccess(),
37
+ EditorActions.openRecord({
38
+ record,
39
+ recordSource,
40
+ })
41
+ )
42
+ ),
43
+ catchError((error) =>
44
+ of(
45
+ EditorActions.saveRecordFailure({
46
+ error,
47
+ })
54
48
  )
55
49
  )
50
+ )
56
51
  )
57
52
  )
58
53
  )
@@ -63,12 +58,14 @@ export class EditorEffects {
63
58
  ofType(EditorActions.saveRecordSuccess),
64
59
  withLatestFrom(this.store.select(selectRecord)),
65
60
  switchMap(([_, record]) => {
66
- this.gn4PlateformService.cleanRecordAttachments(record).subscribe({
67
- next: (_) => undefined,
68
- error: (err) => {
69
- console.error(err)
70
- },
71
- })
61
+ if (record.uniqueIdentifier !== null) {
62
+ this.gn4PlateformService.cleanRecordAttachments(record).subscribe({
63
+ next: (_) => undefined,
64
+ error: (err) => {
65
+ console.error(err)
66
+ },
67
+ })
68
+ }
72
69
  return EMPTY
73
70
  }),
74
71
  catchError((error) => {
@@ -106,10 +103,9 @@ export class EditorEffects {
106
103
  ofType(EditorActions.undoRecordDraft),
107
104
  withLatestFrom(this.store.select(selectRecord)),
108
105
  switchMap(([, record]) => this.editorService.undoRecordDraft(record)),
109
- map(([record, recordSource, alreadySavedOnce]) =>
106
+ map(([record, recordSource]) =>
110
107
  EditorActions.openRecord({
111
108
  record,
112
- alreadySavedOnce,
113
109
  recordSource,
114
110
  })
115
111
  )
@@ -141,4 +137,34 @@ export class EditorEffects {
141
137
  )
142
138
  )
143
139
  )
140
+
141
+ checkIsRecordPublished$ = createEffect(() =>
142
+ this.actions$.pipe(
143
+ ofType(EditorActions.openRecord),
144
+ map(({ record }) => record.uniqueIdentifier),
145
+ switchMap((uniqueIdentifier) =>
146
+ this.recordsRepository.getRecordPublicationStatus(uniqueIdentifier)
147
+ ),
148
+ map((isPublished) =>
149
+ EditorActions.isPublished({
150
+ isPublished: isPublished,
151
+ })
152
+ )
153
+ )
154
+ )
155
+
156
+ checkCanEditRecord$ = createEffect(() =>
157
+ this.actions$.pipe(
158
+ ofType(EditorActions.openRecord),
159
+ map(({ record }) => record.uniqueIdentifier),
160
+ switchMap((uniqueIdentifier) =>
161
+ this.recordsRepository.canEditRecord(uniqueIdentifier)
162
+ ),
163
+ map((canEditRecord) =>
164
+ EditorActions.canEditRecord({
165
+ canEditRecord: canEditRecord,
166
+ })
167
+ )
168
+ )
169
+ )
144
170
  }
@@ -14,9 +14,6 @@ export class EditorFacade {
14
14
 
15
15
  record$ = this.store.pipe(select(EditorSelectors.selectRecord))
16
16
  recordSource$ = this.store.pipe(select(EditorSelectors.selectRecordSource))
17
- alreadySavedOnce$ = this.store.pipe(
18
- select(EditorSelectors.selectRecordAlreadySavedOnce)
19
- )
20
17
  saving$ = this.store.pipe(select(EditorSelectors.selectRecordSaving))
21
18
  saveError$ = this.store.pipe(
22
19
  select(EditorSelectors.selectRecordSaveError),
@@ -35,14 +32,15 @@ export class EditorFacade {
35
32
  hasRecordChanged$ = this.store.pipe(
36
33
  select(EditorSelectors.selectHasRecordChanged)
37
34
  )
35
+ isPublished$ = this.store.pipe(select(EditorSelectors.selectIsPublished))
36
+ canEditRecord$ = this.store.pipe(select(EditorSelectors.selectCanEditRecord))
38
37
 
39
- openRecord(
40
- record: CatalogRecord,
41
- recordSource: string,
42
- alreadySavedOnce: boolean
43
- ) {
38
+ openRecord(record: CatalogRecord, recordSource: string) {
44
39
  this.store.dispatch(
45
- EditorActions.openRecord({ record, recordSource, alreadySavedOnce })
40
+ EditorActions.openRecord({
41
+ record,
42
+ recordSource,
43
+ })
46
44
  )
47
45
  this.setCurrentPage(0)
48
46
  }
@@ -70,4 +68,12 @@ export class EditorFacade {
70
68
  checkHasRecordChanged(record: CatalogRecord) {
71
69
  this.store.dispatch(EditorActions.hasRecordChangedSinceDraft({ record }))
72
70
  }
71
+
72
+ isPublished(isPublished: boolean) {
73
+ this.store.dispatch(EditorActions.isPublished({ isPublished }))
74
+ }
75
+
76
+ canEditRecord(canEditRecord: boolean) {
77
+ this.store.dispatch(EditorActions.canEditRecord({ canEditRecord }))
78
+ }
73
79
  }
@@ -18,13 +18,14 @@ export const EDITOR_FEATURE_KEY = 'editor'
18
18
  export interface EditorState {
19
19
  record: CatalogRecord | null
20
20
  recordSource: string | null
21
- alreadySavedOnce: boolean
22
21
  saving: boolean
23
22
  saveError: SaveRecordError | null
24
23
  changedSinceSave: boolean
25
24
  editorConfig: EditorConfig
26
25
  currentPage: number
27
26
  hasRecordChanged: { user: string; date: Date }
27
+ isPublished: boolean
28
+ canEditRecord: boolean
28
29
  }
29
30
 
30
31
  export interface EditorPartialState {
@@ -34,27 +35,24 @@ export interface EditorPartialState {
34
35
  export const initialEditorState: EditorState = {
35
36
  record: null,
36
37
  recordSource: null,
37
- alreadySavedOnce: false,
38
38
  saving: false,
39
39
  saveError: null,
40
40
  changedSinceSave: false,
41
41
  editorConfig: DEFAULT_CONFIGURATION,
42
42
  currentPage: 0,
43
43
  hasRecordChanged: null,
44
+ isPublished: true,
45
+ canEditRecord: true,
44
46
  }
45
47
 
46
48
  const reducer = createReducer(
47
49
  initialEditorState,
48
- on(
49
- EditorActions.openRecord,
50
- (state, { record, recordSource, alreadySavedOnce }) => ({
51
- ...state,
52
- changedSinceSave: false,
53
- recordSource: recordSource ?? null,
54
- alreadySavedOnce,
55
- record,
56
- })
57
- ),
50
+ on(EditorActions.openRecord, (state, { record, recordSource }) => ({
51
+ ...state,
52
+ changedSinceSave: false,
53
+ recordSource: recordSource ?? null,
54
+ record,
55
+ })),
58
56
  on(EditorActions.saveRecord, (state) => ({
59
57
  ...state,
60
58
  saving: true,
@@ -110,6 +108,14 @@ const reducer = createReducer(
110
108
  on(EditorActions.hasRecordChangedSinceDraftSuccess, (state, { changes }) => ({
111
109
  ...state,
112
110
  hasRecordChanged: changes,
111
+ })),
112
+ on(EditorActions.isPublished, (state, { isPublished }) => ({
113
+ ...state,
114
+ isPublished: isPublished,
115
+ })),
116
+ on(EditorActions.canEditRecord, (state, { canEditRecord }) => ({
117
+ ...state,
118
+ canEditRecord: canEditRecord,
113
119
  }))
114
120
  )
115
121
 
@@ -30,11 +30,6 @@ export const selectRecordChangedSinceSave = createSelector(
30
30
  (state: EditorState) => state.changedSinceSave
31
31
  )
32
32
 
33
- export const selectRecordAlreadySavedOnce = createSelector(
34
- selectEditorState,
35
- (state: EditorState) => state.alreadySavedOnce
36
- )
37
-
38
33
  export const selectEditorConfig = createSelector(
39
34
  selectEditorState,
40
35
  (state: EditorState) => state.editorConfig
@@ -48,11 +43,11 @@ export const selectCurrentPage = createSelector(
48
43
  export const selectRecordSections = createSelector(
49
44
  selectEditorState,
50
45
  (state: EditorState) => {
51
- const currentPage = state.editorConfig.pages[state.currentPage]
52
- if (!currentPage) {
46
+ const currentPageConfig = state.editorConfig.pages[state.currentPage]
47
+ if (!currentPageConfig) {
53
48
  return [] as EditorSectionWithValues[]
54
49
  }
55
- return currentPage.sections.map((section) => ({
50
+ return currentPageConfig.sections.map((section) => ({
56
51
  ...section,
57
52
  fieldsWithValues: section.fields.map((fieldConfig) => ({
58
53
  config: fieldConfig,
@@ -66,3 +61,13 @@ export const selectHasRecordChanged = createSelector(
66
61
  selectEditorState,
67
62
  (state: EditorState) => state.hasRecordChanged
68
63
  )
64
+
65
+ export const selectIsPublished = createSelector(
66
+ selectEditorState,
67
+ (state: EditorState) => state.isPublished
68
+ )
69
+
70
+ export const selectCanEditRecord = createSelector(
71
+ selectEditorState,
72
+ (state: EditorState) => state.canEditRecord
73
+ )
@@ -17,6 +17,7 @@
17
17
  class="flex flex-row gap-[8px]"
18
18
  [(ngModel)]="service.accessServiceProtocol"
19
19
  [disabled]="disabled"
20
+ (change)="resetLayersSuggestion()"
20
21
  >
21
22
  <mat-radio-button
22
23
  *ngFor="let protocolOption of protocolOptions"
@@ -30,29 +31,59 @@
30
31
  <div class="flex flex-col gap-4">
31
32
  <gn-ui-url-input
32
33
  class="w-full"
33
- (valueChange)="handleUrlChange($event)"
34
+ (uploadClick)="handleUploadClick($event)"
35
+ (valueChange)="handleUrlValueChange($event)"
34
36
  [disabled]="disabled"
35
37
  [value]="url"
36
- [showValidateButton]="false"
38
+ [showValidateButton]="activeLayerSuggestion"
37
39
  >
38
- <ng-icon name="iconoirCloudUpload"></ng-icon>
40
+ <ng-content *ngIf="activeLayerSuggestion">
41
+ <ng-icon name="iconoirCloudUpload"></ng-icon>
42
+ </ng-content>
39
43
  </gn-ui-url-input>
40
44
 
45
+ <p class="text-sm text-red-500 pl-4" *ngIf="errorMessage" translate>
46
+ editor.record.form.field.onlineResource.edit.identifier.error
47
+ </p>
48
+
41
49
  <gn-ui-text-input
42
50
  class="grow border-b border-gray-300 pb-4"
43
51
  [(value)]="service.identifierInService"
44
52
  [placeholder]="getIdentifierPlaceholder() | translate"
45
53
  data-cy="identifier-in-service"
46
54
  [disabled]="disabled"
55
+ *ngIf="
56
+ !activeLayerSuggestion ||
57
+ (url && errorMessage) ||
58
+ (modifyMode && layers === undefined)
59
+ "
47
60
  ></gn-ui-text-input>
48
-
61
+ <gn-ui-dropdown-selector
62
+ class="border-b border-gray-300 pb-4"
63
+ [showTitle]="false"
64
+ [title]="
65
+ 'editor.record.form.field.onlineResource.edit.identifier.select.label'
66
+ | translate
67
+ "
68
+ [choices]="layers || []"
69
+ *ngIf="activeLayerSuggestion && layers !== undefined"
70
+ [selected]="service.identifierInService"
71
+ (selectValue)="handleSelectValue($event)"
72
+ >
73
+ </gn-ui-dropdown-selector>
49
74
  <gn-ui-button
50
75
  (buttonClick)="submitIdentifier(service.identifierInService)"
51
- [disabled]="disabled || !service.identifierInService || !url"
76
+ [disabled]="disabled || !service.identifierInService"
52
77
  type="primary"
78
+ *ngIf="
79
+ !modifyMode &&
80
+ ((activeLayerSuggestion && layers) ||
81
+ !activeLayerSuggestion ||
82
+ (url && errorMessage))
83
+ "
53
84
  >
54
- <span class="text-white font-bold" translate
55
- >editor.record.form.field.onlineResource.edit.identifier.submit</span
85
+ <span class="text-white font-bold" translate>
86
+ editor.record.form.field.onlineResource.edit.identifier.submit</span
56
87
  >
57
88
  </gn-ui-button>
58
89
  </div>
@@ -1,10 +1,12 @@
1
1
  import { CommonModule } from '@angular/common'
2
2
  import {
3
3
  ChangeDetectionStrategy,
4
+ ChangeDetectorRef,
4
5
  Component,
5
6
  EventEmitter,
6
7
  Input,
7
8
  OnChanges,
9
+ OnInit,
8
10
  Output,
9
11
  } from '@angular/core'
10
12
  import { FormsModule } from '@angular/forms'
@@ -17,6 +19,8 @@ import {
17
19
  } from '../../../../../../../libs/common/domain/src/lib/model/record'
18
20
  import {
19
21
  ButtonComponent,
22
+ DropdownChoice,
23
+ DropdownSelectorComponent,
20
24
  TextInputComponent,
21
25
  UrlInputComponent,
22
26
  } from '../../../../../../../libs/ui/inputs/src'
@@ -27,6 +31,7 @@ import {
27
31
  provideNgIconsConfig,
28
32
  } from '@ng-icons/core'
29
33
  import { iconoirCloudUpload } from '@ng-icons/iconoir'
34
+ import { getLayers } from '../../../../../../../libs/util/shared/src'
30
35
 
31
36
  @Component({
32
37
  selector: 'gn-ui-online-service-resource-input',
@@ -35,6 +40,7 @@ import { iconoirCloudUpload } from '@ng-icons/iconoir'
35
40
  changeDetection: ChangeDetectionStrategy.OnPush,
36
41
  standalone: true,
37
42
  imports: [
43
+ DropdownSelectorComponent,
38
44
  ButtonComponent,
39
45
  CommonModule,
40
46
  FormsModule,
@@ -52,18 +58,21 @@ import { iconoirCloudUpload } from '@ng-icons/iconoir'
52
58
  }),
53
59
  ],
54
60
  })
55
- export class OnlineServiceResourceInputComponent implements OnChanges {
56
- @Input() service: Omit<DatasetServiceDistribution, 'url'>
61
+ export class OnlineServiceResourceInputComponent implements OnChanges, OnInit {
62
+ @Input() service: DatasetServiceDistribution
57
63
  @Input() protocolHint?: string
58
64
  @Input() disabled? = false
65
+ @Input() modifyMode? = false
59
66
  @Output() urlChange: EventEmitter<string> = new EventEmitter()
60
67
  @Output() identifierSubmit: EventEmitter<{
61
68
  url: string
62
69
  identifier: string
63
70
  }> = new EventEmitter()
64
71
 
72
+ errorMessage = false
65
73
  selectedProtocol: ServiceProtocol
66
74
  url: string
75
+ layers: DropdownChoice[] | undefined = undefined
67
76
 
68
77
  protocolOptions: {
69
78
  label: string
@@ -99,6 +108,14 @@ export class OnlineServiceResourceInputComponent implements OnChanges {
99
108
  },
100
109
  ]
101
110
 
111
+ constructor(private cdr: ChangeDetectorRef) {}
112
+
113
+ get activeLayerSuggestion() {
114
+ return !['wps', 'GPFDL', 'esriRest', 'other'].includes(
115
+ this.service.accessServiceProtocol
116
+ )
117
+ }
118
+
102
119
  ngOnChanges() {
103
120
  this.selectedProtocol =
104
121
  this.protocolOptions.find(
@@ -106,8 +123,50 @@ export class OnlineServiceResourceInputComponent implements OnChanges {
106
123
  )?.value ?? 'other'
107
124
  }
108
125
 
109
- handleUrlChange(url: string) {
126
+ ngOnInit() {
127
+ if (this.service.url) {
128
+ this.url = this.service.url.toString()
129
+ }
130
+ }
131
+
132
+ handleUrlValueChange(url: string) {
133
+ this.url = url
134
+ this.service.url = new URL(url)
135
+ this.resetLayersSuggestion()
136
+ this.urlChange.emit(this.url)
137
+ }
138
+
139
+ async handleUploadClick(url: string) {
110
140
  this.url = url
141
+
142
+ try {
143
+ const layers = await getLayers(url, this.service.accessServiceProtocol)
144
+ this.layers = layers.map((l) => {
145
+ return {
146
+ label: l.title ? `${l.title} ${l.name ? `(${l.name})` : ''}` : l.name,
147
+ value: l.name || l.title,
148
+ }
149
+ })
150
+
151
+ if (this.layers.length === 0) {
152
+ throw new Error('No layers found')
153
+ }
154
+ } catch (e) {
155
+ this.errorMessage = true
156
+ this.layers = undefined
157
+ }
158
+
159
+ this.cdr.detectChanges()
160
+ }
161
+
162
+ handleSelectValue(val: string) {
163
+ this.service.identifierInService = val
164
+ }
165
+
166
+ resetLayersSuggestion() {
167
+ this.errorMessage = false
168
+ this.layers = undefined
169
+ this.service.identifierInService = null
111
170
  }
112
171
 
113
172
  submitIdentifier(identifier: string) {
@@ -2,7 +2,7 @@
2
2
  <gn-ui-dropdown-selector
3
3
  [title]="label"
4
4
  [showTitle]="false"
5
- [choices]="licenceOptions"
5
+ [choices]="choices"
6
6
  [selected]="selectedLicence"
7
7
  (selectValue)="handleLicenceSelection($event)"
8
8
  [extraBtnClass]="'input-as-button gn-ui-text-input'"
@@ -26,35 +26,47 @@ type Licence = {
26
26
  })
27
27
  export class FormFieldLicenseComponent implements OnInit {
28
28
  @Input() label: string
29
- @Input() recordConstraints: Constraint[] = []
30
- @Output() recordConstraintsChange: EventEmitter<Constraint[]> =
29
+ @Input() recordLicences: Constraint[] = []
30
+ @Output() recordLicencesChange: EventEmitter<Constraint[]> =
31
31
  new EventEmitter()
32
32
 
33
+ choices: Licence[] = AVAILABLE_LICENSES.map((license) => ({
34
+ label: marker(`editor.record.form.license.${license}`),
35
+ value: license,
36
+ }))
37
+
33
38
  selectedLicence: string
34
39
 
35
40
  ngOnInit(): void {
36
- // get the licence from the record constraints if it is one of the open data licence list
37
- this.selectedLicence = this.recordConstraints.find((constraint) => {
38
- return this.licenceOptions.find((licence) => {
39
- return licence.value === constraint.text
40
- })
41
- })?.text
42
- // otherwise pre-select the first licence option
43
- if (this.selectedLicence === undefined) {
44
- this.selectedLicence = this.licenceOptions[0].value // cannot select 'etalab' as default as this would toggle the OpenData Toggle
45
- this.recordConstraintsChange.emit([{ text: this.selectedLicence }])
41
+ if (this.recordLicences.length === 0) {
42
+ this.selectedLicence = 'unknown'
43
+ } else {
44
+ this.selectedLicence = this.recordLicences.find((constraint) => {
45
+ return this.choices.find((licence) => {
46
+ return licence.value === constraint.text
47
+ })
48
+ })?.text
46
49
  }
47
- }
48
50
 
49
- get licenceOptions(): Licence[] {
50
- return AVAILABLE_LICENSES.map((license) => ({
51
- label: marker(`editor.record.form.license.${license}`),
52
- value: license,
53
- }))
51
+ if (this.selectedLicence === undefined) {
52
+ this.choices = [
53
+ {
54
+ value: this.recordLicences[0].text,
55
+ label: this.recordLicences[0].text,
56
+ },
57
+ ...this.choices,
58
+ ]
59
+ this.selectedLicence = this.recordLicences[0].text
60
+ }
54
61
  }
55
62
 
56
63
  handleLicenceSelection(licenceValue: string) {
57
64
  this.selectedLicence = licenceValue
58
- this.recordConstraintsChange.emit([{ text: licenceValue }])
65
+ if (licenceValue === 'unknown') {
66
+ this.recordLicencesChange.emit([])
67
+ return
68
+ } else {
69
+ this.recordLicencesChange.emit([{ text: licenceValue }])
70
+ }
59
71
  }
60
72
  }
@@ -5,7 +5,6 @@
5
5
  (uploadCancel)="handleUploadCancel()"
6
6
  [uploadProgress]="uploadProgress"
7
7
  (urlChange)="handleUrlChange($event)"
8
- [disabled]="disabled$ | async"
9
8
  ></gn-ui-file-input>
10
9
  <div class="h-[8px]"></div>
11
10
  <gn-ui-sortable-list
@@ -42,17 +41,9 @@
42
41
  class="w-full"
43
42
  [disabled]="true"
44
43
  [value]="onlineResource.url"
45
- [showValidateButton]="false"
46
44
  [disabled]="disabled$ | async"
45
+ [showValidateButton]="false"
47
46
  ></gn-ui-url-input>
48
47
  </div>
49
48
  </ng-template>
50
- <div
51
- *ngIf="disabled$ | async"
52
- class="p-4 text-sm border border-primary bg-primary-lightest rounded-lg"
53
- translate
54
- data-test="disabled-message"
55
- >
56
- editor.record.form.field.draft.only.disabled
57
- </div>
58
49
  </div>
@@ -30,7 +30,6 @@ import { PlatformServiceInterface } from '../../../../../../../../../libs/common
30
30
  import { map, Subscription } from 'rxjs'
31
31
  import { MatDialog } from '@angular/material/dialog'
32
32
  import { MAX_UPLOAD_SIZE_MB } from '../../../../fields.config'
33
- import { EditorFacade } from '../../../../+state/editor.facade'
34
33
 
35
34
  @Component({
36
35
  selector: 'gn-ui-form-field-online-link-resources',
@@ -69,17 +68,12 @@ export class FormFieldOnlineLinkResourcesComponent {
69
68
 
70
69
  protected MAX_UPLOAD_SIZE_MB = MAX_UPLOAD_SIZE_MB
71
70
 
72
- disabled$ = this.editorFacade.alreadySavedOnce$.pipe(
73
- map((alreadySavedOnce) => !alreadySavedOnce)
74
- )
75
-
76
71
  constructor(
77
72
  private notificationsService: NotificationsService,
78
73
  private translateService: TranslateService,
79
74
  private platformService: PlatformServiceInterface,
80
75
  private cd: ChangeDetectorRef,
81
- private dialog: MatDialog,
82
- private editorFacade: EditorFacade
76
+ private dialog: MatDialog
83
77
  ) {}
84
78
 
85
79
  handleFileChange(file: File) {
@@ -4,7 +4,6 @@
4
4
  (selectedValue)="onSelectedTypeChange($event.value)"
5
5
  extraClasses="grow text-sm"
6
6
  data-cy="online-resources-type"
7
- [disabled]="disabled$ | async"
8
7
  ></gn-ui-switch-toggle>
9
8
  <div class="h-[8px]"></div>
10
9
  <gn-ui-file-input
@@ -14,7 +13,6 @@
14
13
  (uploadCancel)="handleUploadCancel()"
15
14
  [uploadProgress]="uploadProgress"
16
15
  (urlChange)="handleDownloadUrlChange($event)"
17
- [disabled]="disabled$ | async"
18
16
  ></gn-ui-file-input>
19
17
  <div
20
18
  *ngIf="selectedType === 'service'"
@@ -23,7 +21,6 @@
23
21
  <gn-ui-online-service-resource-input
24
22
  [service]="newService"
25
23
  [disabled]="disabled$ | async"
26
- (urlChange)="handleServiceUrlChange($event)"
27
24
  (identifierSubmit)="handleIdentifierSubmit($event)"
28
25
  ></gn-ui-online-service-resource-input>
29
26
  </div>
@@ -57,28 +54,22 @@
57
54
  [(value)]="onlineResource.description"
58
55
  ></gn-ui-text-area>
59
56
  </div>
60
- <ng-container *ngIf="onlineResource.type === 'service'">
57
+ <ng-container *ngIf="onlineResource.type === 'service'; else urlInput">
61
58
  <span class="w-full border-b border-gray-300"></span>
62
59
  <gn-ui-online-service-resource-input
63
60
  [service]="onlineResource"
64
- [disabled]="disabled$ | async"
61
+ [modifyMode]="true"
65
62
  ></gn-ui-online-service-resource-input>
66
63
  </ng-container>
67
- <span class="w-full border-b border-gray-300"></span>
68
- <gn-ui-url-input
69
- class="w-full"
70
- [disabled]="true"
71
- [value]="onlineResource.url"
72
- [showValidateButton]="false"
73
- ></gn-ui-url-input>
64
+ <ng-template #urlInput>
65
+ <span class="w-full border-b border-gray-300"></span>
66
+ <gn-ui-url-input
67
+ class="w-full"
68
+ [disabled]="true"
69
+ [value]="onlineResource.url"
70
+ [showValidateButton]="false"
71
+ ></gn-ui-url-input>
72
+ </ng-template>
74
73
  </div>
75
74
  </ng-template>
76
- <div
77
- *ngIf="disabled$ | async"
78
- class="p-4 text-sm border border-primary bg-primary-lightest rounded-lg"
79
- translate
80
- data-test="disabled-message"
81
- >
82
- editor.record.form.field.draft.only.disabled
83
- </div>
84
75
  </div>