geonetwork-ui 2.5.0-dev.22c177ea1 → 2.5.0-dev.4e621e7b5

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 (159) hide show
  1. package/esm2022/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.mjs +11 -1
  2. package/esm2022/libs/api/metadata-converter/src/lib/gn4/types/metadata.model.mjs +1 -1
  3. package/esm2022/libs/api/repository/src/lib/gn4/elasticsearch/elasticsearch.service.mjs +20 -17
  4. package/esm2022/libs/api/repository/src/lib/gn4/gn4-repository.mjs +22 -2
  5. package/esm2022/libs/common/domain/src/lib/model/record/metadata.model.mjs +1 -1
  6. package/esm2022/libs/common/domain/src/lib/repository/records-repository.interface.mjs +1 -1
  7. package/esm2022/libs/feature/dataviz/src/lib/chart-view/chart-view.component.mjs +7 -4
  8. package/esm2022/libs/feature/dataviz/src/lib/service/data.service.mjs +23 -15
  9. package/esm2022/libs/feature/dataviz/src/lib/table-view/table-view.component.mjs +7 -4
  10. package/esm2022/libs/feature/editor/src/lib/components/constraint-card/constraint-card.component.mjs +3 -3
  11. package/esm2022/libs/feature/editor/src/lib/components/record-form/form-field/form-field-contacts-for-resource/form-field-contacts-for-resource.component.mjs +2 -1
  12. package/esm2022/libs/feature/editor/src/lib/components/record-form/form-field/form-field-rich/form-field-rich.component.mjs +2 -2
  13. package/esm2022/libs/feature/editor/src/lib/fields.config.mjs +2 -2
  14. package/esm2022/libs/feature/record/src/lib/data-view/data-view.component.mjs +4 -3
  15. package/esm2022/libs/feature/record/src/lib/map-view/map-view.component.mjs +3 -2
  16. package/esm2022/libs/feature/record/src/lib/state/mdview.actions.mjs +4 -1
  17. package/esm2022/libs/feature/record/src/lib/state/mdview.effects.mjs +7 -2
  18. package/esm2022/libs/feature/record/src/lib/state/mdview.facade.mjs +9 -1
  19. package/esm2022/libs/feature/record/src/lib/state/mdview.reducer.mjs +19 -1
  20. package/esm2022/libs/feature/record/src/lib/state/mdview.selectors.mjs +6 -1
  21. package/esm2022/libs/feature/search/src/lib/results-table/results-table-container.component.mjs +1 -1
  22. package/esm2022/libs/ui/elements/src/index.mjs +2 -1
  23. package/esm2022/libs/ui/elements/src/lib/application-banner/application-banner.component.mjs +78 -0
  24. package/esm2022/libs/ui/elements/src/lib/record-api-form/record-api-form.component.mjs +2 -1
  25. package/esm2022/libs/ui/elements/src/lib/ui-elements.module.mjs +10 -4
  26. package/esm2022/libs/ui/inputs/src/lib/autocomplete/autocomplete.component.mjs +7 -2
  27. package/esm2022/libs/ui/search/src/lib/results-table/action-menu/action-menu.component.mjs +14 -4
  28. package/esm2022/libs/ui/search/src/lib/results-table/results-table.component.mjs +10 -3
  29. package/esm2022/libs/util/data-fetcher/src/lib/data-fetcher.mjs +5 -4
  30. package/esm2022/libs/util/data-fetcher/src/lib/readers/base-cache.mjs +12 -0
  31. package/esm2022/libs/util/data-fetcher/src/lib/readers/base-file.mjs +3 -3
  32. package/esm2022/libs/util/data-fetcher/src/lib/readers/base.mjs +1 -1
  33. package/esm2022/libs/util/data-fetcher/src/lib/readers/csv.mjs +2 -2
  34. package/esm2022/libs/util/data-fetcher/src/lib/readers/excel.mjs +2 -2
  35. package/esm2022/libs/util/data-fetcher/src/lib/readers/geojson.mjs +2 -2
  36. package/esm2022/libs/util/data-fetcher/src/lib/readers/gml.mjs +5 -3
  37. package/esm2022/libs/util/data-fetcher/src/lib/readers/json.mjs +2 -2
  38. package/esm2022/libs/util/data-fetcher/src/lib/readers/wfs.mjs +19 -11
  39. package/esm2022/libs/util/data-fetcher/src/lib/utils.mjs +9 -7
  40. package/esm2022/translations/de.json +3 -4
  41. package/esm2022/translations/en.json +4 -13
  42. package/esm2022/translations/es.json +3 -4
  43. package/esm2022/translations/fr.json +15 -16
  44. package/esm2022/translations/it.json +20 -20
  45. package/esm2022/translations/nl.json +3 -4
  46. package/esm2022/translations/pt.json +3 -4
  47. package/fesm2022/geonetwork-ui.mjs +407 -207
  48. package/fesm2022/geonetwork-ui.mjs.map +1 -1
  49. package/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.d.ts.map +1 -1
  50. package/libs/api/metadata-converter/src/lib/gn4/types/metadata.model.d.ts +3 -0
  51. package/libs/api/metadata-converter/src/lib/gn4/types/metadata.model.d.ts.map +1 -1
  52. package/libs/api/repository/src/lib/gn4/elasticsearch/elasticsearch.service.d.ts +1 -0
  53. package/libs/api/repository/src/lib/gn4/elasticsearch/elasticsearch.service.d.ts.map +1 -1
  54. package/libs/api/repository/src/lib/gn4/gn4-repository.d.ts +2 -1
  55. package/libs/api/repository/src/lib/gn4/gn4-repository.d.ts.map +1 -1
  56. package/libs/common/domain/src/lib/model/record/metadata.model.d.ts +6 -0
  57. package/libs/common/domain/src/lib/model/record/metadata.model.d.ts.map +1 -1
  58. package/libs/common/domain/src/lib/repository/records-repository.interface.d.ts +2 -1
  59. package/libs/common/domain/src/lib/repository/records-repository.interface.d.ts.map +1 -1
  60. package/libs/feature/dataviz/src/lib/chart-view/chart-view.component.d.ts +2 -1
  61. package/libs/feature/dataviz/src/lib/chart-view/chart-view.component.d.ts.map +1 -1
  62. package/libs/feature/dataviz/src/lib/service/data.service.d.ts +2 -2
  63. package/libs/feature/dataviz/src/lib/service/data.service.d.ts.map +1 -1
  64. package/libs/feature/dataviz/src/lib/table-view/table-view.component.d.ts +2 -1
  65. package/libs/feature/dataviz/src/lib/table-view/table-view.component.d.ts.map +1 -1
  66. package/libs/feature/editor/src/lib/components/record-form/form-field/form-field-contacts-for-resource/form-field-contacts-for-resource.component.d.ts.map +1 -1
  67. package/libs/feature/editor/src/lib/components/record-form/form-field/form-field-rich/form-field-rich.component.d.ts.map +1 -1
  68. package/libs/feature/record/src/lib/data-view/data-view.component.d.ts +1 -0
  69. package/libs/feature/record/src/lib/data-view/data-view.component.d.ts.map +1 -1
  70. package/libs/feature/record/src/lib/map-view/map-view.component.d.ts.map +1 -1
  71. package/libs/feature/record/src/lib/state/mdview.actions.d.ts +16 -1
  72. package/libs/feature/record/src/lib/state/mdview.actions.d.ts.map +1 -1
  73. package/libs/feature/record/src/lib/state/mdview.effects.d.ts +5 -0
  74. package/libs/feature/record/src/lib/state/mdview.effects.d.ts.map +1 -1
  75. package/libs/feature/record/src/lib/state/mdview.facade.d.ts +2 -0
  76. package/libs/feature/record/src/lib/state/mdview.facade.d.ts.map +1 -1
  77. package/libs/feature/record/src/lib/state/mdview.reducer.d.ts +4 -1
  78. package/libs/feature/record/src/lib/state/mdview.reducer.d.ts.map +1 -1
  79. package/libs/feature/record/src/lib/state/mdview.selectors.d.ts +2 -0
  80. package/libs/feature/record/src/lib/state/mdview.selectors.d.ts.map +1 -1
  81. package/libs/ui/elements/src/index.d.ts +1 -0
  82. package/libs/ui/elements/src/index.d.ts.map +1 -1
  83. package/libs/ui/elements/src/lib/application-banner/application-banner.component.d.ts +16 -0
  84. package/libs/ui/elements/src/lib/application-banner/application-banner.component.d.ts.map +1 -0
  85. package/libs/ui/elements/src/lib/record-api-form/record-api-form.component.d.ts.map +1 -1
  86. package/libs/ui/elements/src/lib/ui-elements.module.d.ts +2 -1
  87. package/libs/ui/elements/src/lib/ui-elements.module.d.ts.map +1 -1
  88. package/libs/ui/inputs/src/lib/autocomplete/autocomplete.component.d.ts.map +1 -1
  89. package/libs/ui/search/src/lib/results-table/action-menu/action-menu.component.d.ts +4 -2
  90. package/libs/ui/search/src/lib/results-table/action-menu/action-menu.component.d.ts.map +1 -1
  91. package/libs/ui/search/src/lib/results-table/results-table.component.d.ts +3 -1
  92. package/libs/ui/search/src/lib/results-table/results-table.component.d.ts.map +1 -1
  93. package/libs/util/data-fetcher/src/lib/data-fetcher.d.ts +2 -2
  94. package/libs/util/data-fetcher/src/lib/data-fetcher.d.ts.map +1 -1
  95. package/libs/util/data-fetcher/src/lib/readers/base-cache.d.ts +8 -0
  96. package/libs/util/data-fetcher/src/lib/readers/base-cache.d.ts.map +1 -0
  97. package/libs/util/data-fetcher/src/lib/readers/base-file.d.ts +2 -2
  98. package/libs/util/data-fetcher/src/lib/readers/base-file.d.ts.map +1 -1
  99. package/libs/util/data-fetcher/src/lib/readers/base.d.ts +2 -2
  100. package/libs/util/data-fetcher/src/lib/readers/base.d.ts.map +1 -1
  101. package/libs/util/data-fetcher/src/lib/readers/gml.d.ts +5 -3
  102. package/libs/util/data-fetcher/src/lib/readers/gml.d.ts.map +1 -1
  103. package/libs/util/data-fetcher/src/lib/readers/wfs.d.ts +7 -4
  104. package/libs/util/data-fetcher/src/lib/readers/wfs.d.ts.map +1 -1
  105. package/libs/util/data-fetcher/src/lib/utils.d.ts +2 -2
  106. package/libs/util/data-fetcher/src/lib/utils.d.ts.map +1 -1
  107. package/package.json +1 -1
  108. package/src/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.ts +25 -0
  109. package/src/libs/api/metadata-converter/src/lib/gn4/types/metadata.model.ts +4 -0
  110. package/src/libs/api/repository/src/lib/gn4/elasticsearch/elasticsearch.service.ts +22 -16
  111. package/src/libs/api/repository/src/lib/gn4/gn4-repository.ts +41 -2
  112. package/src/libs/common/domain/src/lib/model/record/metadata.model.ts +3 -1
  113. package/src/libs/common/domain/src/lib/repository/records-repository.interface.ts +4 -1
  114. package/src/libs/common/fixtures/src/lib/records.fixtures.ts +75 -0
  115. package/src/libs/feature/dataviz/src/lib/chart-view/chart-view.component.ts +4 -1
  116. package/src/libs/feature/dataviz/src/lib/service/data.service.ts +42 -21
  117. package/src/libs/feature/dataviz/src/lib/table-view/table-view.component.ts +2 -1
  118. package/src/libs/feature/editor/src/lib/components/constraint-card/constraint-card.component.html +1 -1
  119. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-contacts-for-resource/form-field-contacts-for-resource.component.ts +1 -0
  120. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-rich/form-field-rich.component.ts +1 -1
  121. package/src/libs/feature/editor/src/lib/fields.config.ts +1 -1
  122. package/src/libs/feature/record/src/lib/data-view/data-view.component.html +2 -0
  123. package/src/libs/feature/record/src/lib/data-view/data-view.component.ts +3 -0
  124. package/src/libs/feature/record/src/lib/map-view/map-view.component.ts +2 -1
  125. package/src/libs/feature/record/src/lib/state/mdview.actions.ts +16 -0
  126. package/src/libs/feature/record/src/lib/state/mdview.effects.ts +21 -2
  127. package/src/libs/feature/record/src/lib/state/mdview.facade.ts +15 -0
  128. package/src/libs/feature/record/src/lib/state/mdview.reducer.ts +30 -1
  129. package/src/libs/feature/record/src/lib/state/mdview.selectors.ts +12 -0
  130. package/src/libs/ui/elements/src/index.ts +1 -0
  131. package/src/libs/ui/elements/src/lib/application-banner/application-banner.component.css +0 -0
  132. package/src/libs/ui/elements/src/lib/application-banner/application-banner.component.html +25 -0
  133. package/src/libs/ui/elements/src/lib/application-banner/application-banner.component.ts +70 -0
  134. package/src/libs/ui/elements/src/lib/record-api-form/record-api-form.component.ts +2 -0
  135. package/src/libs/ui/elements/src/lib/ui-elements.module.ts +3 -0
  136. package/src/libs/ui/inputs/src/lib/autocomplete/autocomplete.component.ts +6 -0
  137. package/src/libs/ui/search/src/lib/results-table/action-menu/action-menu.component.html +37 -1
  138. package/src/libs/ui/search/src/lib/results-table/action-menu/action-menu.component.ts +8 -2
  139. package/src/libs/ui/search/src/lib/results-table/results-table.component.html +2 -0
  140. package/src/libs/ui/search/src/lib/results-table/results-table.component.ts +6 -0
  141. package/src/libs/util/data-fetcher/src/lib/data-fetcher.ts +13 -4
  142. package/src/libs/util/data-fetcher/src/lib/readers/base-cache.ts +14 -0
  143. package/src/libs/util/data-fetcher/src/lib/readers/base-file.ts +2 -1
  144. package/src/libs/util/data-fetcher/src/lib/readers/base.ts +2 -2
  145. package/src/libs/util/data-fetcher/src/lib/readers/csv.ts +1 -1
  146. package/src/libs/util/data-fetcher/src/lib/readers/excel.ts +1 -1
  147. package/src/libs/util/data-fetcher/src/lib/readers/geojson.ts +1 -1
  148. package/src/libs/util/data-fetcher/src/lib/readers/gml.ts +7 -7
  149. package/src/libs/util/data-fetcher/src/lib/readers/json.ts +1 -1
  150. package/src/libs/util/data-fetcher/src/lib/readers/wfs.ts +34 -11
  151. package/src/libs/util/data-fetcher/src/lib/utils.ts +36 -32
  152. package/translations/de.json +3 -4
  153. package/translations/en.json +4 -13
  154. package/translations/es.json +3 -4
  155. package/translations/fr.json +15 -16
  156. package/translations/it.json +20 -20
  157. package/translations/nl.json +3 -4
  158. package/translations/pt.json +3 -4
  159. package/translations/sk.json +3 -4
@@ -275,8 +275,8 @@ export const DEFAULT_CONFIGURATION: EditorConfig = {
275
275
  labelKey: marker('editor.record.form.page.description'),
276
276
  sections: [
277
277
  TITLE_SECTION,
278
- ABOUT_SECTION,
279
278
  CLASSIFICATION_SECTION,
279
+ ABOUT_SECTION,
280
280
  GEOGRAPHICAL_COVERAGE_SECTION,
281
281
  ],
282
282
  },
@@ -11,11 +11,13 @@
11
11
  <div class="relative h-[460px]">
12
12
  <gn-ui-table-view
13
13
  *ngIf="mode === 'table'"
14
+ [cacheActive]="cacheActive$ | async"
14
15
  [link]="selectedLink$ | async"
15
16
  ></gn-ui-table-view>
16
17
  <gn-ui-chart-view
17
18
  *ngIf="mode === 'chart'"
18
19
  (chartConfig$)="setChartConfig($event)"
20
+ [cacheActive]="cacheActive$ | async"
19
21
  [link]="selectedLink$ | async"
20
22
  ></gn-ui-chart-view>
21
23
  </div>
@@ -36,6 +36,9 @@ export class DataViewComponent {
36
36
  @Input() mode: 'table' | 'chart'
37
37
  @Input() displaySource = true
38
38
  @Output() chartConfig$ = new BehaviorSubject<DatavizConfigurationModel>(null)
39
+ cacheActive$ = this.mdViewFacade.isHighUpdateFrequency$.pipe(
40
+ map((highF) => !highF)
41
+ )
39
42
  compatibleDataLinks$ = combineLatest([
40
43
  this.mdViewFacade.dataLinks$,
41
44
  this.mdViewFacade.geoDataLinks$,
@@ -239,7 +239,8 @@ export class MapViewComponent implements AfterViewInit {
239
239
  link.accessServiceProtocol === 'ogcFeatures')) ||
240
240
  link.type === 'download'
241
241
  ) {
242
- return this.dataService.readAsGeoJson(link).pipe(
242
+ const cacheActive = true // TODO implement whether should be true or false
243
+ return this.dataService.readAsGeoJson(link, cacheActive).pipe(
243
244
  map((data) => ({
244
245
  type: 'geojson',
245
246
  data,
@@ -2,6 +2,7 @@ import { DatavizConfigurationModel } from '../../../../../../libs/common/domain/
2
2
  import { createAction, props } from '@ngrx/store'
3
3
  import {
4
4
  CatalogRecord,
5
+ DatasetFeatureCatalog,
5
6
  UserFeedback,
6
7
  } from '../../../../../../libs/common/domain/src/lib/model/record'
7
8
 
@@ -28,6 +29,21 @@ export const loadFullMetadataFailure = createAction(
28
29
  props<{ otherError?: string; notFound?: boolean }>()
29
30
  )
30
31
 
32
+ export const loadFeatureCatalog = createAction(
33
+ "[Metadata view] Load metadata's feature catalog",
34
+ props<{ metadata: CatalogRecord }>()
35
+ )
36
+
37
+ export const loadFeatureCatalogSuccess = createAction(
38
+ '[Metadata view] Load metadata feature catalog success',
39
+ props<{ datasetCatalog: DatasetFeatureCatalog | null }>()
40
+ )
41
+
42
+ export const loadFeatureCatalogFailure = createAction(
43
+ '[Metadata view] Load metadata feature catalog failure',
44
+ props<{ error?: string }>()
45
+ )
46
+
31
47
  export const closeMetadata = createAction('[Metadata view] close')
32
48
 
33
49
  /*
@@ -1,11 +1,10 @@
1
1
  import { Injectable } from '@angular/core'
2
2
  import { Actions, createEffect, ofType } from '@ngrx/effects'
3
3
  import { exhaustMap, mergeMap, of } from 'rxjs'
4
- import { catchError, map, switchMap } from 'rxjs/operators'
4
+ import { catchError, filter, map, switchMap, take } from 'rxjs/operators'
5
5
  import * as MdViewActions from './mdview.actions'
6
6
  import { RecordsRepositoryInterface } from '../../../../../../libs/common/domain/src/lib/repository/records-repository.interface'
7
7
  import { PlatformServiceInterface } from '../../../../../../libs/common/domain/src/lib/platform.service.interface'
8
-
9
8
  @Injectable()
10
9
  export class MdViewEffects {
11
10
  constructor(
@@ -33,6 +32,26 @@ export class MdViewEffects {
33
32
  )
34
33
  )
35
34
 
35
+ loadFeatureCatalog$ = createEffect(() =>
36
+ this.actions$.pipe(
37
+ ofType(MdViewActions.loadFullMetadataSuccess),
38
+ filter(({ full }) => full !== undefined),
39
+ switchMap(({ full }) => this.recordsRepository.getFeatureCatalog(full)),
40
+ map((featureCatalog) =>
41
+ MdViewActions.loadFeatureCatalogSuccess({
42
+ datasetCatalog: featureCatalog,
43
+ })
44
+ ),
45
+ catchError((error) =>
46
+ of(
47
+ MdViewActions.loadFeatureCatalogFailure({
48
+ error: error.message,
49
+ })
50
+ )
51
+ )
52
+ )
53
+ )
54
+
36
55
  /*
37
56
  Related effects
38
57
  */
@@ -52,11 +52,26 @@ export class MdViewFacade {
52
52
  filter((md) => !!md)
53
53
  )
54
54
 
55
+ featureCatalog$ = this.store.pipe(select(MdViewSelectors.getFeatureCatalog))
56
+
55
57
  isIncomplete$ = this.store.pipe(
56
58
  select(MdViewSelectors.getMetadataIsIncomplete),
57
59
  filter((incomplete) => incomplete !== null)
58
60
  )
59
61
 
62
+ isHighUpdateFrequency$ = this.metadata$.pipe(
63
+ map((record) => {
64
+ if (record.updateFrequency instanceof Object) {
65
+ return (
66
+ record.updateFrequency.per === 'day' &&
67
+ record.updateFrequency.updatedTimes > 1
68
+ )
69
+ }
70
+
71
+ return record.updateFrequency === 'continual'
72
+ })
73
+ )
74
+
60
75
  error$ = this.store.pipe(select(MdViewSelectors.getMetadataError))
61
76
 
62
77
  related$ = this.store.pipe(select(MdViewSelectors.getRelated))
@@ -3,6 +3,7 @@ import * as MetadataViewActions from './mdview.actions'
3
3
  import { DatavizConfigurationModel } from '../../../../../../libs/common/domain/src/lib/model/dataviz/dataviz-configuration.model'
4
4
  import {
5
5
  CatalogRecord,
6
+ DatasetFeatureCatalog,
6
7
  UserFeedback,
7
8
  } from '../../../../../../libs/common/domain/src/lib/model/record'
8
9
 
@@ -17,6 +18,9 @@ export interface MetadataViewState {
17
18
  allUserFeedbacksLoading: boolean
18
19
  addUserFeedbackLoading: boolean
19
20
  chartConfig?: DatavizConfigurationModel
21
+ featureCatalog?: DatasetFeatureCatalog
22
+ featureCatalogLoading: boolean
23
+ featureCatalogError: string | null
20
24
  }
21
25
 
22
26
  export const initialMetadataViewState: MetadataViewState = {
@@ -24,6 +28,8 @@ export const initialMetadataViewState: MetadataViewState = {
24
28
  loadingFull: false,
25
29
  allUserFeedbacksLoading: false,
26
30
  addUserFeedbackLoading: false,
31
+ featureCatalogLoading: false,
32
+ featureCatalogError: null,
27
33
  }
28
34
 
29
35
  const metadataViewReducer = createReducer(
@@ -105,7 +111,30 @@ const metadataViewReducer = createReducer(
105
111
  addUserFeedbackLoading: false,
106
112
  allUserFeedbacksLoading: false,
107
113
  })
108
- )
114
+ ),
115
+
116
+ /**
117
+ * FeatureCatalog reducers
118
+ */
119
+
120
+ on(MetadataViewActions.loadFeatureCatalog, (state) => ({
121
+ ...state,
122
+ featureCatalogError: null,
123
+ featureCatalogLoading: true,
124
+ })),
125
+ on(
126
+ MetadataViewActions.loadFeatureCatalogSuccess,
127
+ (state, { datasetCatalog }) => ({
128
+ ...state,
129
+ featureCatalog: datasetCatalog,
130
+ featureCatalogLoading: false,
131
+ })
132
+ ),
133
+ on(MetadataViewActions.loadFeatureCatalogFailure, (state, { error }) => ({
134
+ ...state,
135
+ featureCatalogError: error,
136
+ featureCatalogLoading: false,
137
+ }))
109
138
  )
110
139
 
111
140
  export function reducer(
@@ -64,3 +64,15 @@ export const getAddUserFeedbacksLoading = createSelector(
64
64
  getMdViewState,
65
65
  (state: MetadataViewState) => state.addUserFeedbackLoading
66
66
  )
67
+
68
+ /*
69
+ Feature Catalog Selectors
70
+ */
71
+ export const getFeatureCatalog = createSelector(
72
+ getMdViewState,
73
+ (state: MetadataViewState) => state.featureCatalog
74
+ )
75
+ export const getFeatureCatalogIsLoading = createSelector(
76
+ getMdViewState,
77
+ (state: MetadataViewState) => state.featureCatalogLoading
78
+ )
@@ -22,3 +22,4 @@ export * from './lib/thumbnail/thumbnail.component'
22
22
  export * from './lib/ui-elements.module'
23
23
  export * from './lib/user-feedback-item/user-feedback-item.component'
24
24
  export * from './lib/user-preview/user-preview.component'
25
+ export * from './lib/application-banner/application-banner.component'
@@ -0,0 +1,25 @@
1
+ <div
2
+ *ngIf="message && bannerOpen"
3
+ class="absolute left-0 right-0 text-wrap bg-white mt-4 max-h-24"
4
+ >
5
+ <div
6
+ class="flex flex-row py-2.5 px-5 gap-5 justify-start border max-h-20"
7
+ [ngClass]="classList"
8
+ >
9
+ <div [ngClass]="message.length > 200 ? 'pt-5' : 'pt-1'">
10
+ <ng-icon [name]="icon"></ng-icon>
11
+ </div>
12
+ <div class="flex flex-col justify-start gap-2.5">
13
+ <span *ngIf="title" class="font-bold">{{ title }}</span>
14
+ <span class="font-medium max-w-2xl" [innerHTML]="message"></span>
15
+ </div>
16
+ <button
17
+ *ngIf="closeEnabled"
18
+ class="self-start"
19
+ type="button"
20
+ (click)="closeMessage()"
21
+ >
22
+ <ng-icon name="matCloseOutline"> </ng-icon>
23
+ </button>
24
+ </div>
25
+ </div>
@@ -0,0 +1,70 @@
1
+ import { ChangeDetectionStrategy, Component, Input } from '@angular/core'
2
+ import { CommonModule } from '@angular/common'
3
+ import {
4
+ NgIconComponent,
5
+ provideIcons,
6
+ provideNgIconsConfig,
7
+ } from '@ng-icons/core'
8
+ import {
9
+ matCloseOutline,
10
+ matInfoOutline,
11
+ matWarningAmberOutline,
12
+ } from '@ng-icons/material-icons/outline'
13
+ import { matWarning } from '@ng-icons/material-icons/baseline'
14
+
15
+ @Component({
16
+ selector: 'gn-ui-application-banner',
17
+ standalone: true,
18
+ imports: [CommonModule, NgIconComponent],
19
+ changeDetection: ChangeDetectionStrategy.OnPush,
20
+ templateUrl: './application-banner.component.html',
21
+ styleUrl: './application-banner.component.css',
22
+ providers: [
23
+ provideIcons({
24
+ matWarningAmberOutline,
25
+ matInfoOutline,
26
+ matCloseOutline,
27
+ matWarning,
28
+ }),
29
+ provideNgIconsConfig({ size: '1.5em' }),
30
+ ],
31
+ })
32
+ export class ApplicationBannerComponent {
33
+ @Input() message: string
34
+ @Input() title: string
35
+ @Input() closeEnabled = false
36
+ @Input() extraClass = ''
37
+ @Input() icon = ''
38
+ msgClass = ''
39
+ bannerOpen = true
40
+
41
+ @Input() set type(value: 'primary' | 'secondary' | 'light') {
42
+ switch (value) {
43
+ case 'primary':
44
+ this.msgClass = 'bg-primary-darkest border-primary text-white'
45
+ this.icon = 'matWarning'
46
+ break
47
+ case 'light':
48
+ this.msgClass =
49
+ 'bg-primary-opacity-10 border-primary-lightest text-black'
50
+ this.icon = 'matInfoOutline'
51
+ break
52
+ case 'secondary':
53
+ default:
54
+ this.msgClass = 'bg-primary-opacity-50 border-primary-darker text-black'
55
+ this.icon = 'matWarningAmberOutline'
56
+ break
57
+ }
58
+ }
59
+
60
+ get classList() {
61
+ if (this.message.length > 200) {
62
+ return `${this.msgClass} ${this.extraClass} overflow-y-scroll items-start`
63
+ }
64
+ return `${this.msgClass} ${this.extraClass} items-center`
65
+ }
66
+
67
+ closeMessage() {
68
+ this.bannerOpen = false
69
+ }
70
+ }
@@ -161,6 +161,8 @@ export class RecordApiFormComponent {
161
161
  maxFeatures: limit !== '-1' ? Number(limit) : undefined,
162
162
  limit: limit !== '-1' ? Number(limit) : -1,
163
163
  offset: offset !== '' ? Number(offset) : undefined,
164
+ outputCrs:
165
+ format === ('application/json' || 'geojson') ? 'EPSG:4326' : undefined,
164
166
  }
165
167
 
166
168
  if (this.endpoint instanceof WfsEndpoint) {
@@ -19,6 +19,7 @@ import { MarkdownParserComponent } from './markdown-parser/markdown-parser.compo
19
19
  import { ThumbnailComponent } from './thumbnail/thumbnail.component'
20
20
  import { TimeSincePipe } from './user-feedback-item/time-since.pipe'
21
21
  import { UserPreviewComponent } from './user-preview/user-preview.component'
22
+ import { ApplicationBannerComponent } from './application-banner/application-banner.component'
22
23
 
23
24
  @NgModule({
24
25
  imports: [
@@ -40,6 +41,7 @@ import { UserPreviewComponent } from './user-preview/user-preview.component'
40
41
  MaxLinesComponent,
41
42
  TextInputComponent,
42
43
  ImageInputComponent,
44
+ ApplicationBannerComponent,
43
45
  ],
44
46
  providers: [
45
47
  provideNgIconsConfig({
@@ -53,6 +55,7 @@ import { UserPreviewComponent } from './user-preview/user-preview.component'
53
55
  UserPreviewComponent,
54
56
  MarkdownParserComponent,
55
57
  ImageInputComponent,
58
+ ApplicationBannerComponent,
56
59
  ],
57
60
  })
58
61
  export class UiElementsModule {}
@@ -147,6 +147,12 @@ export class AutocompleteComponent
147
147
  this.error = null
148
148
  }),
149
149
  switchMap((value) => this.action(value)),
150
+ tap((suggestions) => {
151
+ // forcing the panel to open if there are suggestions
152
+ if (suggestions.length > 0) {
153
+ this.triggerRef?.openPanel()
154
+ }
155
+ }),
150
156
  catchError((error: Error) => {
151
157
  this.error = error.message
152
158
  return of([])
@@ -6,6 +6,7 @@
6
6
  >
7
7
  <ul class="flex flex-col gap-2 w-full">
8
8
  <gn-ui-button
9
+ *ngIf="!isDraftPage"
9
10
  type="light"
10
11
  extraClass="flex flex-row items-center gap-2 w-full justify-start"
11
12
  (buttonClick)="duplicate.emit()"
@@ -23,7 +24,10 @@
23
24
  (buttonClick)="displayDeleteMenu()"
24
25
  [disabled]="!canDelete"
25
26
  data-test="record-menu-delete-button"
26
- ><span translate>record.action.delete</span></gn-ui-button
27
+ ><span *ngIf="!isDraftPage" translate>record.action.delete</span>
28
+ <span *ngIf="isDraftPage" translate
29
+ >record.action.rollback</span
30
+ ></gn-ui-button
27
31
  >
28
32
  </ul>
29
33
  </div>
@@ -60,4 +64,36 @@
60
64
  </div>
61
65
  </div>
62
66
  </ng-container>
67
+ <ng-container *ngSwitchCase="'rollbackMenu'">
68
+ <div
69
+ data-test="rollbackMenuSection"
70
+ class="w-80 p-6 flex flex-col gap-3 mt-2 border border-gray-100 bg-white shadow-2xl rounded-2xl"
71
+ >
72
+ <span class="text-lg font-bold text-center">{{
73
+ 'editor.record.undo.confirmation.title' | translate
74
+ }}</span>
75
+ <span class="text-center">{{
76
+ 'editor.record.undo.confirmation.message' | translate
77
+ }}</span>
78
+ <div class="flex flex-row gap-8 justify-center">
79
+ <gn-ui-button
80
+ (buttonClick)="rollback.emit()"
81
+ cdkFocusInitial
82
+ type="primary"
83
+ data-cy="confirm-button"
84
+ [style.--gn-ui-button-width]="'120px'"
85
+ >{{
86
+ 'editor.record.undo.confirmation.confirmText' | translate
87
+ }}</gn-ui-button
88
+ >
89
+ <gn-ui-button
90
+ [style.--gn-ui-button-width]="'120px'"
91
+ (buttonClick)="closeActionMenu.emit()"
92
+ >{{
93
+ 'editor.record.undo.confirmation.cancelText' | translate
94
+ }}</gn-ui-button
95
+ >
96
+ </div>
97
+ </div>
98
+ </ng-container>
63
99
  </ng-container>
@@ -13,7 +13,7 @@ import { ConfirmationDialogComponent } from '../../../../../../../libs/ui/elemen
13
13
  import { ButtonComponent } from '../../../../../../../libs/ui/inputs/src'
14
14
  import { TranslateModule } from '@ngx-translate/core'
15
15
 
16
- type ActionMenuPage = 'mainMenu' | 'deleteMenu'
16
+ type ActionMenuPage = 'mainMenu' | 'deleteMenu' | 'rollbackMenu'
17
17
 
18
18
  @Component({
19
19
  selector: 'gn-ui-action-menu',
@@ -32,9 +32,11 @@ type ActionMenuPage = 'mainMenu' | 'deleteMenu'
32
32
  export class ActionMenuComponent {
33
33
  @Input() canDuplicate: boolean
34
34
  @Input() canDelete: boolean
35
+ @Input() isDraftPage: boolean
35
36
  @Output() duplicate = new EventEmitter<void>()
36
37
  @Output() delete = new EventEmitter<void>()
37
38
  @Output() closeActionMenu = new EventEmitter<void>()
39
+ @Output() rollback = new EventEmitter<void>()
38
40
 
39
41
  @ViewChild(MatMenuTrigger) trigger: MatMenuTrigger
40
42
 
@@ -55,7 +57,11 @@ export class ActionMenuComponent {
55
57
  }
56
58
 
57
59
  displayDeleteMenu() {
58
- this.sectionDisplayed = 'deleteMenu'
60
+ if (this.isDraftPage) {
61
+ this.sectionDisplayed = 'rollbackMenu'
62
+ } else {
63
+ this.sectionDisplayed = 'deleteMenu'
64
+ }
59
65
  this.cdr.markForCheck()
60
66
  }
61
67
  }
@@ -162,9 +162,11 @@
162
162
  <gn-ui-action-menu
163
163
  [canDuplicate]="canDuplicate(item) && !isDuplicating"
164
164
  [canDelete]="canDelete(item)"
165
+ [isDraftPage]="isDraftPage"
165
166
  (duplicate)="handleDuplicate(item)"
166
167
  (delete)="handleDelete(item)"
167
168
  (closeActionMenu)="closeActionMenu()"
169
+ (rollback)="handleRollback(item)"
168
170
  >
169
171
  </gn-ui-action-menu>
170
172
  </ng-template>
@@ -74,6 +74,7 @@ export class ResultsTableComponent {
74
74
  @Output() recordClick = new EventEmitter<CatalogRecord>()
75
75
  @Output() duplicateRecord = new EventEmitter<CatalogRecord>()
76
76
  @Output() deleteRecord = new EventEmitter<CatalogRecord>()
77
+ @Output() rollbackDraft = new EventEmitter<CatalogRecord>()
77
78
  @Output() recordsSelectedChange = new EventEmitter<
78
79
  [CatalogRecord[], boolean]
79
80
  >()
@@ -186,6 +187,11 @@ export class ResultsTableComponent {
186
187
  this.closeActionMenu()
187
188
  }
188
189
 
190
+ handleRollback(item: unknown) {
191
+ this.rollbackDraft.emit(item as CatalogRecord)
192
+ this.closeActionMenu()
193
+ }
194
+
189
195
  setSortBy(col: string, order: 'asc' | 'desc') {
190
196
  this.sortByChange.emit([col, order])
191
197
  }
@@ -17,10 +17,17 @@ export async function openDataset(
17
17
  namespace?: string
18
18
  wfsVersion?: WfsVersion
19
19
  wfsFeatureType?: string
20
- }
20
+ },
21
+ cacheActive?: boolean
21
22
  ): Promise<BaseReader> {
22
23
  const fileType = await inferDatasetType(url, typeHint)
23
- let reader: BaseReader
24
+ let reader:
25
+ | CsvReader
26
+ | JsonReader
27
+ | GeojsonReader
28
+ | ExcelReader
29
+ | GmlReader
30
+ | WfsReader
24
31
  try {
25
32
  switch (fileType) {
26
33
  case 'csv':
@@ -42,6 +49,7 @@ export async function openDataset(
42
49
  reader = await WfsReader.createReader(url, options.wfsFeatureType)
43
50
  break
44
51
  }
52
+ reader.setCacheActive(cacheActive)
45
53
  reader.load()
46
54
  return reader
47
55
  } catch (e: any) {
@@ -61,9 +69,10 @@ export async function openDataset(
61
69
  export async function readDataset(
62
70
  url: string,
63
71
  typeHint?: SupportedType,
64
- options?: any
72
+ options?: any,
73
+ cacheActive = true
65
74
  ): Promise<DataItem[]> {
66
- const reader = await openDataset(url, typeHint, options)
75
+ const reader = await openDataset(url, typeHint, options, cacheActive)
67
76
  try {
68
77
  return await reader.read()
69
78
  } catch (e: any) {
@@ -0,0 +1,14 @@
1
+ import { BaseReader } from './base'
2
+
3
+ export abstract class BaseCacheReader extends BaseReader {
4
+ constructor(
5
+ protected url: string,
6
+ protected cacheActive = true
7
+ ) {
8
+ super(url)
9
+ }
10
+
11
+ setCacheActive(value: boolean) {
12
+ this.cacheActive = value
13
+ }
14
+ }
@@ -2,13 +2,14 @@ import { BaseReader } from './base'
2
2
  import { DataItem, DatasetInfo, PropertyInfo } from '../model'
3
3
  import { getJsonDataItemsProxy, jsonToGeojsonFeature } from '../utils'
4
4
  import { generateSqlQuery } from '../sql-utils'
5
+ import { BaseCacheReader } from './base-cache'
5
6
 
6
7
  type ParseResult = {
7
8
  items: DataItem[]
8
9
  properties: PropertyInfo[]
9
10
  }
10
11
 
11
- export class BaseFileReader extends BaseReader {
12
+ export class BaseFileReader extends BaseCacheReader {
12
13
  private parseResult_: Promise<ParseResult>
13
14
 
14
15
  protected getData(): Promise<ParseResult> {
@@ -11,8 +11,8 @@ import {
11
11
 
12
12
  export class BaseReader {
13
13
  protected selected: FieldName[] = null
14
- protected groupedBy: FieldGroupBy[] = null
15
- protected aggregations: FieldAggregation[] = null
14
+ public groupedBy: FieldGroupBy[] = null
15
+ public aggregations: FieldAggregation[] = null
16
16
  protected filter: FieldFilter = null
17
17
  protected sort: FieldSort[] = null
18
18
  protected startIndex: number = null
@@ -47,6 +47,6 @@ export function parseCsv(text: string): {
47
47
 
48
48
  export class CsvReader extends BaseFileReader {
49
49
  getData() {
50
- return fetchDataAsText(this.url).then(parseCsv)
50
+ return fetchDataAsText(this.url, this.cacheActive).then(parseCsv)
51
51
  }
52
52
  }
@@ -28,6 +28,6 @@ export function parseExcel(buffer: ArrayBuffer): Promise<{
28
28
 
29
29
  export class ExcelReader extends BaseFileReader {
30
30
  getData() {
31
- return fetchDataAsArrayBuffer(this.url).then(parseExcel)
31
+ return fetchDataAsArrayBuffer(this.url, this.cacheActive).then(parseExcel)
32
32
  }
33
33
  }
@@ -24,6 +24,6 @@ export function parseGeojson(text: string): {
24
24
 
25
25
  export class GeojsonReader extends BaseFileReader {
26
26
  getData() {
27
- return fetchDataAsText(this.url).then(parseGeojson)
27
+ return fetchDataAsText(this.url, this.cacheActive).then(parseGeojson)
28
28
  }
29
29
  }
@@ -37,17 +37,17 @@ export function parseGml(
37
37
  }
38
38
 
39
39
  export class GmlReader extends BaseFileReader {
40
- namespace: string
41
- version: WfsVersion
42
-
43
- constructor(url, namespace, version) {
40
+ constructor(
41
+ protected url: string,
42
+ protected namespace: string,
43
+ protected version: WfsVersion,
44
+ protected cacheActive = true
45
+ ) {
44
46
  super(url)
45
- this.namespace = namespace
46
- this.version = version
47
47
  }
48
48
 
49
49
  protected getData() {
50
- return fetchDataAsText(this.url).then((text) =>
50
+ return fetchDataAsText(this.url, this.cacheActive).then((text) =>
51
51
  parseGml(text, this.namespace, this.version)
52
52
  )
53
53
  }
@@ -23,6 +23,6 @@ export function parseJson(text: string): {
23
23
 
24
24
  export class JsonReader extends BaseFileReader {
25
25
  getData() {
26
- return fetchDataAsText(this.url).then(parseJson)
26
+ return fetchDataAsText(this.url, this.cacheActive).then(parseJson)
27
27
  }
28
28
  }